ウィンドウ外に描画


デバイスコンテキストを作る

一般のプログラムは、描画処理はウィンドウ内部で行うべきです
当然、プログラムもそれを望んでいるはずなので問題はありません

しかし、ウィンドウの外にプログラムから描画することはできないのか?
実は、このような行為も可能である

今までは、ただ単純にクライアント領域のデバイスコンテキストを得てきたから
ウィンドウの内部にしか描画できなかったというだけで
ディスプレイ全体のデバイスコンテキストを取得すれば、これを実現できる
このデバイスコンテキストを得るには CreateDC() 関数を使います
HDC CreateDC(
	LPCTSTR lpszDriver , LPCTSTR lpszDevice ,
	LPCTSTR lpszOutput , CONST DEVMODE *lpInitData 
);
lpszDriver は、仕様が Windows95 と Windows NT で多少異なります
Windows95 の場合は NULL を、NT の場合はドライバの名前などを指定します
ただし、ディスプレイのデバイスコンテキストを得る場合は双方ともに
NULL で終わる文字列 "DISPLAY" を指定します
もし "DISPLAY" を渡した場合は、他の引数を全て NULL にします

lpszDevice は、出力デバイスの名前が入った文字列へのポインタを
lpszOutput は無視されるので NULL を
lpInitData はデバイスドライバに対するデバイス固有の初期化データが入った
DEVMODE 構造体へのポインタを指定します

lpszDriver 以外の引数は、今回は一切関係ありません
これらのパラメータは別のデバイス、とくにプリンタに出力するときに重要になります
印刷については後記するため、この場では第一引数だけが重要です

関数が成功すると、指定したデバイスのハンドルが、失敗すると NULL が返ります
このデバイスコンテキストのハンドルで、描画処理を行えます
座標は、当然スクリーン座標になります

デバイスコンテキストが不用になれば DeleteDC() 関数を使います

BOOL DeleteDC(HDC hdc);

hdc には、削除するデバイスコンテキストのハンドルを指定します
成功すれば 0 以外、失敗すれば 0 が返ります
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		hdc = CreateDC(TEXT("DISPLAY") , NULL , NULL , NULL);
		SelectObject(hdc , CreateSolidBrush(RGB(0xFF , 0 , 0)));
		Rectangle(hdc , 100 , 100 , 200 , 200);
		DeleteObject(SelectObject(hdc , GetStockObject(WHITE_BRUSH)));
		DeleteDC(hdc);
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL ,
			hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


もちろん、基本的にはこのような行為は誰も喜びません
クライアント領域以外に描画するメリットがある場合に、使用してください


CreateDC()

HDC CreateDC(
	LPCTSTR lpszDriver , LPCTSTR lpszDevice ,
	LPCTSTR lpszOutput , CONST DEVMODE *lpInitData 
);
指定されたデバイスのデバイスコンテキストを、指定の名前で作成します

(95)lpszDriver - 無視、または "DISPLAY" を指定できます
(NT)lpszDriver - プリンタドライバの名前、または "DISPLAY" を指定できます
lpszDevice - 出力デバイスの名前が入った文字列を指定します
lpszOutput - このパラメータは無視されます。NULL を指定します
lpInitData - 初期化データが入ったDEVMODE 構造体へのポインタを指定します

戻り値 - 指定したデバイスに対するデバイスコンテキストのハンドル。失敗の場合は NULL

DeleteDC()

BOOL DeleteDC(HDC hdc);

指定したデバイスコンテキストを削除します

hdc - デバイスコンテキストのハンドルを指定します

戻り値 - 成功すると 0 以外、失敗すると 0



前のページへ戻る次のページへ