前回は、Microsoft C/C++とWindows APIを使ってダイアログボックスを表示するサンプルを取り上げ、最も基本的なビルドから実行までを説明した。今回は前回取り上げたダイアログボックスを深堀りしていく。ダイアログボックスはソースコードがシンプルでありつつも、挙動を変えるGUIの部品であり、最初に触れるにはちょうどよいのだ。

MessageBox()関数を知る

前回、MessageBox()関数でダイアログを生成できるという話をしたが、もう少し追ってみよう。まず、MessageBox()関数のマニュアルを見ておきたい。これでを読めば大体のことは把握できると思う。

MessageBox function (winuser.h) - Win32 apps | Microsoft Docs

MessageBox()関数はモーダルダイアログボックスを表示する関数だ。次のような書式で呼び出すことになっている。

int MessageBox(

[in, optional] HWND hWnd,

[in, optional] LPCTSTR lpText,

[in, optional] LPCTSTR lpCaption,

[in] UINT uType

);

引数として指定するパラメータの意味は次のとおりだ。

ダイアログボックスのタイトル(lpCaption)とメッセージ(lpText)は任意のテキストを指定することができる。表示するアイコンはあらかじめ用意されているシステムアイコンから選択するほか、表示するボタンもあらかじめ用意されているものを指定することで利用する仕組みになっている。

指定する4つ目のパラメータであるuTypeに指定するフラグが、MessageBox()で表示されるダイアログのUI/UXを設定している。ここには、次のフラグを指定できるようになっている。

このようにシンプルなMessageBox()のモーダルダイアログボックスだが、必要に応じてボタンやアイコンまたはそのほかの挙動を変更できる。MessageBox()ができることを調べるプログラムを作ってみよう。



MessageBox()の動作を調べるプログラム

まず基本的なところとして、(1) 表示するボタン、(2) 表示するアイコン、(3) どのボタンが押されたかの判定について知っておきたいところだ。

ということで、前回のhelloworld.cプログラムを、次のように書き換えてみよう。

helloworld.c

/*

* Reference:

* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winmain

* https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox

*/

#include

void

check_ret(int retCode)

{

LPCTSTR lpText;

switch(retCode) {

case IDOK:

lpText = "「OK」ボタンが押されました。";

break;

case IDCANCEL:

lpText = "「キャンセル」ボタンが押されました。";

break;

case IDABORT:

lpText = "「中止」ボタンが押されました。";

break;

case IDRETRY:

lpText = "「再試行」ボタンが押されました。";

break;

case IDIGNORE:

lpText = "「無視」ボタンが押されました。";

break;

case IDYES:

lpText = "「はい」ボタンが押されました。";

break;

case IDNO:

lpText = "「いいえ」ボタンが押されました。";

break;

case IDTRYAGAIN:

lpText = "「再実行」ボタンが押されました。";

break;

case IDCONTINUE:

lpText = "「続行」ボタンが押されました。";

break;

}

MessageBox(NULL, lpText, "押されたボタン", MB_OK);

}

int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow)

{

LPCTSTR lpText = "新大陸へようこそ!";

LPCTSTR lpCaption = "はじめてのウィンドウプログラミング";

int ret;

// 「OK」

ret = MessageBox(NULL, lpText, lpCaption, MB_OK);

check_ret(ret);

// 「OK」「キャンセル」

ret = MessageBox(NULL, lpText, lpCaption, MB_OKCANCEL);

check_ret(ret);

// 「中止」「再試行」「無視」

ret = MessageBox(NULL, lpText, lpCaption, MB_ABORTRETRYIGNORE);

check_ret(ret);

// 「はい」「いいえ」「キャンセル」

ret = MessageBox(NULL, lpText, lpCaption, MB_YESNOCANCEL);

check_ret(ret);

// 「はい」「いいえ」

ret = MessageBox(NULL, lpText, lpCaption, MB_YESNO);

check_ret(ret);

// 「再試行」「キャンセル」

ret = MessageBox(NULL, lpText, lpCaption, MB_RETRYCANCEL);

check_ret(ret);

// 「キャンセル」「再実行」「続行」

ret = MessageBox(NULL, lpText, lpCaption, MB_CANCELTRYCONTINUE);

check_ret(ret);

// 「OK」「ヘルプ」

ret = MessageBox(NULL, lpText, lpCaption, MB_HELP);

check_ret(ret);

// 注意アイコン

ret = MessageBox(NULL, lpText, lpCaption, MB_OK | MB_ICONWARNING);

// 情報アイコン

ret = MessageBox(NULL, lpText, lpCaption, MB_OK | MB_ICONINFORMATION);

// エラーアイコン

ret = MessageBox(NULL, lpText, lpCaption, MB_OK | MB_ICONERROR);

// クエスチョンアイコン

ret = MessageBox(NULL, lpText, lpCaption, MB_OK | MB_ICONQUESTION);

return 0;

}

