在笔者上篇博文《Delphi MessageBox消息框应用窗口居中实用解决方案》中,提到了用新线程操作 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;
- k, 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;
- k := 0;
- while k < WaitColse do
- begin
- sleep(1000);
- inc(k);
- end; //等待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,关闭消息对话框。