読者です 読者をやめる 読者になる 読者になる

個人的自由ノート

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

ボタンにイベントを付加する 文字列を描画する Win32API

イベント付加と文字列描画を兼ねてやってみました。

#pragma comment(lib, "user32")
#pragma comment(lib, "gdi32")
#include <windows.h>
#define ID_BUTTON1 1000
#define ID_BUTTON2 1001

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

char szClassName[] = "sample01";
char szButtonName[] = "BUTTON";

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 | WS_VISIBLE,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInst,
        NULL);
    CreateWindow(szButtonName,
        "Test",
        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
        200,
        200,
        100,
        50,
        hWnd,
        (HMENU)ID_BUTTON1,
        hInst,
        NULL
    );
    CreateWindow(szButtonName,
        "Test2",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        300,
        200,
        100,
        50,
        hWnd,
        (HMENU)ID_BUTTON2,
        hInst,
        NULL);
    if (!hWnd)
        return FALSE;
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
    HDC hdc;
    PAINTSTRUCT ps;
    static RECT rect;
    static LPTSTR str;
    static PCTSTR ctstr = "テスト";

    switch (msg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        GetClientRect(hWnd, &rect);
        DrawText(hdc, ctstr, -1, &rect,
            DT_CENTER | DT_BOTTOM | DT_WORDBREAK);
        EndPaint(hWnd, &ps);
        break;
    case WM_COMMAND:
        if (HIWORD(wp) == BN_CLICKED) {
            if (LOWORD(wp) == ID_BUTTON1) {
                str = "あいうえお one two three four five";
                hdc = GetDC(hWnd);
                TextOut(hdc, 10, 10, str, lstrlen(str));
                ReleaseDC(hWnd, hdc);
            }
            if (LOWORD(wp) == ID_BUTTON2) {
                str = "かきくけこ kitty on your lap";
                hdc = GetDC(hWnd);
                TextOut(hdc, 10, 40, str, lstrlen(str));
                ReleaseDC(hWnd, hdc);
            }
        }
        break;
    default:
        return (DefWindowProc(hWnd, msg, wp, lp));
    }
    return 0;
}

ニコニコ動画のコメントのようにボタンを押すと文字列がアニメーションする・・・というのをやりたかったのですが、アニメーション機能がないようなので諦めました。DirectXならできるかもしれませんね。多分。

f:id:kh2n:20170413043302p:plain

猫でもわかるWindowsプログラミング 第4版 (猫でもわかるプログラミング)

猫でもわかるWindowsプログラミング 第4版 (猫でもわかるプログラミング)

The sight of spira FFX HD OST


Final Fantasy X HD Remaster OST - Spiran Scenery / Spira Unplugged [HD]

ボタンの作成 Win32API

少し調べたらすぐ載っていることですので、投稿するほどでもないのですが、まずはボタンの作成から。

#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";
char szButtonName[] = "BUTTON";

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 | WS_VISIBLE,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInst,
        NULL);
    CreateWindow(szButtonName,
        "Test",
        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
        0,
        0,
        100,
        50,
        hWnd,
        NULL,
        hInst,
        NULL
    );
    CreateWindow(szButtonName,
        "Test2",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        100,
        0,
        100,
        50,
        hWnd,
        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;
}

CreateWindow関数でボタンを作成しています。普通に考えると面倒ですけど、慣れたら面白いです。

f:id:kh2n:20170412170806p:plain

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

Win32APIで気を良くしたのか、DirectX9でもやってみることにしました。まあ、そろそろ11か12を使えという話なんですけど、持ってる資料が9向けのものが多いです。Windows10でDirectX9のインストールは面倒でしたが、使えてるのでこれで良いかなと。

//  Direct X 9 Sample Program 
//  立方体4個が回転する
// 32bit/64bit マルチバイト/Unicode対応 Visual C++ 2008

#define     szClassName TEXT("3D Box Rotate")

#include <windows.h>
#include <d3dx9.h>
#include <dxerr.h>
#include <tchar.h>

#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"user32.lib")

//頂点フォーマット

#define D3DFVF_VERTEX  (D3DFVF_XYZ | D3DFVF_DIFFUSE)   //トランスフォームされていない頂点の位置座標+ディフューズ カラー成分

typedef struct _D3DVERTEXCOR_ {
    float   x, y, z;   // トランスフォームされていない頂点の位置座標
    DWORD   color;  // ディフューズ カラー成分
}   D3DVERTEXCOR;


#define TIME_SET 500.0f   //  立方体を回転させるスピード 1/1000秒単位

HWND                    hWnd;
LPDIRECT3DDEVICE9       g_pDEV = 0;
LPDIRECT3D9             pD3D;
D3DPRESENT_PARAMETERS   D3DPPWin;


// 立方体の頂点座標を定義(座標は立方体の中心を原点とする)


