ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2487|回复: 6

[原创] 使用API CallWindowProc实现稳定的回调函数方法

[复制链接]

TA的精华主题

TA的得分主题

发表于 2020-12-2 09:46 | 显示全部楼层 |阅读模式

原理将函数地址和参数传给CallWindowProc,由系统进行函数回调。参数多的话可以封装到数组中。
网上有很多详细的介绍,但好像没稳定的实现。自己弄了个通用的方法,用了好几年,简单整理了下,分享给大家。

  1. '运行速度比接口(I_Compare)形式慢3倍左右,非大量回调的算法类基本无影响
  2. 'Application.Run慢XX倍
  3. '排序等算法类建议用接口形式进行回调.
  4. Declare Function CallBackProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpProc As Long, Optional Param1 As Any, Optional Param2 As Any, Optional Param3 As Any, Optional Param4 As Any) As Long

  5. 'lpProc must be a Sub
  6. Sub CallBackSub_(ByVal lpProc As Long, Optional ByRef Param1 = 0, Optional ByRef Param2 = 0, Optional ByRef Param3 = 0, Optional ByRef Param4 = 0)
  7.     Call CallBackProc(lpProc, Param1, Param2, Param3, Param4)
  8. End Sub

  9. 'lpProc must be a Sub
  10. Function CallBackFunction_(ByVal lpProc As Long, Optional ByRef Param1 = 0, Optional ByRef Param2 = 0, Optional ByRef Param3 = 0)
  11.     Call CallBackProc(lpProc, CallBackFunction_, Param1, Param2, Param3)
  12. End Function

  13. '''==回调函数格式=========================================================================================
  14. '''所有参数不一定使用但必须声名,参数类型为variant
  15. Sub SubExample(Param1, Param2, Param3, Param4)
  16.     Debug.Print "SubExample", Param1, Param2, Param3, Param4
  17.     Param1 = 5
  18. End Sub

  19. Sub FunctionExample(Ret, Param1, Param2, Param3)
  20.     Ret = Param1 & Param2
  21.     Debug.Print "FunctionExample"
  22. End Sub
复制代码


CallWindowProc实现回调.zip

18.97 KB, 下载次数: 77

TA的精华主题

TA的得分主题

发表于 2020-12-2 11:45 | 显示全部楼层
楼主你好,能否出一个兼容64位Excel的版本?
我把API函数对应改成64位的,相应参数的类型也做了修改,运行时不报错,但Excel直接崩溃了。

TA的精华主题

TA的得分主题

发表于 2020-12-2 13:07 | 显示全部楼层
ggmmlol 发表于 2020-12-2 11:45
楼主你好,能否出一个兼容64位Excel的版本?
我把API函数对应改成64位的,相应参数的类型也做了修改,运行 ...

其实只要看到这个参数ByVal lpProc As Long的定义,就会知道不管怎么CALL,在64位中肯定是一运行就得飞啊。其实也挺好玩的,多飞几次就习惯了。

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-12-2 14:29 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
ggmmlol 发表于 2020-12-2 11:45
楼主你好,能否出一个兼容64位Excel的版本?
我把API函数对应改成64位的,相应参数的类型也做了修改,运行 ...

主要是参数的内存空间要适配,variant引用都是指针类型。

  1. LRESULT CallWindowProcA( //LRESULT 指针64位
  2.   WNDPROC lpPrevWndFunc,  //指针64位
  3.   HWND    hWnd, //句柄64位
  4.   UINT    Msg, //unsigned int 查了一下应该是32位,问题应该就出在这了。
  5.   WPARAM  wParam, //指针64位
  6.   LPARAM  lParam //指针64位
  7. );
复制代码

我一直没用64位office。试试把所有相关的倒数第三个参数声名为byval long,使用时这个参数只能用long,或者干脆别用这个参数了

TA的精华主题

TA的得分主题

发表于 2020-12-2 14:48 | 显示全部楼层
    LRESULT CallWindowProcA( //LRESULT 指针64位
      WNDPROC lpPrevWndFunc,  //指针64位
      HWND    hWnd, //句柄64位
      UINT    Msg, //unsigned int 查了一下应该是32位,问题应该就出在这了。
      WPARAM  wParam, //指针64位
      LPARAM  lParam //指针64位
    );

    LRESULT CallWindowProcA( //LRESULT 指针64位
      WNDPROC lpPrevWndFunc,  //指针64位
      HWND    hWnd, //句柄64位
      UINT    Msg, //unsigned int 查了一下应该是32位,问题应该就出在这了。
      WPARAM  wParam, //指针64位
      LPARAM  lParam //指针64位
    );

翻译过来就是:
Declare PtrSafe Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcW" ( _
         ByVal lpPrevWndFunc As LongPtr, _
         ByVal hwnd As LongPtr, _
         ByVal msg As Long, _
         ByVal wParam As LongPtr, _
         ByVal lParam As LongPtr) As LongPtr

返回值并不必须是LongPtr,用Long也可以,但要看具体的被Call的函数它的返回值

TA的精华主题

TA的得分主题

发表于 2020-12-2 15:24 | 显示全部楼层

我用的就是64位的API函数声明:
Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal Msg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

TA的精华主题

TA的得分主题

发表于 2020-12-2 17:06 | 显示全部楼层
ggmmlol 发表于 2020-12-2 15:24
我用的就是64位的API函数声明:
Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWin ...

嗯。那应该是你传入的地址有问题。就是你在调用时没有处理好变量的指针和变量之间的转换。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-17 09:32 , Processed in 0.032466 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表