コンソールアプリでは、黒い画面が表示されます。黒い画面は、printfなどで情報を表示するのには便利ですが、 邪魔になることがあります。
コンソールアプリではなく、ウィンドウアプリにすれば、黒い画面は表示されません。 MSYS2で次のような内容の「hello4.c」を作成します。
#include <windows.h>
#include <tchar.h>
INT WINAPI _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
INT nCmdShow)
{
MessageBox(NULL, TEXT("Hello, window app!"), TEXT("INFO"), 0);
return 0;
}
もはや<stdio.h>は必要ありません。 そして、「gcc -mwindows -static -o hello4 hello4.c」を実行すれば、EXEファイル「hello4.exe」ができます。 「-mwindows」を指定すれば、ウィンドウアプリになります。 「-static」は、MSYS2特有のDLLを使わない指定です。 「hello4.exe」をダブルクリックすると、黒い画面が表示されずに、メッセージボックスが表示されます。 必要なDLLが足りないとき、EXEの実行が異常終了するので、ダブルクリックで開けるようにするためには、「-static」が必要になります。
Visual Studioの場合は、「ファイル」→「新規作成」→「プロジェクト」で、「Windows デスクトップ アプリケーション」を 選べばウィンドウ アプリになります。余分なファイルが作成されますが、無視してもかまいません。 「hello4.cpp」をまるごと次のような内容に置き換えて下さい。
#include "stdafx.h"
INT WINAPI _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
INT nCmdShow)
{
MessageBox(NULL, TEXT("Hello, window app!"), TEXT("INFO"), 0);
return 0;
}
そして、「デバッグの開始」を押せば、ビルドが始まり、黒い画面が表示されることなく、 メッセージボックスが表示されます。
_tWinMainという関数は、ウィンドウアプリのメイン関数(エントリーポイント;入り口)であり、C言語の標準のmain関数の代わりです。 TEXTというものは、文字コードを切り替えるためのWin32のマクロであり、次のように定義されています。
#ifdef UNICODE
#define TEXT(quote) L##quote
#else
#define TEXT(quote) quote
#endif
アプリがUnicodeアプリなら、UNICODEマクロが定義されます。 TEXTマクロは、UNICODEマクロが定義されている場合、文字列リテラルの先頭にLを付けます。 Lのついた文字列リテラルは、ワイド文字列になります。例えば、L"これはワイド文字列だよ"は、ワイド文字列です。
実は、MessageBoxという関数もマクロです。UNICODEマクロが定義されていれば、MessageBoxW(Wはワイド文字列という意味)になり、 未定義なら、MessageBoxA(AはANSI文字列という意味)になります。 Unicodeに対応したAPI関数の多くは、このように、UNICODEマクロが定義されているかどうかでANSI版関数かワイド版関数かに、切り替わります。
_tWinMainというのも、WinMain(ANSI版)とwWinMain(ワイド版)を切り替えるためのマクロです。 ただし、ややこしいことに、こっちは、UNICODEではなく_UNICODEマクロで切り替わります。 _tWinMainは<tchar.h>で定義されています。
ANSI文字列というのは、通常のC文字列で、ワイド文字列は、" "の直前にLが付きます。 ANSI文字列は、charの配列かポインタです。ワイド文字列は、WCHARの配列かポインタです。WCHARは、一文字のワイド文字を表す型です。 Windowsでは、sizeof(wchar_t) == sizeof(WCHAR) == 2であり、WCHARは、UTF-16の一文字を表すことができます。
参考資料:UTF-16