Windowsプログラムのいろはは、DOS窓でWin32API

|

Windowsアプリケーションの特徴はウィンドウ。GUIプログラムの基本もウィンドウ。って事は、全てのWindowsアプリケーションはGUIアプリケーション?

などと考えている内に、Win32APIでも触ってみるかという事に。

試しに、Windowsのウィンドウを表示させるだけのサンプルを作ってみました。

ただ、素人にはウィンドウ・プログラムの基本動作は任せられないとマイクロソフトが想定したかどうかは分かりませんが、ウィンドウクラスの登録(RegisterClassEx API)とウィンドウの生成(CreateWindowEx API)で、ほぼ最低限の機能を持つウィンドウが表示されたのには感心しました。


<注意点>

・サンプルを実行すると、プログラム終了と同時にウィンドウが閉じてしまうので、最低限の動作を確認できるように return の直前でメッセージボックス関数を呼び出し、何某かの入力待ちとなるようにしています。

・今回はウィンドウを表示するだけなので、Windowsメッセージを処理する関数は登録しません。代わりにWNDCLASSEXの lpfnWndProc には、デフォルトの処理を実行してくれる DefWindowProc API を登録します。

「stdio.h」を「cstdio」に変更することで、.cppファイルとしてもコンパイル出来ます。


【WNDCLASSEXの構造体】

WNDCLASSEX構造体のメンバー
メンバー名説明
cbSize UINT WNDCLASSEX 構造体のサイズ
style UINT クラスのスタイル
lpfnWndProc WNDPROC ウィンドウ・プロシージャ(関数)のポインタ
cbClsExtra UINT ウィンドウ・クラスの追加データサイズ
cbWndExtra UINT ウィンドウ毎の追加データサイズ
hInstance HINSTANCE 実行プログラムのインスタンス・ハンドル
hIcon HICON ウィンドウを最小化した時に表示に使用されるアイコン
hCursor HCURSOR マウスカーソルがウィンドウ上にある時のカーソル形状
hbrBackground HBRUSH ウィンドウのクライアント領域を塗り潰すのに使うブラシ
lpszMenuName LPCTSTR メニュー名(デフォルトでリソースID)
lpszClassName LPCTSTR ウィンドウ・クラス名
hIconSm HICON システム・メニューに表示される小さなアイコン


【CreateWindowExの引数】

CreateWindowEx APIのパラメータ
パラメータ名説明
dwExStyle DWORD 拡張ウィンドウスタイル(CreateWindowEx API のみ)
lpClassName LPCTSTR ウィンドウ・クラス名
lpWindowName LPCTSTR ウィンドウ名(タイトルバーなどに表示)
dwStyle DWORD ウィンドウ・スタイル
x int ウィンドウの初期位置(左上隅、x座標)
y int ウィンドウの初期位置(左上隅、y座標)
nWidth int ウィンドウの初期サイズ、横幅
nHeight int ウィンドウの初期サイズ、高さ
hWndParent HWIND 子ウィンドウ、親ウィンドウのハンドル
上記以外、 所有ウィンドウのハンドル
hMenu HMENU 子ウィンドウ、子ウィンドウID
上記以外、 メニュー・ハンドル(デフォルトの場合NULL)
hInstance HINSTANCE ウィンドウ・クラスのインスタンス・ハンドル
lpParam LPVOID 任意のパラメータ


お試し環境
  WindowsXP 32bit Edition
  Visual C++ 2008


/*---- Win32API ウィンドウ 作成 ------------- コマンドライン ---------------*/

D:\vc2008\dllchk>cl test.c user32.lib

/*----------------------------------------------------------------------------*/


/*---- test.c ------------------------ お試しソース ------------------------*/

#include <stdio.h>
#include <windows.h>

#define WINCLASS_NAME "Form.003"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wcx;
    int ret;

    /* ウィンドウクラスの登録 */
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.style = CS_HREDRAW | CS_VREDRAW;
    wcx.lpfnWndProc = DefWindowProc;
    wcx.cbClsExtra = 0;
    wcx.cbWndExtra = 0;
    wcx.hInstance = hInstance;
    wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcx.lpszMenuName = NULL;
    wcx.lpszClassName = WINCLASS_NAME;
    wcx.hIconSm = NULL;

    if(!RegisterClassEx(&wcx)) {
        printf("ウィンドウクラスの登録が出来ませんでした。\n");
        return(0);
    }

    /* 登録したクラスのウィンドウを生成 */
    hWnd = CreateWindowEx(WS_EX_LEFT, WINCLASS_NAME, "ウインドウタイトル3", WS_OVERLAPPEDWINDOW, 50, 50, 400, 300, NULL, NULL, hInstance ,NULL);
    if(hWnd == NULL) {
        printf("ウィンドウが作成出来ませんでした。\n");
        return(FALSE);
    }

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

    ret = MessageBox(NULL, "人為的地球温暖化はあやかしだと思うか?", "気候変動", MB_YESNOCANCEL | MB_ICONQUESTION);
    switch(ret) {
    case IDYES :
        MessageBox(NULL, "地球は訴えかけている\n命を護る行動を", "全てを救え、頼んだぞ", MB_OK | MB_ICONWARNING);
        break;
    case IDNO :
        MessageBox(NULL, "宇宙線は囁いている\n坐して死を待つのかと", "地球寒冷化だ", MB_OK | MB_ICONERROR);
        break;
    default :
        MessageBox(NULL, "防御態勢を整えながら\n次の衝撃波に備えよ", "総員配置に付け", MB_CANCELTRYCONTINUE | MB_ICONSTOP);
        break;
    }

    return(0);
}

/*----------------------------------------------------------------------------*/
/*============================================================================*/