落書きノート

ふと自分が気になった事を書いてます

Win32APIのプログラムをコマンドでビルドする

VSでプロジェクト作成をすればできますが、試している段階では色々と面倒なので、ファイル単位で作成して試したいですよね。そういう時にこのようにすればお手軽に試せます。

#pragma comment(lib, "user32")
#pragma comment(lib, "gdi32")
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);

char szClassName[] = "sample01";

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
    LPSTR lpsCmdLine, int nCmdShow) {
    MSG msg;
    BOOL bRet;

    if (!InitApp(hCurInst))
        return FALSE;
    if (!InitInstance(hCurInst, nCmdShow))
        return FALSE;
    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
        if (bRet == -1) {
            MessageBox(NULL, "GetMessageエラー", "Error", MB_OK);
            break;
        }
        else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int)msg.wParam;
}

ATOM InitApp(HINSTANCE hInst) {
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = (HICON)LoadImage(NULL,
        MAKEINTRESOURCE(IDI_APPLICATION),
        IMAGE_ICON,
        0,
        0,
        LR_DEFAULTSIZE | LR_SHARED);
    wc.hCursor = (HCURSOR)LoadImage(NULL,
        MAKEINTRESOURCE(IDC_ARROW),
        IMAGE_CURSOR,
        0,
        0,
        LR_DEFAULTSIZE | LR_SHARED);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = (LPCSTR)szClassName;
    wc.hIconSm = (HICON)LoadImage(NULL,
        MAKEINTRESOURCE(IDI_APPLICATION),
        IMAGE_ICON,
        0,
        0,
        LR_DEFAULTSIZE | LR_SHARED);

    return (RegisterClassEx(&wc));
}

BOOL InitInstance(HINSTANCE hInst, int nCmdShow) {
    HWND hWnd;

    hWnd = CreateWindow(szClassName,
        "Win32APIテスト",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInst,
        NULL);
    if (!hWnd)
        return FALSE;
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return (DefWindowProc(hWnd, msg, wp, lp));
    }
    return 0;
}

行頭にpragma宣言をして、以下のようなコマンドでビルドします。

> cl.exe sample01.cpp user32.lib gdi32.lib

普通のコマンドプロンプトPowershell,Cmderとかでは開発ツールのパスが通ってないので、vcvarsall.batを実行してパスを通さないといけません。ファイルの場所を指定するのが面倒なので、VSに付属している開発者用コマンドプロンプトを使えば簡単にできるようになってます。vcvarsall.batのシンボリックリンクをmklink /Dで作成してもうまくいかなかったのでこうしました。開発者用コマンドプロンプトのショートカットのプロパティで作業用ディレクトリのパスを変更すれば便利に使えます。MS謹製のnmakeコマンドを使えば簡略化できるというのを見ましたが、使い方が・・・。

この方法以外で手軽に試す方法としてMinGW(gcc)もありますね。多分同じように使えると思います。Makefileを用意すれば簡略化できるかも。コマンドはmsys2のbashとかでできそうですかね。Chocolateyでmsys2をインストールすれば簡単にできますね。エディタはVSCodeとかNTEmacsとか。

追記

エディタは、VS2015のエディタを使ってます。Intellisenseの入力補完、凄い便利。おかげで楽になりました。VSCodeやNTEmacsでもできますよ。