goo blog サービス終了のお知らせ 

VCとDXと日記帳

VCとDXでプログラミング
最近はタクティクスオウガのみです…

Winプログラミング 1.0.5

2005-05-13 21:10:12 | Programming_Win
先ずはソースから見てもらいましょう


#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

//==============================================================================================
// Windows メイン処理
//==============================================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    // ウインドウクラスの登録
    WNDCLASS wc;
    ZeroMemory(&wc, sizeof(WNDCLASS));
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = (WNDPROC)WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = "Windows";
    if(!RegisterClass(&wc)) return 0;

    // ウインドウサイズの計算
    int window_width  = 640 + GetSystemMetrics(SM_CXDLGFRAME) * 2;
    int window_height = 480 + GetSystemMetrics(SM_CYDLGFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);

    // サイズの取得
    RECT desktop;
    SystemParametersInfo(SPI_GETWORKAREA, NULL, (LPRECT)&desktop, NULL);	 // デスクトップ(-タスクバー)

    // ウインドウの作成
    HWND hWnd = CreateWindow(
        wc.lpszClassName,
        "タイトル",
        WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX,
        (desktop.right  - window_width) / 2,
        (desktop.bottom - window_height) / 2,
        window_width,
        window_height,
        NULL,
        NULL,
        hInstance,
        NULL);

    // ウインドウの表示
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    // メッセージループ
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

//==============================================================================================
// ウインドウプロシージャ
//==============================================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_KEYDOWN:
       switch(wParam)
        {
        case VK_ESCAPE:
            PostQuitMessage(0);
        }

    case WM_DESTROY:
        // 終了メッセージ
        PostQuitMessage(0);

        return 0;

    default:
        // デフォルト処理
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
}


ゲームなどの場合ウィンドウ(もしくはクライアント)のサイズを指定する場合というのは
ユーザーに自由にそれらのサイズを変更されると困る場合があります
なので今回はサイズの変更が出来ないようにしました
スタイルをWS_OVERLAPPEDWINDOWは一般的なスタイルでサイズの変更が可能です
なので今回のスタイルはWS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOXです
WS_OVERLAPPEDWINDOWからWS_THICKFRAME(サイズ変更)とWS_MAXIMIZEBOX(ウィンドウの最大化)
をなくしたスタイルです

またクライアントのサイズを640*480にして
さらにウィンドウをデスクトップの中央に表示するようにしています
具体的にはSystemParametersInfo()にてデスクトップのサイズを取得し
デスクトップの大きさからウィンドウの大きさを2で割っています
そうすると左右、もしくは上下の大きさが等しくなる、つまり中央に表示することになります

またエスケープキーを押された場合終了するようにしています
(ウインドウプロシージャの部分)

ゲームならばあとは二重起動を禁止した方が良いかもしれません
それはまた後ほど

Winプログラミング 1.0.4.1

2005-05-07 01:36:07 | Programming_Win
Winプログラミング 1.0.4
訂正です

GetSystemMetrics()のパラメータ
SM_CXDLGFRAME,SM_CYDLGFRAMEは
タイトルバーがあり、サイズが変更できないウィンドウの周囲を囲む枠の幅と高さをピクセル単位で取得する
のでウィンドウのスタイルがWS_OVERLAPPEDWINDOW(サイズが変更可能だと)望む通りになりません

サイズ変更可能なウィンドウの場合は
SM_CXDLGFRAME,SM_CYDLGFRAMEではなく
SM_CXSIZEFRAME,SM_CYSIZEFRAMEを使ってください

