cairoをWindowsで直接使う #4
Win32APIを直接利用してcairoで描画する領域を用意してみる。
cairoにはWin32サーフェスが用意されており、
描画対象のデバイスコンテクストのハンドルを渡せばcairoサーフェスとして機能する。
Win32サーフェスを使うときはcairo-win32.hもインクルードする。
#include <windows.h> #include <tchar.h> #include <cairo.h> #include <cairo-win32.h> #define UNUSED_ARGUMENT(x) (void)(x) #define WIDTH 860 #define HEIGHT 520 static TCHAR window_class_name[] = _T("cairoHelloTest"); static TCHAR window_title[] = _T("Hello"); LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void draw_hello(cairo_surface_t *surf); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG msg; UNUSED_ARGUMENT(hPrevInstance); UNUSED_ARGUMENT(lpCmdLine); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = window_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = window_class_name; wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION); if (! RegisterClassEx(&wc)) { MessageBox(NULL, _T("failed to RegisterClassEx"), _T("error"), MB_OK); return 0; } hwnd = CreateWindow(window_class_name, window_title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL); if (! hwnd) { MessageBox(NULL, _T("failed to CreateWindow"), _T("error"), MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static HDC hmdc; static HBITMAP hbmp; cairo_surface_t *surf; switch (uMsg) { case WM_CREATE: hdc = GetDC(hwnd); hmdc = CreateCompatibleDC(hdc); hbmp = CreateCompatibleBitmap(hdc, WIDTH, HEIGHT); SelectObject(hmdc, hbmp); SelectObject(hmdc, GetStockObject(WHITE_BRUSH)); PatBlt(hmdc, 0, 0, WIDTH, HEIGHT, PATCOPY); surf = cairo_win32_surface_create(hmdc); draw_hello(surf); cairo_surface_destroy(surf); ReleaseDC(hwnd, hdc); break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); BitBlt(hdc, 0, 0, WIDTH, HEIGHT, hmdc, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); break; case WM_DESTROY: DeleteObject(hbmp); DeleteDC(hmdc); PostQuitMessage(0); break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); break; } return FALSE; } void draw_hello(cairo_surface_t *surf) { ...snip
WM_CREATE時にオフスクリーンデバイスを作成し、
オフスクリーン用のイメージに関連付け、
そのデバイスコンテクストからcairoサーフェスを作成する。
これにdraw_hello()で描画し、
WM_PAINT時にオフスクリーンから作成したイメージをコピーしてくる。
相変わらずcairoによる描画部分は今までと共通で変更は不要である。