その他

VBA:ハンドル情報(hwnd)配列取得・一覧出力[No70]

投稿日:2020年10月19日 更新日:

スポンサーリンク

VBAでウィンドウハンドル(Window Handle、HWND)を操作するには次の情報が(1つ以上)必要です。

  • ハンドル番号(HAND ID、Handle ID、hwnd ID、Hwnd No)
  • キャプション名(Caption Name、captionName)
  • クラス名(Class Name、className)

ネットに出回っている情報は指定し特定のハンドル情報を取得するものしかなかったので、
今回動作中のhandleを配列に格納するプログラムを自作してみました。今まで以上にhandle情報の取得が容易になると思います。

紹介プログラムを利用するメリット

配列にhandle情報を格納しているので、例えばキャプション名の一部が分かっていれば、その配列をForで回し起動しているWindowのハンドルNoを取得できます。

動作準備

・拡張子xlsmのExcelを新規作成し、「HWND」シートを用意(シート名は半角文字)。

・次の内容の標準モジュール用意。

プログラム(モジュール名:GlobalManagement)


Option Explicit

Public Array_hwndTypeName() As Variant
Public Array_hwndNo()       As Variant
Public Array_captionName()  As Variant
Public Array_className()    As Variant

プログラム(モジュール名:Module_hwnd_01)

ソースコードが長いので分割しました。必ず結合させて1つのmoduleに入れてください。


Option Explicit

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 GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long

Const SHEET_HWND As String = "HWND"

Const HWND_TYPENO_NOW       As Integer = 0
Const HWND_TYPENO_LAST      As Integer = 1
Const HWND_TYPENO_NEXT      As Integer = 2

Const HWND_NAME_NOW         As String = "HWND_NOW"
Const HWND_NAME_NEXT        As String = "HWND_NEXT"
Const HWND_NAME_LAST        As String = "HWND_LAST"

Const HWND_FORNUM_NOW       As Long = 1
Const HWND_FORNUM_NEXT      As Long = 350
Const HWND_FORNUM_LAST      As Long = 50

Const CONST_STARTROW        As Long = 2

Dim Flg_Assigned            As Boolean
Dim dictionary              As Object

Public Sub ハンドル情報出力()
    Call InitSHEET
    Call GetAllParentHwnd
    
    Dim arrayElementsNum As Long
    arrayElementsNum = CountNumberOfArrayElements(Array_hwndTypeName)
    
    Dim startRow As Long: startRow = CONST_STARTROW
    Dim endRow As Long: endRow = startRow + arrayElementsNum - 1
    
    Dim i As Integer
    Dim j As Integer
    For i = startRow To endRow
        j = i - startRow
        With Worksheets(SHEET_HWND)
            .Select
            .Cells(i, 1) = Array_hwndTypeName(j)
            .Cells(i, 2) = Array_hwndNo(j)
            .Cells(i, 3) = Array_captionName(j)
            .Cells(i, 4) = Array_className(j)
        End With
    Next i
End Sub

Private Sub InitSHEET()
    With Worksheets(SHEET_HWND)
        .Select
        .Cells.Clear
        .Cells(1, 1) = "HAND種類"
        .Cells(1, 2) = "HANDID"
        .Cells(1, 3) = "captionName"
        .Cells(1, 4) = "className"
        
        .Range(.Cells(1, 1), .Cells(1, 4)).Font.Color = RGB(0, 0, 0)
        .Range(.Cells(1, 1), .Cells(1, 4)).Interior.Color = RGB(169, 208, 142)
        .Range(.Cells(1, 1), .Cells(1, 4)).Borders.LineStyle = True
        .Range(.Cells(1, 1), .Cells(1, 4)).BorderAround Weight:=xlMedium
    End With
End Sub

Public Sub GetAllParentHwnd()
    Erase Array_hwndTypeName
    Erase Array_hwndNo
    Erase Array_captionName
    Erase Array_className
    
    ReDim Preserve Array_hwndTypeName(0)
    ReDim Preserve Array_hwndNo(0)
    ReDim Preserve Array_captionName(0)
    ReDim Preserve Array_className(0)
    
    Flg_Assigned = False

    Dim hwndNo As Long
    hwndNo = GetForegroundWindow()
    
    Call FindHwnd(HWND_TYPENO_NOW, HWND_NAME_NOW, hwndNo, HWND_FORNUM_NOW)
    Call FindHwnd(HWND_TYPENO_NEXT, HWND_NAME_NEXT, hwndNo, HWND_FORNUM_NEXT)
    Call FindHwnd(HWND_TYPENO_LAST, HWND_NAME_LAST, hwndNo, HWND_FORNUM_LAST)
End Sub

スポンサーリンク


