首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Win32 開發入門(5):單選式選單項目 (CheckMenuRadioItem)

     編輯:關於C++

目標:實現類似單選鈕的選單效果

多個選單項目中同一時間僅有一個被勾選,視覺上如單選鈕群組。

單選式選單效果

資源編輯器設定關鍵:ID 必須連續

為了讓 CheckMenuRadioItem 能以 ID 範圍識別群組,三個選單項目 ID 必須連續(如 501、502、503)。

選單項目 ID 設定

選單資源結構

RC 檔案檢視確認

選單載入兩種方式比較

類別層級 (WNDCLASS.lpszMenuName)


wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN); // 所有該類別視窗自動擁有此選單
HWND hm = CreateWindow(..., NULL, ...); // hMenu 參數給 NULL 也會有選單

視窗層級 (CreateWindow hMenu 參數)


// wc.lpszMenuName = NULL;
HWND hm = CreateWindow(..., LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAIN)), ...);

第二種方式更有彈性,可依視窗決定是否載入選單。

視窗層級載入選單效果

hMenu=NULL 時無選單

CheckMenuRadioItem 使用方法

需先取得彈出式選單控制代碼:


auto hmm = GetMenu(hwnd);        // 取得選單列控制代碼
auto hfmn = GetSubMenu(hmm, 0);  // 取得第一個彈出式選單 (水果)

選單階層結構圖解

WM_COMMAND 中設定單選狀態


case WM_COMMAND: {
    switch (LOWORD(wParam)) {
        case IDM_APPLE:
            CheckMenuRadioItem(hfmn, IDM_APPLE, IDM_BANANA, IDM_APPLE, MF_BYCOMMAND);
            MessageBox(hwnd, L"你選擇了蘋果。", L"提示", MB_OK); break;
        case IDM_PEAR:
            CheckMenuRadioItem(hfmn, IDM_APPLE, IDM_BANANA, IDM_PEAR, MF_BYCOMMAND);
            MessageBox(hwnd, L"你選擇了梨子。", L"提示", MB_OK); break;
        case IDM_BANANA:
            CheckMenuRadioItem(hfmn, IDM_APPLE, IDM_BANANA, IDM_BANANA, MF_BYCOMMAND);
            MessageBox(hwnd, L"你選擇了香蕉。", L"提示", MB_OK); break;
    }
} return 0;

CheckMenuRadioItem 參數說明

  • hMenu:彈出式選單控制代碼
  • idFirst, idLast:群組 ID 範圍 (含首尾)
  • idCheck:要勾選的項目 ID
  • MF_BYCOMMAND:以命令 ID 方式指定 (而非索引)

完整程式碼清單


#include <Windows.h>
#include "resource.h"

LRESULT CALLBACK WindowMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR cmdline, int nShow) {
    WNDCLASS wc = { };
    wc.lpszClassName = L"MainWd";
    wc.hInstance = hThisInst;
    wc.lpfnWndProc = WindowMainProc;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wc);
    
    HWND hm = CreateWindow(L"MainWd", L"我的應用程式", WS_OVERLAPPEDWINDOW,
                           25, 18, 380, 280, NULL,
                           LoadMenu(hThisInst, MAKEINTRESOURCE(IDR_MAIN)),
                           hThisInst, NULL);
    if (hm == NULL) return 0;
    ShowWindow(hm, SW_SHOW);
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WindowMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    auto hmm = GetMenu(hwnd);
    auto hfmn = GetSubMenu(hmm, 0); // [水果] 彈出式選單
    
    switch (msg) {
        case WM_COMMAND: {
            switch (LOWORD(wParam)) {
                case IDM_APPLE:
                    CheckMenuRadioItem(hfmn, IDM_APPLE, IDM_BANANA, IDM_APPLE, MF_BYCOMMAND);
                    MessageBox(hwnd, L"你選擇了蘋果。", L"提示", MB_OK); break;
                case IDM_PEAR:
                    CheckMenuRadioItem(hfmn, IDM_APPLE, IDM_BANANA, IDM_PEAR, MF_BYCOMMAND);
                    MessageBox(hwnd, L"你選擇了梨子。", L"提示", MB_OK); break;
                case IDM_BANANA:
                    CheckMenuRadioItem(hfmn, IDM_APPLE, IDM_BANANA, IDM_BANANA, MF_BYCOMMAND);
                    MessageBox(hwnd, L"你選擇了香蕉。", L"提示", MB_OK); break;
            }
        } return 0;
        case WM_DESTROY:
            PostQuitMessage(0); return 0;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

重點整理

  • 單選選單項目 ID **必須連續**,供 CheckMenuRadioItem 範圍判斷
  • 選單載入:類別層級 vs 視窗層級 (hMenu 參數) 差異
  • 取得彈出式選單控制代碼:GetMenu → GetSubMenu(index)
  • CheckMenuRadioItem(hMenu, idFirst, idLast, idCheck, MF_BYCOMMAND) 設定勾選狀態
  • 使用 auto 關鍵字簡化控制代碼變數宣告
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved