|
|
||||||||||||||||
|
2-4-9. MDI子ウィンドウのプロシージャMDI子ウィンドウ(ドキュメントウィンドウ)のウィンドウプロシージャは、普通のプロシージャとはやや異なります。MDI子ウィンドウのプロシージャ MDIの子ウィンドウのウィンドウプロシージャの例を以下に示します。色が違う部分がMDIに関連した部分です。ApMdisysには、2つのMDI子ウィンドウのウィンドウプロシージャがあります。ApHelloのプロシージャは簡単なので、ここではApReditのプロシージャを提示します。LRESULT CALLBACK ReditProc(HWND hWnd,UINT uMsg
,WPARAM wParam,LPARAM lParam)
{
HWND hEdit = (HWND)GetWindowLong(hWnd,0);
switch(uMsg)
{
//
// MDI子ウィンドウの新規作成で、各種の初期化を行なう。
//
case WM_CREATE:
{
LPCREATESTRUCT pcs;
LPMDICREATESTRUCT pmdic;
HINSTANCE hInst;
LPSTR pFile;
pcs = (CREATESTRUCT *)lParam;
pmdic = (MDICREATESTRUCT *)pcs->lpCreateParams;
pFile = (LPSTR)pmdic->lParam;
hInst = (HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE);
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"RICHEDIT",NULL,
WS_CHILD|WS_BORDER|WS_VISIBLE|WS_VSCROLL|
ES_AUTOVSCROLL|ES_MULTILINE|ES_NOHIDESEL,
0,0,0,0,
hWnd,(HMENU)ID_RTF,hInst,NULL);
SetWindowLong(hWnd,0,(LONG)hEdit);
: (他のコード)
return 0;
}
//
// このウィンドウのクローズに伴う破棄で後処理とメモリ開放
//
case WM_DESTROY:
{
if (hEdit) DestroyWindow(hEdit);
break;
}
//
// ウィンドウをリサイズしたのでRTFコントロールも変更する
//
case WM_SIZE:
{
if (hEdit)
MoveWindow(hEdit,0,0,
LOWORD(lParam),HIWORD(lParam),TRUE);
break; // return 0;はダメ
}
//
// このウィンドウにフォーカスが移った
//
case WM_SETFOCUS:
{
if (hEdit) SetFocus(hEdit);
break;
}
//
// このMDI子ウィンドウがアクティブなため、固有のメニューを設定する。
//
case WM_MDIACTIVATE:
{
HMENU hMenu;
if ((HWND)lParam == hWnd)
{
hMenu = GetSubMenu(hMenuRedit,IDMC_WINDOW+1);
SendMessage(hWndClient,WM_MDISETMENU
,(WPARAM)hMenuRedit,(LPARAM)hMenu);
}
else
{
hMenu = GetSubMenu(hMenuInit,IDMC_WINDOW);
SendMessage(hWndClient,WM_MDISETMENU
,(WPARAM)hMenuInit,(LPARAM)hMenu);
}
DrawMenuBar(hWndMain);
return 0;
}
}
return DefMDIChildProc(hWnd,uMsg,wParam,lParam);
}
MDI子ウィンドウのプロシージャの省略時の処理関数 MDI子ウィンドウのプロシージャの省略時の処理関数は、DefMDIChildProc です。通常は、DefWindowProc 関数を使用しますので間違わないでください。また、以下のウィンドウ管理メッセージは、アプリケーションが処理した場合でも、DefMDIChildProc 関数に渡さなければいけません。上記のコードの、WM_SIZE で break しているのは理由があります。
CreateMDIWindow 関数の最後パラメータの lParam の受け取り CreateMDIWindow 関数の最後パラメータである、lParam は,WM_CREATE で受け取ります。しかしその方法ややや複雑です。まず、ReditProc のlParam は、LPCREATESTRUCT 構造体を指します。そしてそのメンバである、lpCreateParams は、LPMDICREATESTRUCT 構造体を指します。LPMDICREATESTRUCT 構造体の lParam メンバが、CreateMDIWindow 関数の最後パラメータで渡した値になります。ここでは分かり易くするために、3行になっていますが、以下の様にキャスティングしても結構です。MDICREATESTRUCT *pmdic; pmdic = (MDICREATESTRUCT *)((CREATESTRUCT *)lParam)->lpCreateParams; pFile = (LPSTR)pmdic->lParam;ところで、ApMdisysでは、ファイルメニューの「文章ウィンドウの新規作成」コマンドでは、NULLを渡し、「開く」コマンドではユーザが選択したファイル名を渡しています。上記のコードでは省略されていますが、pFile がNULLで無い時は、そのファイルをオープンして、リッチテキストコントロールにロードしています。 ウィンドウ補足メモリブロックの活用 リッチテキストコントロールを作成して、ウィンドウハンドルを得ますが、そのハンドルを、SetWindowLong(hWnd,0,(LONG)hEdit)関数で、補足メモリブロックに設定します。またプロシージャの一番上に、HWND hEdit = (HWND)GetWindowLong(hWnd,0); と1行あります。これは、初期化文ですので、ReditProc が実行される度に、GetWindowLong 関数をコールして、このハンドルを得ます。プロシージャはシステムのパフォーマンスに関わりますので、こんな文でよけいな時間を掛けたくないのですが、スピードよりサイズを重視しました。この文1つで、hEdit を必要とするすべてのメッセージに対応できる利点は見逃せません。WM_MDIACTIVATE メッセージ MDIの子ウィンドウをクリックしたりして、アクティブが移動すると、対象のウィンドウプロシージャに、WM_MDIACTIVATE メッセージが発生します。まず非アクティブになるウィンドウに、wParam にウィンドウハンドルを渡して発生します。次にアクティブになるウィンドウに、lParam にウィンドウハンドルを渡して発生します。よってアクティブになったら、ApReditの場合は、書式メニューを、ApHelloの場合は、表示メニューを追加します。そのための処理が、WM_MDISETMENU メッセージをMDIクライアントウィンドウに送信することで実行されます。
|