つまり
int width = 640 + GetSystemMetrics(SM_CXSIZEFRAME) * 2;
int height = 480 + GetSystemMetrics(SM_CYSIZEFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
に直せばクライアント領域が640*480のウィンドウが作成されます

しかしクライアント領域を指定したい場合一般的には始終その大きさで動作させたい場合が普通でしょう(例えばゲーム)
そのような場合についてはまた後ほど

Winプログラミング 1.0.0.1

2005-05-02 23:53:01 | Programming_Win
int WINAPI WinMain()の戻り値なのですが

return msg.wParam;から
return (int)msg.wParam;へ変更すると警告が出なくなります

これはmsg.wParamをintへの変換(キャスト)を明示するわけです
変更しなくとも動作に問題は無いはずですが
警告が出なくなるので精神衛生上しておいたほうがいいです

Winプログラミング 1.0.4

2005-04-20 07:39:25 | Programming_Win
ウィンドウのサイズ変更です
サイズの変更にはSetWindowPos()を使います
メッセージループの前に


int width  = 640 + GetSystemMetrics(SM_CXDLGFRAME) * 2;
int height = 480 + GetSystemMetrics(SM_CYDLGFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);

SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, width, height, SWP_NOMOVE);


case WM_PAINT;のところを


case WM_PAINT:
    hDC = BeginPaint(hWnd, &ps);
    LineTo(hDC, 640, 480);
    EndPaint(hWnd, &ps);

    return 0;


と変更します

まずwidthとheightにウィンドウのサイズを代入します
ウィンドウのサイズ(width)はクライアント領域と非クライアント領域(GetSystemMetrics(SM_CXDLGFRAME) * 2;)です
(heightも同様)
SetWindowPos()の引数は
ウィンドウのハンドル, 配置順序のハンドル,
横方向の位置, 縦方向の位置,
幅, 高さ,
ウィンドウ位置のオプション
となっています
今回はサイズの変更だけなのでウィンドウ位置のオプションは
現在の位置を維持するSWP_NOMOVEとしました

case WM_PAINT;の部分では
クライアント領域の左上から右下にかけて線を描画しています
これで前回の問題が解消できました

Winプログラミング 1.1.5

2005-04-14 18:18:46 | Programming_Win
長方形の描画です
今回はcase WM_PAINT;の部分のみです


case WM_PAINT:
        hDC = BeginPaint(hWnd, &ps);

        LineTo(hDC, 639, 479);

        Rectangle(hDC, 10, 10, 210, 100);
        RoundRect(hDC, 10, 120, 210, 220, 20, 20);

        EndPaint(hWnd, &ps);

        return 0;


長方形の描画はRectangle()とRoundRect()があります
Rectangle()の引数は
HDC,
左上のx座標, 左上のy座標,
右下のx座標, 右下のy座標
となっています

RoundRect()は5番目の引数までは同じです
その後に
角の丸みの幅, 角の丸みの高さです

ともに四角の内部は塗りつぶされます

ところで線を描画している(始点を設定していないので0, 0 から639, 479まで)
のですがウィンドウサイズに合わせて描画しているはずですがうまくいっていません
これはタイトルバーやメニューバー等を含む大きさなのでこのようなことが起こってしまいます
これを正しくするにはクライアント領域(背景が白い部分)を640, 480にする必要があります
解決法はまた後ほど

Winプログラミング 1.1.4

2005-04-09 02:36:53 | Programming_Win
久々ですが今回も線の描画です
先ずはWinMain()の前に


POINT pt1[] = {{10, 10}, {110, 10}, {110, 110}, {10, 110}};
POINT pt2[] = {{250, 10}, {250,110}, {150, 110}, {150, 10}};


と先に書いておきます
次はおなじみcase WM_PAINT;の部分です


case WM_PAINT:
    hDC = BeginPaint(hWnd, &ps);

    Polyline(hDC, pt1, 4);

    MoveToEx(hDC, 150, 10, NULL);
    PolylineTo(hDC, pt2, 4);

    EndPaint(hWnd, &ps);

    return 0;


Polyline()は線の描画を行います
前回と同じく(10, 10)(110, 10)(110, 110)(10, 110)とコの字形に表示させました
が今回は1行(POINTの宣言を含めると2行)ですむのでよりコードが見やすくなるといえるでしょう
PolylineTo()はPolyline()とほぼ同じですが始点(カレントポジション)を設定する必要があります
もしくは前回書いた線の終点を始点として書くときに使います
始点を(150, 10)として(250, 10)(250,110)(150, 110)(150, 10)と正方形を描画しました

Winプログラミング 1.1.3

