VB6でHWND_BROADCASTが受け取れない

仕事でハマってしまった。また忘れてハマリそうなのでメモ。

Windowsのあるアプリケーションがウィンドウメッセージをブロードキャストしていて、それを受け取って処理する別アプリをVBで書こうととした場合うまく処理できない。

単純にFormをサブクラス化してメッセージを受け取ればできるだろうと高を括っていたのだが、うまくいかない。ブロードキャストするメッセージを登録するのにRegisterWindowMessage APIを使っているが、もしやそれがうまくいっていないのかと思ったがそうでもない。

よくよく調べてみると、VBの場合はちょっと工夫がいるのだということが分かった。

SendMessage(HWND_BROADCAST…)でブロードキャストしたメッセージは、トップレベルウィンドウにしか送られない、とMSDNには書いてある。

VB(確認したのはVB6)では、単純なFormを表示するアプリケーションを作成して動かした場合でも、裏でいくつかのトップレベルウィンドウが生成されているようだ。SPYでウィンドウクラス名を調べてみると、フォームは”Form1″ ThunderRT6FormDCなどとなっているが、それ以外に”Project1″ ThunderRT6Mainというクラスをウィンドウを確認できる。(RT6という部分は多分VBのバージョンによって変わるんだろう)

Form1のウィンドウプロシージャをフックしてサブクラス化しても、このメッセージを受け取ることはできないようなので、試しにThunderRT6Main側をSPYしてみると・・・ビンゴ。

で、このウィンドウのハンドルを取得するには、GetWindow(Form1.hWnd, GW_OWNER)とすればよい。

というわけでやっと解決。悩むこと約数時間。お疲れ様でした<自分

これって、ひょっとするとVB使いさん達の間では常識なんでしょうか・・・?

しかし今回の件でよく分からないのは、以下のような挙動。

A、B、C、Dというアプリがある。AはVCで作成したアプリで、B,CはVB、DはDelphiでそれぞれ作成したものとする。

B,C,Dでは、同じ登録メッセージ(仮にX) を受け取って処理する。また、A,B,CはメッセージXをブロードキャストする。

VBで作成したB,Cは、上で書いた解決策を使わずにForm1のサブクラス化によってブロードキャストメッセージを受け取るようにコーディングしてあるものとする。

すると、BあるいはCからブロードキャストしたメッセージは、B,C,D共に受け取ることができる。
しかし、AからブロードキャストされたメッセージはDしか受け取れない。

これってどういうことなんだろう・・・。

コメントを残す

メールアドレスが公開されることはありません。