Presta atención porque en este artículo vas a hallar la solución que buscas.Esta noticia ha sido aprobado por nuestros expertos para garantizar la calidad y veracidad de nuestro post.
Solución:
Respondiendo a mi propia pregunta… Escribí la siguiente unidad que funciona bien para mí.
Delphi proporciona CreateMessageDialog() para brindarle una plantilla de diálogo, que puede modificar antes de mostrarla. Lo usé para crear una función a la que llamé MessageDlgCustom, que toma los mismos parámetros que un MessageDlg estándar, pero agrega uno más para reemplazar los títulos de los botones.
Maneja correctamente las fuentes personalizadas y ajusta automáticamente los botones para que sean lo suficientemente anchos para su mensaje. Si los botones desbordan el cuadro de diálogo, eso también se ajusta.
Después de usar esa unidad, el siguiente ejemplo funciona:
case MessageDlgCustom('Save your changes?',mtConfirmation,
[mbYes,mbNo,mbCancel],
['&Yes, I would like to save them with this absurdly long button',
'&No, I do not care about my stupid changes',
'&Arg! What are you talking about? Do not close the form!'],
nil) //nil = no custom font
of
mrYes:
begin
SaveChanges;
CloseTheForm;
end; //mrYes (save & close)
mrNo:
begin
CloseForm;
end; //mrNo (close w/o saving)
mrCancel:
begin
//do nothing
end; //mrCancel (neither save nor close)
end; //case
Si alguien más conoce una mejor manera, por favor compártala.
unit CustomDialog;
interface
uses
Dialogs, Forms, Graphics, StdCtrls;
function MessageDlgCustom(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; ToCaptions: array of string;
customFont: TFont) : integer;
procedure ModifyDialog(var frm: TForm; ToCaptions : array of string;
customFont : TFont = nil);
implementation
uses
Windows, SysUtils;
function GetTextWidth(s: string; fnt: TFont; HWND: THandle): integer;
var
canvas: TCanvas;
begin
canvas := TCanvas.Create;
try
canvas.Handle := GetWindowDC(HWND);
canvas.Font := fnt;
Result := canvas.TextWidth(s);
finally
ReleaseDC(HWND,canvas.Handle);
FreeAndNil(canvas);
end; //try-finally
end;
function MessageDlgCustom(const Msg: string;
DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; ToCaptions: array of string;
customFont: TFont): integer;
var
dialog : TForm;
begin
try
dialog := CreateMessageDialog(Msg, DlgType, Buttons);
dialog.Position := poScreenCenter;
ModifyDialog(dialog,ToCaptions,customFont);
Result := dialog.ShowModal;
finally
dialog.Release;
end; //try-finally
end;
procedure ModifyDialog(var frm: TForm; ToCaptions: array of string;
customFont: TFont);
const
c_BtnMargin = 10; //margin of button around caption text
var
i,oldButtonWidth,newButtonWidth,btnCnt : integer;
begin
oldButtonWidth := 0;
newButtonWidth := 0;
btnCnt := 0;
for i := 0 to frm.ComponentCount - 1 do begin
//if they asked for a custom font, assign it here
if customFont <> nil then begin
if frm.Components[i] is TLabel then begin
TLabel(frm.Components[i]).Font := customFont;
end;
if frm.Components[i] is TButton then begin
TButton(frm.Components[i]).Font := customFont;
end;
end;
if frm.Components[i] is TButton then begin
//check buttons for a match with a "from" (default) string
//if found, replace with a "to" (custom) string
Inc(btnCnt);
//record the button width *before* we changed the caption
oldButtonWidth := oldButtonWidth + TButton(frm.Components[i]).Width;
//if a custom caption has been provided use that instead,
//or just leave the default caption if the custom caption is empty
if ToCaptions[btnCnt - 1]<>'' then
TButton(frm.Components[i]).Caption := ToCaptions[btnCnt - 1];
//auto-size the button for the new caption
TButton(frm.Components[i]).Width :=
GetTextWidth(TButton(frm.Components[i]).Caption,
TButton(frm.Components[i]).Font,frm.Handle) + c_BtnMargin;
//the first button can stay where it is.
//all other buttons need to slide over to the right of the one b4.
if (1 < btnCnt) and (0 < i) then begin
TButton(frm.Components[i]).Left :=
TButton(frm.Components[i-1]).Left +
TButton(frm.Components[i-1]).Width + c_BtnMargin;
end;
//record the button width *after* changing the caption
newButtonWidth := newButtonWidth + TButton(frm.Components[i]).Width;
end; //if TButton
end; //for i
//whatever we changed the buttons by, widen / shrink the form accordingly
frm.Width := Round(frm.Width + (newButtonWidth - oldButtonWidth) +
(c_BtnMargin * btnCnt));
end;
end.
Como alternativa, puede utilizar la unidad SynTaskDialog de código abierto. SynTaskDialog usa la API TaskDialog de Windows de forma nativa en las versiones más recientes de Windows y la emula en versiones anteriores. Incluso puedes usarlo con FireMonkey.
Para ver un ejemplo de una función MessageDlg personalizable, eche un vistazo a esta respuesta.
Puede echar un vistazo al componente TDam disponible en GitHub (https://github.com/digao-dalpiaz/Dam).
Este componente le permite crear diálogos de mensajes personalizados con botones predefinidos, utilizando texto formateado (texto HTML) y permitiendo personalizar muchos aspectos de los diálogos.
Además de eso, puede administrar todos los cuadros de diálogo de su aplicación en un "contenedor", que almacena todos los cuadros de diálogo como objetos (TDamMsg).
Ejemplo de mensaje TDam
Las propiedades de TDamMsg permiten personalizar el diálogo del mensaje, como:
- Button1 - título del botón 1
- Button2 - título del botón 2
- Button3 - título del botón 3
Botones: TDamMsgButtons = Define los botones en el cuadro de diálogo del mensaje:
- dbOK: Define un botón OK
- dbYesNo: Define dos botones Sí/No
- dbOne: define un botón por el título definido por Button1
- dbTwo: define dos botones mediante subtítulos definidos por Button1 y Button2
- dbThree: define tres botones por subtítulos definidos por Button1, Button2 y Button3