|
|
|
2-1-8. サブクラス化で広がる世界サブクラスは、コントロールなどの機能拡張に良く使用されます。ウィンドウの本来のプロシージャにフックを掛け、別のユーザが作成した関数に飛ばします。そしてその関数では、メッセージを追加や横取りして、機能を拡張または、統合して目的に添った改変を行ないます。サブクラスは、ウィンドウごとに管理しているプロシージャアドレスを変更します。よって対象のウィンドウしかその機能は搭載されません。以下の方法でサブクラス化を行ないます。
サブクラス化の例 // コンボボックスのオリジナルのプロシージャを保存
static WNDPROC fnCbProc = NULL;
// 指定のコンボボックスにサブクラスを設定する。
VOID SetSubClass(HWND hCombo)
{
if (fnCbProc == NULL)
fnCbProc = (WNDPROC)GetWindowLong(hCombo,GWL_WNDPROC);
SetWindowLong(hCombo,GWL_WNDPROC,(LONG)CbProc);
}
// サブクラス化のためのウィンドウプロシージャ
LRESULT CALLBACK CbProc(HWND hWnd,UINT uMsg
,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_LBUTTONDOWN:
{
if (ある条件)
{
SendMessage(hMainWnd,WM_COMMAND,
MAKEWPARAM(IDM_NEWCMD,0),0);
return 0;
}
break;
}
case WM_MOUSEMOVE:
{
if (ある条件)
{
SetCursor(LoadCursor(hInstance,IDC_FINGER));
return 0;
}
break;
}
case WM_CHAR:
{
if ((TCHAR)wParam == VK_RETURN)
{
SendMessage(hMainWnd,WM_COMMAND
,MAKEWPARAM(IDM_NEWCMD,0),0);
return 0;
}
break;
}
}
return CallWindowProc(fnCbProc,hWnd,uMsg,wParam,lParam);
}
この例では、コンボボックスを左クリックした時と、[Enter]キーを押した時に、WM_COMMAND メッセージを発行して、コマンドの実行を行ないます。またこのコントロールの上をマウスカーソルが移動する時に、ある条件では指カーソルに変更します。
されプログラミングですが、まずコンボボックスを作成した後にそのハンドルをパラメータにして、SetSubClass 関数をコールします。ここでは、GetWindowLong 関数で、オリジナルのプロシージャを得て、SetWindowLong で新しいプロシージャを設定します。なお複数のコンボボックスにサブクラスを設定する場合は、2つ目以降は、GetWindowLong の必要はありません。もし重複してサブクラス化されている可能性がある時は、コンボボックスごとに、オリジナルのプロシージャを管理する必要があります。 これらの例のフックの場合は、オリジナルのプロシージャの前に行なっています。そして、フック内容によっては、オリジナルのプロシージャの処理を行なったり、行なわなかったりします。しましまれに、オリジナルのプロシージャの処理を行なった後に、フックをしたいことがあります。
|