スポンサーリンク
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「ハンドル情報出力」実行の場合
おすすめの使い方
長くなりましたので別記事で紹介します。
-
VBA:親ウィンドウハンドルの配列からハンドル情報を取得[No71]
動作準備 今回は、前回の記事で扱ったエクセル、プログラムを利用することを前提とした「親ウィンドウハンドルの配列からハンドル情報を取得する方法」を紹介します。 まだ前回の記事を読まれて ...
以前ご紹介したこちらのツールを利用することもおすすめです。フォームを利用している処理方法など、興味のある方は是非こちらも目を通してみて下さい。
-
VBAでHandle等を用いて他のアプリケーションを操作する方法[No20]
VBAでIE(Internet Explorer)の操作ができるようになり、次は他のアプリケーションを操作する方法について自分用のメモとして残しておくので、定期的な確認作業をオートメ ...
-
Windowsアプリケーション(ソフトウェア)のハンドル情報まとめ[No21]
Windowsのアプリケーションはハンドル(Hadle)で構成されています。今回はアプリケーションのハンドル情報を記載していきたいと思います。 徐々に追記していきます。 Window ...
関連記事
-
ウィンドウハンドル関連の記事一覧[No74]
記事一覧 ハンドル番号、キャプション名、クラス名について書かれた記事のまとめです。 最後までお付き合いいただきありがとうございます! この情報が誰かの役にたてれば幸 ...
最後までお付き合いいただきありがとうございます!
この情報が誰かの役にたてれば幸いです。