教えて!ExcelVBA!

ExcelVBAの基礎知識・書き方について紹介します。

【ExcelVBA API操作】ウィンドウに直接メッセージを送信しアプリケーションを終了(SendMessage)する方法を教えて!

SendMessage関数は、Windows APIの1つで、ウィンドウに対してメッセージを送信するために使用され、ウィンドウの制御や情報の取得などに利用されます。

API宣言

SendMessage関数を使用するには、Windows APIを宣言する必要があります。以下のようにAPI宣言を行います。

Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

このAPI宣言には、4つの引数があります。
●hWnd:送信先のウィンドウを識別するためのウィンドウハンドル(HWND)を指定します。ウィンドウハンドルは、ウィンドウを一意に識別するための値であり、FindWindowなどの関数を使って取得することが一般的です。
●MSG:送信するメッセージを示す定数を指定します。SendMessage関数は様々なメッセージを送信できますが、どのメッセージを使用するかは操作内容によります。よく使われるメッセージコードを幾つか紹介します。

コード 内容
&H10 ウィンドウに閉じる要求が送られます。通常はウィンドウを閉じるために使用されます。
&HC ウィンドウのテキストを設定できます。SendMessage関数のlParamには、設定したいテキストを指定します。
&HD ウィンドウのテキストを取得できます。SendMessage関数のlParamには、取得したテキストを受け取るためのバッファを指定します。
&H111 メニュー、ボタンなどのコントロールがクリックされたときに送信されるメッセージです。ボタンのクリックやメニューの選択などの操作をエミュレートする際に使用されます。
&H100 キーボードのキーが押されたときに送信されるメッセージです。特定のキーの操作をシミュレートする際に使用されます。
&H200 マウスがウィンドウ内で移動したときに送信されるメッセージです。マウス操作をエミュレートする際に使用されます。
&HFFFF 特定のメッセージを示す定数を使用しない場合に利用される空のメッセージコードとして使われることがあります。

※上記は一部のメッセージコードの例であり、他にもさまざまなメッセージコードがあります。各メッセージコードには、それぞれ独自の目的と動作がありますので、WindowsAPIの公式ドキュメントや参考文献を参照することをおすすめします。
●wParam:メッセージに関連付けられた追加情報を指定します。メッセージによっては使用されない場合もあります。
●lParam:メッセージに関連付けられた追加情報を指定します。メッセージによっては使用されない場合もあります。

使い方

SendMessage関数を呼び出し、メモ帳(Notepad)のウィンドウに対してメッセージを送信します。

Dim result As Long
result = SendMessage(notepadHwnd, &HFFFF, 0, ByVal textToWrite)

戻り値として、ウィンドウがメッセージを処理した結果を示す数値が返されます。ウィンドウがメッセージを正常に処理した場合、0以外の値が返ります。エラーで終了した場合、戻り値は0になります。

プログラミング例

以下に、プログラミング例を幾つか紹介します。

例1:メモ帳を起動してテキストを入力する

Declare PtrSafe Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare PtrSafe Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Sub StartNotepadAndWriteText()
    Dim notepadHwnd As Long
    Dim textToWrite As String
    Dim result As Long
    ' メモ帳のウィンドウクラス名とタイトルを指定してウィンドウハンドルを取得
    notepadHwnd = FindWindow("Notepad", vbNullString)
    If notepadHwnd <> 0 Then
        ' メモ帳のウィンドウにメッセージを送信してテキストを入力する
        textToWrite = "Hello, ExcelVBA!"
        result = SendMessage(notepadHwnd, &HFFFF, 0, ByVal textToWrite)
    Else
        MsgBox "メモ帳が見つかりませんでした。", vbExclamation
    End If
End Sub

例2:外部アプリケーションを終了する

Declare PtrSafe Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare PtrSafe Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Sub CloseExternalApplication()
    Dim appName As String
    Dim appHwnd As Long
    Dim result As Long
    ' 終了させるアプリケーションのタイトルを指定
    appName = "Untitled - Notepad"
    ' アプリケーションのウィンドウハンドルを取得
    appHwnd = FindWindow(vbNullString, appName)
    If appHwnd <> 0 Then
        ' アプリケーションのウィンドウにWM_CLOSEメッセージを送信して終了させる
        result = SendMessage(appHwnd, &H10, 0, 0)
    Else
        MsgBox "指定したアプリケーションが見つかりませんでした。", vbExclamation
    End If
End Sub

これらの例では、SendMessage関数を使用して別のアプリケーション(メモ帳など)を制御しています。第1例ではメモ帳を起動してテキストを入力し、第2例では指定したアプリケーションを終了させています。ただし、外部アプリケーションを操作する場合は慎重に行う必要があります。

まとめ

SendMessage関数を利用することで、外部のアプリケーションを制御したり、アプリケーションを終了させたりすることが可能です。ただし、他のアプリケーションを終了させる操作は慎重に行う必要があります。不要なプロセスを終了させると、他のアプリケーションやシステムに影響を及ぼす場合がありますので、注意してください。