Memorandum

Windowハンドルの取得

Win32APIなどを用い、ウィンドウを指定して何らかの処理を行う場合、必ずウィンドウのハンドルが必要になります。ウィンドウハンドルとはコンピュータが各ウィンドウに割り振る管理番号で、これを指定することで、コンピュータに該当のウィンドウを認識させます。
ここでは、様々な方法で各種のウィンドウハンドルを取得する、サンプルコードとメモを記載します。

ポイント

・Application.Hwndプロパティ
・GetActiveWindow関数(Win32API)
・GetDesktopWindow関数(Win32API)
・FindWindow関数(Win32API)
・FindWindowEx関数(Win32API)
・GetWindow関数(Win32API)


プロパティを用いたウィンドウハンドル取得のサンプルコード

Application.Hwndプロパティ

Excelの最上位のウィンドウ ハンドルをLong型の値で返す。値の取得のみ可能。
Excel2002で追加されたプロパティであるため、Excel2000以前では使用できない。

Sub Get_Hwnd_1()
    MsgBox Excel.Application.Hwnd
End Sub

Win32APIを用いたウィンドウハンドル取得のサンプルコード

次からは、ハンドルを取得するためのWin32API関数である。VBAでWin32APIを宣言する場合、「宣言セクション」(各モジュールの最上部)に記述しなければならない。
DC関連の関数の返り値は、関数が成功するとハンドル番号、失敗すると「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 And Win64 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

全サンプルコード

上記の全てを繋げ、比較を行うサンプルコード。

#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
ページトップへ戻る
Copyright(C) 2009- 坂江 保 All Rights Reserved.