Mesoscopic Programming

タコさんプログラミング専門

ヌメロン製作講座第2回:メニューを追加する

今回はメインウィンドウにメニューを追加します。
まずヘッダファイルにコマンドIDを追加します。
そして各コマンドに対応する関数宣言も追加します。

main.h

#ifndef MAIN_H
#define MAIN_H

#include "window.h"

#include <tchar.h>
#include <afxres.h>

enum CommandID
{
    ID_COMMAND = 0x0100,
    ID_SWITCH_MODE,
    ID_SWITCH_ANAL,
    ID_SWITCH_SECRET,
    ID_CLEAR_RECORD,
    MAX_ID_COMMAND,
};

class Application : public Window
{
public :

    static const SHORT  wndWidth    = 640;
    static const SHORT  wndHeight   = 480;
    static LPCTSTR      className;

    BOOL    Init( HINSTANCE hInstance, int nCmdShow );
    VOID    Run();
    VOID    OnDestroy();
    VOID    OnCommand();
    VOID    OnFileNew();
    VOID    OnFileOpen();
    VOID    OnFileSave();
    VOID    OnAppExit();
    VOID    OnAppAbout();
    VOID    OnSwitchMode();
    VOID    OnSwitchAnal();
    VOID    OnSwitchSecret();
    VOID    OnClearRecord();
};

extern int Message( LPCTSTR text, UINT uType = MB_OK );

#endif // MAIN_H

Message()はMessageBox()関数のラッパです。

次にソースコードを実装します。

main.cpp

#include "main.h"

LPCTSTR     appName = _T( "Numer0n" );
Application app;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    if ( app.Init( hInstance, nCmdShow ) )
    {
        app.Run();
    }

    return 0;
}

int Message( LPCTSTR text, UINT uType )
{
    return MessageBox( app.hwnd, text, appName, uType );
}

LPCTSTR Application :: className = _T( "Application" );

BOOL Application :: Init( HINSTANCE hInstance, int nCmdShow )
{
    WNDCLASSEX  wcx;
    HWND        hWnd;
    HMENU       hMenu;
    HMENU       hSubMenu;

    wcx.cbSize          = sizeof( WNDCLASSEX );
    wcx.style           = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    wcx.lpfnWndProc     = Window :: WindowProc;
    wcx.cbClsExtra      = 0;
    wcx.cbWndExtra      = sizeof( HANDLE );
    wcx.hInstance       = hInstance;
    wcx.hIcon           = LoadIcon( NULL, IDI_APPLICATION );
    wcx.hCursor         = LoadCursor( NULL, IDC_ARROW );
    wcx.hbrBackground   = ( HBRUSH ) ( COLOR_MENU + 1 );
    wcx.lpszMenuName    = NULL;
    wcx.lpszClassName   = className;
    wcx.hIconSm         = LoadIcon( NULL, IDI_WINLOGO );

    RegisterClassEx( & wcx );

    hMenu       = CreateMenu();
    hSubMenu    = CreateMenu();

    AppendMenu( hSubMenu,   MF_STRING,      ID_FILE_NEW,            _T( "新規作成(&N)\tCtrl+N" ) );
    AppendMenu( hSubMenu,   MF_STRING,      ID_FILE_OPEN,           _T( "開く(&O)...\tCtrl+O" ) );
    AppendMenu( hSubMenu,   MF_STRING,      ID_FILE_SAVE,           _T( "保存(&S)...\tCtrl+S" ) );
    AppendMenu( hSubMenu,   MF_SEPARATOR,   0,                      NULL );
    AppendMenu( hSubMenu,   MF_STRING,      ID_APP_EXIT,            _T( "終了(&X)\tAlt+F4" ) );
    AppendMenu( hMenu,      MF_POPUP,       ( UINT_PTR ) hSubMenu,  _T( "ファイル(&F)" ) );

    hSubMenu    = CreateMenu();

    AppendMenu( hSubMenu,   MF_STRING,      ID_SWITCH_MODE,         _T( "開始(&P)\tF2" ) );
    AppendMenu( hSubMenu,   MF_STRING,      ID_SWITCH_ANAL,         _T( "分析(&A)\tF3" ) );
    AppendMenu( hSubMenu,   MF_STRING,      ID_SWITCH_SECRET,       _T( "公開(&O)\tF4" ) );
    AppendMenu( hSubMenu,   MF_SEPARATOR,   0,                      NULL );
    AppendMenu( hSubMenu,   MF_STRING,      ID_CLEAR_RECORD,        _T( "棋譜消去(&C)\tF5" ) );
    AppendMenu( hMenu,      MF_POPUP,       ( UINT_PTR ) hSubMenu,  _T( "ゲーム(&G)" ) );

    hSubMenu    = CreateMenu();

    AppendMenu( hSubMenu,   MF_STRING,      ID_APP_ABOUT,           _T( "アバウト(&A)...\tF1" ) );
    AppendMenu( hMenu,      MF_POPUP,       ( UINT_PTR ) hSubMenu,  _T( "ヘルプ(&H)" ) );

    hWnd        = CreateWindow( className, appName,
                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                                CW_USEDEFAULT, CW_USEDEFAULT, wndWidth, wndHeight,
                                NULL, hMenu, hInstance, ( LPVOID ) this );

    ShowWindow( hWnd, nCmdShow );
    UpdateWindow( hWnd );

    return TRUE;
}

VOID Application :: Run()
{
    MSG msg;

    while ( GetMessage( & msg, NULL, 0, 0 ) )
    {
        TranslateMessage( & msg );
        DispatchMessage( & msg );
    }
}

VOID Application :: OnDestroy()
{
    PostQuitMessage( 0 );
    
    lresult = 0;
}

VOID Application :: OnCommand()
{
    UINT id = LOWORD( wparam );

    switch ( id )
    {
    case ID_FILE_NEW :      OnFileNew();        break;
    case ID_FILE_OPEN :     OnFileOpen();       break;
    case ID_FILE_SAVE :     OnFileSave();       break;
    case ID_APP_EXIT :      OnAppExit();        break;
    case ID_APP_ABOUT :     OnAppAbout();       break;
    case ID_SWITCH_MODE :   OnSwitchMode();     break;
    case ID_SWITCH_ANAL :   OnSwitchAnal();     break;
    case ID_SWITCH_SECRET : OnSwitchSecret();   break;
    case ID_CLEAR_RECORD :  OnClearRecord();    break;

    default :

        return;
    }

    lresult = 0;
}

VOID Application :: OnFileNew()
{
    Message( _T( "「新規作成」は工事中です" ) );
}

VOID Application :: OnFileOpen()
{
    Message( _T( "「開く」は工事中です" ) );
}

VOID Application :: OnFileSave()
{
    Message( _T( "「保存」は工事中です" ) );
}

VOID Application :: OnAppExit()
{
    SendMessage( hwnd, WM_CLOSE, 0, 0 );
}

VOID Application :: OnAppAbout()
{
    Message( _T( "これは「ヌメロン検証プログラム」です" ) );
}

VOID Application :: OnSwitchMode()
{
    Message( _T( "「開始」は工事中です" ) );
}

VOID Application :: OnSwitchAnal()
{
    Message( _T( "「分析」は工事中です" ) );
}

VOID Application :: OnSwitchSecret()
{
    Message( _T( "「公開」は工事中です" ) );
}

VOID Application :: OnClearRecord()
{
    Message( _T( "「棋譜消去」は工事中です" ) );
}

以上です。

次回はキーボードアクセラレータを追加します。
乞うご期待。