
ダイアログボックスのボタンコントロールのフォーカスについて
教えて下さい。
モーダルダイアログにボタン「OK」を一つ貼り付けて
それを「標準のボタン」(BS_DEFPUSHBUTTON)として作成したのですが
ダイアログ表示直後は下画像(1)のようになってエンターキーを押しても
反応しません。何度かカーソルキーを押すとようやく(2)のように
ボタンに枠線がついてエンターで押せるようになるのですが
ダイアログ表示直後に(2)のようにするにはどうするべきでしょうか?
ダイアログのコールバック・プロシージャ(WM_INITDIALOG部分でボタン作成)
LRESULT CALLBACK SettingWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
switch (msg){
case WM_INITDIALOG:
CreateWindowEx(0x00000000,"BUTTON","OK",
WS_CHILD |WS_VISIBLE| WS_TABSTOP | BS_DEFPUSHBUTTON,
16,16,80,21,hWnd,(HMENU)IDOK,GetModuleHandle(0),0);
return TRUE;
}
return FALSE;
}

No.4ベストアンサー
- 回答日時:
>但し付けていただいたリンク先の説明によるとTRUEを返す場合、
>「最初の WS_TABSTOP をもつコントロールにフォーカスがセットされます。」
>ということから考えれば、TRUE戻しでもこのボタンにフォーカスが当たっても良い筈です。
>この場合何故そうならないのかはまだ分かりません。
WM_INITDIALOGのWPARAMに「フォーカスが当たる予定のコントロールID」が入って呼ばれますが、
WM_INITDIALOGをOSが発行した時点ではWM_INITDIALOGのハンドラ内で生成されるコントロールは「まだ生成されていない」ですし、付与されるコントロールIDも不明です。
となると、WM_INITDIALOGのハンドラ内で生成したコントロールにWS_TABSTOPが付いていてもその時点ではどうしようもありません。
BS_DEFPUSHBUTTONが効くのも、WM_INITDIALOGが発行される前、OS側がWM_INITDIALOGのWPARAMに設定するコントロールIDを決定するために精査するとき…と言うことなのではないでしょうか。
この回答への補足
お礼の文面の訂正を。
>>WM_INITDIALOG内でコントロールを作るなということですね。
WM_INITDIALOG内でコントロールを作るなというより
もしそこで作った場合は自分でフォーカスを合わせる、ということだと思います。
それから
>> またBS_PUSHBUTTONにした上で「フォーカス当てのFALSE戻し」にした時は
この場合は逆にフォーカスが当たらないままでした。
これは「フォーカスが当たらない」のではなくて、図(1)の状態になる(ボタンに実線枠が
付かずエンター押しが効かない)の間違いでした。
「点線」のフォーカスそのものは当たっているものと思います。
以上を訂正させて頂きます。申し訳ありません。
なるほど。確かに説明されている通りです。
解説を貰ってストンと自分でもようやく理解出来ました。
>>WM_INITDIALOGをOSが発行した時点ではWM_INITDIALOGのハンドラ内で生成されるコントロールは「まだ生成されていない」ですし、付与されるコントロールIDも不明です。
まさにそれが原因で起こっていた現象だと思います。
WM_INITDIALOG内でコントロールを作るなということですね。
リソースエディタで作成すれば大丈夫なんでしょうか?
有難うございます。またよろしくお願いします。
No.3
- 回答日時:
ダイアログボックスのクライアント内(何かのコントロール)にフォーカスが設定されていれば、
EnterキーでIDOK、ESCキーでIDCANCELが飛んでくるかと思われますが…。
ということで、作成するボタンのIDは別にしないと、デフォルト動作でIDOKが飛んでいるのかどうか判らなくなると思われます。
ダイアログボックスの最初のフォーカスはシステム側で設定されてきます。
# WM_INITDIALOGのWPARAMにコントロールIDが設定されています。
WM_INITDIALOGのメッセージ処理中に、最初のフォーカスを変更したい場合は、#1さんの掲示されているSetFocus()を使用し、
WM_INITDIALOGの応答としてFALSEを返却する必要があります。
http://wisdom.sakura.ne.jp/system/winapi/win32/w …
ダイアログプロシージャからの返却の場合、SetWindowLong()でDWL_MSGRESULTに設定して返すことになりますが…
WM_INITDIALOGの場合はそのまま返却でよい…みたいです。
http://msdn.microsoft.com/en-us/library/ms645428 …
この回答への補足
ここまでのテスト結果を。
IDをIDOKにしてはいけないという所はまだ理解が追いついてないのですが
とりあえずIDを「CommandButton1」などに替えてみてテストしてみました。
ただその時点ではまだ現象は変わりませんでした。
次にその設定のまま「SetFocusでフォーカスをボタンに当ててFALSE戻し」
にすると、これは上手くフォーカスが当たりエンター押しも効きました。
但し付けていただいたリンク先の説明によるとTRUEを返す場合、
「最初の WS_TABSTOP をもつコントロールにフォーカスがセットされます。」
ということから考えれば、TRUE戻しでもこのボタンにフォーカスが当たっても良い筈です。
この場合何故そうならないのかはまだ分かりません。
最後にBS_DEFPUSHBUTTONを「BS_PUSHBUTTON」に替えてやってみたのですが
これはTRUE戻しでも上手く行きました。だとするとDEFPUSHBUTTONは使えないの
かな、とも思ってしまうのですが、、、
またBS_PUSHBUTTONにした上で「フォーカス当てのFALSE戻し」にした時は
この場合は逆にフォーカスが当たらないままでした。
ちょっと迷いそうになってますが、もう少しテストを続けてみます。
有難うございます。書いて頂いたコード、リンクを参考にさせてもらいながら
これからこちらでもテストしたいと思います。少し時間を貰って、また報告します。
No.2
- 回答日時:
XP で試してみたところ、なぜかよくわかりませんが、BS_DEFPUSHBUTTON ではなく BS_PUSHBUTTON にするとダイアログ表示直後でも ENTER キーで反応しました。
ただし、概観はやはり BS_DEFPUSHBUTTON ではなく BS_PUSHBUTTON のものです。この回答への補足
ここまでのテスト結果を。
IDをIDOKにしてはいけないという所はまだ理解が追いついてないのですが
とりあえずIDを「CommandButton1」などに替えてみてテストしてみました。
ただその時点ではまだ現象は変わりませんでした。
次にその設定のまま「SetFocusでフォーカスをボタンに当ててFALSE戻し」
にすると、これは上手くフォーカスが当たりエンター押しも効きました。
但し付けていただいたリンク先の説明によるとTRUEを返す場合、
「最初の WS_TABSTOP をもつコントロールにフォーカスがセットされます。」
ということから考えれば、TRUE戻しでもこのボタンにフォーカスが当たっても良い筈です。
この場合何故そうならないのかはまだ分かりません。
最後にBS_DEFPUSHBUTTONを「BS_PUSHBUTTON」に替えてやってみたのですが
これはTRUE戻しでも上手く行きました。だとするとDEFPUSHBUTTONは使えないの
かな、とも思ってしまうのですが、、、
またBS_PUSHBUTTONにした上で「フォーカス当てのFALSE戻し」にした時は
この場合は逆にフォーカスが当たらないままでした。
ちょっと迷いそうになってますが、もう少しテストを続けてみます。
有難うございます。書いて頂いたコード、リンクを参考にさせてもらいながら
これからこちらでもテストしたいと思います。少し時間を貰って、また報告します。
No.1
- 回答日時:
こんばんは。
う~む、ボタンハンドルを指定してSetFocus()APIを呼び出しても無理でしょうか。
試して見ましたが、SetFocus()APIなしでも、特に問題なく反応しています。
// test.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include"stdafx.h"
#include<windows.h>
#include"resource.h"
//ダイアログ
INT CALLBACK SettingWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_INITDIALOG:
{
HWND hButton = ::CreateWindowEx(0, TEXT("BUTTON"), TEXT("OK"),
WS_CHILD |WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
16, 16, 80, 21, hWnd, (HMENU)IDOK, ::GetModuleHandle(NULL), 0);
//取りあえず呼んでみる
::SetFocus(hButton);
return TRUE;
}
case WM_COMMAND:
if(wp == IDOK)
{
::EndDialog(hWnd, FALSE);
}
break;
}
return FALSE;
}
//ウィンドウ
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
//左ボタンクリックでダイアログを出す
case WM_LBUTTONDOWN:
::DialogBox(::GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), hWnd, &::SettingWndProc);
return 0;
case WM_NCDESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
文字数制限により、WinMain()を省略。
この回答への補足
ここまでのテスト結果を。
IDをIDOKにしてはいけないという所はまだ理解が追いついてないのですが
とりあえずIDを「CommandButton1」などに替えてみてテストしてみました。
ただその時点ではまだ現象は変わりませんでした。
次にその設定のまま「SetFocusでフォーカスをボタンに当ててFALSE戻し」
にすると、これは上手くフォーカスが当たりエンター押しも効きました。
但し付けていただいたリンク先の説明によるとTRUEを返す場合、
「最初の WS_TABSTOP をもつコントロールにフォーカスがセットされます。」
ということから考えれば、TRUE戻しでもこのボタンにフォーカスが当たっても良い筈です。
この場合何故そうならないのかはまだ分かりません。
最後にBS_DEFPUSHBUTTONを「BS_PUSHBUTTON」に替えてやってみたのですが
これはTRUE戻しでも上手く行きました。だとするとDEFPUSHBUTTONは使えないの
かな、とも思ってしまうのですが、、、
またBS_PUSHBUTTONにした上で「フォーカス当てのFALSE戻し」にした時は
この場合は逆にフォーカスが当たらないままでした。
ちょっと迷いそうになってますが、もう少しテストを続けてみます。
有難うございます。書いて頂いたコード、リンクを参考にさせてもらいながら
これからこちらでもテストしたいと思います。少し時間を貰って、また報告します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
画面を強制的に再描画させる方法
C言語・C++・C#
-
VC++でコントロールの境界線を描画する方法
C言語・C++・C#
-
エディットボックスの入力制限について
C言語・C++・C#
-
-
4
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
5
CStringについて
C言語・C++・C#
-
6
テキストボックスからフォーカス外す
C言語・C++・C#
-
7
charからLPTSTRへの変換方法
C言語・C++・C#
-
8
ボタンの表示の色、フォントを変更したい
C言語・C++・C#
-
9
ダイアログの上のテキストボックスの、初期値を設定する方法が分かりません・・・・
C言語・C++・C#
-
10
EDITコントロールで入力できる文字を制限するには?
C言語・C++・C#
-
11
子ダイアログのコントロールにフォーカス(VC++2005)
C言語・C++・C#
-
12
ダイアログ内コントロールの位置取得について
C言語・C++・C#
-
13
エディットコントロールでEnter押した時の動作
C言語・C++・C#
-
14
ダイアログ表示時にチェックボックスにチェックされている状態にするには?
C言語・C++・C#
-
15
ダイアログのWM_KEYDOWNで処理を実行したい
C言語・C++・C#
-
16
イベントハンドラが取得できない VC++ MFC
C言語・C++・C#
-
17
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
18
リストビューの選択状態を取得するメッセージはありますか?
C言語・C++・C#
-
19
自作ダイアログボックス中のエディットボックスでCtrl+Aを使えるようにしたい。
C言語・C++・C#
-
20
サイズ変更枠ダイアログのタイトルバー左端のアイコンを消す
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
コントロールの書式設定で、“コ...
-
ダイアログのスクロールバー
-
エクセルのコントロールツール...
-
フォームでPDFを表示させた...
-
MFCのプロジェクト作成時にコモ...
-
エクセル - リストボックスのマ...
-
VisualBasic 2010でVB6で使って...
-
DateTimePickerでに年月までし...
-
C#.NETでのCOMコンポーネント作...
-
VB.Net Tabコントロール中のす...
-
リストコントロール(MFC or API...
-
ActiveXコントロールを.NETにイ...
-
空のリストビューで1行おきに...
-
VC++でツリーコントロールの文...
-
WindowsMediaPlayer全画面表示...
-
VScrollBarの点滅を何とかしたい。
-
スピンボタンを右クリックして...
-
resource.h
-
エクセルで作った新しいウイン...
-
コンボボックス内の文字サイズ変更
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コントロールの書式設定で、“コ...
-
エクセルのコントロールツール...
-
スピンボタンを右クリックして...
-
ActiveXコントロールを.NETにイ...
-
DateTimePickerでに年月までし...
-
コモンダイアログコントロール...
-
フォームでPDFを表示させた...
-
EXCELVBA リストボックスで選択...
-
CEdit の内容が変わった時にメ...
-
regsvr32でActiveX登録を行ったocx
-
アイテムを点滅させる
-
TabControlとToolBarの背景色変更
-
VisualStudio MFC変数が追加で...
-
空のリストビューで1行おきに...
-
連続で印刷すると画像が更新さ...
-
VBAでリストボックス内で↑↓の操...
-
エクセル - リストボックスのマ...
-
MFC・ダイアログベースで、ダイ...
-
ワードのドロップダウンリスト
-
MFCのプロジェクト作成時にコモ...
おすすめ情報