• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:ダイアログボックスのボタンコントロールのフォーカスについて)

ダイアログボックスのボタンコントロールのフォーカスについて

このQ&Aのポイント
  • ダイアログボックスのボタンコントロールのフォーカスに関する問題について教えてください。
  • ダイアログボックスのボタンに初期フォーカスを設定する方法を教えてください。
  • ボタンコントロールがダイアログ表示直後にフォーカスを受け取るようにするにはどうすればいいですか?

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答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を決定するために精査するとき…と言うことなのではないでしょうか。

jacoby2200
質問者

お礼

なるほど。確かに説明されている通りです。 解説を貰ってストンと自分でもようやく理解出来ました。 >>WM_INITDIALOGをOSが発行した時点ではWM_INITDIALOGのハンドラ内で生成されるコントロールは「まだ生成されていない」ですし、付与されるコントロールIDも不明です。 まさにそれが原因で起こっていた現象だと思います。 WM_INITDIALOG内でコントロールを作るなということですね。 リソースエディタで作成すれば大丈夫なんでしょうか? 有難うございます。またよろしくお願いします。

jacoby2200
質問者

補足

お礼の文面の訂正を。 >>WM_INITDIALOG内でコントロールを作るなということですね。 WM_INITDIALOG内でコントロールを作るなというより もしそこで作った場合は自分でフォーカスを合わせる、ということだと思います。 それから >> またBS_PUSHBUTTONにした上で「フォーカス当てのFALSE戻し」にした時は この場合は逆にフォーカスが当たらないままでした。 これは「フォーカスが当たらない」のではなくて、図(1)の状態になる(ボタンに実線枠が 付かずエンター押しが効かない)の間違いでした。 「点線」のフォーカスそのものは当たっているものと思います。 以上を訂正させて頂きます。申し訳ありません。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答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/win86.html ダイアログプロシージャからの返却の場合、SetWindowLong()でDWL_MSGRESULTに設定して返すことになりますが… WM_INITDIALOGの場合はそのまま返却でよい…みたいです。 http://msdn.microsoft.com/en-us/library/ms645428%28VS.85%29.aspx

jacoby2200
質問者

お礼

有難うございます。書いて頂いたコード、リンクを参考にさせてもらいながら これからこちらでもテストしたいと思います。少し時間を貰って、また報告します。

jacoby2200
質問者

補足

ここまでのテスト結果を。 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 のものです。

jacoby2200
質問者

お礼

有難うございます。書いて頂いたコード、リンクを参考にさせてもらいながら これからこちらでもテストしたいと思います。少し時間を貰って、また報告します。

jacoby2200
質問者

補足

ここまでのテスト結果を。 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()を省略。

jacoby2200
質問者

お礼

有難うございます。書いて頂いたコード、リンクを参考にさせてもらいながら これからこちらでもテストしたいと思います。少し時間を貰って、また報告します。

jacoby2200
質問者

補足

ここまでのテスト結果を。 IDをIDOKにしてはいけないという所はまだ理解が追いついてないのですが とりあえずIDを「CommandButton1」などに替えてみてテストしてみました。 ただその時点ではまだ現象は変わりませんでした。  次にその設定のまま「SetFocusでフォーカスをボタンに当ててFALSE戻し」 にすると、これは上手くフォーカスが当たりエンター押しも効きました。 但し付けていただいたリンク先の説明によるとTRUEを返す場合、 「最初の WS_TABSTOP をもつコントロールにフォーカスがセットされます。」 ということから考えれば、TRUE戻しでもこのボタンにフォーカスが当たっても良い筈です。 この場合何故そうならないのかはまだ分かりません。 最後にBS_DEFPUSHBUTTONを「BS_PUSHBUTTON」に替えてやってみたのですが これはTRUE戻しでも上手く行きました。だとするとDEFPUSHBUTTONは使えないの かな、とも思ってしまうのですが、、、  またBS_PUSHBUTTONにした上で「フォーカス当てのFALSE戻し」にした時は この場合は逆にフォーカスが当たらないままでした。 ちょっと迷いそうになってますが、もう少しテストを続けてみます。

すると、全ての回答が全文表示されます。

関連するQ&A