Windowsアプリケーションの特徴はウィンドウ。GUIプログラムの基本もウィンドウ。って事は、全てのWindowsアプリケーションはGUIアプリケーション?
などと考えている内に、Win32APIでも触ってみるかという事に。
試しに、Windowsのウィンドウを表示させるだけのサンプルを作ってみました。
ただ、素人にはウィンドウ・プログラムの基本動作は任せられないとマイクロソフトが想定したかどうかは分かりませんが、ウィンドウクラスの登録(RegisterClassEx API)とウィンドウの生成(CreateWindowEx API)で、ほぼ最低限の機能を持つウィンドウが表示されたのには感心しました。
<注意点>
・サンプルを実行すると、プログラム終了と同時にウィンドウが閉じてしまうので、最低限の動作を確認できるように return の直前でメッセージボックス関数を呼び出し、何某かの入力待ちとなるようにしています。
・今回はウィンドウを表示するだけなので、Windowsメッセージを処理する関数は登録しません。代わりにWNDCLASSEXの lpfnWndProc には、デフォルトの処理を実行してくれる DefWindowProc API を登録します。
「stdio.h」を「cstdio」に変更することで、.cppファイルとしてもコンパイル出来ます。
【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の引数】
パラメータ名 | 型 | 説明 |
---|---|---|
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);
}
/*----------------------------------------------------------------------------*/
/*============================================================================*/