D3DVERTEXCOR v1[] =     //前面赤の矩形 
{ { -50, -50,  50, 0xffff0000 },
{ 50, -50,  50, 0xffff0000 },
{ -50,  50,  50, 0xffff0000 },
{ 50,  50,  50, 0xffff0000 } };
D3DVERTEXCOR v2[] =     //右側面緑の矩形
{ { 50, -50,  50, 0xff00ff00 },
{ 50, -50, -50, 0xff00ff00 },
{ 50,  50,  50, 0xff00ff00 },
{ 50,  50, -50, 0xff00ff00 } };
D3DVERTEXCOR v3[] =     //上面青の矩形
{ { -50, -50, -50, 0xff0000ff },
{ 50, -50, -50, 0xff0000ff },
{ -50, -50,  50, 0xff0000ff },
{ 50, -50,  50, 0xff0000ff } };
D3DVERTEXCOR v4[] =     //左側面黄の矩形
{ { -50,  50,  50, 0xffffff00 },
{ -50,  50, -50, 0xffffff00 },
{ -50, -50,  50, 0xffffff00 },
{ -50, -50, -50, 0xffffff00 } };
D3DVERTEXCOR v5[] =     //裏面紫の矩形 
{ { -50,  50, -50, 0xffff00ff },
{ 50,  50, -50, 0xffff00ff },
{ -50, -50, -50, 0xffff00ff },
{ 50, -50, -50, 0xffff00ff } };
D3DVERTEXCOR v6[] =     //下面白の矩形
{ { 50,  50, -50, 0xffffffff },
{ -50,  50, -50, 0xffffffff },
{ 50,  50,  50, 0xffffffff },
{ -50,  50,  50, 0xffffffff } };

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HRESULT Init3DDev(HWND hwnd);
void  SetupMatrices(float x, float y, float z = 0);
void Draw(void);


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) {
    MSG     msg;

    WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst,
        NULL,NULL,NULL,NULL,szClassName,NULL };
    if (RegisterClassEx(&wc) == 0)
        return FALSE;
    HWND  hWnd = CreateWindowEx(0, szClassName, szClassName, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 600, 600,
        NULL, NULL, hInst, NULL);
    if (FAILED(Init3DDev(hWnd)))  return FALSE;

    ShowWindow(hWnd, SW_SHOWDEFAULT);
    UpdateWindow(hWnd);
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT) {
        if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
            Draw();
    }
    g_pDEV->Release();
    pD3D->Release();
    UnregisterClass(szClassName, wc.hInstance);
    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0L;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

//デバイス/モード等の初期化
HRESULT Init3DDev(HWND hwnd) {

    hWnd = hwnd;
    pD3D = NULL;
    HRESULT     hr;
    D3DDISPLAYMODE          dmode;

    // デバイス/モード等の初期化
    if (pD3D == NULL)
        pD3D = Direct3DCreate9(D3D_SDK_VERSION);
    if (pD3D == NULL)
        return E_FAIL;
    //現在のディスプレイモードを得る
    if (FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dmode)))
        return E_FAIL;

    // D3DDeviceオブジェクトの作成
    ZeroMemory(&D3DPPWin, sizeof(D3DPPWin));
    D3DPPWin.BackBufferFormat = dmode.Format;
    D3DPPWin.BackBufferCount = 1;
    D3DPPWin.SwapEffect = D3DSWAPEFFECT_DISCARD;
    D3DPPWin.Windowed = TRUE;
    D3DPPWin.EnableAutoDepthStencil = TRUE;
    D3DPPWin.AutoDepthStencilFormat = D3DFMT_D16;
    D3DPPWin.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

    hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
        D3DCREATE_HARDWARE_VERTEXPROCESSING, &D3DPPWin, &g_pDEV);
    if (FAILED(hr)) {
        hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPPWin, &g_pDEV);
        if (FAILED(hr)) {
            hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPPWin, &g_pDEV);
            if (FAILED(hr)) {
                MessageBox(NULL, TEXT("Create Device Error"), TEXT("Surface Error"), MB_OK);
                return E_FAIL;
            }
        }
    }
    return S_OK;
}



//描画環境の設定
void  SetupMatrices(float x, float y, float z) {
    D3DXMATRIX      matView;
    D3DXMATRIX      matProj;
    D3DXMATRIX      w;

    D3DXVECTOR3 v;
    v.x = -x;
    v.y = -z;
    v.z = -y;

    D3DXMatrixRotationAxis(&w, &v, timeGetTime() / TIME_SET); // 任意の軸を回転軸にして回転する行列を作成する。 システム時刻をミリ秒単位で取得


    D3DXMatrixTranslation(&matView, x, y, z); // オフセットを指定して行列を作成する。

    matView = w*matView;
    g_pDEV->SetTransform(D3DTS_VIEW, &matView);

    //透視変換の設定
    D3DXMatrixPerspectiveFovLH(&matProj, D3DXToRadian(45.0f), 1.0f, -300, 300); // 視野に基づいて、左手座標系パースペクティブ射影行列を作成する
    g_pDEV->SetTransform(D3DTS_PROJECTION, &matProj);
    //描画設定
    g_pDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);     //反時計回りの面を消去
    g_pDEV->SetRenderState(D3DRS_LIGHTING, FALSE);           //ライティングしない
    g_pDEV->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);      //Zバッファ使わない
}

