Visual Studio 2008 Express Editionを使い始める、の巻


ちょっとCとC++の勉強もあったまってきたので、「猫でもできるプログラミング」を参考にしながらWindows SDKプログラミングもちょっくらいじりだそうかと思っている昨今。
さっそくイントロダクションでつまったので、備忘録を載せておくことに。

写経すること数分、正直言ってビルド失敗。
で、チキン野郎なので、そのままコピペ・・・したら(エンコーディングの問題からか、)1行になったので、それを分解・・・。
するとどうでしょう。
うごかねぇ~~。。

そのエラーを探ること数分、見つけましたよ、原因を。
そもそも、このページのオーナーさんである粂井さんが一連の記事を書き始めたときのVCのバージョンが4.0だったことが事の発端なんだとか。
というわけで、どこを直せばいいかを書いておこうかなぁ、と。

まず、コンパイラのエラーを見る。

error C2440: '=' : 'HGDIOBJ' から 'HBRUSH' に変換できません。
        'void*' から非 'void' 型への変換には明示的なキャストが必要です。
error C2440: '=' : 'char [25]' から 'LPCWSTR' に変換できません。
        指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
error C2664: 'CreateWindowExW' : 2 番目の引数を 'char [25]' から 'LPCWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
        指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。

最初に、本来HBRUSH型を要求するhbrBackgroundにGetStockObject(WHITE_BRUSH)を入れていることからエラーとなったご様子。
HGDIOBにキャストしてみる。

2番目はszClassNameがchar型なのに対して、LPCWSTR型を要求する場所を引数として入れていることが問題のご様子。
LPCWSTRにキャストしてみる。
(3箇所)

で、該当箇所はこの辺り。

	WNDCLASS myProg;
	if (!hPreInst) {
		myProg.style			= CS_HREDRAW | CS_VREDRAW;
		myProg.lpfnWndProc		= WndProc;
		myProg.cbClsExtra		= 0;
		myProg.cbWndExtra		= 0;
		myProg.hInstance		= hInstance;
		myProg.hIcon			= NULL;
		myProg.hCursor			= LoadCursor(NULL, IDC_ARROW);
		// VC 6.0以降は型のチェックが徐々に厳しくなっている。
		// 本来HBRUSH型を要求するhbrBackgroundにGetStockObject(WHITE_BRUSH)を入れたところ、
		// エラーとなるのでHGDIOBにキャストしている。
		//myProg.hbrBackground	= GetStockObject(WHITE_BRUSH);
		myProg.hbrBackground	= (HBRUSH) GetStockObject(WHITE_BRUSH);
		myProg.lpszMenuName		= NULL;
		// myProg.lpszClassName	= szClassNme;
		myProg.lpszClassName	= (LPCWSTR) szClassNme;
		if (!RegisterClass(&myProg)) return FALSE;
	}
	hWnd = CreateWindow(
		//szClassNme,
		//"俺にもできる?Windowsプログラミング",
		(LPCWSTR) szClassNme,
		(LPCWSTR) "俺にもできる?Windowsプログラミング",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);

で、これを実行すると・・・。
blank_window_false
タイトル、化けちゃってるね・・・。

どうやら、そもそもの修正方法が違うらしい。
粂井さんのサンプルはどうやらSJIS前提らしく、関数もSJIS前提の関数とかっぽい??
現状のプロジェクトファイルはUnicodeで設定されていて、それを直したりすれば行けるっぽい。

とりあえず、文字エンコーディングを直す。
(Alt-F7でプロジェクトのプロパティ)
プロジェクトのプロパティで「構成」が「Unicode文字セットを使用する」とか書いてあると思うんだけど、
vc2008express_property_unicode
「マルチバイト文字セットを使用する」とする。
vc2008express_property_sjis
恐らくこれでSJISになる。

で、今度は別のエラーが。

error C2440: '=' : 'LPCWSTR' から 'LPCSTR' に変換できません。
        指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
error C2664: 'CreateWindowExA' : 2 番目の引数を 'LPCWSTR' から 'LPCSTR' に変換できません。(新しい機能 ; ヘルプを参照)
        指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。

なんだとか。
・・・LPCWSTR型にしなくてよかった、と。。。

さっきの箇所は、これでいいらしい・・・。

	WNDCLASS myProg;
	if (!hPreInst) {
		myProg.style			= CS_HREDRAW | CS_VREDRAW;
		myProg.lpfnWndProc		= WndProc;
		myProg.cbClsExtra		= 0;
		myProg.cbWndExtra		= 0;
		myProg.hInstance		= hInstance;
		myProg.hIcon			= NULL;
		myProg.hCursor			= LoadCursor(NULL, IDC_ARROW);
		// VC 6.0以降は型のチェックが徐々に厳しくなっている。
		// 本来HBRUSH型を要求するhbrBackgroundにGetStockObject(WHITE_BRUSH)を入れたところ、
		// エラーとなるのでHGDIOBにキャストしている。
		//myProg.hbrBackground	= GetStockObject(WHITE_BRUSH);
		myProg.hbrBackground	= (HBRUSH) GetStockObject(WHITE_BRUSH);
		myProg.lpszMenuName		= NULL;
		myProg.lpszClassName	= szClassNme;
		if (!RegisterClass(&myProg)) return FALSE;
	}
	hWnd = CreateWindow(
		szClassNme,
		"俺にもできる?Windowsプログラミング",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);

結果はこれ。
blank_window_success

お粗末さまでした。

Post to Twitter

, , , , ,

Comments are closed.

Bad Behavior has blocked 24 access attempts in the last 7 days.