Win16 API   /   チェックメニュー

ホーム    Windows API Primer

チェックメニュー

Windows API のチェックメニューは、チェックメニューというコンポーネントが用意されているのではなく、普通のメニュー項目に CheckMenuItem 関数でチェックをつける形で実現しています。そしてメニュー項目にチェックが入っているかどうは GetMenuState 関数で取得できます。

checkmenu.c


#include <windows.h>

HMENU menu;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void    AddMenu         (HWND);

int     PASCAL   WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
{
    WNDCLASS wc;
    HWND     hwnd;
    MSG      msg;
    
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = NULL;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = "CHECKMENU";
    
    RegisterClass(&wc);
    
    hwnd             = CreateWindow("CHECKMENU",
                                    "CheckMenu",
                                    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                                    CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
                                    NULL, NULL, hInstance, NULL);
    
    while (GetMessage(&msg, NULL, 0, 0))
    {
        DispatchMessage(&msg);
    }
    
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND label;
           RECT rect;
           UINT state;
    
    switch (msg)
    {
    case WM_CREATE:
        AddMenu(hwnd);
        GetClientRect(hwnd, &rect);
        label = CreateWindow("STATIC",
                             "Checked",
                             WS_CHILD | WS_VISIBLE | SS_CENTER,
                             (rect.right  - 70) / 2,
                             (rect.bottom - 20) / 2,
                             70, 20,
                             hwnd, NULL, NULL, NULL);
        return 0;
    case WM_SIZE:
        GetClientRect(hwnd, &rect);
        SetWindowPos (label, HWND_TOP,
                      (rect.right  - 70) / 2,
                      (rect.bottom - 20) / 2,
                      0, 0, SWP_NOSIZE);
        return 0;
    case WM_COMMAND:
        state = GetMenuState(menu, 1, MF_BYCOMMAND);
        if (state == MF_CHECKED)
        {
            CheckMenuItem(menu, 1, MF_UNCHECKED);
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Unchecked");
        } else {
            CheckMenuItem(menu, 1, MF_CHECKED);
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Checked");
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

void AddMenu(HWND hwnd)
{
    HMENU menubar = CreateMenu();
    menu          = CreateMenu();
    
    AppendMenu   (menu,    MF_STRING, 1, "Check");
    CheckMenuItem(menu,    1, MF_CHECKED);
    AppendMenu   (menubar, MF_POPUP, (UINT)menu, "Menu");
    
    SetMenu      (hwnd, menubar);
}
    


実行結果

Check メニュー項目をクリックするたび、チェックが入ったり入らなかったりします。


コード説明

  1. HMENU menu;
    今回、メニューを2つの関数から参照してますので、グローバル変数にしました。
  2. CheckMenuItem(menu, 1, MF_CHECKED);
    CheckMenuItem 関数でメニュー項目にチェックを入れられます。引数は次のとおりです。
    1. 第1引数に MF_POP メニューを指定します。
    2. 第2引数にメニュー項目の ID を指定します。
    3. 第3引数にチェックの状態を定数で指定します。定数は次のとおりです。
      MF_CHECKEDチェックの入った状態にします
      MF_UNCHECKEDチェックの入っていない状態にします
  3. state = GetMenuState(menu, 1, MF_BYCOMMAND);
    GetMenuState 関数でメニュー項目にチェックが入っているかどうか取得できます。引数は次のとおりです。
    1. 第1引数に MF_POPUP メニューを指定します。
    2. 第2引数にメニュー項目の ID を指定します。
    3. 第3引数に MF_BYCOMMAND 定数を指定します。


14833 visits
Posted: Jul. 21, 2020
Update: Jul. 22, 2020

ホーム        Windows API Primer     目次