ページ 11

Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 11:38
by Fimbul
こんにちは。
ビットマップファイルを読み込んでメモリに描写し、それをBitBlt関数でウィンドウに表示するプログラムを作成したのですが、画像が読み込まれません。
何が不具合の原因でなのでしょうか。

ソースコードファイル名 : window.cpp
ビットマップファイル名 : brs.bmp
ビットマップファイルとソースコードファイルは同じフォルダに在ります。
OS : Windows Vista Home Premium
コンパイラー : Visual C++ 2008 Express Edition

コード:

#include <windows.h>

#define CLASS_NAME TEXT("Class name")
#define WINDOW_NAME TEXT("Window title")
#define FILE_NAME TEXT("brs.bmp")

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	HDC hdc;
	PAINTSTRUCT ps;
	static HDC hMemDC;
	static HBITMAP hBitmap;
	static BITMAP bitmap;

	switch(uMsg) {
		case WM_DESTROY:
			DeleteDC(hMemDC);
			DeleteObject(hBitmap);

			PostQuitMessage(0);
			break;
		case WM_CREATE:
			hdc = GetDC(hWnd);
			hMemDC = CreateCompatibleDC(hdc);
			ReleaseDC(hWnd, hdc);
			hBitmap = (HBITMAP)LoadImage(NULL, FILE_NAME, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

			SelectObject(hMemDC, hBitmap);
			GetObject(hBitmap, sizeof(BITMAP), &bitmap);
			break;
		case WM_PAINT:
			hdc = BeginPaint(hWnd, &ps);
			BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY);
			EndPaint(hWnd, &ps);
			break;
		default:
			return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASS wc;

	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.cbClsExtra = 0; //禁止用語になってしまうため全角で書きます
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = CLASS_NAME;

	if(!RegisterClass(&wc)) {
		return 0;
	}

	RECT rect;
	
	rect.left = 0;
	rect.top = 0;
	rect.right = 504;
	rect.bottom = 358;
	AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_CAPTION, FALSE);
	if(CreateWindow(CLASS_NAME, WINDOW_NAME, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 200, 200, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL) == NULL) {
		return 0;
	}

	MSG msg;

	while(GetMessage(&msg, NULL, 0, 0) > 0) {
		DispatchMessage(&msg);
	}

	return msg.wParam;
}


Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 13:39
by softya(ソフト屋)
試してみましたが、brs.bmpは正常に読み込まれました。
ちなみに、私はbrs.bmpはvcprojの拡張子のファイルと同じ場所に置きました。
プロジェクトのフォルダ構成次第なんですが、vcprojとソースコードは同じフォルダにありますか?

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 14:16
by Fimbul
softya(ソフト屋) さんが書きました:vcprojとソースコードは同じフォルダにありますか?
ありました。
フォルダの内容は以下の通りでした。

Debug
brs.bmp
window.cpp
Window.ncb
Window.sln
Window.vcproj
Window.vcproj.PCUser-PC.PCUser.user

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 15:02
by dic
VC++6.0 にてコピペで描画されました

コード:

hBitmap = (HBITMAP)LoadImage(NULL, FILE_NAME, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
ここで、読み込んでいるかデバッカで見てくれませんか?

コード:

#define FILE_NAME TEXT("brs.bmp")
だから、ユニコードになっているとか?

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 15:40
by Fimbul
dic さんが書きました:

コード:

hBitmap = (HBITMAP)LoadImage(NULL, FILE_NAME, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
ここで、読み込んでいるかデバッカで見てくれませんか?
これで良いのかよく分かりませんが

コード:

hBitmap = (HBITMAP)LoadImage(NULL, FILE_NAME, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
上記のコードの直前では hBitmap = 0x00000000 {unused=??? }
直後では hBitmap = 0x080508e3 {unused=??? }
となっていました。
dic さんが書きました:

コード:

#define FILE_NAME TEXT("brs.bmp")
だから、ユニコードになっているとか?
UNICODEになっていると何がいけないのか分かりませんでした。

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 15:49
by softya(ソフト屋)
UNICODEで定義されているなら問題ないと思います。
これで表示されないのが不思議なので、試しにbrs.bmpを別の画像に差し替えてみてください。

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 16:08
by Fimbul
softya(ソフト屋) さんが書きました: これで表示されないのが不思議なので、試しにbrs.bmpを別の画像に差し替えてみてください。
新規作成したビットマップファイルに差し替えたところ、問題なく表示されました。
Windows フォト ギャラリーやペイントではbrs.bmpを開く事ができ表示もされるので、画像ファイルの問題ではないと思っていました。

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月26日(日) 16:16
by Fimbul
結局、非常に間抜けなミスだったようです。
dicさん、softya(ソフト屋)さん、どうもありがとうございました。

Re: Windows APIでのビットマップ表示の不具合

Posted: 2011年6月27日(月) 05:49
by dic

コード:


WINUSERAPI
HANDLE
WINAPI
LoadImageA(
    HINSTANCE,
    LPCSTR,
    UINT,
    int,
    int,
    UINT);
WINUSERAPI
HANDLE
WINAPI
LoadImageW(
    HINSTANCE,
    LPCWSTR,
    UINT,
    int,
    int,
    UINT);
#ifdef UNICODE
#define LoadImage  LoadImageW
#else
#define LoadImage  LoadImageA
#endif // !UNICODE
と VC++6.0 の winuser.h にはあるので
ユニコードで定義されていると LoadImageW に展開されてて・・・
と、TEXTマクロを使っているので
もしかしたら LoadImageA に展開されているのではないかと勘違いしていました