Private Sub FindHwnd(ByVal hwndType As Integer, _
                     ByVal hwndTypeName As String, _
                     ByVal hwndNo As Long, _
                     ByVal forNum As Long)

    Dim captionName01 As String
    Dim captionName02 As String
    Dim className01   As String
    Dim className02   As String
                     
    Dim arrayMaxSubscripts As Long
    arrayMaxSubscripts = UBound(Array_hwndTypeName)
    
    Dim fromNo As Long
    If Flg_Assigned = False Then
        fromNo = arrayMaxSubscripts
        Set dictionary = CreateObject("scripting.dictionary")
    ElseIf Flg_Assigned = True Then
        fromNo = arrayMaxSubscripts + 1
    Else
        MsgBox "Error. FindHwnd"
        Exit Sub
    End If

    Dim connectString As String
    Dim n As Long: n = fromNo

    Dim i As Long
    For i = 1 To forNum
    
        captionName01 = String(200, vbNullChar)
        className01 = String(200, vbNullChar)
        
        hwndNo = GethwndNo(hwndType, hwndNo)
        GetWindowText hwndNo, captionName01, Len(captionName01)
        GetClassName hwndNo, className01, Len(className01)
        captionName02 = Left(captionName01, InStr(captionName01, vbNullChar) - 1)
        className02 = Left(className01, InStr(className01, vbNullChar) - 1)

        'connectString = hwndTypeName & hwndNo & captionName02 & className02
        connectString = hwndNo & captionName02 & className02

        If (hwndNo <> 0) And (Not dictionary.Exists(connectString)) Then
            dictionary.Add connectString, 0
            
            ReDim Preserve Array_hwndTypeName(n)
            ReDim Preserve Array_hwndNo(n)
            ReDim Preserve Array_captionName(n)
            ReDim Preserve Array_className(n)
            
            Array_hwndTypeName(n) = hwndTypeName
            Array_hwndNo(n) = hwndNo
            Array_captionName(n) = captionName02
            Array_className(n) = className02
            
            n = n + 1
            
            Flg_Assigned = True
        End If
    Next i
    Call CheckNumberOfArrayElements
End Sub

Private Function GethwndNo(ByVal hwndType As Integer, _
                         ByVal hwndNo As Long) As Long
    If hwndType = HWND_TYPENO_NOW Then
        GethwndNo = hwndNo
    ElseIf hwndType = HWND_TYPENO_NEXT Or _
           hwndType = HWND_TYPENO_LAST Then
        GethwndNo = GetNextWindow(hwndNo, hwndType)
    End If
End Function

Private Sub CheckNumberOfArrayElements()
    If (dictionary.Count = CountNumberOfArrayElements(Array_hwndTypeName)) And _
       (dictionary.Count = CountNumberOfArrayElements(Array_hwndNo)) And _
       (dictionary.Count = CountNumberOfArrayElements(Array_captionName)) And _
       (dictionary.Count = CountNumberOfArrayElements(Array_className)) Then
    Else
        MsgBox "Error. GethwndNo"
        Exit Sub
    End If
End Sub

Private Function CountNumberOfArrayElements(ByVal Array_Temp As Variant) As Long
    CountNumberOfArrayElements = UBound(Array_Temp) - LBound(Array_Temp) + 1
End Function

スポンサーリンク

プログラムについて

メインプログラム

「GetAllParentHwnd」と「ハンドル情報出力」の関数がメインプログラムです。

それぞれの意味は次のようになっています。

  • GetAllParentHwnd関数:起動中のWindowハンドル情報を配列で取得します。
  • ハンドル情報出力関数:GetAllParentHwnd関数で格納した情報を「HWND」シートに出力する。プログラム内で「GetAllParentHwnd」を実行してその情報を書き出します。

配列

そして、配列は「Array_hwndTypeName」「Array_hwndNo」「Array_captionName」「Array_className」と4つあります。

各配列の同じ要素番号に同じハンドル情報が入っています。

例えば、ハンドル情報が45個あったら、配列は配列名(0)から配列名(44)まであります。そしてまた例えば「Array_hwndTypeName(28)」「Array_hwndNo(28)」「Array_captionName(28)」「Array_className(28)」は同じハンドルの情報です。

それぞれの配列に格納されているものは以下。

  • 「Array_hwndTypeName」には「GetNextWindow」APIを使う際に利用する文字列「HWND_NOW」「HWND_NEXT」「HWND_LAST」のどれかが格納。
  • 「Array_hwndNo」にはハンドル番号が格納。
  • 「Array_captionName」にはキャプション名が格納。
  • 「Array_className」にはクラス名が格納。

その他

重複データは削除され除外してます。ハンドル0番は格納していません。

親ハンドルしか対象にしてません。

実行イメージ

Sub「GetAllParentHwnd」実行の場合

Sub「ハンドル情報出力」実行の場合

おススメの使い方

長くなりましたので別記事で紹介します。

no image
VBA:親ウィンドウハンドルの配列からハンドル情報を取得[No71]
動作準備 次の記事のエクセル、プログラムを利用前提の紹介となります。 プログラム ハンドル番号から取得する Option Explicit Public Sub ViewHwnd() ...

こちらのツール利用もお勧め。フォーム利用している処理。

no image
VBAでハンドル情報(Handle等)を用いて他のアプリケーション(ソフトウェア)を操作する。[No20]
VBAでIE(Internet Explorer)の操作ができるようになって、次は他のアプリケーションを操作する方法。自分用のメモとして残しておきます。定期的な確認作業をオートメーシ ...
no image
Windowsアプリケーション(ソフトウェア)のハンドル情報まとめ[No21]
Windowsのアプリケーションはハンドル(Hadle)で構成されています。今回はアプリケーションのハンドル情報を記載していきたいと思います。 徐々に追記していきます。 Window ...

関連記事

no image
ウィンドウハンドル関連の記事一覧[No74]
記事一覧 ハンドル番号、キャプション名、クラス名について書かれた記事のまとめです。 最後までお付き合いいただきありがとうございます! この情報が誰かの役にたてれば幸 ...

最後までお付き合いいただきありがとうございます!

この情報が誰かの役にたてれば幸いです。

スポンサーリンク

タグ

-その他

© 2021 BookALittle