EternalWindows
リージョン / リージョンデータ

リージョンをファイル等に保存したい場合は、 リージョンのバイナリデータを取得する必要があります。 このようなリージョンデータは、GetRegionDataで取得することができます。

DWORD GetRegionData(
  HRGN hRgn,
  DWORD dwCount,
  LPRGNDATA lpRgnData
);

hRgnは、リージョンのハンドルを指定します。 dwCountは、lpRgnDataのサイズを指定します。 lpRgnDataは、リージョンデータを受け取るバッファを指定します。 NULLを指定した場合は、バッファに必要なサイズが戻り値として返されます。

次に、GetRegionDataを呼び出す例を示します。

#include <windows.h>

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	HRGN   hrgn;
	DWORD  dwSize;
	LPBYTE lpData;
	HANDLE hFile;
	DWORD  dwWriteByte;
	
	hrgn = CreateRectRgn(50, 50, 200, 100);

	dwSize = GetRegionData(hrgn, 0, NULL);
	lpData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwSize);
	GetRegionData(hrgn, dwSize, (LPRGNDATA)lpData);
	
	DeleteObject(hrgn);

	hFile = CreateFile(TEXT("sample.dat"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	WriteFile(hFile, lpData, dwSize, &dwWriteByte, NULL);
	CloseHandle(hFile);
	
	return 0;
}

まず、CreateRectRgnなどのリージョンを作成する関数を呼び出します。 次に、GetRegionDataの第3引数をNULLに指定して呼び出し、 リージョンデータを受け取るのに必要なバッファのサイズを取得します。 そして、バッファを確保してから、2回目のGetRegionDataでhrgnのリージョンデータを取得します。 後は、これをファイルに保存します。

リージョンデータからリージョンを作成するには、ExtCreateRegionを呼び出します。

HRGN ExtCreateRegion(
  const XFORM *lpXform,
  DWORD nCount,
  const RGNDATA *lpRgnData
);

lpXformは、座標変換データを格納しているXFORM構造体のアドレスを指定します。 不要な場合は、NULLを指定することができます。 nCountは、lpRgnDataのサイズを指定します。 lpRgnDataは、リージョンデータを格納しているバッファを指定します。

今回のプログラムは、ファイルからリージョンデータを読み取り、 それを基にリージョンを作成して描画します。

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	TCHAR      szAppName[] = TEXT("sample");
	HWND       hwnd;
	MSG        msg;
	WNDCLASSEX wc;

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WindowProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hinst;
	wc.hIcon         = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	wc.hCursor       = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = szAppName;
	wc.hIconSm       = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	
	if (RegisterClassEx(&wc) == 0)
		return 0;

	hwnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL);
	if (hwnd == NULL)
		return 0;

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	static HRGN hrgn = NULL;

	switch (uMsg) {

	case WM_CREATE: {
		HANDLE hFile;
		DWORD  dwReadByte;
		DWORD  dwSize;
		LPBYTE lpData;

		hFile = CreateFile(TEXT("sample.dat"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
			return -1;

		dwSize = GetFileSize(hFile, NULL);
		lpData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwSize);
		ReadFile(hFile, lpData, dwSize, &dwReadByte, NULL);

		hrgn = ExtCreateRegion(NULL, dwSize, (LPRGNDATA)lpData);
		HeapFree(GetProcessHeap(), 0, lpData);

		return hrgn != NULL ? 0 : -1;
	}

	case WM_PAINT: {
		HDC         hdc;
		PAINTSTRUCT ps;

		hdc = BeginPaint(hwnd, &ps);

		FillRgn(hdc, hrgn, (HBRUSH)GetStockObject(GRAY_BRUSH));

		EndPaint(hwnd, &ps);

		return 0;
	}

	case WM_DESTROY:
		if (hrgn != NULL)
			DeleteObject(hrgn);
		PostQuitMessage(0);
		return 0;

	default:
		break;

	}

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

WM_CREATEでsample.datからデータを取得し、 これをExtCreateRegionに指定します。 取得したデータがリージョンデータとして正しいものであれば、 リージョンのハンドルが返ることになります。


戻る