在窗口调整事件

问题

每当主Excel窗口resize时调用过程。

第一次尝试:

Sub Workbook_WindowResize(ByVal Wn As Window) Debug.Print Wn.Width & "x" & Wn.Height End Sub 

结果:

每当“内部”工作簿窗口resize时调用子例程,但在应用程序窗口resize时不调用子例程。

第二次尝试

 Dim WithEvents App As Application Private Sub App_WindowResize(ByVal Wb As Workbook, ByVal Wn As Window) Debug.Print Wn.Width & "x" & Wn.Height End Sub 

结果:

奇怪的是,同样的事情发生之前,这一定让我感到惊讶。 该事件只发生在工作簿窗口的大小,而不是应用程序窗口。

出于这个原因,我开始研究使用Windows API。

有很多使用Windows API设置SystemWide键盘和鼠标钩子的例子。 这是沿着同样的路线:

 Public Enum enHookTypes WH_CALLWNDPROC = 4 WH_CALLWNDPROCRET = 12 WH_CBT = 5 WH_DEBUG = 9 WH_FOREGROUNDIDLE = 11 WH_GETMESSAGE = 3 WH_HARDWARE = 8 WH_JOURNALPLAYBACK = 1 WH_JOURNALRECORD = 0 WH_MOUSE = 7 WH_MSGFILTER = (-1) WH_SHELL = 10 WH_SYSMSGFILTER = 6 WH_KEYBOARD_LL = 13 WH_MOUSE_LL = 14 WH_KEYBOARD = 2 End Enum Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As LongPtr, ByVal lpfn As Long, ByVal hMod As Long, ByVal dwThreadId As Long) As LongPtr Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Private Declare Function GetLastError Lib "kernel32" () As Long 'Ensure that your hook procedure does not interfere with the normal operation of other hook procedures Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Public hndl As Long Sub HookWindow() hndl = SetWindowsHookEx(WH_CALLWNDPROC, AddressOf measureWindow, Application.Hinstance, 0&) Debug.Print hndl & "~~" & GetLastError() End Sub Sub unhookWindow() ret = UnhookWindowsHookEx(hndl) Debug.Print ret End Sub Public Sub measureWindow(code As Long, wParam As Long, lParam As Long) If code > 0 Then Debug.Print ThisWorkbook.Windows(1).Width & "x" & ThisWorkbook.Windows(1).Height Else ret = CallNextHookEx(measureWindow, code, wParam, lParam) End If End Sub 

结果:

如果我replaceWH_CALLWNDPROC

 hndl = SetWindowsHookEx(WH_CALLWNDPROC, AddressOf measureWindow, Application.Hinstance, 0&) 

使用WH_KEYBOARD_LL时,只要按下一个键就会调用子程序。 同样,如果我用WH_MOUSE_LLreplace它,每当移动鼠标或按下鼠标button时,都会调用子例程。

问题是,当我试图钩子程序WH_CALLWNDPROC什么也没有发生?

为什么?

我仍然不确定,但对于除了WH_MOUSE_LL和enHookTypes以外的所有ENHMS enHookTypes都是WH_KEYBOARD_LL 。 通过WinAPI文档查看我读到,您可以使用GetLastError从Kernel32.dll做一些指示为什么操作失败。

到目前为止我得到的错误数字是(十进制) error 5 (对于JOURNAL钩子)和其余的error 1428

最终这也失败了。

Application.Windows是在应用程序中打开的Worbooks的窗口对象的集合。 WindowResize事件是在非最大化窗口更改大小时引发的。 Workbook_WindowResize(ByVal Wn As Window)暴露在工作簿对象本身中。 当非最大化工作簿的窗口更改大小时,Application_WindowResize(作为工作簿的ByVal Wb)作为窗口的ByVal Wn事件必须与应用程序内的ANY / ALL工作簿有关。 因此事件所传递的参考文献的差异。 在工作簿对象中,它只是第一种情况下引发事件的工作簿的窗口,在这里没有问题(它是“我”工作簿的窗口)。 这是工作簿和工作簿的窗口,当它是在应用程序级别提出的,因为事件涉及的工作簿需要标识:)而且,Excel没有针对应用程序窗口本身的“调整大小”事件,您需要去那个API。

对于后来的Excel版本(2010年以后),每个Excel应用程序窗口都有一个工作簿,工作簿的窗口总是以旧的方式最大化,并且Workbook和Application事件都引用相同的工作簿,并且会按照您的想法工作他们来。