在笔者《Delphi MessageBox消息框应用窗口居中实用解决方案-CSDN博客》中,提到了用新线程操作 MessageBox 消息对话框,使其显示在 HWND 窗口中央而不是桌面中央。其实,在新线程中还可以对消息框做更多的操作。本文就增加一个定时回答默认按钮的功能,可在一定时间后自动选择默认选项,关闭消息对话框,从而让程序自动进行下去。只增加几行代码和一个指定等待时间的全局变量就能实现这个功能。具体代码如下:
implementation
{$R *.dfm}
//============从这里开始到下面结束这段代码放在调用程序之前即可================
type
TMyThread = class(TThread) //定义新线程
protected
procedure Execute; override; //新线程创建后即运行
end;
var
hMain: HWND;
MsgTitle: string;
WaitColse: integer; //全局变量,通过它们向新线程传递相关参数
procedure TMyThread.Execute; //新线程执行程序
var
mR, pR, sR: TRect;
X, Y: Integer;
hMsg: HWND;
begin
FreeOnTerminate := True; { 这可以让线程执行完毕后随即释放 }
sleep(5); // 等消息框建立
hMsg := FindWindow(nil, PChar(MsgTitle)); //根据消息窗口标题获取其句柄
GetWindowRect(hMsg, mR); // 取消息框窗口矩形位置大小
GetWindowRect(hMain, pR); // 取父窗口矩形位置大小
GetWindowRect(GetDesktopWindow, sR); // 取屏幕桌面矩形位置大小
X := pR.Left + (pR.Width - mR.Width) div 2;
Y := pR.Top + (pR.Height - mR.Height) div 2; //将消息框座标设定在HWND窗口中央
if X < 0 then
X := 0;
if X > sR.Width - mR.Width then
X := sR.Width - mR.Width;
if Y < 0 then
Y := 0;
if Y > sR.Height - mR.Height then
Y := sR.Height - mR.Height; //将消息框限制在桌面内
SetWindowPos(hMsg, HWND_TOP, X, Y, 0, 0, SWP_NOSIZE or SWP_SHOWWINDOW or
SWP_NOOWNERZORDER); //将消息框移动到 HWND 窗口中央。
if WaitColse = 0 then //如果等待时间为0,则与原来一样,等待用户响应
exit;
sleep(1000 * WaitColse ); //等待WaitColse秒。
PostMessage(hMsg, WM_KEYDOWN, 13, 0);
PostMessage(hMsg, WM_KEYUP, 13, 0); //向消息框窗口发送回车,选择默认按钮
end;
// 主函数。在HWND中央显示消息框。Wait为等待时间(秒),为0或省略则一直等待用户选择。
function MsgBox(const HWND: HWND; const msg, title: string;
const mbType: WORD; const Wait: integer = 0): WORD;
begin
hMain := HWND;
if not IsWindow(hMain) then
hMain := GetDesktopWindow; //如果HWND不存在则为桌面
if title <> '' then
MsgTitle := title
else
MsgTitle := #32; //如果消息对话框无标题则将标题设为空格方便新线程查找
WaitColse := Wait;
TMyThread.Create(False); //创建新线程且立即运行
result := MessageBox(HWND, PChar(msg), PChar(MsgTitle), mbType + MB_TOPMOST);
end;
// ===========================代码结束=================================
扩展后的函数为 MsgBox,如果HWND = 0且省略 Wait 参数,则与 MessageBox 完全一样。扩展用法:
如果 HWND 存在,MessageBox 窗口将显示在该窗口的中央,否则显示在桌面中央;
如果有 Wait 参数且不为0,则用户如果在 Wait 秒内没有选择按钮,到时自动选择默认按钮。
例如:
procedure TForm3.Button1Click(Sender: TObject);
begin
if MsgBox(handle, '消息内容', '消息标题', MB_YESNO or MB_DEFBUTTON2, 5) = mrYes then
close;
end;
按 Form3 中的 Button1 按钮后,消息框会显示在 Form3 窗口中央。在5秒内用户如果按Yes,则关闭 Form3,如果5秒后还未操作,则自动按默认选项 No,关闭消息对话框。