WinAPI MonitorFromPoint的正确VBA声明及调用异常解惑
WinAPI中MonitorFromPoint函数的正确VBA声明解析
官方文档声明的问题
微软文档给出的基于POINTAPI结构体的VBA声明,在实际调用中出现32位Office报错、64位Office返回0的问题,核心原因是参数传递方式不匹配:
原声明中POINT As POINTAPI默认按引用传递,但WinAPI的MonitorFromPoint要求POINT结构体按值传递。32位Office会因调用约定不匹配触发错误49;64位Office虽不报错,但传递的是结构体指针而非实际坐标值,导致函数无法正确解析,返回0。
修正后的带POINTAPI的正确声明如下(包含32/64位兼容的条件编译):
#If VBA7 Then Declare PtrSafe Function MonitorFromPoint Lib "user32.dll" ( _ ByVal POINT As POINTAPI, _ ByVal dwFlags As Long) As LongPtr #Else Declare Function MonitorFromPoint Lib "user32.dll" ( _ ByVal POINT As POINTAPI, _ ByVal dwFlags As Long) As Long #End If Type POINTAPI X As Long Y As Long End Type
注意:POINTAPI是 blittable 类型(内存布局与C++一致),按值传递时能正确匹配WinAPI的参数要求。
拆分X/Y参数的可行声明
你找到的将X、Y拆分为独立ByVal参数的声明,能在32/64位Office中正常工作,原因是它直接按值传递两个Long类型的坐标,本质上等价于传递完整的POINT结构体值,WinAPI内部会自动将这两个值组合为POINT结构体处理。该声明写法如下:
#If VBA7 Then Declare PtrSafe Function MonitorFromPoint Lib "user32.dll" ( _ ByVal X As Long, _ ByVal Y As Long, _ ByVal dwFlags As Long) As LongPtr #Else Declare Function MonitorFromPoint Lib "user32.dll" ( _ ByVal X As Long, _ ByVal Y As Long, _ ByVal dwFlags As Long) As Long #End If
关于Win32API_PtrSafe.TXT的疑问
微软提供的Win32API_PtrSafe.TXT并未收录所有WinAPI的VBA声明,仅覆盖了常用的标准写法。拆分参数的写法虽未被收录,但完全符合WinAPI的参数规范,是合法且有效的VBA调用方式。
内容的提问来源于stack exchange,提问作者Jamie Garroch - MVP
相关产品推荐
相关产品推荐

