저는 카이로를 Win32 윈도우에서 작동 시키려고합니다. 아이디어는 단지 깜박임이없는 렌더링을 만드는 것입니다.카이로 Win32 이중 버퍼링 선형 그래디언트
창 HDC로 직접 카이로 표면을 만들면 크기 조정시 창이 깜박입니다. 그것은 정상적이며 예상됩니다. 일반적인 해결책은 호환 장치 컨텍스트를 만들고 비트 맵으로 렌더링 한 다음 해당 비트 맵을 창 HDC에 블 리팅하는 것입니다.
문제는 창 HDC를 사용할 때 작동했던 동일한 드로잉 코드가 이중 버퍼 장치 컨텍스트에서 작동하지 않는다는 것입니다. 그라디언트 서클이 아닌 검은 색 사각형을 얻었습니다.
작고 기능적인 예입니다. #define DOUBLE_BUFFER
행을 주석 처리하면 카이로 렌더링이 창 HDC에 바로 그려집니다. 그렇지 않으면 생성 된 객체로 그릴 것입니다.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <cairo.h>
#include <cairo-win32.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("CairoTestApp");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Cairo Test Application");
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int main(int argc, const char *argv)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL, _T("Call to RegisterClassEx failed!"), szTitle, NULL);
return 1;
}
hInst = hInstance; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
256, 256,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL, _T("Call to CreateWindow failed!"), szTitle, NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
// DestroyWindow(hWnd);
UnregisterClass(szWindowClass, hInstance);
return 0;
}
void gradientExample(cairo_t* cr) {
cairo_pattern_t *pat;
pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0);
cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
cairo_rectangle (cr, 0, 0, 256, 256);
cairo_set_source (cr, pat);
cairo_fill (cr);
cairo_pattern_destroy (pat);
pat = cairo_pattern_create_radial (115.2, 102.4, 25.6,
102.4, 102.4, 128.0);
cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 1);
cairo_set_source (cr, pat);
cairo_arc (cr, 128.0, 128.0, 76.8, 0, 2 * 3.14159);
cairo_fill (cr);
cairo_pattern_destroy (pat);
}
#define DOUBLE_BUFFER
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, World!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
{
HDC newDC = CreateCompatibleDC(hdc);
RECT theRect;
GetClientRect(hWnd, &theRect);
int width, height;
width = theRect.right - theRect.left;
height = theRect.bottom - theRect.top;
HBITMAP theBmp = CreateCompatibleBitmap(newDC, width, height);
HGDIOBJ oldBmp = SelectObject(newDC, theBmp);
//Test some text.
#ifdef DOUBLE_BUFFER
TextOut(newDC, 5, 5, greeting, _tcslen(greeting));
#else
TextOut(hdc, 5, 5, greeting, _tcslen(greeting));
#endif
{
#ifdef DOUBLE_BUFFER
cairo_surface_t *surface = cairo_win32_surface_create(newDC);
#else
cairo_surface_t *surface = cairo_win32_surface_create(hdc);
#endif
cairo_t *cr = cairo_create(surface);
// Draw on the cairo context.
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);
gradientExample(cr);
cairo_surface_finish(surface);
// Cleanup.
cairo_destroy(cr);
cairo_surface_destroy(surface);
}
#ifdef DOUBLE_BUFFER
BitBlt(hdc, 0, 0, width, height, newDC, theRect.left, theRect.top, SRCCOPY);
#endif
SelectObject(newDC, oldBmp);
DeleteDC(newDC);
}
EndPaint(hWnd, &ps);
break;
case WM_ERASEBKGND:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN: // Is A Key Being Held Down?
{
if(wParam == VK_ESCAPE)
{
PostMessage(hWnd, WM_CLOSE, 0, 0);
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}