● メモ帳の文字列を消去する… その前に ●

ここからなんとなく面白くなってきます。でも、このページはちょっと長いよ。

前回、メモ帳を終了させる手段に SendMessage API関数を使用しました。今回もこれを使用します。前回は、以下のような使用方法でした。

ret = SendMessage(hNotepad, WM_CLOSE, 0&, ByVal 0&)

この関数は、指定のウインドウハンドルを持つウインドウに、Windowsメッセージを送る という機能を持っています。上の例で言えば、ウインドウハンドルが hNotepad であるウインドウに(=メモ帳) WM_CLOSE を送ったということになります。要するに、メモ帳を閉じろ ということです。第3引数、第4引数はメッセージに応じて変わってきます。それについては、ここでは触れません。Win32 SDK 等で調べてくださいね。

さて、今回はメモ帳の文字列を消去するということをやります。先ほどの要領でいけば、メモ帳に空文字をセットしろ というメッセージを送ればいいと思われますが実際やってみると違うのであります。試しに、以下のコードを実行してみてください。

ret = SendMessage(hNotepad, WM_SETTEXT, 0&, ByVal "")

何とびっくり、メモ帳のタイトルバーの文字列がなくなってしまいましたね。実は、第1引数には文字列編集領域のハンドルを指定してやらねばいけないのです。あくまでも、メモ帳はメインのフォーム全体に文字列編集領域が乗っかっているという形であり、それぞれ独自にウインドウハンドルを持っているのです。それでは、どうやったら文字列編集領域のハンドルを取得できるのでしょうか。まず、Spy++ というツールを使用してみましょう。これはVisual C++ 等に付属しているツールで、実際に存在しているウインドウの情報を列挙してくれます。さて、メモ帳を起動し、Spy++を起動し、メモ帳の情報を探すと以下のようになっていました。

Edit とあるラインが実は文字列編集領域のウインドウを示してくれています。これをみると、ハンドルが "00030544" でクラス名が"Edit"ということになります。(ここではクラス名については説明しません。)この "Edit" というクラス名は常に同じ名前で、起動のたびに変わることはありません。ここに、目を付けて文字列編集領域(以下、エディットボックス)のハンドルを取得することにします。突拍子もなく関数名を出すのは恐縮なのですが、 FindWindowEx という関数で取得することが可能です。引数で指定したウインドウを見つけたら、そのウインドウハンドルを返してくれます。宣言・引数は以下の通りです。

Declare Function FindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

 hWnd1  …  親ウインドウのハンドル
 hWnd2  …  子ウインドウのハンドル
 lpsz1  …  クラス名
 lpsz2  …  タイトルバーの文字列

以下のコードを試してください。

'第4引数は vbNullString じゃないよ、エディットボックスが空という状態を想定しているので
Debug.Print Hex(FindWindowEx(hNotepad, 0, "Edit", ""))

これで、エディットボックスのウインドウハンドルが取得できました。ところが、私はこの方法は好きではありません。なんとなく、"Edit"という部分に苦しいものを感じます。また、エディットボックスの文字列が常に空というわけではありません。(まあ、その場合は vbNullString を指定すればいいのすが…) もう少し、自然な感じでやりたいものです。ここまでやって、「何だそりゃ、詐欺じゃねぇか」という方もいると思いますが、もう少し我慢してくださいね。

先ほど軽く流した FindWindowEx API 関数の第1引数を見てください。ここは親ウインドウを指定しなければなりません。さっきは親ウインドウとして hNotepad を指定しました。もうお分かりでしょう。メモ帳のフォーム全体が親であるということは、エディットボックスは子にしかなり得ません。Spy++ を見てもその関係はお分かりでしょう。ということで、次のAPI関数が出てくるわけです。

Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long

このAPI関数は、指定ウインドウと関係のあるウインドウのハンドルを取得するものです。第1引数に検索対象となるウインドウハンドル、第2引数に第1引数で指定したウインドウとの関係を指定します。ここでの場合は、GW_CHILD を指定すればいいのです。それでは、関数を書きますよ。というか、やっと書けます。う〜ん、この場合はメモ帳のウインドウハンドルと一緒に取得した方が楽かな。ということで、メモ帳のハンドルを取得するために用意した標準モジュールに書いてください。

Priavte Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long

Private Const GW_CHILD = 5

'---------------------------------------------------------------
' 関数名: ghEditbox
' 機能 : エディットボックスのハンドルを取得する
' 引数 : なし
' 返り値 : 正常:ハンドル エラー:0
'---------------------------------------------------------------
Property Get ghEditbox() As Long

  ghEditbox = GetWindow(m_Handle, GW_CHILD)

End Property

さて、ここまでやればもう少し。フォームモジュールの宣言セクションに1行、cmdExecuteNotePad_Clickイベントに1行コードを書けば終わりです。

Private hEditbox As Long '起動したメモ帳のエディットボックスのハンドル

Private Sub cmdExecuteNotePad_Click()

  'メモ帳は1つだけ起動すればよろしい
  If hNotepad Then Exit Sub

  'メモ帳起動、メモ帳のパスは自分で調べてね
  Call ExecuteNotepad("C:\Windows\Notepad.exe")

  'メモ帳のハンドル取得
  hNotepad = gHandleVB5

  'エディットボックスのハンドル取得
  hEditbox = ghEditbox  '<-この部分を付け足しましょう

End Sub

私としても、もう書きたくないので、メモ帳の文字列を消去する方法は次のページで紹介します。今更、紹介するまでもないかもしれませんが…


[ インデックスページへ  |  前のページへ  |  次のページへ ]