WIN32、VC++2005で開発中です。
ダイアログが複数あり各々に違う背景色を着けたい場合、
下記のようなプログラムを書いたのですが、IF文の中に行けません。
「i」には0が入ってしまうんですが、なぜでしょうか?
ほかにいい方法ありませんか?
ボタンコントロールではちゃんと判別してくれました。
case WM_CTLCOLORDLG:
i = GetWindowLong( (HWND)lParam, GWL_ID );
if ( i == IDD_ICHI_D ) { //位置出し画面描画
return (BOOL)CreateSolidBrush( RGB( 255,170,255 ));
}
break;
WIN32初心者なのでなるべくわかりやすくご教授お願いします。
No.3ベストアンサー
- 回答日時:
こんにちは。
>>「i」には0が入ってしまうんですが、なぜでしょうか?
ハンドルからIDが取り出せるのは、コントロールだけの様です。
>>ほかにいい方法ありませんか?
SetWindowLong()/GetWindowLong()で自由データに構造体のポインタ等を渡してプロシージャの中で参照するやり方が手っ取り早いです。
その為にはGWL_USERDATAフラグを使用しますが、ダイアログの場合はDWL_USERフラグの方を使用します。
http://msdn.microsoft.com/ja-jp/library/cc364760 …
>>return (BOOL)CreateSolidBrush( RGB( 255,170,255 ));
ブラシハンドルの削除責任はダイアログ側に有ります。此のやり方ですと、リソースが開放されないので要注意です。
以下参考程度に。
//ダイアログのブラシとIDのペア
struct DialogData
{
explicit DialogData(UINT ui = 0, HBRUSH h = 0) : uiID(ui), hBrush(h)
{}
UINTuiID;
HBRUSHhBrush;
};
//--------------------------ダイアログプロシージャ内--------------------------------
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 …
「DialogBoxParam()」モーダルダイアログの場合
http://msdn.microsoft.com/en-us/library/ms645465 …
No.2
- 回答日時:
>「i」には0が入ってしまうんですが、なぜでしょうか?
この関数には欠陥があります。
この関数はエラー時0を返すということになっていますが
関数の成功時に返却する要求したデータフラグに対する
32 ビット値のなかに0も含まれています。
故にこの関数のエラー処理は戻り値ではなく、
SetLastError及びGetLastErrorによる
拡張エラー情報を使う必要があります
LONG Ret;
SetLastError(0);
Ret = GetWindowLong( (HWND)lParam, GWL_ID );
if ( Ret==0 && (GetLastError()!=0)){
//エラー処理
}
まずはこれで本当にエラーが無いのか、
エラーならどういたエラーなのか調べてみてください。
No.1
- 回答日時:
★アドバイス
>ダイアログが複数あり各々に違う背景色を着けたい場合、
↑
これはダイアログのプロシージャが共通なのですか?
どの道 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++;
}
こんな感じでどうでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript 追加ボタンを押した際に ok ボタンを押した場合のみ入力値が追記されるようにしたいです 6 2022/05/29 09:57
- C言語・C++・C# C言語 3 2022/11/09 13:27
- JavaScript switch文のswitch(n)の部分を複数の値にするか、if文に変えてほしいです。 1 2022/07/27 17:18
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Visual Basic(VBA) 列と行の名前(重複あり)が交差するセルに、データを入力したい 2 2022/06/25 22:42
- Visual Basic(VBA) VBAの繰り返し処理について教えてください。 3 2022/08/02 13:21
- Java java 引数 戻り値のあるメソッド 3 2023/02/12 06:23
- JavaScript HTMLでJavaScriptを使ってパスワードの強化判定のプログラムを作成しています。 一通り作っ 2 2022/10/19 01:41
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- Excel(エクセル) vba 同じブック内での転記について 4 2023/01/15 14:42
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
vbaから他のアプリを終了
-
Excel VBA で外部アプリケーシ...
-
メッセージボックスの選択ボタ...
-
VBA 複数セルが空白なら印刷さ...
-
windowsメールスロットについて...
-
他のウィンドウのボタンを自動...
-
チェックボックスのキーダウン...
-
SetWindowText関数について
-
msgboxの表示位置
-
有効でないウインドウハンドル...
-
VB6でシャットダウン、ログオフ...
-
コールバック関数とは…(C言語)
-
メッセージハンドラ
-
点滅で知らせる方法
-
デスクトップ上のアイコンの位...
-
システム例外のメッセージを変...
-
エクセルで作った新しいウイン...
-
グラフの交点の求め方(Excel)
-
「アイテムは収集されました」...
-
フォントの大きさ
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
vbaから他のアプリを終了
-
他のウィンドウのボタンを自動...
-
メッセージボックスの選択ボタ...
-
msgboxの表示位置
-
VBAでコントロールのハンドルを...
-
メッセージハンドラ
-
SetWindowText関数について
-
WM_NCLBUTTONUPについて
-
VB.netでFindWindowExやると・...
-
デスクトップ上のアイコンの位...
-
点滅で知らせる方法
-
SendMessage で ESC など
-
チェックボックスのキーダウン...
-
キーボード・フックのアプリを...
-
マウスフックについて
-
DEVICECHANGE() の受け取り
-
CloseHandle()
-
システム例外のメッセージを変...
-
VB6でシャットダウン、ログオフ...
-
Excel VBA で外部アプリケーシ...
おすすめ情報