2011-09-12 3 views
0

저는 카이로를 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; 
} 

답변

2

원본 장치 컨텍스트 (hdc)를 매개 변수로 사용하여 CreateCompatibleBitmap을 호출 해보십시오. 그렇지 않으면 방금 만든 가정용 호환 DC의 기본 흑백 더미 비트 맵을 기반으로 하나를 얻을 것이라고 생각합니다.

관련 문제