○サブクラス化

ウィンドウズはすべてウインドウです(あたりまえかw)ですからボタンの中にもウィンドウプロシージャーがあり、その外のダイアログやウィンドウにもウィンドウプロシージャーがあります。
ボタンなどのコントロールはボタンの中のウィンドウプロシージャの中でボタンらしい動きを実現してそのメッセージを外のダイアログなどに送り出しているのです。

でもボタンなどの動きを変えたいときや、ボタンの外に送り出されないメッセージを処理したいときには元のプロシージャをすげ替える必要があります。


■まずはすげ替えるプロシージャ

コントロール内だけしか拾えないWM_LBUTTONDOWNメッセージを拾って、外に自作メッセージを送信します
この時にreturn 0;をすると元のプロシージャは呼び出されません。

#define WM_USER_MSG2	(WM_USER+101) //自作メッセージ
HWND hWnd;

WNDPROC DefaultProc;

LRESULT CALLBACK SubProc(HWND sub_hWnd,UINT msg,WPARAM wp,LPARAM lp){
	switch (msg){
		case WM_LBUTTONDOWN:
			//外に対して自作メッセージを送信 wpに自分のコントロールIDをセット
			SendMessage(hWnd,WM_USER_MSG2,GetDlgCtrlID(sub_hWnd),NULL);
			//元のプロシージャにメッセージを渡したくないときは return 0; する
			//return 0;
			break;
	}
	//元のプロシージャを呼び出す
	return CallWindowProc(DefaultProc,sub_hWnd,msg,wp,lp);
}


■コントロールのプロシージャを上のプロシージャにすげ替え

まずはウィンドウアプリケーションの通常のプロシージャを作成してその中で
ダイアログのIDC_EDIT1のプロシージャをすげ替えます。
すげ替えられるとEDIT1に対してマウスをクリックするとWM_USER_MSG2が飛んできます。


/ダイアログプロシージャー
BOOL CALLBACK DlgProc(HWND hDlg,UINT msg,WPARAM wp,LPARAM lp){
	switch (msg){
		case WM_INITDIALOG:
		{
			hWnd=hDlg;
			HWND hCont1=GetDlgItem(hDlg,IDC_EDIT1);
			DefaultProc=(WNDPROC)GetWindowLong(hCont1, GWL_WNDPROC);
			SetWindowLong(hCont1,GWL_WNDPROC,(LONG)SubProc);
		}
		break;
		case WM_USER_MSG2:
			printf("ID %d\n",wp);
			break;

この下もいろいろ続く・・・・


▲トップページ > Windows と C++