前回はコマンドラインで実行して文字を表示するだけのプログラムでしたが、
Windowsですからウィンドウ有りのものに挑戦したいと思います。


MinGWによるWindows Programming に書いてある「例題その2メニューを持たせる」を
参考にしてやってみました。


■作成するファイルリスト
resource.h
myapp.rc
winmain.c
wndproc.c
Makefile


ここで気づくことは、拡張子が .rc という見慣れないものがあることです。
これはリソースの作成に使われるリソーススクリプト というものです。
ウィンドウにメニューを付けたいときにこのリソースを使う方法があります。
リソースを使わなくてもメニュー付加ならAPI関数とかでもできるようです。


リソースはCコンパイラではなくリソースコンパイラでコンパイルして、できた
オブジェクトファイルをリンカで組み込む形になります。
リソースコンパイラはMinGWをインストールした実行ファイル置き場に用意されて
います。(windres.exe)



■resource.h
(wndproc.cとmyapp.rcから呼ばれるヘッダファイル)


#define IDM_FILE_EXIT 10001
#define IDM_FILE_OPEN 10002


■wndproc.c
(送られたメッセージを元にいろいろな処理をする。ウィンドウプロシージャ)


#define STRICT
#include <windows.h>
#include "resource.h"

LRESULT CALLBACK WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    int wmId, wmEv;
    switch( uMsg )
    {
    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEv = HIWORD(wParam);
        switch (wmId)
        {
        case IDM_FILE_EXIT:
            DestroyWindow(hwnd);
            break;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}



■myapp.rc
(リソースファイル メニュー付加用)


#include "resource.h"

MyMenu MENU DISCARDABLE
BEGIN
    POPUP "File(ファイル)"
    BEGIN
        MENUITEM "Open(オープン)", IDM_FILE_OPEN
        MENUITEM SEPARATOR
        MENUITEM "Exit(終了)", IDM_FILE_EXIT
    END
END




■winmain.c
(Windowsプログラムはここに書かれているWinMain関数から始まります)


#define STRICT
#include <windows.h>

#define MY_CLASS_NAME "MyClass"
#define MY_WINDOW_TITLE "MyTitle表\示"

/* Prototype */
LRESULT CALLBACK
    WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow )
{
    MSG msg;
    WNDCLASSEX wcex;
    HWND hwnd;

    /* Register the window class for the main window. */
    if( hPrevInstance == NULL )
    {

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc = WndProc;
        wcex.cbClsExtra = 0;
        wcex.cbWndExtra = 0;
        wcex.hInstance = hInstance;
        wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName = "MyMenu";
        wcex.lpszClassName = MY_CLASS_NAME;
        wcex.hIconSm = 0;

        if ( RegisterClassEx( &wcex ) == 0 )
            return 0;
    }

    /* Create our window. */
    hwnd = CreateWindow( MY_CLASS_NAME, MY_WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        (HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL );
    /*
    * If the window cannot be created, terminate
    * the application.
    */
    if( hwnd == NULL )
        return 0;

    /* Show the window and paint its contents. */
    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );

    /* Start the message loop. */
    while( GetMessage( &msg, (HWND)NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    /* Return the exit code to the system. */
    return msg.wParam;
}




■Makefile
(リソースコンパイルおよびCコンパイル手順を書いて最終的なプログラムを出力)


SRC=winmain.c wndproc.c
OBJS=$(SRC:.c=.o)
RC=myapp.rc
WINDRES=$(RC:.rc=.o)
PROG=window.exe
CC=gcc
CFLAGS=-Wall -O3
LDFLAGS=-mwindows
RM=del

%.o: %.c
    $(CC) $(CFLAGS) -o $@ -c $<


.PHONY : all
all: $(PROG)


$(PROG): $(OBJS) $(WINDRES)
    $(CC) $(OBJS) $(WINDRES) $(LDFLAGS) -o $@


$(WINDRES): $(RC) resource.h
    windres $(RC) $(WINDRES)


wndproc.o: resource.h


.PHONY : clean
clean:
    $(RM) $(OBJS) $(WINDRES)



依存関係を無理やり書いたMakefileなのでごちゃごちゃしてます。



各種ファイルを作成して、DOS窓を起動してそこに
> make
と打つと、実行ファイルwindow.exeが作成されます。


> window
と打つか、直接ファイルをダブルクリックで実行するとウィンドウが現れると
思います。


ちょっとしたメニューがあり、そこに日本語がいくつか表示できてると思いますが
「MyTitle表示」という文字に注目してみます。
これはwinmain.cの"MyTitle表\示"部分が反映されてますが、表と示の間に\文字が
あります。
もしこの\文字を取り除いてコンパイルすると文字化けします。
これはシフトJISコードの0x5c問題というものです。
とりあえずは「表\示」や「\x95\x5c示」みたいにエスケープして回避するしか
なさそうですね。


※「表」以外にも0x5c問題の文字はいくつかあります
ソ 噂 欺 圭 構 蚕 十 申 貼 能 表 暴 予