前回はコマンドラインで実行して文字を表示するだけのプログラムでしたが、
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_OPEN 10002
■wndproc.c
(送られたメッセージを元にいろいろな処理をする。ウィンドウプロシージャ)
#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
(リソースファイル メニュー付加用)
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関数から始まります)
#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コンパイル手順を書いて最終的なプログラムを出力)
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問題の文字はいくつかあります
ソ 噂 欺 圭 構 蚕 十 申 貼 能 表 暴 予