• Delphi中用MessageBox()API函数做倒计时对话框(使用Hook安装CBTHookCallback,计时器更改文字,SetWindowText API真正修改文字,引用未知函数)good


    API有隐藏的MessageBoxTimeOut函数可以做计时对话框,缺点是不能显示还剩下多少秒关闭。

    1. const
    2.   IDTIMEDOUT = 32000;
    3. function MessageBoxTimeOut(hWnd: HWND;
    4.   lpText: PChar; lpCaption: PChar; uType: UINT; wLanguageId: WORD;
    5.   dwMilliseconds: DWORD): Integer; stdcall; external
    6.   user32 name 'MessageBoxTimeoutA';

    其实只要获得对话框的句柄就可以用时间器修改窗体或者按钮标题实现倒计时提示。
    窗体激活后可以通过Hook CBT捕获HCBT_ACTIVATE
    参考如下方法:

    1. var
    2.   hookHandle: THandle;
    3.   dialogHandle: THandle;
    4.   second: Integer;
    5. function CBTHookCallback(nCode: Integer;
    6.   wParam: WPARAM;
    7.   lParam: LPARAM
    8.   ): Integer; stdcall;
    9. begin
    10.   case nCode of
    11.     HCBT_ACTIVATE:
    12.       begin
    13.         dialogHandle := wParam;
    14.         second := 5;
    15.         UnhookWindowsHookEx(hookHandle);
    16.       end;
    17.   end;
    18.   Result := CallNextHookEx(hookHandle, nCode, wParam, lParam);
    19. end;
    20. procedure TForm1.Button1Click(Sender: TObject);
    21. begin
    22.   Timer1.Enabled := True;
    23.   hookHandle := SetWindowsHookEx(WH_CBT, CBTHookCallback, HInstance, 0);
    24.   MessageBox(Handle, 'Zswang 路过', '倒计时(5)', 0);
    25. end;
    26. procedure TForm1.Timer1Timer(Sender: TObject);
    27. begin
    28.   Dec(second);
    29.   if second <= then
    30.   begin
    31.     PostMessage(dialogHandle, WM_CLOSE, 0, 0);
    32.     TTimer(Sender).Enabled := False;
    33.   end;
    34.   SetWindowText(dialogHandle, PChar(Format('倒计时(%d)', [second])));
    35. end;

    相对来说,C#中写得更麻烦一些,因为要自己什么API,如下是修改按钮标题的例子:

      1. public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
      2. [DllImport("user32.dll")]
      3. public static extern IntPtr SetWindowsHookEx(int hookid,
      4.     HookProc pfnhook, IntPtr hinst, int threadid);
      5. [DllImport("user32.dll")]
      6. public static extern IntPtr CallNextHookEx(IntPtr hhook,
      7.     int code, IntPtr wparam, IntPtr lparam);
      8. [DllImport("kernel32.dll")]
      9. public static extern IntPtr GetModuleHandle(string modName);
      10. [DllImport("user32.dll")]
      11. public static extern bool UnhookWindowsHookEx(IntPtr hhook);
      12. public const int WH_CBT = 5;
      13. public const int HCBT_ACTIVATE = 5;
      14. IntPtr hookHandle = IntPtr.Zero;
      15. public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);
      16. [DllImport("user32.dll")]
      17. public static extern int EnumChildWindows(IntPtr hWndParent,
      18.     WNDENUMPROC lpEnumFunc, int lParam);
      19. [DllImport("user32.dll")]
      20. public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,
      21.     int nMaxCount);
      22. [DllImport("user32.dll")]
      23. public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString,
      24.     int nMaxCount);
      25. [DllImport("user32.dll")]
      26. public static extern void SetWindowText(IntPtr hwnd, string lpString);
      27. public bool EnumChild(IntPtr hwnd, int lParam)
      28. {
      29.     StringBuilder vBuffer = new StringBuilder(256);
      30.     GetClassName(hwnd, vBuffer, vBuffer.Capacity);
      31.     if (vBuffer.ToString().ToLower() == "button") // 按钮
      32.     {
      33.         StringBuilder vText = new StringBuilder(256);
      34.         GetWindowText(hwnd, vText, vText.Capacity);
      35.         if (vText.ToString().ToLower().IndexOf("&a") >= 0) // 终止
      36.             SetWindowText(hwnd, "停不要动");
      37.         if (vText.ToString().ToLower().IndexOf("&r") >= 0) // 重试
      38.             SetWindowText(hwnd, "再来一次");
      39.         if (vText.ToString().ToLower().IndexOf("&i") >= 0) // 忽略
      40.             SetWindowText(hwnd, "就这样吧");
      41.     }
      42.     return true;
      43. }
      44. private IntPtr CBTHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
      45. {
      46.     switch (nCode)
      47.     {
      48.         case HCBT_ACTIVATE:
      49.             EnumChildWindows(wParam, new WNDENUMPROC(EnumChild), 0);
      50.             UnhookWindowsHookEx(hookHandle);
      51.             break;
      52.     }
      53.     return CallNextHookEx(hookHandle, nCode, wParam, lParam);
      54. }
      55. private void button1_Click(object sender, EventArgs e)
      56. {
      57.     hookHandle = SetWindowsHookEx(WH_CBT, new HookProc(CBTHookCallback),
      58.         GetModuleHandle(null), 0);
      59.     MessageBox.Show("Zswang 路过", "提示", MessageBoxButtons.AbortRetryIgnore);
      60. }

    http://blog.csdn.net/zswang/article/details/3081063

  • 相关阅读:
    21.面向对象:多态与多态性、面向对象进阶:内置方法,反射。异常处理
    mysql 复习
    Python之math模块
    mysql数据类型转换
    Remmina
    JWT校验流程源码
    JWT签发token
    elasticsearch使用
    Flask基础
    初识Flask
  • 原文地址:https://www.cnblogs.com/findumars/p/6347883.html
Copyright © 2020-2023  润新知