Win16 API   /   メニュー

ホーム    Windows API Primer

メニュー

menu.c


#include <windows.h>

#define NEW  101
#define OPEN 102
#define SAVE 103
#define QUIT 104
#define UNDO 201
#define REDO 202
#define CUT  203
#define COPY 204
#define PAST 205
#define ABOU 301

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

int     PASCAL   WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
{
    WNDCLASS wc;
    HWND     hwnd;
    MSG      msg;

    HMENU    menubar  = CreateMenu();
    HMENU    menufile = CreateMenu();
    HMENU    menuedit = CreateMenu();
    HMENU    menuhelp = CreateMenu();

    AppendMenu(menufile, MF_STRING, NEW,  "New" );
    AppendMenu(menufile, MF_STRING, OPEN, "Open");
    AppendMenu(menufile, MF_STRING, SAVE, "Save");
    AppendMenu(menufile, MF_SEPARATOR, 0,  NULL );
    AppendMenu(menufile, MF_STRING, QUIT, "Quit");
    AppendMenu(menubar,  MF_POPUP, (UINT)menufile, "File");
    AppendMenu(menuedit, MF_STRING, UNDO, "Undo");
    AppendMenu(menuedit, MF_STRING, REDO, "Redo");
    AppendMenu(menuedit, MF_SEPARATOR, 0,  NULL );
    AppendMenu(menuedit, MF_STRING, CUT,  "Cut" );
    AppendMenu(menuedit, MF_STRING, COPY, "Copy");
    AppendMenu(menuedit, MF_STRING, PAST, "Paste");
    AppendMenu(menubar,  MF_POPUP, (UINT)menuedit, "Edit");
    AppendMenu(menuhelp, MF_STRING, ABOU, "About");
    AppendMenu(menubar,  MF_POPUP, (UINT)menuhelp, "Help");

    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 = "MENU";

    RegisterClass(&wc);

    hwnd             = CreateWindow("MENU",
                                    "Menu",
                                    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                                    CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
                                    NULL, menubar, 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;

    switch (msg)
    {
    case WM_CREATE:
        GetClientRect(hwnd, &rect);
        label = CreateWindow("STATIC",
                             "",
                             WS_CHILD | WS_VISIBLE | SS_CENTER,
                             (rect.right  - 50) / 2,
                             (rect.bottom - 15) / 2,
                             50, 15, hwnd, NULL, NULL, NULL);
        return 0;
    case WM_SIZE:
        GetClientRect(hwnd, &rect);
        SetWindowPos (label, HWND_TOP, (rect.right - 50) / 2,
                     (rect.bottom - 15) / 2, 0, 0, SWP_NOSIZE);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_COMMAND:
        switch (wParam)
        {
        case NEW:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"New");
            break;
        case OPEN:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Open");
            break;
        case SAVE:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Save");
            break;
        case QUIT:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            //PostQuitMessage(0);
            break;
        case UNDO:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Undo");
            break;
        case REDO:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Redo");
            break;
        case CUT:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Cut");
            break;
        case COPY:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Copy");
            break;
        case PAST:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Paste");
            break;
        case ABOU:
            MessageBox(hwnd, "Menu Ver. 1.0", "About", MB_OK);
            break;
        }
        return 0;
    }
    
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

    


実行結果

メニュー項目をクリックすると、そのメニューの名前がラベルに表示されます。
Quit メニューをクリックするとアプリケーションが終了します。About メニューをクリックするとメッセージボックスが表示されます。


コード説明

  1. #define FILE 100
    メニューのコマンドの ID 用に定数を設定しておきます。
  2. HMENU menubar = CreateMenu();
    CreateMenu 関数でメニューを作ります。メニューの型は HMENU になります。作らなければならない変数はメニューバーとメニューバーに表示されるメニューだけです。
  3. AppendMenu(menufile, MF_STRING, NEW, "New" );
    AppendMenu 関数でメニューバーにメニューを追加したり、メニューにメニュー項目を追加できます。引数は次のとおりです。
    1. 第1引数に追加されるほうのメニューバーかメニューを指定します。
    2. 第2引数に何として追加するかを定数で指定します。定数は次のとおりです。
      MF_STRING
      通常のメニュー項目として追加する
      MF_SEPARATOR
      セパレーターとして追加する
      MF_POPUP
      子メニュー(メニュー項目)を持つメニューとして追加する
    3. 第3引数にメニューの ID を指定します。セパレーターは 0 になります。メニューバーに表示されるメニューについては 変数名を UINT でキャストして ID とします。
    4. 第4引数にメニューやメニュー項目に表示される文字列を指定します。セパレーターの場合は NULL を指定します。
  4. NULL, menubar, hInstance, NULL);
    CreateWindow の第9引数に メニューバーを指定すると、そのウィンドウのメニューバーになります。
  5. switch (wParam)
    WM_COMMAND: メッセージ中で、wParam に入っている ID でコマンドを選別します。
  6. SendMessage(hwnd, WM_CLOSE, 0, 0);
    ウィンドウに WM_CLOSE メッセージを送ると、そのウィンドウが閉じます。ウィンドウが閉じると WM_DESTROY メッセージが呼び出されてアプリケーションが終了します。この部分は
    PostQuitMessage(0); と記述して、直接アプリケーションを終了させても構いません。
  7. MessageBox(hwnd, "Menu Ver. 1.0", "About", MB_OK);
    MessageBox 関数は、簡単なダイアログを表示します。引数は次のとおりです。
    1. 第1引数にメッセージボックスの親となるウィンドウを指定します。親となるウィンドウがない場合は NULL を指定します。
    2. 第2引数にメッセージボックスに表示する文字列を指定します。
    3. 第3引数にメッセージボックスのタイトルを指定します。ここに 0 もしくは NULL を指定すると、"error" というタイトルになります。
    4. 第4引数にメッセージボックスに表示されるボタンの種類を定数で指定します。MB_OK は OK ボタンだけを表示します。定数には次のようなものが用意されています。
      MB_YESNOYes と No を表示します
      MB_OKCANCELOK と Cancel を表示します
      MB_YESNOCANCELYes と No と Cancel を表示します

