一体どうすればよいのでしょうか。
ウィンドウのサブクラス化は別名「メッセージの横取り」とも呼ばれます。 本来のプロシージャに行くはずのメッセージを「横取り」して、 自分で好きなように処理を行うことができます。上の例でいえば本来 エジットコントロール(ウィンドウ)のプロシージャに行くはずのメッセージを 別なところで取ってしまい、そこで処理を行います。 これは、元々のプロシージャに機能を追加する、というように善意に 解釈することもできます。
まず、氏名のエジットコントロール(ウィンドウ)をサブクラス化します。 そして、その中でWM_KEYDOWNメッセージの処理をします。 しかし、このウィンドウに来るすべてのメッセージを処理していたのでは 大変です。自分で処理しないメッセージは元々のプロシージャに任せることに します。(要するにおいしい所だけ取ってしまう。あなたの会社にも そんな人いませんか?)
では、具体的な方法を解説します。
と、まあこんな風に行います。GetWindowLong関数はすでにインスタンスハンドルを取得するところで 何回も出てきました。第19章を参照してください。1.GetWindowLongで元々のプロシージャのアドレス(FARPROC)を取得する。 具体的には、 FARPROC Org_WndProc; Org_WndProc = (FARPROC)GetWindowLong(サブクラス化するウィンドウのハンドル, GWL_WNDPROC); 2.サブクラス化の実行 SetWindowLong(サブクラス化するウィンドウのハンドル, GWL_WNDPROC, (LONG)新しいプロシージャ); 3.必要がなくなったらサブクラス化の解除 SetWindowLong(サブクラス化したウィンドウのハンドル, GWL_WNDPROC, (LONG)Org_WndProc); 4.新しいプロシージャの中では、 自分で処理しないものは、CallWindowProcで元のプロシージャに押しつける return (CallWindowProc(Org_WndProc, サブクラス化したウィンドウのハンドル, msg, wp, lp)); 自分で処理したものは、0を返します。
それと、16ビット版では少しやり方が異なります。 2の新しいプロシージャを直接登録するのではなく
というようにします。また、解除するときは元のプロシージャに戻して、 さらにFreeProcInstance((FARPROC)newproc);を実行します。32ビットの方が簡単ですね。FARPROC newproc, orgproc; newproc = MakeProcInstance((FARPROC)新しいプロシージャ, インスタンスハンドル); SetWindowLong(サブクラス化するウィンドウのハンドル, GWL_WNDPROC, (LONG)newproc);
では、具体的にプログラムを考えてみます。まず、エジットコントロール(ウィンドウ)は
2つありますから、これらをサブクラス化します。あたらいいプロシージャを
それぞれ、MyWndProc1, MyWndProc2とします。
MyWndProc1でWM_KEYDOWNメッセージを捕まえたら押されたキーを調べます。 もし、タブキーか下矢印ならフォーカスを次のウィンドウに移します。 それ以外のキーなら、元々のプロシージャに戻します。
MyWndProc2でも同じようなことをします。タブキーか、上矢印ならフォーカスを 変更します。
フォーカスの変更(セット)はSetFocus関数で行います。
戻り値は、直前のフォーカスを持っていたウィンドウのハンドルです。失敗は NULLを返します。HWND SetFocus( HWND hWnd // 新しくセットされるウィンドウのハンドル );
具体的なプログラムは次章でやります。今回はサブクラス化の概念の
解説でした。
[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]
Update May/22/1997 By Y.Kumei