windows - 在窗口调整大小事件

标签 windows vba excel winapi vb6

问题

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

第一次尝试:

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

结果:

每当调整“内部”工作簿窗口大小时调用子例程,但不会在调整应用程序窗口大小时调用。 IE。在调整包含应用程序实例的多文档界面子项的大小时发生。

第二次尝试

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 设置系统范围键盘和鼠标 Hook 的示例。这是沿着相同的路线:

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

结果:

如果我将 WH_CALLWNDPROC 替换为:

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

使用 WH_KEYBOARD_LL 时,只要按下一个键,就会调用子例程。同样,如果我用 WH_MOUSE_LL 替换它,则只要移动鼠标或按下鼠标按钮,就会调用子例程。

问题是,当我尝试将子例程挂接到 WH_CALLWNDPROC 时,没有任何反应吗?

为什么?

我仍然不确定,但是 enHookTypes 中的所有 ENUMS 都是如此,除了 WH_MOUSE_LLWH_KEYBOARD_LL。通过查看 WinAPI 文档,我了解到您可以使用 Kernel32.dll 中的 GetLastError 确实获得了操作失败原因的一些指示。

到目前为止,我得到的错误编号是(十进制)error 5(对于 JOURNAL Hook )和 error 1428 其余的。

最终这也失败了。

最佳答案

Application.Windows 是应用程序中打开的工作簿的窗口对象的集合。当非最大化 窗口更改大小时,将引发 WindowResize 事件。 Workbook_WindowResize(ByVal Wn As Window) 在工作簿对象本身中公开。当非最大化工作簿的窗口改变大小时,Application_WindowResize(ByVal Wb as Workbook, ByVal Wn As Window) 事件与应用程序中的任何/所有工作簿有关。因此,事件传递的引用存在差异。在第一种情况下,它只是引发事件的工作簿的一个窗口,位于工作簿对象内,毫无疑问它是哪个窗口(它是“我”工作簿的窗口)。它既是工作簿又是工作簿的窗口,当它在应用程序级别被提升时,因为与事件相关的工作簿需要识别 :) 不,Excel 没有应用程序窗口本身的“调整大小”事件,您需要转到 API。

对于更高版本的 Excel(2010 之后),每个 Excel 应用程序窗口有一个工作簿,工作簿的窗口始终在旧意义上最大化,并且工作簿和应用程序事件都引用同一个工作簿,并且可以像你会希望他们这样做。

关于windows - 在窗口调整大小事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40112547/

相关文章:

excel - 如何在excel或VBA中搜索具有多个 "-"的项目?

Excel ActiveX 控件损坏, "Can' t 退出设计模式”, "Object library invalid"

excel - 单元格中的所有文本都使用相同的字体吗?

arrays - Excel:动态数组公式

excel - 如何创建 =IF(OR()) 语句来计算真/假条件值的数量?

c++ - 如何在windows中安装VOGLE图形库

windows - 不允许远程连接Postgresql

windows - 在 Windows 中为 msysgit 设置 openssh 端口

vba - 从excel填充word文档而不删除书签

c - 像在 Linux 上一样在命令行中显示实际错误