API有隐藏的MessageBoxTimeOut函数可以做计时对话框,缺点是不能显示还剩下多少秒关闭。
其实只要获得对话框的句柄就可以用时间器修改窗体或者按钮标题实现倒计时提示。
窗体激活后可以通过Hook CBT捕获HCBT_ACTIVATE
参考如下方法:
相对来说,C#中写得更麻烦一些,因为要自己什么API,如下是修改按钮标题的例子:
- const
- IDTIMEDOUT=32000;
- functionMessageBoxTimeOut(hWnd:HWND;
- lpText:PChar;lpCaption:PChar;uType:UINT;wLanguageId:WORD;
- dwMilliseconds:DWORD):Integer;stdcall;external
- user32name'MessageBoxTimeoutA';
窗体激活后可以通过Hook CBT捕获HCBT_ACTIVATE
参考如下方法:
- var
- hookHandle:THandle;
- dialogHandle:THandle;
- second:Integer;
- functionCBTHookCallback(nCode:Integer;
- wParam:WPARAM;
- lParam:LPARAM
- ):Integer;stdcall;
- begin
- casenCodeof
- HCBT_ACTIVATE:
- begin
- dialogHandle:=wParam;
- second:=5;
- UnhookWindowsHookEx(hookHandle);
- end;
- end;
- Result:=CallNextHookEx(hookHandle,nCode,wParam,lParam);
- end;
- procedureTForm1.Button1Click(Sender:TObject);
- begin
- Timer1.Enabled:=True;
- hookHandle:=SetWindowsHookEx(WH_CBT,CBTHookCallback,HInstance,0);
- MessageBox(Handle,'Zswang路过','倒计时(5)',0);
- end;
- procedureTForm1.Timer1Timer(Sender:TObject);
- begin
- Dec(second);
- ifsecond<=0then
- begin
- PostMessage(dialogHandle,WM_CLOSE,0,0);
- TTimer(Sender).Enabled:=False;
- end;
- SetWindowText(dialogHandle,PChar(Format('倒计时(%d)',[second])));
- end;
- publicdelegateIntPtrHookProc(intnCode,IntPtrwParam,IntPtrlParam);
- [DllImport("user32.dll")]
- publicstaticexternIntPtrSetWindowsHookEx(inthookid,
- HookProcpfnhook,IntPtrhinst,intthreadid);
- [DllImport("user32.dll")]
- publicstaticexternIntPtrCallNextHookEx(IntPtrhhook,
- intcode,IntPtrwparam,IntPtrlparam);
- [DllImport("kernel32.dll")]
- publicstaticexternIntPtrGetModuleHandle(stringmodName);
- [DllImport("user32.dll")]
- publicstaticexternboolUnhookWindowsHookEx(IntPtrhhook);
- publicconstintWH_CBT=5;
- publicconstintHCBT_ACTIVATE=5;
- IntPtrhookHandle=IntPtr.Zero;
- publicdelegateboolWNDENUMPROC(IntPtrhwnd,intlParam);
- [DllImport("user32.dll")]
- publicstaticexternintEnumChildWindows(IntPtrhWndParent,
- WNDENUMPROClpEnumFunc,intlParam);
- [DllImport("user32.dll")]
- publicstaticexternintGetClassName(IntPtrhWnd,StringBuilderlpClassName,
- intnMaxCount);
- [DllImport("user32.dll")]
- publicstaticexternintGetWindowText(IntPtrhWnd,StringBuilderlpString,
- intnMaxCount);
- [DllImport("user32.dll")]
- publicstaticexternvoidSetWindowText(IntPtrhwnd,stringlpString);
- publicboolEnumChild(IntPtrhwnd,intlParam)
- {
- StringBuildervBuffer=newStringBuilder(256);
- GetClassName(hwnd,vBuffer,vBuffer.Capacity);
- if(vBuffer.ToString().ToLower()=="button")//按钮
- {
- StringBuildervText=newStringBuilder(256);
- GetWindowText(hwnd,vText,vText.Capacity);
- if(vText.ToString().ToLower().IndexOf("&a")>=0)//终止
- SetWindowText(hwnd,"停不要动");
- if(vText.ToString().ToLower().IndexOf("&r")>=0)//重试
- SetWindowText(hwnd,"再来一次");
- if(vText.ToString().ToLower().IndexOf("&i")>=0)//忽略
- SetWindowText(hwnd,"就这样吧");
- }
- returntrue;
- }
- privateIntPtrCBTHookCallback(intnCode,IntPtrwParam,IntPtrlParam)
- {
- switch(nCode)
- {
- caseHCBT_ACTIVATE:
- EnumChildWindows(wParam,newWNDENUMPROC(EnumChild),0);
- UnhookWindowsHookEx(hookHandle);
- break;
- }
- returnCallNextHookEx(hookHandle,nCode,wParam,lParam);
- }
- privatevoidbutton1_Click(objectsender,EventArgse)
- {
- hookHandle=SetWindowsHookEx(WH_CBT,newHookProc(CBTHookCallback),
- GetModuleHandle(null),0);
- MessageBox.Show("Zswang路过","提示",MessageBoxButtons.AbortRetryIgnore);
- }