質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

2回答

974閲覧

ラジオボタンのチェック動作を取得できない

yama_07

総合スコア4

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

0クリップ

投稿2023/01/07 09:53

実現したいこと

Win32APIでラジオボタンを作成し、どのラジオボタンが押されたかを取得したいです。そこでまず、ラジオボタンが押されたことが正しく取得できているかを確認するためにメッセージボックスを表示させるようにしました。

発生している問題

ラジオボタンを押しても、ラジオボタンを押したことを通知するメッセージボックスが表示されません。
以下のコードで表示されない原因を知りたいです。

ソースコード

c++

1#include<windows.h> 2#include<tchar.h> 3 4 5#define STRLEN 256 6#define ID_Men 11 7#define ID_Lady 12 8 9LRESULT CALLBACK windowfunc(HWND, UINT, WPARAM, LPARAM); 10 11HWND CreateParentWindow(HWND, HINSTANCE, int, const TCHAR szWinName[], const int, const int); 12 13static const TCHAR szWinName[] = _T("key"); 14HINSTANCE hInst; 15HFONT hFont, hFont1; 16 17HWND hGroupX, radioMen, radioLady; 18 19BOOL RadioFunc(HWND, LPARAM); 20 21const HBRUSH BackGround_clear = CreateSolidBrush(RGB(242, 252, 245)); 22const COLORREF TextBackground = RGB(242, 252, 245); 23 24RECT Winsize = { 0,0,1000,750 }; 25 26long i; 27 28//WinMain関数 29int WINAPI WinMain(_In_ HINSTANCE hThisInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPSTR lpszArgs, _In_ int nWinMode) 30{ 31 HWND hwnd=NULL; 32 MSG msg; 33 34 // メインウィンドウの作成 35 CreateParentWindow(hwnd, hThisInst, nWinMode, szWinName, Winsize.right - Winsize.left, Winsize.bottom - Winsize.top); 36 37 38 //インスタンスハンドルの保存 39 hInst = hThisInst; 40 41 //キーボードアクセラレータのロード 42 //haccel = LoadAccelerators(hThisInst, MAKEINTRESOURCE(IDR_ACCELERATOR1)); 43 44 //メッセージループの生成 45 while (GetMessage(&msg, NULL, 0, 0)) { 46 TranslateMessage(&msg); 47 DispatchMessage(&msg); 48 } 49 50 return((int)msg.wParam); 51} 52 53LRESULT CALLBACK windowfunc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 54{ 55 56 switch (msg){ 57 case WM_CREATE: 58 RadioFunc(hwnd, lparam); 59 break; 60 61 case WM_COMMAND: 62 switch (LOWORD(wparam)){ 63 case ID_Men: 64 if (BST_CHECKED == SendMessage(radioMen, BM_GETCHECK, 0, 0)) { 65 MessageBox(hwnd, _T("男が押されました。"), _T("Message Box"), MB_OK); 66 } 67 break; 68 case ID_Lady: 69 if (BST_CHECKED == SendMessage(radioLady, BM_GETCHECK, 0, 0)) { 70 MessageBox(hwnd, _T("女が押されました。"), _T("Message Box"), MB_OK); 71 } 72 break; 73 default: 74 break; 75 } 76 break; 77 case WM_DESTROY: 78 PostQuitMessage(0); 79 break; 80 81 default: 82 return (DefWindowProc(hwnd, msg, wparam, lparam)); 83 84 } 85 86} 87// 親ウィンドウ作成 88HWND CreateParentWindow(HWND hwnd, HINSTANCE hThisInst, int nWinMode, const TCHAR szWinName[], const int nWidth, const int nHeight) 89{ 90 WNDCLASSEX wcl; 91 92 //ウィンドウクラスの定義 93 wcl.cbSize = sizeof(WNDCLASSEX); //WNDCLASSEX構造体のサイズ 94 wcl.style = 0; //ウィンドウクラススタイル 95 wcl.lpfnWndProc = windowfunc; //ウィンドウ関数 96 wcl.cbClsExtra = 0; //ウィンドウクラスのエキストラ 97 wcl.cbWndExtra = 0; //ウィンドウインスタンスのエキストラ 98 wcl.hInstance = hThisInst; //このプログラムのインスタンスへのハンドル 99 wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); //アイコンへのハンドル 100 wcl.hCursor = LoadCursor(NULL, IDC_ARROW); //カーソルへのハンドル 101 wcl.hbrBackground = BackGround_clear; //(HBRUSH)COLOR_WINDOW背景ブラシへのハンドル 102 wcl.lpszMenuName = NULL; //メニュー 103 wcl.lpszClassName = szWinName; //ウィンドウクラス名 104 wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); //スモールアイコンへのハンドル 105 106 //ウィンドウクラスの登録 107 if (!RegisterClassEx(&wcl)) { 108 return(0); 109 } 110 111 //ウィンドウの生成 112 hwnd = CreateWindow( 113 szWinName, //ウィンドウクラス名 114 szWinName, //ウィンドウ名 115 WS_OVERLAPPEDWINDOW, //ウィンドウスタイル 116 CW_USEDEFAULT, //x座標 117 CW_USEDEFAULT, //y座標 118 nWidth, //幅 119 nHeight, //高さ 120 HWND_DESKTOP, //親ウィンドウへのハンドル 121 NULL, //メニューへのハンドル 122 hThisInst, //このプログラムのインスタンスへのハンドル 123 NULL //追加引数 124 ); 125 126 //ウィンドウの表示 127 ShowWindow(hwnd, nWinMode); 128 UpdateWindow(hwnd); 129 130 return hwnd; 131} 132 133BOOL RadioFunc(HWND hwnd, LPARAM lparam) { 134 135 hGroupX = CreateWindow( 136 _T("BUTTON"), 137 _T("性別"), 138 WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 139 0, 0, 200, 100, 140 hwnd, 141 NULL, 142 ((LPCREATESTRUCT)(lparam))->hInstance, 143 NULL 144 ); 145 146 radioMen = CreateWindow( 147 _T("BUTTON"), 148 _T("男性"), 149 WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP, 150 10, 30, 150, 30, 151 hGroupX, 152 (HMENU)ID_Men, 153 ((LPCREATESTRUCT)(lparam))->hInstance, 154 NULL 155 ); 156 157 radioLady = CreateWindow( 158 _T("BUTTON"), 159 _T("女性"), 160 WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 161 10, 60, 150, 30, 162 hGroupX, 163 (HMENU)ID_Lady, 164 ((LPCREATESTRUCT)(lparam))->hInstance, 165 NULL 166 ); 167 168 //フォントの作成 169 hFont = CreateFont( 170 25, 0, 0, 0, 171 FW_MEDIUM, 172 FALSE, FALSE, FALSE, 173 SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, 174 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 175 (VARIABLE_PITCH | FF_DONTCARE), _T("メイリオ")); 176 177 178 hFont1 = CreateFont( 179 30, 0, 0, 0, 180 FW_MEDIUM, 181 FALSE, FALSE, FALSE, 182 SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, 183 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 184 (VARIABLE_PITCH | FF_DONTCARE), _T("メイリオ")); 185 186 SendMessage(radioMen, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 187 SendMessage(radioLady, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 188 SendMessage(hGroupX, WM_SETFONT, (WPARAM)hFont1, MAKELPARAM(FALSE, 0)); 189 190 return true; 191} 192