2005-03-24 23:49:45 | Programming_Win
今回は線の描画です
今回もウインドウプロシージャのcase WM_PAINT;部分だけを載せます


case WM_PAINT:
        // クライアント領域の再描画処理
        hDC = BeginPaint(hWnd, &ps); //デバイスコンテキストの取得
    MoveToEx(hDC, 10, 10, NULL);
    LineTo(hDC, 110, 10);
    LineTo(hDC, 110, 110);
    LineTo(hDC, 10, 110);
        EndPaint(hWnd, &ps); //デバイスコンテキストの解放

        return 0;


線の描画にはLineTo()を使います
まずMoveToEx()で始点を設定します
LineTo()で次の点を設定し描画します
今回は(10, 10)(110, 10)(110, 110)(10, 110)とコの字形に表示させました

Winプログラミング 1.1.2

2005-03-22 02:59:16 | Programming_Win
今回はピクセル制御です
ウインドウプロシージャのcase WM_PAINT;部分だけを載せます
他の部分の変更はありません


case WM_PAINT:
        // クライアント領域の再描画処理
        hDC = BeginPaint(hWnd, &ps); //デバイスコンテキストの取得
    SetPixel(hDC, 10, 30, 0x00000000);
    SetPixel(hDC, 11, 30, 0x00000000);
    SetPixel(hDC, 10, 31, 0x00000000);
    SetPixel(hDC, 11, 31, 0x00000000);
        EndPaint(hWnd, &ps); //デバイスコンテキストの解放

        return 0;


ピクセル制御を行うにはSetPixel()を使います
SetPixel()はピクセルの色を変更します
今回は1ピクセルではわかりにくいので(10,30)(11,30)(10,31)(11,31)の4ピクセルを
黒(0x00000000)に表示させました

Winプログラミング 1.1.1

2005-03-18 06:39:47 | Programming_Win
今回も文字列の表示です
が色を変えてみます
といっても前回からの変更は一行追加されただけです
今回もウインドウプロシージャだけです


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hDC; //デバイスコンテキストハンドル
    PAINTSTRUCT ps; //ペイント構造体

    char str[] = "表示したい文字列";

    switch(msg)
    {
    case WM_DESTROY:
        // 終了メッセージ
        PostQuitMessage(0);

        return 0;

    case WM_PAINT:
        // クライアント領域の再描画処理
        hDC = BeginPaint(hWnd, &ps); //デバイスコンテキストの取得
    SetTextColor(hDC, RGB(255, 0, 0)); //色を設定
        TextOut(hDC, 10, 10, str, lstrlen(str)); //文字列の表示
        EndPaint(hWnd, &ps); //デバイスコンテキストの解放

        return 0;

    default:
        // デフォルト処理-
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
}


追加されたのはSetTextColor()です
Rが255でGとBが0なので赤となります

SetTextColor(hDC, 0x000000ff);でも同じ結果になります
この場合最初の00、そしてBGRと逆になることに注意です
0xとは16進数表記という意味です
ff(16) = 255(10)ですので同じになるというわけです

Winプログラミング 1.1

2005-03-17 22:34:26 | Programming_Win
今回は文字列の表示です
ウインドウプロシージャのみの変更なのでウインドウプロシージャだけ
その他は
Winプログラミング 1.0
と同じです


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hDC; //デバイスコンテキストハンドル
    PAINTSTRUCT ps; //ペイント構造体

    char str[] = "表示したい文字列";

    switch(msg)
    {
    case WM_DESTROY:
        // 終了メッセージ
        PostQuitMessage(0);

        return 0;

    case WM_PAINT:
        // クライアント領域の再描画処理
        hDC = BeginPaint(hWnd, &ps); //デバイスコンテキストの取得
        TextOut(hDC, 10, 10, str, lstrlen(str)); //文字列の表示
        EndPaint(hWnd, &ps); //デバイスコンテキストの解放

        return 0;

    default:
        // デフォルト処理-
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
}


TextOut()
の引数は
デバイスコンテキストハンドル
描画開始座標X
描画開始座標Y
文字列のポインタ
文字数
となっています