【VBA×WindowsAPI】Editコントロール(テキストボックス)内の文字列を操作する
Editコントロール(テキストボックス)は、ユーザにテキストの入力させるために使われるコントロールです。本来、Excel VBAだけでは操作不能なExcel以外のアプリケーションのEditコントロールですが、Windows APIと組み合わせることで文字列の入力や取得をプログラムとして処理することが可能になります。これにより、ユーザが手入力している作業をExcel外の領域でも自動化することができます。
本ページではそんな文字列の入力コントロールであるEditコントロールに対して、VBAで文字列入力と現在の入力されている文字列を取得する方法を解説していきます。コントロールの種類の調べ方をはじめ、ボタンやコンボボックス等のその他コントロールの自動化は下記メインページを参照下さい。
Editコントロールを操作
Editコントロールはテキストボックスのような文字入力が可能なコントロールのことです。メモ帳でいうと文字入力エリアは1つの大きなEditコントロールであり、ファイル保存する際にファイル名を入力するエリアや検索する文字列を入力するエリアなどもすべてEditコントロールにあたります。
本ページではEditコントロールに対して「指定の文字列を入力する方法」と「現在入力されている文字列を取得する方法」の2つの方法を解説します。ここではEditコントロールと表記していますがStaticコントロール(ラベル)に対しても全く同じ方法で文字列の変更/取得を行うことが可能です。
VBAで別アプリケーションのEditコントロールを操作するには下記のWindows APIを利用します。
それぞれ関数のより詳細な使い方の解説は各関数のリンクページを参照下さい。
FindWindow関数 :指定のウィンドウのハンドルを取得する
FindWindowEx関数 :指定のウィンドウ内にある子ウィンドウのハンドルを取得する
SendMessage関数 :指定のウィンドウにメッセージを送信する
「そもそもWindows APIって何?」という方はコチラ(メインページ)も併せて参照下さい。
サンプルコード
指定のEditコントロールに対して文字列を取得、入力するサンプルコードは下記の通りです。
メモ帳ウィンドウを開いた状態で下記コードを実行すると、SetText関数でメモ帳内に指定した文字列を入力、GetText関数で現在のEditコントロール内の値(文字列)を取得することができます。サンプルコードではEditコントロールとしてメモ帳のテキストエリアを取得していますが、別の領域のEditコントロールのハンドルを取得すればそのEditコントロールの文字列を操作することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
Option Explicit Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr Private Const WM_SETTEXT As Long = &HC 'テキストに文字列をセット Private Const WM_GETTEXT As Long = &HD 'テキストの文字列を取得 Private Const WM_GETTEXTLENGTH As Long = &HE 'テキストの文字数を取得 '---------------------------------------------------------------- ' メイン処理 '---------------------------------------------------------------- Sub main() Dim hWndNotepad As LongPtr Dim hWndEdit As LongPtr 'メモ帳のウィンドウハンドル取得 hWndNotepad = FindWindow("notepad", vbNullString) 'メモ帳のEditコントロールのハンドルを取得 hWndEdit = FindWindowEx(hWndNotepad, 0, "Edit", vbNullString) 'Editコントロールに指定文字列を入力 Call SetText(hWndEdit, "入力する文字列") 'Editコントロールの文字列を取得 Debug.Print GetText(hWndEdit) End Sub '---------------------------------------------------------------- ' Editコントロールに指定文字列を入力する '---------------------------------------------------------------- Private Sub SetText(ByVal hWndEdit As LongPtr, ByVal sText As String) 'Editコントロールに文字を設定する Call SendMessage(hWndEdit, WM_SETTEXT, 0, ByVal sText) End Sub '---------------------------------------------------------------- ' Editコントロールの文字列を取得する '---------------------------------------------------------------- Private Function GetText(ByVal hWndEdit As LongPtr) As String Dim lLen As LongPtr Dim sBuf As String Dim sText As String 'Editコントロールの文字数分の固定長文字列を用意 lLen = SendMessage(hWndEdit, WM_GETTEXTLENGTH, 0, 0) sBuf = String(CLng(lLen) + 1, vbNullChar) 'Editコントロールの文字列を取得 Call SendMessage(hWndEdit, WM_GETTEXT, Len(sBuf), ByVal sBuf) sText = left(sBuf, InStr(sBuf, vbNullChar) - 1) GetText = sText End Function |
コード解説
Windows APIを使ってEditコントロールの文字列を操作するには下記の手順を行います。
操作対象のEditコントロールハンドルの取得はウィンドウ(アプリケーション)の構造により取得手順が変わるので、Spy++等のツールを使用してウィンドウの構造を調べる必要があります。構造の確認ができたらFindWindowEx関数を使うことで該当コントロールのハンドルを取得することが可能です。
2. 取得したハンドルに文字列入力のメッセージを送信 (文字列入力時)
2. 取得したハンドルに文字列取得のメッセージを送信 (文字列取得時)
取得したハンドルに文字列入力のメッセージを送信
Editコントロールのハンドルに対して”文字列を入力するためのメッセージ”と合わせて入力したい文字列を送信することで、その文字列をEditコントロールに入力することができます。メッセージの送信はSendMessage関数を使い、下記のように書きます。
Call SendMessage(hWndEdit, WM_SETTEXT, 0, ByVal sText)
第1引数のhWndEditには文字列入力を行うEditコントロールのハンドル、第2引数にはウィンドウの文字列を設定するメッセージ「WM_SETTEXT」(定数値)、第3引数は今回の場合では使用しないので「0」、第4引数のsTextには送信する文字列をByVal(値渡し)でそれぞれ入力します。
「WM_SETTEXT」は該当のヘッダーファイル内に定義されていますが、VBAでは関数の呼び出しを行っているだけなので定数自体の定義はされていません。そのため「Const WM_SETTEXT= &HC」というかたちでコードの初めに定義しています。(引数として直接「&HC」を入力しても可)
これにより、指定のEditコントロールに指定した文字列を送信(入力)することができます。このとき既にEditコントロール内に文字列が入力されている場合は送信した文字列で上書きされます。元の文字列に追記したい場合、まずEditコントロール内の文字列を取得して、その文字列の後ろに入力したい文字列を付け加えたものを送信すれば追記と同じ結果を得ることができます。
取得したハンドルに文字列取得のメッセージを送信
Editコントロールのハンドルに対して”文字列を取得するためのメッセージ”と合わせて文字列を受け取るための空の文字列を送信することで、Editコントロール内にある文字列を取得することができます。メッセージの送信はSendMessage関数を使い、下記のように書きます。
Call SendMessage(hWndEdit, WM_GETTEXT, Len(sBuf), ByVal sBuf)
第1引数のhWndEditには文字列の取得を行う対象のEditコントロールのハンドル、第2引数にはウィンドウの文字列を取得するメッセージ「WM_GETTEXT」(定数値)、第3引数には取得する文字列の文字数、第4引数には文字列を受け取るための空の固定長文字列をByVal(値渡し)でそれぞれ入力します。
「WM_GETTEXT」は該当のヘッダーファイル内に定義されていますが、VBAでは関数の呼び出しを行っているだけなので定数自体の定義はされていません。そのため「Const WM_GETTEXT= &HD」というかたちでコードの初めに定義しています。(引数として直接「&HD」を入力しても可)
文字列を取得する際はその文字列の文字数と、文字数分の空の固定長文字列を入力する必要があります。このとき「必ず100文字以内に収まる」というような確証がある場合は定数値でも問題ありませんが、文字数が可変で上限がいくつになるかも予測できないような場合は事前に文字数を取得しておく必要があります。文字数の取得は同じくSendMessage関数で下記のように記載します。
lLen = SendMessage(hWndEdit, WM_GETTEXTLENGTH, 0, 0)
第1引数のhWndEditには文字数の取得を行う対象のEditコントロールのハンドル、第2引数にはウィンドウ内の文字列の文字数を取得するメッセージ「WM_GETTEXTLENGTH」(定数値)、第3,第4引数は今回の場合では使用しないので「0」をそれぞれ入力することで戻り値として指定のEditコントロール内にある文字列の文字数を取得することができます。
これにより、指定のEditコントロール内にある文字列を取得することができます。
関連情報
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:ウィンドウ メッセージ (Windows とメッセージ) – Win32 apps