Saltar al contenido

¿Cuál es la mejor manera en Delphi para mostrar cuadros de diálogo de mensajes personalizados?

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

Reseñas y calificaciones de la guía

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *