SAK 図書館
VB テクニック編2 - Windows API、ウィンドウハンドル取得、ウィンドウ制御
■SAK 関数利用規程
・テクニック編で紹介する関数は、私こと Y.SAK の開発関数である。
・著作権明示部分の改編は認めない。
・個人、企業がこれらの関数を使用したり、一部を使用して新たなシステムや
プログラムを開発することは自由です。
・但し、これらの関数を一部でも使用しているソフトウェアをシェアウェア、
その他有償プロダクトとして配布・販売するには、私の許可が必要です。
(無償のフリーソフトウェアなら、自由に配布しても良い。)
・これらの関数を使用して発生した、いかなる形での損害も私こと Y.SAK は
賠償しません。
■ウィンドウハンドル取得
【説明】
・ウィンドウのオーナハンドルを取得する。
別のプログラムのウィンドウ制御などに HWND が必要なので、この関数を
使用して取得すると良い。
アプリケーションハンドルは、通常ウィンドウハンドルで代用できる。
どうしてもインスタンスハンドルが欲しければ、
hInstance = GetWindowLong(hWnd, GWL_HINSTANCE);
で、HINSTANCE を取得すれば良い。
【使い方】
・次の例は、Excel をクラス名で見つけている。Excel が起動されていれば、
Excel のウィンドウハンドルが返る。
キャプションが vbNullString になっているのは、シートをオープンしてい
るとキャプションにシート名が入ったりして、キャプションが不定になるた
めである。
・vbNullString は、C 言語の NULL と等しい。
dim hwindow as long
hwindow = FindWindow("XLMAIN", vbNullString)
If hwindow = 0 Then msgbox "エラー"
msgbox hwindow
・次の例は、電卓をキャプションで見つけている。電卓が起動されていれば、
そのウィンドウハンドルが返る。
クラス名は vbNullString で指定していない。
dim hwindow as long
hwindow = FindWindow(vbNullString, "電卓")
If hwindow = 0 Then msgbox "エラー"
msgbox hwindow
・FindWindow では、トップレベルウィンドウしか検索できないが、
FindWindowEx は、親ウィンドウハンドルや子ウィンドウハンドルを指定
することによって、チャイルドウィンドウを検索できる。
次の例は、メモ帳の親ウィンドウハンドルを元に FindWindowEx で、
メモ帳の edit チャイルドウィンドウを見つけている。
dim hwindow as long
hwindow = FindWindow(vbNullString, "無題 - メモ帳")
if hwindow <> 0 then
hwindow = FindWindowEx(hwindow, 0, "edit", vbNullString)
end if
If hwindow = 0 Then msgbox "エラー"
msgbox hwindow
'=======================================================================
'** Windows API 定義
Public Declare Function FindWindowA Lib "user32" (ByVal cnm As String, ByVal cap As String) As Long
Public Declare Function FindWindowW Lib "user32" (ByVal cnm As String, ByVal cap As String) As Long
Public Declare Function FindWindowExA Lib "user32" (ByVal hpar As Long, ByVal hchi As Long, ByVal cnm As String, ByVal cap As String) As Long
Public Declare Function FindWindowExW Lib "user32" (ByVal hpar As Long, ByVal hchi As Long, ByVal cnm As String, ByVal cap As String) As Long
'=======================================================================
' ウィンドウハンドル取得
'=======================================================================
Public Function FindWindow(cnm As String, cap As String) As Long
If GetOS() = VER_PLATFORM_WIN32_NT Then
FindWindow = FindWindowW(cnm, cap)
Else
FindWindow = FindWindowA(cnm, cap)
End If
End Function
'=======================================================================
' 拡張ウィンドウハンドル取得
'=======================================================================
Public Function FindWindowEx(hpar As Long, hchi As Long, cnm As String, cap As String) As Long
If GetOS() = VER_PLATFORM_WIN32_NT Then
FindWindowEx = FindWindowExW(hpar, hchi, cnm, cap)
Else
FindWindowEx = FindWindowExA(hpar, hchi, cnm, cap)
End If
End Function
■キャプション取得
【説明】
・ウィンドウのキャプション、つまり、タイトルを取得する。
【使い方】
・電卓が起動されていなければ起動して、そのキャプションを取得する。
(他のアプリケーション、アプリ実行、アプリ起動、他のプログラム起動)
dim hwindow as long
dim i as long
dim cap as string
hwindow = FindWindow("SciCalc", vbNullString)
If hwindow = 0 Then
on local error resume next
shell "calc.exe", 1
on local error goto 0
hwindow = FindWindow("SciCalc", vbNullString)
end if
If hwindow <> 0 Then
cap = space(200)
i = GetWindowText(hwindow, cap, len(cap))
if i > 0 then cap = Trim(Left(cap, InStr(cap, Chr(0)) - 1))
msgbox cap
else
msgbox "エラー"
end if
'=======================================================================
'** Windows API 定義
Public Declare Function GetWindowTextA Lib "user32" (ByVal hwd As Long, ByVal buf As String, ByVal bln As Long) As Long
Public Declare Function GetWindowTextW Lib "user32" (ByVal hwd As Long, ByVal buf As String, ByVal bln As Long) As Long
'=======================================================================
' キャプション取得
'=======================================================================
Public Function GetWindowText(hwd As Long, buf As String, bln As Long) As Long
If GetOS() = VER_PLATFORM_WIN32_NT Then
GetWindowText = GetWindowTextW(hwd, buf, bln)
Else
GetWindowText = GetWindowTextA(hwd, buf, bln)
End If
End Function
■ウィンドウメッセージ送信
【説明】
・ウィンドウプロシジャにメッセージを送信する。
ウィンドウプロシジャの処理が終わるまで、制御は戻らない。
・PostMessage() と基本には同じなので、使い方は次で説明する。
'=======================================================================
'** Windows API 定義
Public Declare Function SendMessageA Lib "user32" (ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, ByVal lpara As Long) As Long
Public Declare Function SendMessageW Lib "user32" (ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, ByVal lpara As Long) As Long
'=======================================================================
' ウィンドウメッセージ送信
'=======================================================================
Public Function SendMessage(hwd As Long, msg As Long, wpara As Long, lpara As Long) As Long
If GetOS() = VER_PLATFORM_WIN32_NT Then
SendMessage = SendMessageW(hwd, msg, wpara, lpara)
Else
SendMessage = SendMessageA(hwd, msg, wpara, lpara)
End If
End Function
■ウィンドウメッセージポスト
【説明】
・ウィンドウプロシジャにメッセージをポストする。
ポストすると、制御が直ちに戻ってくる。
【使い方】
・電卓が起動されていれば、終了させる。
(他のアプリケーション終了、外部アプリケーション終了、外部アプリ終了)
Const WM_CLOSE = 16
dim hwindow as long
hwindow = FindWindow("SciCalc", vbNullString)
If hwindow <> 0 Then
PostMessage hwindow, WM_CLOSE, 0, 0
end if
msgbox "OK"
'=======================================================================
'** Windows API 定義
Public Declare Function PostMessageA Lib "user32" (ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, ByVal lpara As Long) As Long
Public Declare Function PostMessageW Lib "user32" (ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, ByVal lpara As Long) As Long
'=======================================================================
' ウィンドウメッセージポスト
'=======================================================================
Public Function PostMessage(hwd As Long, msg As Long, wpara As Long, lpara As Long) As Long
If GetOS() = VER_PLATFORM_WIN32_NT Then
PostMessage = PostMessageW(hwd, msg, wpara, lpara)
Else
PostMessage = PostMessageA(hwd, msg, wpara, lpara)
End If
End Function
■キー送信
【説明】
・キー入力メッセージを他のウィンドウに送信する。
【使い方】
・電卓が起動されていなければ起動して、「987」を送信する。
電卓では、これで正常に受信できるが、Excel XP に送信したテストでは、
「998877」のように 2 個単位で受信してしまう。
(IME の影響は受けない。)
Const WM_CHAR = &H102
dim hwindow as long
hwindow = FindWindow("SciCalc", vbNullString)
If hwindow = 0 Then
on local error resume next
shell "calc.exe", 1
on local error goto 0
hwindow = FindWindow("SciCalc", vbNullString)
end if
If hwindow <> 0 Then
PostMessage hwindow, WM_CHAR, Asc("9"), 0
PostMessage hwindow, WM_CHAR, Asc("8"), 0
PostMessage hwindow, WM_CHAR, Asc("7"), 0
msgbox "OK"
else
msgbox "エラー"
end if
■ウィンドウクラス名取得
【説明】
・ウィンドウクラス名を取得する。
【使い方】
・FindWindow で確実にウィンドウを見つけるには、クラス名が必要となる。
WinSight 等のツールがない場合は、次のように調査することができる。
ここでは、その時のキャプションで FindWindow してウィンドウクラスを
取得している。
dim hwindow as long
dim clnm as string
dim i as long
hwindow = FindWindow(vbNullString, "電卓")
If hwindow <> 0 Then
clnm = space(200)
i = GetClassName(hwindow, clnm, len(clnm))
if i > 0 then
i = instr(clnm, chr(0))
if i = 0 then
clnm = ""
else
clnm = left(clnm, i - 1)
end if
msgbox "クラス名= " & clnm
else
msgbox "GetClassName エラー"
end if
else
msgbox "FindWindow エラー"
end if
'** Windows API 定義
Public Declare Function GetClassNameA Lib "user32" (ByVal hwd As Long, ByVal clnm As string, ByVal sz As Long) As Long
Public Declare Function GetClassNameW Lib "user32" (ByVal hwd As Long, ByVal clnm As string, ByVal sz As Long) As Long
'=======================================================================
' ウィンドウクラス名取得
'=======================================================================
Public Function GetClassName(hwd As Long, clnm As string, sz As Long) As Long
If GetOS() = VER_PLATFORM_WIN32_NT Then
GetClassName = GetClassNameW(hwd, clnm, sz)
Else
GetClassName = GetClassNameA(hwd, clnm, sz)
End If
End Function
■子ウィンドウハンドル取得(チャイルドウィンドウハンドル取得)
【説明】
・チャイルドウィンドウハンドル取得する。
【使い方】
・メモ帳の様にチャイルドウィンドウがひしつしかない場合は、簡単なコード
で済む。兄弟ウィンドウや更に子の子が存在する場合は、GetWindow の GW_
パラメタを駆使して目的のウィンドウハンドルを得る。
複数の子ウィンドウのどれが目的のウィンドウかは、クラス名や CHILD_ID
で判別すると良い。
const GW_HWNDFIRST = 0
const GW_HWNDLAST = 1
const GW_HWNDNEXT = 2
const GW_HWNDPREV = 3
const GW_OWNER = 4
const GW_CHILD = 5
dim hwindow as long
dim hchild as long
hwindow = FindWindow("Notepad", vbNullString)
If hwindow = 0 Then
msgbox "FindWindow エラー"
end
end if
hchild = GetWindow(hwindow, GW_CHILD)
If hchild = 0 Then
msgbox "GetWindow エラー"
end
end if
msgbox "子ウィンドウハンドル= " & hchild
'** Windows API 定義
Public Declare Function GetWindow Lib "user32" (ByVal hwd As Long, ByVal cmd As Long) As Long
■ウィンドウ表示
【説明】
・ウィンドウの表示を指定する。
【使い方】
Const SW_HIDE = 0
Const SW_SHOWNORMAL = 1
Const SW_SHOWNA = 8
Const SW_SHOWMAXIMIZED = 3
Const SW_MINIMIZE = 6
dim hwindow as long
hwindow = FindWindow(vbNullString, "電卓")
If hwindow = 0 Then
msgbox "FindWindow エラー"
end
end if
msgbox "電卓を非表示にします。"
ShowWindow hwindow, SW_HIDE
msgbox "電卓を表示します。"
ShowWindow hwindow, SW_SHOWNORMAL
'** Windows API 定義
Public Declare Function ShowWindow Lib "user32" (ByVal hwindow As Long, ByVal cmdshow As Long) As Long
■VB テクニック編資料
■VB 入門編資料
■VB 基礎編資料
■VB ビジュアル編資料