Archive for 3月 7th, 2010

WindowsでBitBltなるものを勉強

最近ちょっと落ち着いてきたので、「プログラミングWindows」を読み進めていたんだけど、どーにもつまらない。
俺がやりたいのは、ドット単位での画面描画なのに、ずーっとベクター系。
で、終わったと思えば「キーボード」の章。
ん~・・・。

やりたいことは結構単純で、リアルタイム3DCGの本があるからその公式やらを元にウィンドウ内に書き込みたいなぁ、と。
だから、勉強方法を変えてみることにした。
ウィンドウ描いてその中をラスタライズして2Dにしたリアルタイム3Dを表示したいだけ。
思い切ってページをすっ飛ばして、画面のビットマップ情報をいじることに。
その手始めとして「BitBlt(Bit-block transfer:ビットブリット)」というのをやってみた。

#include <windows.h>

LRESULT CALLBACK MyWindow(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance, LPSTR lpCmdLine,int iCmdShow)
{
	static	TCHAR	szAppName[] =
		TEXT("おいらのアプリ");	//アプリ名?
	HWND			hwnd;	//ウィンドウハンドル
	MSG				msg;	//メッセージ
	WNDCLASS		wndCls;	//ウィンドウクラス構造体

	//ウィンドウスタイルを指定
	wndCls.style			= CS_HREDRAW | CS_VREDRAW;
	//ウィンドウプロシージャを指定
	wndCls.lpfnWndProc		= MyWindow;
	wndCls.cbClsExtra		= 0;
	wndCls.cbWndExtra		= 0;
	//インスタンスハンドル変数を指定
	wndCls.hInstance		= hInstance;
	//ウィンドウのアイコンを指定
	wndCls.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	//カーソルの形を指定
	wndCls.hCursor			= LoadCursor(NULL, IDC_CROSS);
	//バックグラウンド色を指定
	wndCls.hbrBackground	= (HBRUSH) GetStockObject(WHITE_BRUSH);
	wndCls.lpszMenuName		= NULL;
	wndCls.lpszClassName	= szAppName;

	if (!RegisterClass(&wndCls)) {
		MessageBox(NULL,
			TEXT("このプログラムはWindowsNT以降対応です。"),
			TEXT("そーりー"), MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindow(szAppName, TEXT("どうよ? - Bitmap Viewer"),
						WS_OVERLAPPEDWINDOW,
						CW_USEDEFAULT, CW_USEDEFAULT,
						CW_USEDEFAULT, CW_USEDEFAULT,
						NULL, NULL, hInstance, NULL);

	//ウィンドウ表示状態を指定
	ShowWindow(hwnd, iCmdShow);
	//ウィンドウ更新実行
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0)) { //メッセージループ
		TranslateMessage(&msg);	//命令変換?
		DispatchMessage(&msg);	//命令転送
	}

	return msg.wParam;
}

LRESULT CALLBACK MyWindow(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int	cxClient, cyClient, cxSource, cySource;
	HDC			hdcClient, hdcWindow;
	PAINTSTRUCT ps;
	int			x, y;
	TCHAR		buff[512];

	switch (message) {
		case WM_CREATE:
			cxSource = GetSystemMetrics (SM_CXSIZEFRAME) +
					GetSystemMetrics (SM_CXSIZE);

			cySource = GetSystemMetrics (SM_CYSIZEFRAME) +
					GetSystemMetrics (SM_CYCAPTION);

			wsprintf(buff,
				TEXT("GetSystemMetrics (SM_CXSIZEFRAME):%d\n")
				TEXT("GetSystemMetrics (SM_CXSIZE):%d\n")
				TEXT("GetSystemMetrics (SM_CYSIZEFRAME):%d\n")
				TEXT("GetSystemMetrics (SM_CYCAPTION):%d"),
				GetSystemMetrics (SM_CXSIZEFRAME),
				GetSystemMetrics (SM_CXSIZE),
				GetSystemMetrics (SM_CYSIZEFRAME),
				GetSystemMetrics (SM_CYCAPTION));
			MessageBox(NULL, buff, TEXT("情報"), MB_OK);
			return 0;

		case WM_SIZE:
			cxClient = LOWORD (lParam);
			cyClient = HIWORD (lParam);
			return 0;

		case WM_PAINT:
			hdcClient = BeginPaint (hwnd, &ps);
			hdcWindow = GetWindowDC (hwnd);

			for (y = 0; y < cyClient; y += cySource)
				for (x = 0; x < cxClient; x += cxSource) {
					BitBlt (hdcClient, x, y, cxSource, cySource,
							hdcWindow, 0, 0, SRCCOPY);
				}

			ReleaseDC (hwnd, hdcWindow);
			EndPaint (hwnd, &ps);
			return 0;

		case WM_DESTROY:
			PostQuitMessage (0);
			return 0;
	}

	return DefWindowProc (hwnd, message, wParam, lParam);
}

ほぼほぼ「プログラミングWindows」上のソースの写経。
何がやりたいかというと、タイトルバーの左端にあるアイコンをウィンドウ内に敷き詰めるというもの。
改造点はプログラムが立ち上がる際に、アイコンの左端の取得アイコン座標の情報を表示する点。

一生やってろと言いたくなるくらいのペースに苦笑い。

そんだけ。

Post to Twitter

, ,

No Comments

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