0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

指定した文字列がタイトルに含まれるウィンドウのハンドルを取得するVBAコード

Last updated at Posted at 2022-01-09

Win32API を呼び出してウィンドウの操作をする場合、操作したいウィンドウのハンドルを取得する必要がある。

たいていはウィンドウのタイトル文字列を頼りにハンドル(hWnd)を取得するのだが、完全なタイトル文字列(title_str)がわかっている場合は、API の FindWindow関数で

    hWnd = FindWindow(vbNullString, title_str)

と、簡単にハンドルを取得できる。が、タイトル文字列の一部を頼りにウィンドウハンドルを取得する場合は、ちょっと面倒くさくなる。

流れとしては、

  1. 基準となるウィンドウ(最前面の)ハンドルを取得する。FindWindow
  2. 基準ウィンドウからスタートして、現在開いているすべての可視ウィンドウをループし、ウィンドウのタイトルを調べる。GetWindowText
  3. タイトルの中に指定した文字が含まれている可視ウィンドウIsWindowVisible があれば、ループを終了しウィンドウハンドルを取得する。GetWindow
WindowModule.bas
Option Explicit

'// API呼び出し(Declare)宣言

#If VBA7 Then

    '// Office2010以降で64/32bit共通の宣言

    '// 指定されたクラス名(lpClassName)とウィンドウ名(lpWindowName)を持つウィンドウのハンドルを返す
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    
    '// 指定されたウィンドウ(hWnd)と指定された関係(wCmd)にあるウィンドウのハンドルを返す
    Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As LongPtr, ByVal wCmd As Long) As LongPtr

    '// ウィンドウ(hWnd)のタイトルをバッファ(lpString)に格納する
    Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long

    '// ウィンドウの可視状態を取得する
    Public Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Long
   
#Else

    '// Office2007以前での宣言

    '// 指定されたクラス名(lpClassName)とウィンドウ名(lpWindowName)を持つウィンドウのハンドルを返す
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

    '// 指定されたウィンドウ(hWnd)と指定された関係(wCmd)にあるウィンドウのハンドルを返す
    Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
    
    '// ウィンドウ(hWnd)のタイトル(lpString)を取得する
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

    '// ウィンドウの可視状態を取得する
    Public Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long

#End If
    
Private Const GW_HWNDNEXT   As Long = 2
Private Const ERROR_SUCCESS As Long = 0
'// タイトルに cap_str が含まれるウィンドウのハンドルを返す

Function GetHwnd(ByVal cap_str As String) As LongPtr

    Dim hWnd        As LongPtr
    Dim wCaption    As String * 255

    '// 基準となるウィンドウハンドルを取得
    '// FindWindow は、どちらの引数にも vbNullString を指定すると
    '// 最前面のウィンドウのハンドルを返す
    hWnd = FindWindow(vbNullString, vbNullString)
    
    Do Until hWnd = ERROR_SUCCESS
    
        '// 可視ウィンドウのみ
        If CBool(IsWindowVisible(hWnd)) Then        
            '// ウィンドウのキャプション(タイトル文字列)を取得
            '// GetWindowText は、ウィンドウタイトルをバッファ(wCaption)に格納する
            GetWindowText hWnd, wCaption, Len(wCaption)            
            If InStr(wCaption, cap_str) > 0 Then Exit Do
        End If
                        
        '// 次のウィンドウのウィンドウハンドルを取得
        '// GetWindow は、第二引数に GW_HWNDNEXT(=2)をして指定すると
        '// 次のウィンドウのハンドルを返す
        hWnd = GetWindow(hWnd, GW_HWNDNEXT)
    Loop
    
    GetHwnd = hWnd

End Function

逆に、ウィドウハンドル(hWnd)がわかっている場合にウィンドウタイトルを取得するのは比較的簡単である。
ウィンドウタイトルをバッファ(wCaption)に格納する GetWindowText関数の動き(引数)を理解しよう。

'// 指定したハンドルのウィンドウタイトルを返す

' GetWindowText は、バッファ(wCaption)にウィンドウタイトルを格納する
' 255文字分のバッファを取っておいたのでバッファの後半(タイトル文字列以降)は
' Null文字になるため、Left関数で Null文字より前の文字列を取り出す。

Function GetWindowTitle(ByVal hWnd As LongPtr) As String
    Dim wCaption As String * 255
    GetWindowText hWnd, wCaption, Len(wCaption)    
    GetWindowTitle = Left(wCaption, InStr(wCaption, vbNullChar) - 1)
End Function

<参考サイト>

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?