Windows API
C言語についてズブの素人がWindows APIを説明してみる試み。
間違いは沢山あると思いますので、参考にするかしないかはあなた次第かも。
WindowsAPIの種類
Windows APIには様々な種類があります。
バージョン | 説明 |
---|---|
win16 | 初期のWindowsからWindows 9x系まで利用される。 |
win32 | Windows NT系で利用された。 |
win64 | Windows XPから利用される |
メッセージボックスの表示
次のようなメッセージボックスを表示する。
#include <windows.h>
#include <tchar.h>
int WINAPI WinMain(
HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, _T("Hello world"), _T("Hello Qiita"), MB_OK);
return 0;
}
むずかしいところが多いので一つ一つ解説していきます。
#include <windows.h>
windows.hはWindows APIを利用するためのヘッダファイルです。
また、これはさらにいくつかの小さなヘッダファイルをインクルードするファイル(マスターインクルードファイル)です。
例えば以下のようなヘッダファイルをインクルードします。
- windef.h:固有の型定義(INT, LONG, FLOAT, CHAR, PSTR, etc)
- winbase.h:最低限の関数プロトタイプ、構造体、define
- wingdi.h:グラフィックス関連
- etc...
ヘッダファイルとは
プログラムにおいて使用される定数、関数、変数その他さまざまの宣言する必要があるデータ・命令の宣言を記述したファイル。
ソースファイルの一部となってコンパイラに読み込まれる形となる。
int WINAPI WinMain(...
ここはちょっとむずかった
WINAPIってなに?
先ほど説明したwindows.hの小ファイルであるwindef.hでは次のように説明されています。
#define WINAPI __stdcall
次のように定義されていました。__stdcallというのはWin32 API関数を呼び出すときの規約です。この規則とは
- 関数が呼び出されたときに引数がどのようにメモリのスタックという位置に配置されるか
- 関数の戻り値がどのように扱われるか
を定義するルールのことです。
そしてほとんどのWindows関数はWin 32 API関数を呼び出す規約、要はWINAPI(__stdcall)で定義されています。
注意すべき点として、WINAPIは関数がとる引数の型や引数の数を定義しているわけではないということです。
WinMain関数ってなに?
重要なことですが、Windowsプログラムにmain関数はないです。
プログラムの開始点はWinMainとなります。このWinMainはWindowsアプリケーション専用のものであり、GUIアプリケーションに合わせた4つの引数をとります。
第一引数はHINSTANCEと呼ばれる型です。
インスタンスハンドルとは、プログラムの識別をするためのハンドルです。
また、これはアプリケーションのリソース管理やウィンドウ作成など、アプリケーションの初期化、管理につかわれます。
ハンドル
OSやアプリケーションが内部でリソースを管理するために使用する識別子です。この識別子はポインタや番号として現れます。
ファイルハンドルであるHANDLE型やウィンドウハンドルであるHWND型、リソースハンドルであるHINSTANCE型などで使われます。
第二引数は同様にインスタンスハンドルの型をとりますが、32bit Windowsの場合は常にNULL
をとります。
16bit Windowsではアプリケーションが同時に複数実行されていることがありました。このhPrevInstanceは、現在のアプリケーションが起動する前に実行されていた同じアプリケーションのインスタンスのハンドルが示されており、
前回起動したインスタンスにアクセスすることができたのです。
32bit Windowsではアプリケーションは同じプロセス空間で動作するために、前回や今回などの区別はなくなり、hPrevInstanceはもはや意味を持たなくなりました。
その結果hPrevInstanceの値は常にNULL
として渡される様になりました。
第三引数はLPSTR(Windows標準の文字型)の型をとります。
コマンドラインから引数をうけとります。なお、Windows APIではスペースで区切っても、一つの文字列として認識されます。
第四引数は整数型をとります。
ここにはウィンドウの表示状態を表す整数値が入ります。ShowWindow
関数に渡してウィンドウの表示方法を最大化、最小化、通常表示にするかを指定したりに使います。
MessageBox(...)
名前の通りメッセージボックスを表示に表示します。
これは4つの引数をとります。
第一引数にはhInstance型をとります。
ここにウィンドウハンドルを指定すると、メッセージボックスがそのウィンドウの上に表示されたり、親ウィンドウの操作をメッセージボックスの操作を終えるまで制限したりします。
ここでは主な親ウィンドウが無いのでNULLにします。
第二引数にはLPCSTR型をとります。
これはLong Pointer to Constant TString
という意味で文字列を表します。
要は文字列型です。ここに入力された引数はメッセージボックスの表示内容となります。TEXT関数は文字列をTCHARの文字列リテラルに変換することができます。
第三引数にはLPCSTR型をとります。
ここに入力された引数はメッセージボックスのタイトルとなります。
第四引数にはUINT型をとります。
これはunsigned intのことで非負整数を指しています。
通常のINT型では正の数は
$2^{31} - 1$ = $2,147,483,647$まで表現可能ですが、
正だけしか使えない反面、使用できるデータは1bit分増えて表現できる正の数が
$2^{32} - 1$ = $4,294,967,295$まで表現可能です。
ただ、これは普通、定数で指定します。MB_OK
はOKボタンを表示します。
これらの定数はwinuser.h
で定義されています。
以下の表が定義された定数です。
// ボタンの種類
#define MB_OK 0x00000000 // OKボタンのみ
#define MB_OKCANCEL 0x00000001 // OKとキャンセルボタン
#define MB_ABORTRETRYIGNORE 0x00000002 // 中止、再試行、無視ボタン
#define MB_YESNOCANCEL 0x00000003 // はい、いいえ、キャンセルボタン
#define MB_YESNO 0x00000004 // はいといいえボタン
#define MB_RETRYCANCEL 0x00000005 // 再試行とキャンセルボタン
// アイコンの種類
#define MB_ICONHAND 0x00000010 // ハンドアイコン (停止)
#define MB_ICONQUESTION 0x00000020 // クエスチョンアイコン (疑問)
#define MB_ICONEXCLAMATION 0x00000030 // 警告アイコン (感嘆)
#define MB_ICONASTERISK 0x00000040 // 情報アイコン (アスタリスク)
// デフォルトボタンの種類
#define MB_DEFBUTTON1 0x00000000 // デフォルトボタン1
#define MB_DEFBUTTON2 0x00000100 // デフォルトボタン2
#define MB_DEFBUTTON3 0x00000200 // デフォルトボタン3
#define MB_DEFBUTTON4 0x00000300 // デフォルトボタン4
// モーダルの種類
#define MB_APPLMODAL 0x00000000 // アプリケーションモーダル
#define MB_SYSTEMMODAL 0x00001000 // システムモーダル
#define MB_TASKMODAL 0x00002000 // タスクモーダル
// その他
#define MB_ICONMASK 0x000000F0 // アイコン用ビットマスク
#define MB_DEFMASK 0x00000300 // デフォルトボタン用ビットマスク
また、ボタン、アイコン、デフォルトボタン、モーダルなどはビット単位の論理和演算子|で組み合わせて使うことができます。
#include <windows.h>
int WINAPI WinMain(
HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, TEXT("Hello World"), TEXT("Hello Qiita"), MB_YESNOCANCEL | MB_ICONASTERISK);
return 0;
}
これを実行すると
と表示されました。アイコンとして情報マークが表示され、選択肢はYESNOCANCEL
のまま出力されました。
終わりに
細かい知識が身についた気がする。
難しいというかさまざまな定義を暗記する作業のような気がした。
意外と面白いのでこれからもWindowsAPIを触ってみたい。