
ダイアログボックスのボタンコントロールのフォーカスについて
教えて下さい。
モーダルダイアログにボタン「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で質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBA 参照先で選んだファイルをコピーし、出力先に別名で保存したい 8 2022/05/13 20:37
- JavaScript 追加ボタンを押した際に ok ボタンを押した場合のみ入力値が追記されるようにしたいです 6 2022/05/29 09:57
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- JavaScript jsで診断コンテンツのページ内切り替えについて 1 2023/04/14 17:31
- Excel(エクセル) マクロでボタンにつける名前がどこに設定されているかわからないケースがありました。 1 2023/06/19 19:37
- Visual Basic(VBA) Vba LongPtrについて教えてください 2 2022/08/19 11:14
- JavaScript スマフォではボタンを表示させたくない 2 2023/01/20 14:26
- JavaScript ①入力フォーム→②確認表示画面→③送信完了画面のコードを書いているのです、 入力フォームから受け取っ 2 2022/05/10 16:45
- Visual Basic(VBA) 【ExcelVBA】動的にボタン、ボタン名を生成できますか? 7 2022/04/08 12:54
このQ&Aを見た人はこんなQ&Aも見ています
-
性格いい人が優勝
できるだけ性格いい人になって回答をお願いします。
-
テキストボックスからフォーカス外す
C言語・C++・C#
-
エディットボックスの入力制限について
C言語・C++・C#
-
エディットコントロールでEnter押した時の動作
C言語・C++・C#
-
-
4
CStringをwchar_tに変換したい
C言語・C++・C#
-
5
サイズ変更枠ダイアログのタイトルバー左端のアイコンを消す
C言語・C++・C#
-
6
ダイアログ内コントロールの位置取得について
C言語・C++・C#
-
7
EDITコントロールで入力できる文字を制限するには?
C言語・C++・C#
-
8
WS_TABSTOPが機能するコントロールを作る
C言語・C++・C#
-
9
リストコントロールのデータの変更を検知したい
C言語・C++・C#
-
10
画面を強制的に再描画させる方法
C言語・C++・C#
-
11
CWnd::EnableWindow()の扱い方
C言語・C++・C#
-
12
コンボボックスでデフォルト値の設定
C言語・C++・C#
-
13
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
14
リストビューの選択状態を取得するメッセージはありますか?
C言語・C++・C#
-
15
子ダイアログのコントロールにフォーカス(VC++2005)
C言語・C++・C#
-
16
static 文字が上に張り付いて・・・
C言語・C++・C#
-
17
フォーカスについてお教えください
C言語・C++・C#
-
18
VC++で文字列から任意の文字を削除するにはどうしたらいいですか?
C言語・C++・C#
-
19
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
20
ボタンの表示の色、フォントを変更したい
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
コントロールの書式設定で、“コ...
-
DateTimePickerでに年月までし...
-
エクセルのコントロールツール...
-
エクセル - リストボックスのマ...
-
VBAでリストボックス内で↑↓の操...
-
ActiveXコントロールを.NETにイ...
-
コモンダイアログコントロール...
-
CEdit の内容が変わった時にメ...
-
リストボックスの同期
-
VB.Net Tabコントロール中のす...
-
CFromViewの OnDrawメソッドに...
-
タブインデックスをより簡単に...
-
コンボボックスでコントロール...
-
ワードのドロップダウンリスト
-
Win32のリストコントロールで縦...
-
Accessのタブコントロールを2...
-
リストコントロールにセットす...
-
フォームでPDFを表示させた...
-
win32 ダイアログリソース ピ...
-
スクロールバーを点滅させない方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コントロールの書式設定で、“コ...
-
エクセルのコントロールツール...
-
ActiveXコントロールを.NETにイ...
-
DateTimePickerでに年月までし...
-
スピンボタンを右クリックして...
-
フォームでPDFを表示させた...
-
コモンダイアログコントロール...
-
連続で印刷すると画像が更新さ...
-
VBAでリストボックス内で↑↓の操...
-
EXCELVBA リストボックスで選択...
-
ワードのドロップダウンリスト
-
エクセル - リストボックスのマ...
-
リストコントロール(MFC or API...
-
VScrollBarの点滅を何とかしたい。
-
MFC・ダイアログベースで、ダイ...
-
CEdit の内容が変わった時にメ...
-
Excel VBAでのMultipageの選択
-
TabControlとToolBarの背景色変更
-
警告表示を非表示にしたい
-
ダイアログボックスのボタンコ...
おすすめ情報