0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WindowsAPIでメッセージボックスを表示する

Posted at

Windows API

C言語についてズブの素人がWindows APIを説明してみる試み。
間違いは沢山あると思いますので、参考にするかしないかはあなた次第かも。

そもそもこれなに?

Windows APIはC言語などから利用可能なWindowsの機能のことです。
Cの標準ライブラリではできないGUI周りのコードを書くことができます。

WindowsAPIの種類

Windows APIには様々な種類があります。

バージョン 説明
win16 初期のWindowsからWindows 9x系まで利用される。
win32 Windows NT系で利用された。
win64 Windows XPから利用される

メッセージボックスの表示

次のようなメッセージボックスを表示する。

image.png

HelloWorld.c
#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では次のように説明されています。

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  // デフォルトボタン用ビットマスク

また、ボタン、アイコン、デフォルトボタン、モーダルなどはビット単位の論理和演算子|で組み合わせて使うことができます。

HelloWorld.c
#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;
}

これを実行すると

image.png

と表示されました。アイコンとして情報マークが表示され、選択肢はYESNOCANCELのまま出力されました。

終わりに

細かい知識が身についた気がする。
難しいというかさまざまな定義を暗記する作業のような気がした。
意外と面白いのでこれからもWindowsAPIを触ってみたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?