【问题标题】:Hook into a child class SysTreeView32 of VBE window挂钩到 VBE 窗口的子类 SysTreeView32
【发布时间】:2013-06-07 04:06:41
【问题描述】:

虽然熟悉 VBA,但我对 WinApi 调用还是很陌生。我想要做的是挂钩到 VBE 窗口(项目资源管理器 TreeView)的子类 SysTreeView32。我想通过修改注册表项(或者发送鼠标点击 (mouse_event),尽管我更喜欢第一个选项)来展开/折叠树视图元素。
我可以使用以下代码找到 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 的帮助下,我可以访问子类的名称、属性等。

但我无法弄清楚如何访问/激活(甚至返回 HWID)SysTreeView32 子类以折叠/展开元素(文件夹)。我还不确定如何迭代元素,但我会在之后研究这个。这里的问题是访问SysTreeView32 类。我怎样才能实现它?

当我尝试将此消息发送到 msgbox 时
FindWindow("wndclass_desked_gsk", Application.Caption)

FindWindow("SysTreeView32", Application.Caption)
0 被返回,所以我显然做错了什么:/
感谢您的时间。

【问题讨论】:

    标签: api winapi vba parent-child


    【解决方案1】:

    你应该使用:

    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 对象”节点的代码

    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
    

    【讨论】:

    • +∞ 这简直太完美了!我只需要修改它以仅折叠 Microsoft Excel 对象,但我认为我将能够自己管理它!...好吧,我不认为我现在只是在玩它,而且我还没有完全还没有理解
    • 我已更新代码以检查节点文本并仅隐藏 excel 对象
    【解决方案2】:

    如果从另一个子程序调用此子程序(在我的情况下,XL 插件中的子程序链接到打开 VBE 的自定义按钮),并且另一个模块被突出显示(可能在另一个项目中),那么我找到了

        Application.VBE.MainWindow.Caption
    

    不起作用。要捕获我使用的突出显示的模块:

        Private Sub VisualBasicEditor()
          On Error Resume Next
          WinName = "Microsoft Visual Basic - " + ActiveWorkbook.Name + " [Running] - [" + Application.VBE.ActiveCodePane.CodeModule.Name + " (Code)]"
          Application.VBE.MainWindow.Visible = True
          Call CollapseXLObjects
        End Sub
    

    并在包含Sub CollapseXLObjects的模块中声明

        Public WinName As String
    

    Sub CollapseXLObjects

        hWndVBE = FindWindowEx(0, 0, "wndclass_desked_gsk", WinName)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多