Как лучше всего в Delphi показывать настраиваемые диалоги сообщений? - PullRequest
15 голосов
/ 08 июля 2009

Я использую Delphi и хочу показать пользовательский текст в кнопках MessageDlg, , как описано здесь . Каков наилучший способ сделать это?

Ответы [ 4 ]

11 голосов
/ 08 июля 2009

Отвечая на мой собственный вопрос .... Я написал приведенный ниже блок, который хорошо работает для меня.

Delphi предоставляет CreateMessageDialog () , чтобы предоставить вам шаблон диалога, который вы можете изменить перед отображением. Я использовал это для создания функции, которую я назвал MessageDlgCustom, которая принимает те же параметры, что и стандартный MessageDlg, но добавляет еще один для заголовков кнопок замены.

Он правильно обрабатывает пользовательские шрифты и автоматически настраивает кнопки, чтобы они были достаточно широкими для их сообщения. Если кнопки переполняют диалоговое окно, то это тоже настраивается.

После использования этого устройства работает приведенный ниже пример:

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

Если кто-то знает лучший способ, пожалуйста, поделитесь им.

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.
3 голосов
/ 06 февраля 2016

В качестве альтернативы вы можете использовать Open Source SynTaskDialog единицу. SynTaskDialog изначально использует API-интерфейс Windows TaskDialog в новых версиях Windows и эмулирует его в более старых версиях. Вы даже можете использовать его с FireMonkey .

Для примера настраиваемой функции MessageDlg взгляните на этот ответ .

2 голосов
/ 18 февраля 2019

Вы можете взглянуть на компонент TDam, доступный на GitHub (https://github.com/digao-dalpiaz/Dam).

Этот компонент позволяет создавать настраиваемые диалоговые окна сообщений с предварительно определенными кнопками, используя форматированный текст (HTML Text) и позволяя настраивать многие аспекты диалогов.

Кроме того, вы можете управлять всеми диалогами вашего приложения в «контейнере», который хранит все диалоги как объекты (TDamMsg).

Пример сообщения TDam

Свойства TDamMsg позволяют настроить диалог сообщений, например:

  • Button1 - заголовок кнопки 1
  • Button2 - заголовок кнопки 2
  • Button3 - заголовок кнопки 3

Buttons: TDamMsgButtons = Определяет кнопки в диалоговом окне сообщения:

  • dbOK: определяет одну кнопку OK
  • dbYesNo: определяет две кнопки Да / Нет
  • dbOne: определяет одну кнопку с помощью заголовка Button1
  • dbTwo: определяет две кнопки с помощью заголовков Button1 и Button2
  • dbThree: определяет три кнопки с помощью заголовков Button1, Button2 и Button3
1 голос
/ 09 июля 2009

Кроме того, убедитесь, что ваш сторонний контроль также позвоните своему заказному сообщению dlg и нестандартно Функция MessageDlg. Это если они на самом деле используй это. Возможно, что сторонний контроль не используйте Delphi Messagedlg и вызвать MessageBox API напрямую. Если это так, вы могли бы в конечном итоге с несоответствиями в отображении сообщения коробки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...