EternalWindows
コントロールパネル / cplファイルの関数

今回は、cplファイルを作成するための手順を押さえることにします。 そのためにはまず、cplファイルが何をするべきなのかを考えなければなりません。 既に述べてきたようにcplファイルの正体はDLLであり、 その内部に埋め込まれているアイコンや文字列が コントロールパネルに表示されることになります。 これらを表示できるのは一重に、cplファイルをロードしたプロセスが 適切なメッセージをcplファイルに送っているからであり、 cplファイルがそのメッセージをCPlApplet関数で処理しているからなのです (CPlAppletは、Contorl Panel Applet のことで、シーピーエルアプレットと読みます)。

LONG CPlApplet(
    HWND hwndCPl,
    UINT uMsg,
    LPARAM lParam1,
    LPARAM lParam2
);

hwndCPlは、cplファイルをロードしたプロセスのメインウインドウのハンドルです。 これは、ダイアログを表示するときに親ウインドウとして利用することができます (hwndCPlを指定してGetWindowModuleFileNameのような関数を呼び出した場合、 それに関連付けられているEXEがrundll32.exeだと分かりますが、 どうやらこのウインドウは非表示になっているようです)。 uMsgは、cplファイルをロードしたプロセスから送られてきたメッセージです。 これらのメッセージはCPLメッセージと呼ばれ、以下のようなものが定義されています。

メッセージ 意味
CPL_INIT cplファイルをロードしたプロセスが、最初に送ってくるメッセージ。 このメッセージで、cplファイル内で扱うことになるデータを初期化する。 初期化に成功した場合は0でない値を返す。 lParam1、lParam2は共に0。
CPL_GETCOUNT CPL_INITの後に送られるメッセージ。 cplファイルがサポートするダイアログの数を返すことになる。 実は、cplファイルは複数のアイコンをコントロールパネルに表示することができ、 そのようなときは個々のアイコンに応じて違ったダイアログを表示するはずである。 こうなった場合、最終的にダイアログを表示するときには、 どのダイアログを表示すればよいかという情報が必要になるが、 このメッセージで返した値がダイアログ番号の算出に利用されることにより、 CPL_INQUIREとCPL_DBLCLK、CPL_STOPでダイアログを識別できる。 lParam1、lParam2は共に0。
CPL_INQUIRE CPL_GETCOUNTの後に送られるメッセージ。 送られる数は、CPL_GETCOUNTで返した値に比例する。 このメッセージはcplファイルをロードしたプロセスが、 アイコンと文字列を問い合わせるために使われる。 lParam1はダイアログ番号、lParam2はCPLINFO構造体へのアドレス。 ダイアログ番号はゼロベースの値であり、 最大値はCPL_GETCOUNTで返した値から1引いたものである。
CPL_DBLCLK ユーザーがアイコンをクリックしたときに送られるメッセージ。 このメッセージでダイアログを表示することになる。 lParam1はダイアログ番号、lParam2はアプリケーション定義値。
CPL_STOP CPL_DBLCLKで制御を返したときに送られる。 このメッセージが送られたということは、既にダイアログが閉じられており、 ダイアログ番号を確認して、対応するダイアログの後始末処理を行うことになる。 lParam1はダイアログ番号、lParam2はアプリケーション定義値。
CPL_EXIT cplファイルをロードしたプロセスが最後に送るメッセージ。 一般には、FreeLibaryを呼び出す前にこのメッセージが送られる。 cplファイル内では、このメッセージでcplファイル全体の後始末を行う。 ダイアログのために使用したメモリの開放等は、CPL_STOPで行うべきである。 lParam1、lParam2は共に0。

個々のメッセージの意味については実際にコードを書くときにも説明するため、 今の段階で理解しておく必要はありません。 また、一般にはサポートするダイアログは1つでしょうから、 ダイアログ番号についても特に気にする必要はありません。 しかし、CPL_INQUIREメッセージについては、特別に述べておくことがあります。 CPL_INQUIREメッセージのとき、lParam2はCPLINFO構造体へのアドレスとなっており、 個々のメンバはコントロールパネルに表示すべきリソースの識別子を要求します。

typedef struct tagCPLINFO
{
    int         idIcon;
    int         idName;
    int         idInfo;
    LONG_PTR    lData;
} CPLINFO, *LPCPLINFO;

idIconには、アイコンの識別子を指定します。 この識別子で表されるアイコンがコントロールパネルに表示されます。 idNameは、文字列の識別子を指定します。 この文字列は、コントロールパネルでアイコンの隣に表示されます。 idInfoにも文字列の識別子を指定します。 この文字列は、コントロールパネルでアイコンの上にカーソルを乗せたとき、 ツールチップとして表示されます。 lDataは、プログラムが自由に扱ってよいとされるメンバです。 ここで指定した値が、CPL_DBLCLKとCPL_STOPのlParam2となります。

識別子を代入するというのは、アイコンや文字列をリソースとして 作成しなければならないことを意味しています。 そのため、アイコン1つと文字列2つ、 CPL_DBLCLKのときに表示するダイアログとを合わせて、 最低でも計4つリソースを用意することになるでしょう。

CPlAppletはEXEから呼び出される関数であるため、エクスポートしなくてはなりません。 ここでのエクスポート方法は、__declspecキーワードを使わずに、 必ずdefファイルによるエクスポートを採用するべきです。 そのため、開発環境にdefファイルを追加する作業も必要になります。 また、作成したDLLの拡張子を.cplに変更し、 それをc:\WINDOWS\system32に移動させなければなりません。 このフォルダにcplファイルを置くことにより、コントロールパネルに反映されます。


戻る