プログラミング工房 > WideStudio > Tips >

ウィンドウのサブクラス化によるメッセージ処理のカスタマイズ

(2006/04/27更新)

 WideStudioはマルチプラットフォーム間で移植性の高いソースを書けることがひとつのウリですが、かゆいところに手が届く実用的なソフト作ろうとするとどうしてもプラットフォーム依存のコードを入れたくなってしまうことがあります。

 例えばWindowsの場合、WideStudioのデフォルトのメインウィンドウクラスでは扱えない(扱わない)ウィンドウメッセージを処理するためにウィンドウのサブクラス化を行いたいというケースです。

 Windowsでのウィンドウのサブクラス化とは、ウィンドウがメッセージを受け取ったときにメッセージ内容の識別とその結果に応じた処理を行うために呼び出されるウィンドウプロシージャというコールバック関数を、新しく定義したものに置き換える(再登録する)ことを意味します。(以後の「ウィンドウプロシージャ」はすべてWindows用語のそれを指します)


新しいウィンドウプロシージャの定義とウィンドウプロシージャ置き換え処理の記述

 ウィンドウのサブクラス化をコーディングする簡単な例としては、メインウィンドウのInitializeトリガから呼び出されるプロシージャ関数のファイル(ファイルが存在しなければ新規イベントプロシージャを作成する)に以下のようなコードを追加する方法が考えられます。(以後の「プロシージャ関数」はすべてWideStudio用語のそれを指します)


 >> サンプル1

 上のコードではまず、ウィンドウプロシージャの置き換え時に必要なウィンドウハンドルを得るためのクラスを定義したヘッダファイル"WSDdev.h"と、Windows独自のデータ型やAPIを使えるようにするためのヘッダファイル"windows.h"をインクルードし(このファイルは別途用意する必要はありません)、次に新しいウィンドウプロシージャで処理するメッセージを定義しています。メッセージの数が多くなる場合には別のヘッダファイル内に定義してそれをインクルードしてもかまいません。

 その次の変数"MainWnd_EventProc"は、置き換え前のウィンドウプロシージャの関数ポインタを格納するためのものです。新しいウィンドウプロシージャで処理しないメッセージは必ず古いウィンドウプロシージャに渡して処理させなければなりません。古いウィンドウプロシージャのポインタは、最後に説明するウィンドウプロシージャの置き換え処理時に取得することができます。

 最後の行は新しいウィンドウプロシージャのプロトタイプ宣言です。


 >> サンプル2

 2つ目のコードは新しいウィンドウプロシージャの定義です。戻り値と引数の型は固定です。関数内では受け取ったメッセージの内容に応じた処理を行います。ここで処理しないメッセージは"CallWindowProc" APIを使って置き換え前のウィンドウプロシージャに渡して処理してもらいます。


 >> サンプル3

 最後のコードはウィンドウプロシージャの置き換え処理です。WideStudioが作成したプロシージャ関数内に記述します。今回の例ではメインウィンドウのプロシージャ関数ファイルにコードを追加していると仮定していますから、変数"object"はメインウィンドウ自身を指しています。

 ここではWideStudioのライブラリに含まれるクラスとそのメソッドを利用してメインウィンドウのウィンドウハンドルを取得し、それを引数にしてWin32 APIの"SetWindowLong"関数を実行してメインウィンドウのウィンドウプロシージャを再登録しています。変数に代入された"SetWindowLong"関数の戻り値は上で説明した新しいウィンドウプロシージャ内で使われます。


このテクニックの使い道

 このテクニックを利用すると、例えばFootyテキストエディタコントロールなどの独自のメッセージ処理が必要なライブラリをWideStudio製アプリケーションで使えるようになります。


(付記)

 このページを作るにあたっては、WideStudioメーリングリストの過去ログ、およびTaizouKun brand officeさんが公開されているプログラム"MyHelp"のソースを参考にさせていただきました。