このプログラムをビルドするためのnmakeのMakefileは前回と同じでよい。

Makefile.nmake

CMD= helloworld

CC= cl.exe

CFLAGS= /c /source-charset:utf-8

LINK= link.exe

LIBS= user32.lib

LFLAGS=

EXIST= cmd.exe /C if exist

all: build

build: $(CMD).exe

$(CMD).exe: $(CMD).obj

$(LINK) $(LFLAGS) $(LIBS) *.obj

dir

.c.o:

$(CC) $(CFLAGS) $*.c

run: build

$(CMD).exe

clean:

$(EXIST) $(CMD).obj del *.obj

$(EXIST) $(CMD).exe del $(CMD).exe

dir

corruption-run:

$(CC) /c $(CMD).c

$(LINK) $(LFLAGS) $(LIBS) *.obj

$(CMD).exe

プログラムの内容は基本的に前回と同じだ。MessageBox()の4つ目の引数に指定する内容が前回は0だったが、今回はこの部分を明示的に変更して何度も呼び出して動きを確認しているほか、どのボタンが押されたかを判定する返り値も調べて、その結果もMessageBox()で表示するようにしている。



プログラムを実行して動作を確認

ビルドして実行してみよう。まず、次のようにMB_OKに対応するモーダルダイアログボックスが起動してくる。

uType: MB_OKのモーダルダイアログボックス


ここで「OK」ボタンを押せば次のように結果が同じくモーダルダイアログボックスで表示される。

押されたボタンの確認


以降は、書いてあるとおりにモーダルダイアログボックスが表示されるので、ボタンを押して次の表示へ進んでいけばよい。(どのボタンが押されたかの表示は省くとして)次に、その結果を掲載しておく。

uType: MB_OKCANCELのモーダルダイアログボックス


uType: MB_ABORTRETRYIGNOREのモーダルダイアログボックス


uType: MB_YESNOCANCELのモーダルダイアログボックス


uType: MB_YESNOのモーダルダイアログボックス


uType: MB_RETRYCANCELのモーダルダイアログボックス


uType: MB_CANCELTRYCONTINUEのモーダルダイアログボックス


uType: MB_HELPのモーダルダイアログボックス


uType: MB_OK|MB_ICONWARNINGのモーダルダイアログボックス


uType: MB_OK|MB_ICONINFORMATIONのモーダルダイアログボックス


uType: MB_OK|MB_ICONERRORのモーダルダイアログボックス


uType: MB_OK|MB_ICONQUESTIONのモーダルダイアログボックス


Windowsユーザーであれば見覚えのあるモーダルダイアログボックスが表示されていることがわかるんじゃないだろうか。こんな感じで、Windowsにおけるウィンドウプログラミングの経験がほとんどなくても、比較的すぐにGUIプログラミングはできてしまう。

最初のプログラミングに扱いやすいMessageBox()

MessageBox()は扱いやすい。引数も必要最低限なものしかなくてソースコードは短くて済み、その結果は明らかだし、GUIアプリケーションを開発する場合の基本中の基本として覚えておいて損することもない。最初に取り組んでみるのにふさわしい対象だ。

自分ではじめてアプリケーションを開発する場合、こんな感じで小さいところから徐々に試していくとよい。まずは小さく作って細かく実行して確認していく。こうした作業の繰り返しから、プログラミングを身につけていこう。

○参考

MessageBox function (winuser.h) - Win32 apps | Microsoft Docs

Walkthrough: Compile a C program on the command line | Microsoft Docs

NMAKE Reference | Microsoft Docs