実現したいこと
WindowsAPIを利用したアプリづくりの学習中に躓いたところを解決したいです。
前提
上に述べたようにアプリづくりの練習としてコンボボックスを触っています。
内容としてはSendMessage()を利用してできたインデックス付きの4項目を選ぶとそれに応じた数字を出力するつもりでした。
発生している問題・エラーメッセージ
エラーは起こっていないのですが、コンボボックスの項目が1個目しか出てきません。
その理由と改善策を知りたいです。
該当のソースコード
今回の内容に関して大きくかかわるのはBOOL CALLBACK DialogProc()だと思うのですが、どこがダメか分からないためとりあえずCppファイルの全体を載せておきます。
C++
1//============================================================================= 2// ダイアログボックスベースのアプリケーション 3// === モードレスダイアログ版 === 4//============================================================================= 5#include <windows.h> 6#include <windowsx.h> 7#include "resource.h" 8 9BOOL CALLBACK DialogProc(HWND hWnd, UINT uMes, WPARAM wp, LPARAM lp); 10BOOL QuitMessage(HWND hDlg); 11 12int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, 13 _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { 14 // モードレスダイアログボックスを作成する 15 // ダイアログボックスが作成されると処理が戻ります 16 static HWND hDlg; 17 hDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, 18 (DLGPROC)DialogProc); 19 20 // アクセラレータのロード 21 // HACCEL hAccel; // アクセラレータテーブルのハンドル 22 // hAccel = LoadAccelerators(hInstance, MAKEINTATOM(IDR_ACCELERATOR)); 23 24 // メッセージループを生成する 25 MSG msg; 26 do { 27 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 28 if (msg.message == WM_QUIT) 29 break; // PeekMessage while()ループを抜ける 30 // if(TranslateAccelerator(hWnd, hAccel, &msg)) 31 // continue; 32 TranslateMessage(&msg); 33 DispatchMessage(&msg); 34 } 35 if (msg.message == WM_QUIT) 36 break; // WaitMessage while()ループを抜ける 37 } while (WaitMessage()); 38 39 return (int)msg.wParam; 40} 41 42BOOL CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wp, LPARAM lp) { 43 static HINSTANCE hInstance; 44 int i; 45 int iListNo = 0; 46 LPCTSTR lpszList[] = { L"LIST0", L"LIST1", L"LIST2", L"LIST3" }; 47 wchar_t lpszMessage[64]; 48 49 switch (uMsg) { 50 case WM_INITDIALOG: // ダイアログを作成するときに呼び出される 51 hInstance = (HINSTANCE)GetWindowLongPtr(hDlg, GWLP_HINSTANCE); 52 SetClassLongPtr(hDlg, // アイコンの設定 53 GCLP_HICON, (LONG_PTR)LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON))); 54 ShowWindow(hDlg, SW_SHOW); // ウィンドウを表示する 55 UpdateWindow(hDlg); 56 for (i = 0; i < 4; i++) { 57 SendMessage(GetDlgItem(hDlg, IDC_COMBO1), CB_INSERTSTRING, 58 (WPARAM)i, (LPARAM)lpszList[i]); 59 SendMessage(GetDlgItem(hDlg, IDC_COMBO1), CB_SETCURSEL, 60 (WPARAM)iListNo, 0L); 61 } 62 63 break; 64 65 case WM_CLOSE: // ×印を押したとき 66 if (QuitMessage(hDlg)) { // 終了確認のメッセージを表示する 67 DestroyWindow(hDlg); // ダイアログを破棄する 68 PostQuitMessage(0); // WinMainにWM_QUITを送る 69 return TRUE; 70 } 71 return TRUE; 72 73 // メニューから呼び出されるメッセージ 74 case WM_COMMAND: 75 switch (LOWORD(wp)) { 76 case IDM_QUIT: // [ファイル]-[アプリケーションの終了] 77 PostMessage(hDlg, WM_CLOSE, 0, 0L); 78 return TRUE; 79 case IDOK: 80 iListNo = (int)(DWORD)SendMessage(GetDlgItem(hDlg, IDC_COMBO1), 81 CB_GETCURSEL, 0L, 0L); 82 wsprintf(lpszMessage, L"%d番が選択されました。", iListNo); 83 MessageBox(hDlg, lpszMessage, L"確認", MB_OK); 84 EndDialog(hDlg, 0); 85 return TRUE; 86 case IDCANCEL: 87 EndDialog(hDlg, 0); 88 return FALSE; 89 } 90 break; 91 } 92 return FALSE; // 何もしないときはFALSEを返す 93} 94 95BOOL QuitMessage(HWND hDlg) { 96 if (MessageBox(hDlg, TEXT("終了してもよろしいですか?"), TEXT("終了確認"), 97 MB_YESNO | MB_ICONQUESTION) == IDYES) 98 return TRUE; 99 return FALSE; 100}
試したこと
コンボボックスの部分をリストボックスに変える
・IDC_COMBO1→IDC_LIST1
・CB_INSERTSTRING, CB_SETCURSEL, CB_GETCURSELの頭をLBにする
上記を行ったところうまくいってました。
なのでリストボックスとコンボボックスの違いだと思うのですが…
補足情報(FW/ツールのバージョンなど)
VisualStudio2022で行っています。
1:
コンボボックスの種類は、「シンプル(標準)、ドロップダウン、ドロップダウンリスト」のどれですか?
2:
>エラーは起こっていないのですが、コンボボックスの項目が1個目しか出てきません。
これのスクリーンショットをアップできますか?
3:(シンプル以外)
コンボボックスにフォーカスをあてて、カーソルキーで上下させてみてください。
それでも一つしか項目がありませんか?
4:(ヒントから解決できなければ)
IDC_COMBO1のスタイルや幅等の数値は提示できますか?
#rcファイルをコード表示するか、適当なテキストエディタで開いて該当箇所を取得し、質問に追記してください。
推測:
COMBOBOX(シンプル以外)は「右のボタン(▼)を押したときに下方向に伸びる選択領域」をどのくらい伸ばすのかをリソースに設定する必要がある。
これを忘れると右のボタンを押しても下に伸びないので、選択肢が存在しないように見えてしまいかねない。
VSのダイアログエディターであれば、ダイアログに張り付けたコンボボックスの右ボタン(▼)を押せば選択領域のサイズ指定モードになります。
#具体的にはサイズ選択トラッカーが下方向のみの操作(黒い■が下中央のみ)になる。
推測のとおりでした...
コンボボックスにはドロップダウンを使っており、伸びる領域を増やせば見えるようになりました!

回答1件
あなたの回答
tips
プレビュー