関数化

上記の menu.c は、メニューを作る箇所を別の関数にまとめると見やすいコードになります。

menu2.c


#include <windows.h>

#define NEW  101
#define OPEN 102
#define SAVE 103
#define QUIT 104
#define UNDO 201
#define REDO 202
#define CUT  203
#define COPY 204
#define PAST 205
#define ABOU 301

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 = "MENU";

    RegisterClass(&wc);
    
    hwnd             = CreateWindow("MENU",
                                    "Menu",
                                    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;
    
    switch (msg)
    {
    case WM_CREATE:
        AddMenu(hwnd);
        GetClientRect(hwnd, &rect);
        label = CreateWindow("STATIC",
                             "",
                             WS_CHILD | WS_VISIBLE | SS_CENTER,
                             (rect.right  - 50) / 2,
                             (rect.bottom - 15) / 2,
                             50, 15, hwnd, NULL, NULL, NULL);
        return 0;
    case WM_SIZE:
        GetClientRect(hwnd, &rect);
        SetWindowPos (label, HWND_TOP, (rect.right - 50) / 2,
                      (rect.bottom - 15) / 2, 0, 0, SWP_NOSIZE);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_COMMAND:
        switch (wParam)
        {
        case NEW:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"New");
            break;
        case OPEN:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Open");
            break;
        case SAVE:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Save");
            break;
        case QUIT:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            //PostQuitMessage(0);
            break;
        case UNDO:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Undo");
            break;
        case REDO:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Redo");
            break;
        case CUT:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Cut");
            break;
        case COPY:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Copy");
            break;
        case PAST:
            SendMessage(label, WM_SETTEXT, 0, (LPARAM)"Paste");
            break;
        case ABOU:
            MessageBox(hwnd, "Menu Ver. 1.0", "About", MB_OK);
            break;
        }
        return 0;
    }
    
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

void AddMenu(HWND hwnd)
{
    HMENU    menubar  = CreateMenu();
    HMENU    menufile = CreateMenu();
    HMENU    menuedit = CreateMenu();
    HMENU    menuhelp = CreateMenu();

    AppendMenu(menufile, MF_STRING, NEW,  "New" );
    AppendMenu(menufile, MF_STRING, OPEN, "Open");
    AppendMenu(menufile, MF_STRING, SAVE, "Save");
    AppendMenu(menufile, MF_SEPARATOR, 0,  NULL );
    AppendMenu(menufile, MF_STRING, QUIT, "Quit");
    AppendMenu(menubar,  MF_POPUP, (UINT)menufile, "File");
    AppendMenu(menuedit, MF_STRING, UNDO, "Undo");
    AppendMenu(menuedit, MF_STRING, REDO, "Redo");
    AppendMenu(menuedit, MF_SEPARATOR, 0,  NULL );
    AppendMenu(menuedit, MF_STRING, CUT,  "Cut" );
    AppendMenu(menuedit, MF_STRING, COPY, "Copy");
    AppendMenu(menuedit, MF_STRING, PAST, "Paste");
    AppendMenu(menubar,  MF_POPUP, (UINT)menuedit, "Edit");
    AppendMenu(menuhelp, MF_STRING, ABOU, "About");
    AppendMenu(menubar,  MF_POPUP, (UINT)menuhelp, "Help");
    
    SetMenu   (hwnd, menubar);
}

    

コード説明

  1. NULL, NULL, hInstance, NULL);
    WinMain 関数の中の CreateWindow 関数の第9引数にメニューの指定はしていません。
  2. SetMenu (hwnd, menubar);
    今回は SetMenu 関数で第1引数のメインウィンドウに、第2引数のメニューを設定しています。


247 visits
Posted: Jul. 18, 2020
Update: Jul. 19, 2020

ホーム        Windows API Primer     目次