|
|||||
<このサンプルの概要> 全てのウィンドウとコントロールの情報を表示するサンプルソースを作ってみました。 VB6のフォームにTreeViewを1つ追加してお試しください。 ステータスバー(msctls_statusbar32)の各パートの文字列を取得する関数もありますが、 この関数はVB6のデバッグでは動きません。EXEを作ってお試しください。 VB.NET版はこちらです。 全てのウィンドウとコントロールの情報を表示するサンプル(VB.NET) 本サンプルのキーワードは以下のAPIです。 (1)EnumWindows (2)EnumChildWindows (3)GetClassName (4)SendMessage (5)GetWindowThreadProcessId (6)OpenProcess (7)CloseHandle (8)VirtualAllocEx (9)VirtualFreeEx (10)ReadProcessMemory (11)WriteProcessMemory ★標準モジュール(Module1.bas) Private Const SB_GETPARTS = &H406 Private Const SB_GETTEXT = &H402 Private Const SB_GETTEXTLENGTH = &H403 Private Const PROCESS_VM_OPERATION = &H8& Private Const PROCESS_VM_READ = &H10& Private Const PROCESS_VM_WRITE = &H20& Private Const MEM_RESERVE = &H2000& Private Const MEM_COMMIT = &H1000& Private Const MEM_RELEASE = &H8000& Private Const PAGE_READWRITE = &H4& Private Const WM_GETTEXT = &HD Private Declare Function EnumWindows Lib "user32.dll" _ (ByVal lpEnumFunc As Long, lParam As Any) As Long Private Declare Function EnumChildWindows Lib "user32" _ (ByVal hwndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _ (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function GetWindowThreadProcessId Lib "user32" _ (ByVal hWnd As Long, lplngProcessId As Long) As Long Private Declare Function OpenProcess Lib "kernel32" _ (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _ ByVal lngProcessId As Long) As Long Private Declare Function CloseHandle Lib "kernel32" _ (ByVal hObject As Long) As Long Private Declare Function VirtualAllocEx Lib "kernel32.dll" _ (ByVal lngProcessH As Long, lpAddress As Any, ByVal dwSize As Long, _ ByVal flAllocationType As Long, ByVal flProtect As Long) As Long Private Declare Function VirtualFreeEx Lib "kernel32" _ (ByVal lngProcessH As Long, ByVal lpAddress As Long, ByVal dwSize As Long, _ ByVal dwFreeType As Long) As Integer Private Declare Function ReadProcessMemory Lib "kernel32" _ (ByVal lngProcessH As Long, lpBaseAddress As Any, lpBuffer As Any, _ ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long Private Declare Function WriteProcessMemory Lib "kernel32" _ (ByVal lngProcessH As Long, lpBaseAddress As Any, lpBuffer As Any, _ ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long ' コントロール毎の情報を設定するコレクション Private colWindows As New Collection ' ウィンドウとコントロールを全て取得 Public Function GetAllWindows() As Collection On Error Resume Next Dim i As Long Dim lngRet As Long ' コントロール毎の情報を設定するコレクション生成 Set colWindows = New Collection Set 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 Long, lParam As Long) As Long On Error Resume Next Dim lngRet As Long Dim strClassB As String * 255, strTitleB As String * 255 Dim strClass As String, strTitle As String ' クラス名取得 lngRet = GetClassName(hWnd, strClassB, 255) strClass = StripNulls(strClassB) ' ウィンドウのタイトル取得 lngRet = SendMessage(hWnd, WM_GETTEXT, 255, ByVal strTitleB) strTitle = StripNulls(strTitleB) ' 取得した情報を配列に設定 Dim strDa(2) As Variant strDa(0) = hWnd strDa(1) = strClass strDa(2) = strTitle ' 取得した情報をコレクションに設定 Dim colDa As New Collection colDa.Add strDa ' トップレベルウィンドウ毎のコレクションに追加 colWindows.Add colDa ' リターン EnumWindowsProc = 1 End Function ' 指定された親ウィンドウに属するコントロールを全て取得 Function EnumChildWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Long On Error Resume Next Dim lngRet As Long Dim strClassB As String * 255, strTitleB As String * 255 Dim strClass As String, strTitle As String ' クラス名取得 lngRet = GetClassName(hWnd, strClassB, 255) strClass = StripNulls(strClassB) ' ウィンドウのタイトル取得 lngRet = SendMessage(hWnd, WM_GETTEXT, 255, ByVal strTitleB) strTitle = StripNulls(strTitleB) ' クラス名毎の特殊処理 If strClass = "msctls_statusbar32" Then strTitle = strTitle & "(" & GetStatusBarText(hWnd) & ")" End If ' 取得した情報を配列に設定 Dim strDa(2) As Variant strDa(0) = hWnd strDa(1) = strClass strDa(2) = strTitle ' コントロール毎のコレクションに追加 colWindows.Item(lParam).Add strDa ' リターン EnumChildWindowsProc = 1 End Function ' ステータスバーの文字列を全て取得 Public Function GetStatusBarText(hWnd As Long) As String On Error Resume Next Dim lngLen As Long Dim lngPart As Long Dim lngNo As Long Dim strTmpB As String * 255 Dim strTmp As String ' ステータスバーのパート数を取得 lngPart = SendMessage(hWnd, SB_GETPARTS, 0, 0) ' ステータスバーの各パートの文字列を取得 For lngNo = 0 To lngPart - 1 ' ステータスバーの各パートの文字列の長さを取得 lngLen = SendMessage(hWnd, SB_GETTEXTLENGTH, ByVal lngNo, ByVal 0) lngLen = (lngLen And &HFFFF&) ' 共有メモリを使用しステータスバーの各パートの文字列を取得 If lngLen > 0 Then Call SendMessageByVAEString(hWnd, SB_GETTEXT, lngNo, strTmpB) strTmp = StripNulls(strTmpB) GetStatusBarText = GetStatusBarText & strTmp End If ' 各パートをカンマ区切りの文字列にする If lngNo < lngPart - 1 Then GetStatusBarText = GetStatusBarText & "," End If Next lngNo End Function ' 共有メモリを使用しSendMessageを発行/情報取得 Public Function SendMessageByVAEString( _ ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As String) As Long On Error Resume Next Dim lngRet As Long Dim lngProcessId As Long Dim lngProcessH As Long Dim lngVirtual As Long Dim bytBuf() As Byte lParam = String(Len(lParam), 0) bytBuf = StrConv(lParam, vbFromUnicode) ' 指定されたコントロールが存在するプロセスのIDを取得 Call GetWindowThreadProcessId(hWnd, lngProcessId) ' プロセスのオープン lngRet = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or _ PROCESS_VM_WRITE, False, lngProcessId) If lngRet = 0 Then SendMessageByVAEString = 0 Exit Function End If lngProcessH = lngRet ' プロセス内に共有メモリ確保 lngRet = VirtualAllocEx(lngProcessH, ByVal 0, UBound(bytBuf) + 1, _ MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE) If lngRet = 0 Then SendMessageByVAEString = 0 Call CloseHandle(lngProcessH) Exit Function End If lngVirtual = lngRet ' 共有メモリ初期化 lngRet = WriteProcessMemory(lngProcessH, lngVirtual, bytBuf(0), UBound(bytBuf) + 1, ByVal 0) If lngRet = 0 Then SendMessageByVAEString = 0 Call VirtualFreeEx(lngProcessH, lngVirtual, 0, MEM_RELEASE) Call CloseHandle(lngProcessH) Exit Function End If ' SendMessage発行 SendMessageByVAEString = SendMessage(hWnd, wMsg, wParam, lngVirtual) ' 共有メモリから情報取得 lngRet = ReadProcessMemory(lngProcessH, lngVirtual, bytBuf(0), UBound(bytBuf) + 1, ByVal 0) If lngRet = 0 Then SendMessageByVAEString = 0 Call VirtualFreeEx(lngProcessH, lngVirtual, 0, MEM_RELEASE) Call CloseHandle(lngProcessH) Exit Function End If ' 共有メモリから取得した文字列をユニコード変換 lParam = StrConv(bytBuf, vbUnicode) ' 共有メモリ解放 lngRet = VirtualFreeEx(lngProcessH, lngVirtual, 0, MEM_RELEASE) If lngRet = 0 Then SendMessageByVAEString = 0 End If ' プロセスのクローズ lngRet = CloseHandle(lngProcessH) If lngRet = 0 Then SendMessageByVAEString = 0 End If End Function ' 文字列からNULL文字以降をカット Public Function StripNulls(ByVal strOrg As String) As String On Error Resume Next If (InStr(strOrg, Chr(0)) > 0) Then strOrg = Left(strOrg, InStr(strOrg, Chr(0)) - 1) End If StripNulls = strOrg End Function ★フォームモジュール(Form1.frm) ' フォームロード Private Sub Form_Load() Dim i As Long Dim j As Long Dim strClass As String Dim strTitle As String Dim strSpace As String ' ウィンドウとコントロールの全ての情報を取得 Dim colWindows As Collection Set colWindows = GetAllWindows() ' 親ウィンドウ毎のコレクションループ For i = 1 To colWindows.Count ' 子コントロール毎のコレクション取得 Dim colChilds As Collection Set colChilds = colWindows.Item(i) 'If colChilds.Count >= 1 Then ' 全ての親ウィンドウを対象 If colChilds.Count > 1 Then ' 子コントロールを持つ物のみ対象 ' 子コントロール毎のコレクションループ For j = 1 To colChilds.Count strSpace = StrConv(String(50, " "), vbFromUnicode) ' コレクションからクラス名取得 strClass = StrConv(colChilds.Item(j)(1), vbFromUnicode) If LenB(strClass) < 30 Then strClass = LeftB$(strClass & strSpace, 30) End If strClass = StrConv(strClass, vbUnicode) ' コレクションから文字列取得 strTitle = StrConv(colChilds.Item(j)(2), vbFromUnicode) If LenB(strTitle) < 50 Then strTitle = LeftB$(strTitle & strSpace, 50) End If strTitle = StrConv(strTitle, vbUnicode) If j = 1 Then ' 親ウィンドウの情報をツリービューへ追加 Call TreeView1.Nodes.Add( _ , , "R" & _ Right$("00000000" & Hex(colChilds.Item(j)(0)), 8), _ Right$("00000000" & Hex(colChilds.Item(j)(0)), 8) & " - " & _ strClass & " - " & strTitle) Else ' 子コントロールの情報をツリービューへ追加 Call TreeView1.Nodes.Add( _ "R" & Right$("00000000" & Hex(colChilds.Item(1)(0)), 8), _ tvwChild, "C" & _ Right$("00000000" & Hex(colChilds.Item(j)(0)), 8), _ Right$("00000000" & Hex(colChilds.Item(j)(0)), 8) & " - " & _ strClass & " - " & strTitle) End If Next j End If Next i End Sub ' フォームリサイズ Private Sub Form_Resize() ' ツリービューの幅設定 If Me.ScaleWidth - (TreeView1.Left * 2) > 0 Then TreeView1.Width = Me.ScaleWidth - (TreeView1.Left * 2) End If ' ツリービューの高さ設定 If Me.ScaleHeight - (TreeView1.Top * 2) > 0 Then TreeView1.Height = Me.ScaleHeight - (TreeView1.Top * 2) End If End Sub |