Windowハンドルの取得2012.11.19
Win32APIなどを用い、ウィンドウを指定して何らかの処理を行う場合、必ずウィンドウのハンドルが必要になります。ウィンドウハンドルとはコンピュータが各ウィンドウに割り振る管理番号で、これを指定することで、コンピュータに該当のウィンドウを認識させます。
ここでは、様々な方法で各種のウィンドウハンドルを取得する、サンプルコードとメモを記載します。
ポイント
・Application.Hwndプロパティ
・GetActiveWindow関数(Win32API)
・GetDesktopWindow関数(Win32API)
・FindWindow関数(Win32API)
・FindWindowEx関数(Win32API)
・GetWindow関数(Win32API)
Excelマクロ管理ツール
プロパティを用いたウィンドウハンドル取得のサンプルコード
Application.Hwndプロパティ
Excelの最上位のウィンドウ ハンドルをLong型の値で返す。値の取得のみ可能。
Excel2002で追加されたプロパティであるため、Excel2000以前では使用できない。
Sub Get_Hwnd_1() MsgBox Excel.Application.Hwnd End Sub
Win32APIを用いたウィンドウハンドル取得のサンプルコード
次からは、ハンドルを取得するためのWin32API関数である。VBAでWin32APIを宣言する場合、「宣言セクション」(各モジュールの最上部)に記述しなければならない。
これら関数の返り値は、関数が成功するとハンドル番号、失敗すると「0」を返す。
●64ビットOfficeへの対応
Win32APIの使用時に気をつけることは、64ビット版のOfficeへの対応である。対応させるためには重要な点が2つある。
1つ目は、Declare の後に、Ptrsafe 属性を設定すること。2つ目は、変数の型の変更。
分岐によって、32ビット用の宣言と、64ビット用の宣言を行うことで、互換性を持たすことができる。
次は、分岐による関数宣言例である(宣言セクションに記述)。
#If VBA7 Then Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr '64bit Dim myHwnd As LongPtr #Else Declare Function GetActiveWindow Lib "user32" () As Long Dim myHwnd As Long #End If
パソコン環境によっては、上記コードの一部が赤く表示されることもあるが、動作に問題はなくコードは実行できる。
GetDesktopWindow関数
デスクトップのウィンドウハンドルを取得
【宣言】
#If VBA7 Then Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr Dim myHwnd As LongPtr #Else Declare Function GetDesktopWindow Lib "user32" () As Long Dim myHwnd As Long #End If
【使用例】
Sub Get_Hwnd_2() MsgBox GetDesktopWindow() End Sub
GetActiveWindow関数
アクティブになっているウィンドウハンドルの取得
【宣言】
#If VBA7 Then Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr '64bit Dim myHwnd As LongPtr #Else Declare Function GetActiveWindow Lib "user32" () As Long Dim myHwnd As Long #End If
【使用例】
Sub Get_Hwnd_3() MsgBox GetActiveWindow() End Sub
FindWindow関数
クラスやウィンドウの名前からウィンドウハンドルを取得
【宣言】
#If VBA7 Then Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As LongPtr Dim myHwnd As LongPtr #Else Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Dim myHwnd As Long #End If
lpClassName・・・クラス名
lpWindowName・・・ウィンドウ名
引数は省略不可。指定しない場合はvbNullStringで対応する。
2つの引数を共にvbNullStringにした場合は、最前面のWindowのハンドルを取得する。
【使用例】
'代表的なアプリケーションのクラス名 'Excel「XLMAIN」 Word「OpusApp」 PowerPoint「PP10FrameClass」 Access「OMain」 'Visual Basic Editor「wndclass_desked_gsk」 Internet Explorer「IEFrame」 'メモ帳「Notepad」 ペイント「MSPaintApp」 電卓「SciCalc」 ワードパッド「WordPadClass」
Sub Get_Hwnd_4() MsgBox FindWindow("XLMAIN", vbNullString) MsgBox FindWindow(vbNullString, Application.Caption) End Sub
FindWindowEx関数
親ウィンドウを基準に、クラスやウィンドウの名前から子ウィンドウのハンドルを取得
【宣言】
#If VBA7 Then Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As LongPtr, _ ByVal hwndChildAfter As LongPtr, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As LongPtr Dim myHwnd As LongPtr #Else Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Dim myHwnd As Long #End If
【引数】
hwndParent・・・親Windowのハンドル
hwndChildAfter・・・検索を開始する子Windowのハンドル。「0」の場合、最初の子Windowから検索
lpClassName・・・クラス名
lpWindowName・・・ウィンドウ名
【使用例】
Sub Get_Hwnd_5() myHwnd = FindWindow("XLMAIN", vbNullString) If myHwnd = 0 Then Exit Sub 'Excelのクライアント領域のウィンドウハンドル MsgBox FindWindowEx(myHwnd, 0, "XLDESK", vbNullString) End Sub
GetWindow関数
あるウィンドウを基準に、他の任意のウィンドウハンドルを取得する
【宣言】
#If VBA7 Then Declare PtrSafe Function GetWindow Lib "user32" ( _ ByVal hwnd As LongPtr, _ ByVal wCmd As Long) As LongPtr Dim myHwnd As LongPtr #Else Declare Function GetWindow Lib "user32" ( _ ByVal hwnd As Long, _ ByVal wCmd As Long) As Long Dim myHwnd As Long #End If '///GetWindowの定数/// Const GW_HWNDFIRST = 0 '基準となるWindowと同じ種類のうち最前面のWindow Const GW_HWNDLAST = 1 '基準となるWindowと同じ種類のうち最背面のWindow Const GW_HWNDNEXT = 2 '基準となるWindowの次のWindow Const GW_HWNDPREV = 3 '基準となるWindowの前のWindow Const GW_OWNER = 4 '基準となるWindowのオーナーWindow Const GW_CHILD = 5 '基準となるWindowの子WindowのうちトップレベルのWindow
【引数】
hwnd・・・基準となるウィンドウのハンドル
wCmd・・・どのような検索コマンドを実行するかを指定。定数を使用。
【使用例】
Sub Get_Hwnd_6() myHwnd = FindWindow("XLMAIN", vbNullString) MsgBox GetWindow(myHwnd, GW_CHILD) End Sub
書籍紹介本を執筆しました
知りたいがすぐわかる! やりたいがすぐできる!
「Excel VBA 逆引きで学ぶ ユーザーフォーム&コントロール」(Kindle版)
ユーザーフォームを扱えると、VBAでできることが大きく広がります!
本書では、知りたいこと、やりたいことから、逆引きで学びを深められます。
※ 第1章~5章まで公開しています
全サンプルコード
上記の全てを繋げ、比較を行うサンプルコード。
#If VBA7 Then Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As LongPtr Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As LongPtr, _ ByVal hwndChildAfter As LongPtr, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As LongPtr Declare PtrSafe Function GetWindow Lib "user32" ( _ ByVal hwnd As LongPtr, _ ByVal wCmd As Long) As LongPtr Dim myHwnd As LongPtr Dim myCHwnd As LongPtr #Else Declare Function GetActiveWindow Lib "user32" () As Long Declare Function GetDesktopWindow Lib "user32" () As Long Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Declare Function GetWindow Lib "user32" ( _ ByVal hwnd As Long, _ ByVal wCmd As Long) As Long Dim myHwnd As Long Dim myCHwnd As Long #End If '///GetWindowの定数/// Const GW_HWNDFIRST = 0 '基準となるWindowと同じ種類のうち最前面のWindow Const GW_HWNDLAST = 1 '基準となるWindowと同じ種類のうち最背面のWindow Const GW_HWNDNEXT = 2 '基準となるWindowの次のWindow Const GW_HWNDPREV = 3 '基準となるWindowの前のWindow Const GW_OWNER = 4 '基準となるWindowのオーナーWindow Const GW_CHILD = 5 '基準となるWindowの子WindowのうちトップレベルのWindow
Sub Get_Hwnd() Dim strWndCap As String myHwnd = GetDesktopWindow() MsgBox "GetDesktopWindow:" & myHwnd myHwnd = Excel.Application.hwnd 'Excel2000以前では使用できない MsgBox "Application.Hwnd:" & myHwnd myHwnd = GetActiveWindow() MsgBox "GetActiveWindow:" & myHwnd myHwnd = FindWindow("XLMAIN", vbNullString) MsgBox "FindWindow(""XLMAIN"", vbNullString):" & myHwnd strWndCap = Application.Caption myHwnd = FindWindow(vbNullString, strWndCap) MsgBox "FindWindow(vbNullString, strWndCap):" & myHwnd myCHwnd = FindWindowEx(myHwnd, 0, "XLDESK", vbNullString) 'Excelのクライアント領域 MsgBox "FindWindowEx:" & myCHwnd myHwnd = GetWindow(myHwnd, GW_CHILD) MsgBox "GetWindow(myHwnd, GW_CHILD):" & myHwnd End Sub