【PC】VB6 から VB2010 へ移行(その4)プロセス間通信(VB6での受信)
前回のプログラムで、送信された文字列のメッセージは、受信できなければ意味がない。では受信する API とか コントロールがあるのか、というと VB6 にも VB2010 にもない(笑)
仕方がないのでサブクラス化を行って受信することにする。
VB6にしてもVB2010にしても、フォームはクラスでもある。フォームクラスには、プロパティやメソッドなど、あらかじめ決められた機能が提供されるが、この機能群にないことするために「引っかけて、横道にそれて、こっちの道に」ということをするのがサブクラス化。ちょうど、本当なら真っ直ぐおうちに帰るはずなのに、ナンパにあって、ちょっとくっついていってしまい予定(仕様)にないことをする、という感じで、ナンパ=サブクラス化と思えばわかりやすい(わかりにくいかも(笑))
サブクラスの中で、送られてきた文字列のメッセージを処理する。
Private Declare Function CallWindowProc Lib _ "user32" (ByVal oldproc As Long, _ ByVal hwnd As Long, _ ByVal msg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Private Declare Function GetWindowLong Lib _ "user32" (ByVal hwd As Long, _ ByVal NIndex As Long) As Long Declare Function SetWindowLong Lib _ "user32" (ByVal hwnd As Long, _ ByVal NIndex As Long, _ ByVal dwNewLong As Long) As Long Const GWL_WNDPROC = (-4) public OldWndProc as long public strMsg as string const pmSTART = &h0 const pmDATA = &h1 const pmEND = &h2 Public sub 前準備() 'サブクラス化 OldWndProc = GetWindowLong("メッセージを待ち受ける窓のハンドル".hwnd, GWL_WNDPROC) SetWindowLong "メッセージを待ち受ける窓のハンドル".hwnd, _ GWL_WNDPROC, AddressOf WndProc end sub Public Function WndProc(ByVal hWnd As Long, _ ByVal msg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long 'PostMessage されると、ここに飛んでくる。 if msg = "適当な共有名" then select case wParam case pmSTART 'メッセージバッファをクリア(送信開始) strMsg = "" WndProc = 0 Exit Function case pmDATA 'メッセージバッファに追加(送信) strMsg = strMsg & chr(lParam) WndProc = 0 Exit Function case pmEND '受信完了(送信終了) '======================== ' ' strMsg が 送られてきた ' メッセージなので ' 適宜解析するなりする ' '======================== WndProc = 0 Exit Function end select end if 'デフォルトメッセージ処理をする WndProc = CallWindowProc(OldWndProc, hwnd, msg, wParam, lParam) End Function Public sub 後の処理() 'サブクラス化を終了する SetWindowLong "メッセージを待ち受ける窓のハンドル".hwnd, GWL_WNDPROC, OldWndProc end sub
sub前準備を最初に呼び出し、
oldWndProc にもともとのフォームの処理を保持させて
横道である WndProcサブルーチンにそれるようにセッティングする。
こうすると 送信側から PostMessage されたメッセージが、WndProc サブルーチンに送られるので、ここで受信の処理を行う。
筆者は、3つの勝手コマンド pmSTART,pmDATA,pmEND で、変数msgStr に 送信されてきた文字をためこんで pmEND を受け取ったら、解析なり実行なり、機能の起動なり、という処理を行うようにしている。
WndProc で自分とは無関係の(PostMessageの処理)以外のものが来たら
oldWndProc で保存しておいた、本来のフォームの処理を行うようにする。
最後に、用事が終わったら後処理として、oldWndProc に戻してあげる。
これで受信ができるようになる。
気をつける点として このやり方をすると VB6 の IDE(統合開発環境)で ステップイン/アウトのデバッグなんかをやりたくなるが、うまくいかないことも多い。ハングアップしたり、事情で強制終了したりすることも増える(笑)きちんと設計してからの方が良さそうだ。
ソースを見るとわかるとおり、前回の送信も結構端折っていたりするので、そのままコピペでは動かないが、おおよそ、このような感じ。
それでも、ひどく、ややこしい。
これは、サブクラス化という技法を使うのに、WinAPI を使っているからで、たいへん汚らしいプログラムになりがちだ。
これが VB2010 になると、もっとシンプルになったりする。
VB2010 では、さらにクラスを継承したり、機能(プロパティやメソッド)を追加したり、平行にジャンプさせたりがやりたい放題になっているので、VB6 のような無理矢理感のあるサブクラス化をしなくても、WndProcが書けてしまったりする。このお話は、また次回に・・・