いまさらwindowsプログラミング

ちょっと気分転換で、windowsプログラミングを。
VC++ExpressEditionを使っています。

WinMain

#include <windows.h>

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    return 0;
}

これまでのようにcoutで出力できるように、コンソールを割り当てましょう。

#include <windows.h>
#include <iostream>

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define new  ::new( _NORMAL_BLOCK, __FILE__, __LINE__ )


int main()
{
    std::cout << "hoge" << std::endl;
    return 0;
}

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    //メモリリークの検出
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    //コンソールの割り当て
    AllocConsole();
    FILE* out = 0; freopen_s( &out, "CON", "w", stdout );
    FILE* in = 0; freopen_s( &in, "CON", "r", stdin );

    int ret = main();
    getchar();

    //コンソール解放
    fclose( out );
    fclose( in );
    FreeConsole();

    return ret;
}

以降、int main()で処理を記述していきます。
main終了時にgetchar()を呼び出して停止しているので、必要なければ消してください。

ウィンドウの作成

ウィンドウの作り方はgoogle先生にお任せして、ここではすぐにクラス化していきます。
とりあえず、java風にしていきましょうか。
以下のように使用できるFrameクラスを作ります。

#include "System.h"
#include "Frame.h"

int main()
{
    std::cout << "hoge" << std::endl;

    //デフォルトのプロシージャを使って、ウィンドウクラスの登録。
    System::DefRegisterClass();
	
    //ウィンドウの作成
    Frame frame;
    frame.Create( 100, 100 );    //w, h

    System::MessageLoop();

    return 0;
}
System.h
#pragma once
#include <windows.h>

class System
{
private:
    static LRESULT CALLBACK WinProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
public:
    static bool DefRegisterClass();
    static void MessageLoop();
};
System.cpp
#include "System.h"

LRESULT CALLBACK System::WinProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
    if( msg == WM_DESTROY )
    {
        PostQuitMEssage( 0 );
        return 0;
    }
    return DefWindowProc( hwnd, msg, wp, lp );
}

bool System::DefRegisterClass()
{
    WNDCLASSEX wc =
    { 
        sizeof( WNDCLASSEX ),
        CS_HREDRAW | CS_VREDRAW,
        &System::WinProc,
        0, 0,
        GetModuleHandle( 0 ),
        LoadIcon( 0, IDI_APPLICATION ),
        LoadCursor( 0, IDC_ARROW ),
        ( HBRUSH )GetStockObject( BLACK_BRUSH ),
        0,
        "hoge",
        0
    };
    if( !RegisterClassEx( &wc ) )return false;

    return true;
}

void System::MessageLoop()
{
    MSG msg;
    while( GetMessage( &msg, 0, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

ウィンドウクラス名は適当に"hoge"となっています。

Frame.h
#pragma once
#include <windows.h>

class Frame
{
private:
    HWND hwnd;

public:
    Frame();
    ~Frame();

public:
    bool Create( int w, int h );
};
Frame.cpp
#include "Frame.h"

Frame::Frame()
    : hwnd( 0 )
{
}

Frame::~Frame(void)
{
}

bool Frame::Create( int w, int h )
{
    hwnd = CreateWindowEx
        ( 0
        , "hoge"
        , "title"
        , WS_OVERLAPPEDWINDOW
        , CW_USEDEFAULT
        , CW_USEDEFAULT
        , w
        , h
        , 0
        , 0
        , GetModuleHandle( 0 )
        , this
        );
    if( hwnd == 0 )return false;

    ShowWindow( hwnd, SW_SHOW );

    return true;
}

インスタンスハンドルはWinMainから渡してくるのが面倒だったので、GetModuleHandle( 0 )で取得しています。

次回はイベントを処理できるようにリスナを作っていきます。
自作functionを使っていきたいですね。