試したこと

ネットでラジオボタンのチェック状態の取得方法について調べて自分のソースコードと比較していましたが、このコードのどこに原因があるのか分かりませんでした。

補足情報(FW/ツールのバージョンなど)

Visual Studio 2019
c++

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

回答ではありません

ただの補足です。

補足

Windowsではグループボックスとラジオボタンは両方コントロールとしてはボタンになります。グループボックスは他のコントロールを囲むだけで何の機能もありませんが、ラジオボタンのWS_GROUPはこのグループボックスに囲まれているかどうかで、グループが分かれるようになっています。詳細は以下を読んで下さい(その辺の説明ないですけど…)。

グループ ボックス
https://learn.microsoft.com/ja-jp/windows/win32/controls/button-types-and-styles#group-boxes

ラジオ ボタン
https://learn.microsoft.com/ja-jp/windows/win32/controls/button-types-and-styles#radio-buttons

ラジオボタンの説明を読むと、

ユーザーがいずれかの状態を選択すると、ラジオ ボタンはキーボード フォーカスを受け取ります。 システムは、ボタンの親ウィンドウに 、BN_CLICKED 通知コードを含む WM_COMMAND メッセージを送信します。 自動ラジオボタンから送信された場合、親ウィンドウはこのメッセージを処理する必要はありません。これは、システムによってそのスタイルのチェック状態が自動的に設定されるためです。 ただし、親ウィンドウは、そのスタイルのチェック状態を設定する役割を担うため、自動以外のラジオ ボタンから送信された場合は、親ウィンドウでメッセージを処理する必要があります。 ラジオ ボタンのスタイルに関係なく、状態が変わると、ボタンが自動的に再描画されます。

とあり、ラジオボタンの親ウィンドウにグループボックスを指定してしまうと、WM_COMMANDがグループボックスに行ってしまい、メインウィンドウのウィンドウ プロシージャで処理できなくなってしまいます。

先述したようにラジオボタンのグループ化は囲まれているかどうかだけでどのグループボックスが親ウィンドウかどうかに関係ないので、親ウィンドウにはメインウィンドウを指定することでメインウィンドウのウィンドウプロシージャでラジオボタンからのWM_COMMAND(BN_CLICKED)メッセージを扱うことができます。

