【发布时间】:2009-07-08 19:26:09
【问题描述】:
我正在使用 Delphi,我想在 MessageDlg as described here 的按钮中显示自定义文本。最好的方法是什么?
【问题讨论】:
标签: delphi user-interface
我正在使用 Delphi,我想在 MessageDlg as described here 的按钮中显示自定义文本。最好的方法是什么?
【问题讨论】:
标签: delphi user-interface
回答我自己的问题....我编写了以下对我很有效的单元。
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.
【讨论】:
MessageDlgCustom('Confirm?',mtCustom, mbYesNoCancel, ['Yes, sir!','',''], nil); 一样,将使用默认值而不是空字符串。请检查它。
作为替代方案,您可以使用开源SynTaskDialog 单元。 SynTaskDialog 在较新的 Windows 版本上本机使用 Windows TaskDialog API,并在旧版本上模拟它。你甚至可以use it with FireMonkey。
有关可自定义 MessageDlg 函数的示例,请查看 this answer。
【讨论】:
您可以查看 GitHub (https://github.com/digao-dalpiaz/Dam) 上提供的 TDam 组件。
此组件允许您使用预定义按钮创建自定义消息对话框,使用格式化文本(HTML 文本),并允许自定义对话框的许多方面。
除此之外,您可以将所有应用程序对话框管理到一个“容器”中,该容器将所有对话框存储为对象 (TDamMsg)。
TDamMsg 属性允许自定义消息对话框,例如:
按钮:TDamMsgButtons = 定义消息对话框中的按钮:
【讨论】:
另外,请确保您的第 3 方也可以控制 调用您的自定义消息 dlg 而不是标准 MessageDlg 函数。那就是如果他们真的 使用它。有可能是第 3 方控制 不要使用 Delphi messagedlg 并调用 MessageBox API 直接。如果是这种情况,你可能会 最终显示消息不一致 盒子。
【讨论】: