2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Win32 API] GUI アプリケーションでコンソール出力する & 文字コードの注意点

Posted at

GUI アプリケーションのデバッグ時等にコンソール出力する方法です。

AllocConsole() 関数を使用する方法では文字コードの注意が必要です (※後述) 。

※本記事では文字列をすべて Unicode で扱うことにします。
※本記事では WSL 上の MinGW-w64 でコンパイルすることを想定しています。

1. 方法1: CUI (コンソール) アプリケーションとしてコンパイルする

GUI アプリケーションであっても CUI アプリケーションとしてコンパイルし、コンソールから実行するとそのコンソールに文字列を入出力できます。

※以下の例では標準出力のみ。

main.cpp
# include <windows.h>
# include <iostream>
# include <fcntl.h>

// 
int AppMain() {

	// 出力の文字コード指定
	_setmode(fileno(stdout), _O_U8TEXT);

	// 
	const int id = MessageBoxW(NULL, L"Test", L"Info", MB_ICONINFORMATION | MB_YESNO);

	// 
	std::wcout << L"MessageBox: " << id << std::endl;

	_wsystem(L"PAUSE");

	return 0;

}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
	return AppMain();
}
build.sh
# !/bin/bash

# g++ ver.5.1 以降を想定
x86_64-w64-mingw32-g++ -Wall -std=c++14 \
	-finput-charset=UTF-8 -fexec-charset=CP932 \
	-municode \
	-static-libgcc -static-libstdc++ \
	-o main.exe \
	main.cpp
  1. ソースコードは UTF-8
  2. 実行ファイル内の文字列は CP932 (Shift_JIS)
  3. 標準出力は UTF-8
  4. Windows のコンソール上では Unicode が (特定の条件下で) 自動で変換されるため、文字化けしない

参考「_setmode | Microsoft Docs
参考「C言語のワイド文字入出力 — Windows Console 編 | 雑記帳

2. 方法2: 別途コンソール画面を生成する

AllocConsole() 関数を使用することでコンソール画面を表示できます。

現在アクティブなコンソール出力デバイスは CONOUT$ で表され、_wfreopen_s() 関数を用いて stdout の出力先の再割り当てをすることで標準出力として使えるようになります。

注意点として、stdout の出力デバイス等の再割り当てを行う場合、出力モードを w でなく w+ にしないと Windows のコンソール上で Unicode 文字列が自動変換されず、文字化けします。

※以下の例では標準出力のみ。

main.cpp
# include <windows.h>
# include <iostream>
# include <fcntl.h>
# include <cstdlib>

// 
int AppMain() {

	// コンソール画面生成
	AllocConsole();

	FILE *stream;

	_wfreopen_s(&stream, L"CONOUT$", L"w+", stdout);

	// 出力の文字コード指定
	_setmode(fileno(stdout), _O_U8TEXT);

	// 
	const int id = MessageBoxW(NULL, L"Test", L"Info", MB_ICONINFORMATION | MB_YESNO);

	// 
	std::wcout << L"テスト MessageBox: " << id << std::endl;

	_wsystem(L"PAUSE");

	return 0;

}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
	return AppMain();
}
build.sh
# !/bin/bash

# g++ ver.5.1 以降を想定
x86_64-w64-mingw32-g++ -Wall -std=c++14 \
	-finput-charset=UTF-8 -fexec-charset=CP932 \
	-municode \
	-Wl,-subsystem,windows \
	-static-libgcc -static-libstdc++ \
	-o main.exe \
	main.cpp

参考「AllocConsole function - Windows Console | Microsoft Docs
参考「freopen_s, _wfreopen_s | Microsoft Docs
参考「Windows GUIプログラムでデバッグ情報をコンソールを表示させる | プログラミングテクニック集キヤミー」(※出力モードが w になっていますが、w+ にすべきです)
参考「C言語のワイド文字入出力 — Windows Console 編 | 雑記帳

2
4
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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?