コード例

差分だけですが、例としてメインウィンドウにさらにラジオボタンを追加した場合にグループが分かれるかどうか実験したコードを載せておきます。

diff

1--- a/hoge.cpp 2+++ b/hoge.cpp 3@@ -5,6 +5,8 @@ 4 #define STRLEN 256 5 #define ID_Men 11 6 #define ID_Lady 12 7+#define ID_Gorilla 13 8+#define ID_PanTroglodytes 14 9 10 LRESULT CALLBACK windowfunc(HWND, UINT, WPARAM, LPARAM); 11 12@@ -14,7 +16,7 @@ static const TCHAR szWinName[] = _T("key"); 13 HINSTANCE hInst; 14 HFONT hFont, hFont1; 15 16-HWND hGroupX, radioMen, radioLady; 17+HWND hGroupX, radioMen, radioLady, radioGorilla, radioPanTroglodytes; 18 19 BOOL RadioFunc(HWND, LPARAM); 20 21@@ -148,7 +150,7 @@ BOOL RadioFunc(HWND hwnd, LPARAM lparam) { 22 _T("男性"), 23 WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP, 24 10, 30, 150, 30, 25- hGroupX, 26+ hwnd, 27 (HMENU)ID_Men, 28 ((LPCREATESTRUCT)(lparam))->hInstance, 29 NULL 30@@ -159,12 +161,34 @@ BOOL RadioFunc(HWND hwnd, LPARAM lparam) { 31 _T("女性"), 32 WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 33 10, 60, 150, 30, 34- hGroupX, 35+ hwnd, 36 (HMENU)ID_Lady, 37 ((LPCREATESTRUCT)(lparam))->hInstance, 38 NULL 39 ); 40 41+ radioGorilla = CreateWindow( 42+ _T("BUTTON"), 43+ _T("ゴリラ"), 44+ WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP, 45+ 10, 120, 150, 30, 46+ hwnd,//hGroupX, 47+ (HMENU)ID_Gorilla, 48+ ((LPCREATESTRUCT)(lparam))->hInstance, 49+ NULL 50+ ); 51+ 52+ radioPanTroglodytes = CreateWindow( 53+ _T("BUTTON"), 54+ _T("チンパンジー"), 55+ WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 56+ 10, 150, 150, 30, 57+ hwnd,//hGroupX, 58+ (HMENU)ID_PanTroglodytes, 59+ ((LPCREATESTRUCT)(lparam))->hInstance, 60+ NULL 61+ ); 62+ 63 //フォントの作成 64 hFont = CreateFont( 65 25, 0, 0, 0, 66@@ -185,6 +209,8 @@ BOOL RadioFunc(HWND hwnd, LPARAM lparam) { 67 68 SendMessage(radioMen, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 69 SendMessage(radioLady, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 70+ SendMessage(radioGorilla, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 71+ SendMessage(radioPanTroglodytes, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 72 SendMessage(hGroupX, WM_SETFONT, (WPARAM)hFont1, MAKELPARAM(FALSE, 0)); 73 74 return true;

イメージ説明

投稿2023/01/07 13:32

dameo

総合スコア943

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yama_07

2023/01/07 14:29

ご丁寧に回答ありがとうございます。とてもわかりやすかったです。 今の自分の理解だとグループボックスは、「複数のボタンをグループ化する」ことよりも「複数のボタンを囲ってグループであることをユーザーに示す」という意味合いの方が強そうですね。
guest

0

ベストアンサー

もしかして
誤)hGroupX
正)hwnd
ではないでしょうか?

c++

1 radioMen = CreateWindow( 2 _T("BUTTON"), 3 _T("男性"), 4 WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP, 5 10, 30, 150, 30, 6 //hGroupX, 7 hwnd, 8 (HMENU)ID_Men, 9 ((LPCREATESTRUCT)(lparam))->hInstance, 10 NULL 11 ); 12 13 radioLady = CreateWindow( 14 _T("BUTTON"), 15 _T("女性"), 16 WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 17 10, 60, 150, 30, 18 //hGroupX, 19 hwnd, 20 (HMENU)ID_Lady, 21 ((LPCREATESTRUCT)(lparam))->hInstance, 22 NULL 23 );

投稿2023/01/07 11:39

cx20

総合スコア4633

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yama_07

2023/01/07 12:35

回答ありがとうございます。おっしゃる通りでした。助かりました。 追加で質問なんですが、グループボックスで複数のラジオボタンをグループ化した場合(今回の例だと親ウィンドウがhGroupXのまま)、そのグループ化されたラジオボタンのチェック状態というのは取得できないのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問