- ベストアンサー
VC++2005でWM_CTLCOLORDLGを使用してダイアログの背景色を切り替える方法
- WIN32、VC++2005で開発中の方に質問です。WM_CTLCOLORDLGを使用して、複数のダイアログに異なる背景色を設定する方法を教えてください。
- 質問者さんは、WM_CTLCOLORDLGを使用してダイアログの背景色を設定しようとしていますが、IF文の中に行くことができません。なぜIF文の中に行かないのか、そして他の方法はありますか?
- ボタンコントロールではちゃんと判別してくれましたが、WM_CTLCOLORDLGではなぜかiの値が0になってしまいます。WIN32初心者の方でもわかりやすい方法を教えてください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。 >>「i」には0が入ってしまうんですが、なぜでしょうか? ハンドルからIDが取り出せるのは、コントロールだけの様です。 >>ほかにいい方法ありませんか? SetWindowLong()/GetWindowLong()で自由データに構造体のポインタ等を渡してプロシージャの中で参照するやり方が手っ取り早いです。 その為にはGWL_USERDATAフラグを使用しますが、ダイアログの場合はDWL_USERフラグの方を使用します。 http://msdn.microsoft.com/ja-jp/library/cc364760.aspx >>return (BOOL)CreateSolidBrush( RGB( 255,170,255 )); ブラシハンドルの削除責任はダイアログ側に有ります。此のやり方ですと、リソースが開放されないので要注意です。 以下参考程度に。 //ダイアログのブラシとIDのペア struct DialogData { explicit DialogData(UINT ui = 0, HBRUSH h = 0) : uiID(ui), hBrush(h) { } UINT uiID; HBRUSH hBrush; }; //--------------------------ダイアログプロシージャ内-------------------------------- case WM_INITDIALOG : { //ダイアログハンドルにlParamをセットする ::SetWindowLong(hDlg, DWL_USER, lParam); return TRUE; } case WM_CTLCOLORDLG: { //ハンドルを取る const HWND hDlg = (HWND)lParam; //ハンドルにセットしたポインタを取る const DialogData* p = (DialogData*)::GetWindowLong(hDlg, DWL_USER); //一応確認 if(p) { //背景用のブラシを返す return (BOOL)p->hBrush; } break; } case WM_DESTROY : { //ハンドルがなくなるので、関連付けた動的メモリを開放する DialogData* p = (DialogData*)::GetWindowLong(hDlg, DWL_USER); if(p) { //背景用のブラシハンドルを消去 ::DeleteObject(p->hBrush); //動的メモリを開放 delete p; //無いとは思うが、念のため ::SetWindowLong(hDlg, DWL_USER, 0); } return FALSE; } //------------------------------------------------------------------------------------- //--------------------------------ダイアログを作成する時--------------------------------- //この動的メモリをプロシージャに送り届ける DialogData* p = new DialogData(IDD_DIALOG1, ::CreateSolidBrush( RGB( 255,170,255 ))); //最後のパラメータに指定すると、WM_INITDIALOGのlParamで受け取る事が出来ます HWND hDlg = ::CreateDialogParam(hInst, MAKEINTRESOURCE(p->uiID), 0, &::DialogProc, (LPARAM)p); //---------------------------------------------------------------------------------- ダイアログを作成すると同時にデータを送り届ける為には以下を使用します。 「CreateDialogParam()」モードレスダイアログの場合 http://msdn.microsoft.com/ja-jp/library/cc410696.aspx 「DialogBoxParam()」モーダルダイアログの場合 http://msdn.microsoft.com/en-us/library/ms645465(VS.85).aspx
その他の回答 (2)
- aris-wiz
- ベストアンサー率38% (96/252)
>「i」には0が入ってしまうんですが、なぜでしょうか? この関数には欠陥があります。 この関数はエラー時0を返すということになっていますが 関数の成功時に返却する要求したデータフラグに対する 32 ビット値のなかに0も含まれています。 故にこの関数のエラー処理は戻り値ではなく、 SetLastError及びGetLastErrorによる 拡張エラー情報を使う必要があります LONG Ret; SetLastError(0); Ret = GetWindowLong( (HWND)lParam, GWL_ID ); if ( Ret==0 && (GetLastError()!=0)){ //エラー処理 } まずはこれで本当にエラーが無いのか、 エラーならどういたエラーなのか調べてみてください。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス >ダイアログが複数あり各々に違う背景色を着けたい場合、 ↑ これはダイアログのプロシージャが共通なのですか? どの道 GetWindowLong の GWL_ID は 0(HMENUの値)になってしまうため 質問にある方法では判定できないでしょう。 GWL_ID はコントロールID を取得するときしか使えない。 (ダイアログのIDではないため) ・判定方法1 (1)SetWindowLong 関数(GWL_USERDATA)を使って ID をセット (2)GetWindowLong 関数(GWL_USERDATA)を使って ID を取得/判定 または (1)SetProp 関数(プロパティ)を使って ID をセット (2)GetProp 関数(プロパティ)を使って ID を取得/判定 という組み合わせを利用します。 ・判定方法2 グローバル変数(ハンドルの配列)を用意して WM_CTLCOLORDLG 内で ウインドウ・ハンドルを使って分岐する方法もあります。 こちらの方が初心者向けです。 ・あと気になった点。 >return (BOOL)CreateSolidBrush( RGB( 255,170,255 )); ↑ これはマズイです。 WM_CTLCOLORDLG 内などでは HBRUSH 型の変数に CreateSolidBrush 関数の戻り値を 保存しておき、return のときにその保存された変数を使って戻します。 こうしないとメモリリークとなり再描画がおかしくなります。 (実行して画面の再描画がある回数を越えると表示がおかしくなる) サンプル: // 背景ブラシのグローバル変数 static HBRUSH gBrushTable[ MAX_DIALOG ]; ←ダイアログの最大値 static INT gMaxDialog; ←ダイアログの生成個数 // 共通なプロシージャ関数 BOOL CALLBACK DialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ){ case WM_INITDIALOG: SetWindowLong( hDlg, GWL_USERDATA, (LONG)lParam ); return TRUE; case WM_CLOSE: { INT nIDD = (INT)SetWindowLong(hDlg,GWL_USERDATA); DeleteObject( gBrushTable[nIDD] ); gBrushTable[ nIDD ] = NULL; EndDialog( hDlg, IDOK ); return TRUE; } case WM_CTLCOLORDLG: return gBrushTable[ SetWindowLong(hDlg,GWL_USERDATA) ]; default: return FALSE; } } // ダイアログ1の生成 INT nID = 1; if ( CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD),hWndParent,DialogProc,nID) != NULL ){ gBrushTable[ nID ] = CreateSolidBrush( RGB(255,170,255) ); gMaxDialog++; } // ダイアログ2の生成 INT nID = 2; if ( CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD),hWndParent,DialogProc,nID) != NULL ){ gBrushTable[ nID ] = CreateSolidBrush( RGB(255,200,0) ); gMaxDialog++; } こんな感じでどうでしょうか。