NonSoft

全てのウィンドウとコントロールの情報を表示するサンプル(VB.NET)

 サンプルソース
<このサンプルの概要>
全てのウィンドウとコントロールの情報を表示するサンプルソースを作ってみました。
VB.NETのフォームにTreeViewを1つ追加してお試しください。
ステータスバー(msctls_statusbar32)の各パートの文字列を取得する関数はVB6版を参照ください。

VB6版はこちらです。
全てのウィンドウとコントロールの情報を表示するサンプル(VB6)

本サンプルのキーワードは以下のAPIです。
(1)EnumWindows
(2)EnumChildWindows
(3)GetClassName
(4)SendMessage

★標準モジュール(Module1.vb)
Module Module1
    ' APIの定義
    Private Const WM_GETTEXT = &HD
    Private Delegate Function D_EnumWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
    Private Delegate Function D_EnumChildWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
    Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As D_EnumWindowsProc, ByVal lParam As Integer) As Integer
    Private Declare Function EnumChildWindows Lib "user32.dll" (ByVal hwndParent As Integer, ByVal lpEnumFunc As D_EnumChildWindowsProc, ByVal lParam As Integer) As Integer
    Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hWnd As Integer, ByVal lpClassName As Byte(), ByVal nMaxCount As Integer) As Integer
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Byte()) As Integer

    ' コントロール毎の情報を設定するコレクション
    Private colWindows As New Collection

    ' ウィンドウとコントロールを全て取得
    Public Function GetAllWindows() As Collection
        On Error Resume Next
        Dim i As Long
        Dim lngRet As Long

        ' コントロール毎の情報を設定するコレクション生成
        colWindows = New Collection
        GetAllWindows = colWindows

        ' トップレベルウィンドウを全て取得
        lngRet = EnumWindows(AddressOf EnumWindowsProc, 0)

        ' 親ウィンドウに属するコントロールを全て取得
        For i = 1 To colWindows.Count
            lngRet = EnumChildWindows(colWindows.Item(i).Item(1)(0), AddressOf EnumChildWindowsProc, i)
        Next i
    End Function

    ' トップレベルウィンドウを全て取得
    Public Function EnumWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
        On Error Resume Next
        Dim lngRet As Long
        Dim bytClass As Byte() = New Byte(255) {}
        Dim bytTitle As Byte() = New Byte(255) {}
        Dim strClass As String
        Dim strTitle As String

        ' クラス名取得
        lngRet = GetClassName(hWnd, bytClass, 255)
        strClass = StripNulls(bytClass)

        ' ウィンドウのタイトル取得
        lngRet = SendMessage(hWnd, WM_GETTEXT, 255, bytTitle)
        strTitle = StripNulls(bytTitle)

        ' 取得した情報を配列に設定
        Dim strDa(2) As Object
        strDa(0) = hWnd
        strDa(1) = strClass
        strDa(2) = strTitle

        ' 取得した情報をコレクションに設定
        Dim colDa As New Collection
        colDa.Add(strDa)

        ' トップレベルウィンドウ毎のコレクションに追加
        colWindows.Add(colDa)

        ' リターン
        EnumWindowsProc = 1
    End Function

    ' 指定された親ウィンドウに属するコントロールを全て取得
    Private Function EnumChildWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
        On Error Resume Next
        Dim lngRet As Long
        Dim bytClass As Byte() = New Byte(255) {}
        Dim bytTitle As Byte() = New Byte(255) {}
        Dim strClass As String
        Dim strTitle As String

        ' クラス名取得
        lngRet = GetClassName(hWnd, bytClass, 255)
        strClass = StripNulls(bytClass)

        ' ウィンドウのタイトル取得
        lngRet = SendMessage(hWnd, WM_GETTEXT, 255, bytTitle)
        strTitle = StripNulls(bytTitle)

        ' 取得した情報を配列に設定
        Dim strDa(2) As Object
        strDa(0) = hWnd
        strDa(1) = strClass
        strDa(2) = strTitle

        ' コントロール毎のコレクションに追加
        colWindows.Item(lParam).Add(strDa)

        ' リターン
        EnumChildWindowsProc = 1
    End Function

    ' 文字列からNULL文字以降をカット
    Private Function StripNulls(ByVal bytOrg As Byte()) As String
        On Error Resume Next
        Dim strOrg As String = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(bytOrg)
        If (InStr(strOrg, Chr(0)) > 0) Then
            strOrg = Left(strOrg, InStr(strOrg, Chr(0)) - 1)
        End If
        StripNulls = strOrg
    End Function
End Module

★フォームモジュール(Form1.vb)
Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Long
        Dim j As Long
        Dim bytClass As Byte()
        Dim bytTitle As Byte()
        Dim bytSpace As Byte()

        ' ウィンドウとコントロールの全ての情報を取得
        Dim colWindows As Collection
        colWindows = GetAllWindows()

        ' 親ウィンドウ毎のコレクションループ
        For i = 1 To colWindows.Count
            ' 子コントロール毎のコレクション取得
            Dim colChilds As Collection
            colChilds = colWindows.Item(i)

            'If colChilds.Count >= 1 Then       ' 全ての親ウィンドウを対象
            If colChilds.Count > 1 Then         ' 子コントロールを持つ物のみ対象
                ' 子コントロール毎のコレクションループ
                Dim treeNodeTop As TreeNode = Nothing
                For j = 1 To colChilds.Count
                    bytSpace = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetBytes(New String(" ", 50))

                    ' コレクションからクラス名取得
                    bytClass = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetBytes(colChilds.Item(j)(1))
                    If bytClass.Length < 30 Then
                        Dim p As Integer = bytClass.Length
                        ReDim Preserve bytClass(bytClass.Length + bytSpace.Length - 1)
                        Array.Copy(bytSpace, 0, bytClass, p, bytSpace.Length)
                        ReDim Preserve bytClass(30 - 1)
                    End If
                    Dim strClass As String = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(bytClass)

                    ' コレクションから文字列取得
                    bytTitle = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetBytes(colChilds.Item(j)(2))
                    If bytTitle.Length < 50 Then
                        Dim p As Integer = bytTitle.Length
                        ReDim Preserve bytTitle(bytTitle.Length + bytSpace.Length - 1)
                        Array.Copy(bytSpace, 0, bytTitle, p, bytSpace.Length)
                        ReDim Preserve bytTitle(50 - 1)
                    End If
                    Dim strTitle As String = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(bytTitle)

                    If j = 1 Then
                        ' 親ウィンドウの情報をツリービューへ追加
                        treeNodeTop = New TreeNode(strClass & " - " & strTitle)
                        TreeView1.Nodes.Add(treeNodeTop)
                    Else
                        ' 子コントロールの情報をツリービューへ追加
                        Dim treeNodeSub As TreeNode = New TreeNode(strClass & " - " & strTitle)
                        treeNodeTop.Nodes.Add(treeNodeSub)
                    End If
                Next j
            End If
        Next i
    End Sub
End Class