//描画処理
void Draw(void) {
    if (!g_pDEV)
        return;
    //黒で塗りつぶして消去
    g_pDEV->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);
    //描画の開始
    g_pDEV->BeginScene();

    //描画環境の設定

    SetupMatrices(80, 80, 400);
    //デバイスに使用する頂点フォーマットをセットする
    g_pDEV->SetFVF(D3DFVF_VERTEX);
    //ストリームを使わないで直接データを渡して描画する
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v1, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v2, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v3, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v4, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v5, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v6, sizeof(D3DVERTEXCOR));

    SetupMatrices(80, -80, 400);
    //ストリームを使わないで直接データを渡して描画する
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v1, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v2, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v3, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v4, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v5, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v6, sizeof(D3DVERTEXCOR));

    SetupMatrices(-80, 80, 400);
    //ストリームを使わないで直接データを渡して描画する
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v1, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v2, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v3, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v4, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v5, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v6, sizeof(D3DVERTEXCOR));

    SetupMatrices(-80, -80, 400);
    //ストリームを使わないで直接データを渡して描画する
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v1, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v2, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v3, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v4, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v5, sizeof(D3DVERTEXCOR));
    g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v6, sizeof(D3DVERTEXCOR));

    g_pDEV->EndScene();
    g_pDEV->Present(NULL, NULL, NULL, NULL);
}
> cl.exe buildtest.cpp d3d9.lib d3dx9.lib winmm.lib user32.lib

環境変数はINCLUDEにDX9のインクルードパスを、LIBとLIBPATHにライブラリパスを。エラーが出たので、x86を優先して設定してます。これで試しやすくなりました。

f:id:kh2n:20170412004606p:plain

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でもできますよ。

OCamlで問題を解く

open Printf;;
print_string "整数値 : ";;
let num = read_int();;
let rec search n = if num = n then
                     printf "%d\n" n
                   else if num mod n = 0 then
                     begin
                       printf "%d " n;
                       search (n + 1)
                     end
                   else
                     search (n + 1);;
search 1;;



open Printf;;
print_string "nの値 : ";;
let n = read_int();;
let rec pow s = printf "%dの2乗は%d\n" s (s * s);
                if s = n then
                  ()
                else
                  pow (s + 1);;
pow 1;;

C言語で問題を解く

#include <stdio.h>

int main(void) {
  int a,b;
  printf("aの値 : ");
  scanf("%d", &a);
  while(1) {
    printf("bの値 : ");
    scanf("%d", &b);
    if(a >= b)
      printf("aより大きな値を入力せよ!\n");
    else
      break;
  }
  printf("b - aは%dです。\n", b - a);
  return 0;
}


#include <stdio.h>

int main(void) {
  int a;
  int keta = 0;
  printf("正の整数値 : ");
  scanf("%d", &a);
  while(a) {
    a /= 10;
    keta++;
  }
  printf("桁数は%dです。\n", keta);
  return 0;
}



#include <stdio.h>

int main(void) {
  printf("   |  1  2  3  4  5  6  7  8  9\n");
  printf("---+---------------------------\n");
  int i,j;
  for(i = 1; i < 10; i++) {
    printf(" %d |", i);
    for(j = 1; j < 10; j++) {
      printf(" %2d", i * j);
    }
    printf("\n");
  }
  return 0;
}



#include <stdio.h>

int main(void) {
  printf("   |  1  2  3  4  5  6  7  8  9\n");
  printf("---+---------------------------\n");
  int i,j;
  for(i = 1; i < 10; i++) {
    printf(" %d |", i);
    for(j = 1; j < 10; j++) {
      printf(" %2d", i + j);
    }
    printf("\n");
  }
  return 0;
}



#include <stdio.h>

int main(void) {
  int a, i, j;
  printf("段数は : ");
  scanf("%d", &a);
  for(i = 0; i < a; i++) {
    for(j = 0; j < a; j++) {
      printf("*");
    }
    puts("");
  }
  return 0;
}




#include <stdio.h>

int main(void) {
  int h, w, i, j;
  printf("高さは : ");
  scanf("%d", &h);
  printf("横幅は : ");
  scanf("%d", &w);
  for(i = 0; i < h; i++) {
    for(j = 0; j < w; j++) {
      printf("*");
    }
    puts("");
  }
  return 0;
}