尽管熟悉VBA,但我对WinApi调用还是很陌生的。我想做的是挂钩到VBE窗口(项目浏览器TreeView)的子类SysTreeView32。我想通过修改注册表项(或发送鼠标点击(mouse_event),尽管我更喜欢第一个选项)来展开/折叠树 View 元素。
我可以使用以下代码找到Excel主窗口:

Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
              (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Sub Find_Window()
    Dim hWndExcel As Long
    hWndExcel = FindWindow("XLMAIN", Application.Caption)
    MsgBox hWndExcel
End Sub
借助Window Detective,我可以访问子类的名称,属性等。

但是我无法解决如何访问/激活(甚至返回SysTreeView32子类的HWID)折叠/展开元素(文件夹)。我还不确定如何迭代这些元素,但是我将在以后进行研究。这里的问题是访问SysTreeView32类。我该如何实现?

当我尝试使用msgboxFindWindow("wndclass_desked_gsk", Application.Caption)要么FindWindow("SysTreeView32", Application.Caption)一个0返回,所以我显然做错了:/
感谢您的时间。

最佳答案

您应该使用:

application.vbe.mainwindow.caption

这是一些合拢代码示例
Private Const TVE_COLLAPSE = &H1
Private Const TVE_COLLAPSERESET = &H8000
Private Const TVE_EXPAND = &H2
Private Const TVE_EXPANDPARTIAL = &H4000
Private Const TVE_TOGGLE = &H3
Private Const TV_FIRST = &H1100
Private Const TVM_EXPAND = (TV_FIRST + 2)
Private Const TVM_GETNEXTITEM = (TV_FIRST + 10)
Private Const TVGN_ROOT = &H0
Private Const TVGN_NEXTVISIBLE = &H6

Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
                              (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
                                    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Sub CollapseProjects()
   Dim hWndVBE As Long, hWndPE As Long, hWndTvw As Long, hNode As Long, varReturn
   hWndVBE = FindWindowEx(0, 0, "wndclass_desked_gsk", Application.VBE.MainWindow.Caption)
   hWndPE = FindWindowEx(hWndVBE, 0, "PROJECT", vbNullString)
   hWndTvw = FindWindowEx(hWndPE, 0, "SysTreeView32", vbNullString)
   hNode = SendMessage(hWndTvw, TVM_GETNEXTITEM, TVGN_ROOT, 0&)
   Do While hNode <> 0
      varReturn = SendMessage(hWndTvw, TVM_EXPAND, TVE_COLLAPSE, hNode)
      hNode = SendMessage(hWndTvw, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, hNode)
   Loop
End Sub

进一步说明,这是仅折叠“Microsoft Excel Objects”节点的代码
Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
                              (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
                                    (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SendMessageB Lib "user32" Alias "SendMessageA" _
                                     (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Private Const MAX_ITEM        As Long = 256
Private Const TV_FIRST        As Long = &H1100
Private Const TVM_EXPAND      As Long = (TV_FIRST + 2)
Private Const TVM_GETNEXTITEM As Long = (TV_FIRST + 10)
Private Const TVM_GETITEM     As Long = (TV_FIRST + 12)
Const TVE_COLLAPSE            As Long = &H1
Const TVE_EXPAND              As Long = &H2
Private Const TVGN_ROOT       As Long = &H0
Private Const TVGN_NEXT       As Long = &H1
Private Const TVIF_TEXT       As Long = &H1
Private Const TVGN_NEXTVISIBLE = &H6

Private Type TVITEM   ' was TV_ITEM
   mask                       As Long
   hItem                      As Long
   state                      As Long
   stateMask                  As Long
   pszText                    As String
   cchTextMax                 As Long
   iImage                     As Long
   iSelectedImage             As Long
   cChildren                  As Long
   lParam                     As Long
End Type


Sub CollapseXLObjects()
   Dim hWndVBE                As Long
   Dim hWndPE                 As Long
   Dim hWndTvw                As Long
   Dim hNode                  As Long
   Dim tvi                    As TVITEM
   Dim nChild                 As Long
   Dim sText                  As String
   Dim varReturn

   hWndVBE = FindWindowEx(0, 0, "wndclass_desked_gsk", Application.VBE.MainWindow.Caption)
   hWndPE = FindWindowEx(hWndVBE, 0, "PROJECT", vbNullString)
   hWndTvw = FindWindowEx(hWndPE, 0, "SysTreeView32", vbNullString)

   hNode = SendMessage(hWndTvw, TVM_GETNEXTITEM, TVGN_ROOT, 0&)

   Do While hNode <> 0
      tvi.hItem = hNode
      tvi.mask = TVIF_TEXT
      tvi.cchTextMax = MAX_ITEM
      tvi.pszText = String(MAX_ITEM, 0)
      nChild = SendMessageB(hWndTvw, TVM_GETITEM, 0&, tvi)
      If InStr(1, tvi.pszText, "Microsoft Excel Objects", vbTextCompare) > 0 Then
         varReturn = SendMessage(hWndTvw, TVM_EXPAND, TVE_COLLAPSE, hNode)
      Else
         varReturn = SendMessage(hWndTvw, TVM_EXPAND, TVE_EXPAND, hNode)
      End If
      hNode = SendMessage(hWndTvw, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, hNode)
   Loop
End Sub

关于api - Hook 到VBE窗口的子类SysTreeView32,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17041881/

10-11 10:35