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 <= 0 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

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

  1. Restful风格API中用put还是post做新增操作有什么区别?

    Restful风格API中用put还是post做新增操作有什么区别? 转 头条面试归来,有些话想和Java开发者说!>>> 这个是华为面试官问我的问题,回来我找了很多资料,想验证这个 ...

  2. 用CIL写程序:写个函数做加法

    前言: 上一篇文章小匹夫为CIL正名的篇幅比较多,反而忽略了写那篇文章初衷--即通过写CIL代码来熟悉它,了解它.那么既然有上一篇文章做基础(炮灰),想必各位对CIL的存在也就释然了,兴许也燃起了一点 ...

  3. RCurl getURL()函数做debug

    getURL()函数做获取网页做debug,三步骤 1.首先创建一个对象debugGatherer(),该对象包含三个函数:(update(), value(), reset()); R> de ...

  4. 阿里云api调用做简单的cmdb

    阿里云api调用做简单的cmdb 1 步骤 事实上就是调用阿里api.获取可用区,比方cn-hangzhou啊等等.然后在每一个区调用api 取ecs的状态信息,最好写到一个excel里面去.方便排序 ...

  5. js中ajax连接服务器open函数的另外两个默认参数get请求和默认异步(open的post方式send函数带参数)(post请求和get请求区别:get:快、简单 post:安全,量大,不缓存)(服务器同步和异步区别:同步:等待服务器响应当中浏览器不能做别的事情)(ajax和jquery一起用的)

    js中ajax连接服务器open函数的另外两个默认参数get请求和默认异步(open的post方式send函数带参数)(post请求和get请求区别:get:快.简单 post:安全,量大,不缓存)( ...

  6. python3中匿名函数做参数,匿名函数做实参,eval关键字

    一:说到匿名函数,大家都感到陌生又熟悉,今天我带大家了解一下py3中的匿名函数,以及匿名函数作为函数的参数的情况 主要通过以下实例来说明: 实例一: newarr =[33,44444,6222,88 ...

  7. C++ 友元 (全局函数做友元) (类做友元) (成员函数做友元)

    1 //友元 全局函数做友元 2 /* 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...

  8. 【Go语言学习笔记】函数做参数和闭包

    函数做参数 在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型.类似于重写(同名覆盖). 回调函数:函数有一个参数是函数类型,这个 ...

  9. python Django教程 之 模型(数据库)、自定义Field、数据表更改、QuerySet API

    python  Django教程  之 模型(数据库).自定义Field.数据表更改.QuerySet API 一.Django 模型(数据库) Django 模型是与数据库相关的,与数据库相关的代码 ...

随机推荐

  1. 浅谈CAS(Compare and Swap) 原理

    浅谈CAS原理java并发编程也研究了一段时间了,对CAS的原理总是不太理解,今天再研究了一下,记录一些自己的理解.    说到CAS,再java中的某些情况下,甚至jdk1.5以后的大多数情况,并发 ...

  2. Java与C#的语法区别

    1.作用域 在java中 { { int a=1; } int a=2;//以上a作用域外的以下,再声明同名的变量,是允许的: } 在C#中,以上是不允许的[只要在同一个作用域内,以上或以下的代码中 ...

  3. C++ Primer章课后编程问题

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3V1Z2xlMjAxMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  4. C# 静态构造函数,静态变量执行顺序(精华版)(规正版)

    一.成员初始化整体顺序 1.成员赋值初始化先于构造函数: 2.成员赋值初始先从子类再到基类: 3.构造函数初始化先从基类再到子类: 4.静态成员初始化优先于实例成员初始化: 二.对类型静态成员构造的大 ...

  5. events(事件): 基础1

    1    所有能触发事件的对象都是 EventEmitter 类的实例. 这些对象开放了一个 eventEmitter.on() 函数,允许将一个或多个函数绑定到会被对象触发的命名事件上. 事件名称通 ...

  6. docker入门2:基础操作(1)

    -- 列出所有的容器 docker ps -a  (没有-a就是只列出启动的) -- 开启/关闭/移除容器 docker start|stop|rm CONTAINER_ID|CONTAINER_NA ...

  7. C#连接Oracle数据库乱码问题

    C#连接Oracle数据库乱码问题 数据库连接之前,设置环境变量,如下 Environment.SetEnvironmentVariable("NLS_LANG", "A ...

  8. Java Swing界面编程(29)---JCheckBox事件处理

    JCheckBox和JRadioButton的事件处理监听接口是一样的,都是使用ItemListener接口. package com.beyole.util; import java.awt.Con ...

  9. 怎样从一名程序员过度到项目经理(整理自csdn论坛) 选择自 whoopee 的 Blog

    1.从程序员到PM,是一条脱变的路,事实上程序员走的路最终不应该是项目经理.首先有一点需要明白的就是,一定规模的项目中,项目经理不需要太懂技术,他可以是一知半解.项目经理的任务不是在技术方面,技术相关 ...

  10. JSON的一些要点总结 专题

    JavaScript Object Notation CSRF (pronounced sea-surf) 字面量(literal):字符串的意思和要表达的意思是一致的 JSON 是一种数据交换格式( ...