[cairo] W32: Drawing globally-transparent stuff with cairo

LRN lrn1986 at gmail.com
Thu Mar 27 08:54:05 PDT 2014


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I've been trying to somehow hack GTK to have RGBA GdkWindows, with
mixed results so far (i either get massive alpha corruption, or crash
pixman inside bitblt).

Decided to take a step back and see if i can make it work 100%
correctly with just GDI & cairo. Turns out, i can't.

I've attached an example, compile with
gcc main.c -o main.exe -I/mingw/include/cairo -lcairo -lgdi32 -ldwmapi

It draws two gradients - one transparent, and one opaque.
Transparency only works when window is invalidated and repainted (such
as when it is obscured by another window and later shown again).

The problem is most likely W32-specific, and not directly related to
cairo, but i simply can't find what is wrong :(
- -- 
O< ascii ribbon - stop html email! - www.asciiribbon.org
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (MingW32)

iQEcBAEBAgAGBQJTNEmaAAoJEOs4Jb6SI2CwbuQH/15TjvBKgwEW2Hs0aGXjs6Uu
DEXyX/ewUjpdJdRVRqQdLfxW0jYBkK2GXYHtZq6xzxen/zCRBJ/49OEHZzgh/wcU
3VPfWDeETQPgpwHQ8OSZdwF9HFfObsb7rRYsk9CddL10qkU6MYCfZS85CTDWmL4g
h72CoJi3RlmmbATg46KFHPuDCGldFBoeD4W1IPgB0zqG62b6j/1NboRUeW1H1m+V
HS5JVSOYOqn6EF5fK2ub/dxCtG79Ldmls0fKacZdpsJi2/nBxJnaCtlJeVVN0jZS
0I7AUHX5iOOoh3/siQC3Giv7voqzt3cJhd9XCNyJYPrUdXZMH8HulkBbn5JyUBc=
=Eovk
-----END PGP SIGNATURE-----
-------------- next part --------------
#include <windows.h>
#include <dwmapi.h>
#include <math.h>
#include <stdio.h>
#include "cairo-win32.h"

/**
  Gradient demonstration.
  Taken from http://cairographics.org/samples/
*/
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, 0.5);
  cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 0.3);
  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 * M_PI);
  cairo_fill (cr);
  cairo_pattern_destroy (pat);
}

/**
  Changes the dimensions of a window's client area.
*/
void SetClientSize( HWND hwnd, int clientWidth, int clientHeight ) {
  if ( IsWindow( hwnd ) ) {
    DWORD dwStyle = GetWindowLongPtr( hwnd, GWL_STYLE ) ;
    DWORD dwExStyle = GetWindowLongPtr( hwnd, GWL_EXSTYLE ) ;
    HMENU menu = GetMenu( hwnd ) ;
    RECT rc = { 0, 0, clientWidth, clientHeight } ;
    AdjustWindowRectEx( &rc, dwStyle, menu ? TRUE : FALSE, dwExStyle );
    SetWindowPos( hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
                  SWP_NOZORDER | SWP_NOMOVE ) ;
  }
}

/**
  Handles WM_PAINT.
*/
LRESULT onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
  PAINTSTRUCT ps ;
  HDC hdc = BeginPaint( hwnd, &ps );

  // Create the cairo surface and context.
  cairo_surface_t *surface = cairo_win32_surface_create (hdc);
  cairo_t *cr = cairo_create (surface);
  cairo_set_source_rgba (cr, 0, 0, 0, 0);
  cairo_paint (cr);
  // Draw on the cairo context.
  gradientExample( cr );

  // Cleanup.
  cairo_destroy (cr);
  cairo_surface_destroy (surface);
  EndPaint(hdc, &ps);

  return 0 ;
}

/**
  Handles WM_CLOSE.
*/
LRESULT onClose( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
  PostQuitMessage( 0 );
  return 0 ;
}

/**
  Handles our window's messages.
*/
LRESULT CALLBACK WndProc( HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam ) {
  LRESULT r;
  BLENDFUNCTION bf;
  bf.BlendOp = AC_SRC_OVER;
  bf.BlendFlags = 0;
  bf.SourceConstantAlpha = 254;
  bf.AlphaFormat = AC_SRC_ALPHA;
  HDC dc;
  switch(msg) {
    case WM_PAINT: return onPaint( hwnd, wParam, lParam );
    case WM_CLOSE: return onClose( hwnd, wParam, lParam );
    default: return DefWindowProc(hwnd,msg,wParam,lParam);
  }
}


int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR args, int nShow ) {
  MSG  msg ;
  WNDCLASSEX wc;
  DWORD dwExStyle;
  DWORD dwStyle;
  memset (&wc, 0, sizeof (wc));
  wc.cbSize = sizeof (wc);
  wc.lpszClassName = TEXT( "CairoGdiWndClass" );
  wc.hInstance     = hInst ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);

  RegisterClassEx(&wc);
  dwExStyle = 0;
  dwStyle = WS_OVERLAPPEDWINDOW;
  HWND hwnd = CreateWindowEx(dwExStyle, wc.lpszClassName,TEXT("Cairo & GDI Demo"),
                            dwStyle, 0,0,256,256,0,0,hInst,0);

  DWM_BLURBEHIND bb = {0};
  HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
  bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
  bb.hRgnBlur = hRgn;
  bb.fEnable = TRUE;
  DwmEnableBlurBehindWindow(hwnd, &bb);

  PIXELFORMATDESCRIPTOR pfd = {
    sizeof(PIXELFORMATDESCRIPTOR),
    1,                                /* Version Number */
    PFD_DRAW_TO_WINDOW      |         /* Format Must Support Window */
    PFD_SUPPORT_COMPOSITION |         /* Format Must Support Composition */
    PFD_DOUBLEBUFFER,                 /* Must Support Double Buffering */
    PFD_TYPE_RGBA,                    /* Request An RGBA Format */
    32,                               /* Select Our Color Depth */
    0, 0, 0, 0, 0, 0,                 /* Color Bits Ignored */
    8,                                /* An Alpha Buffer */
    0,                                /* Shift Bit Ignored */
    0,                                /* No Accumulation Buffer */
    0, 0, 0, 0,                       /* Accumulation Bits Ignored */
    24,                               /* 24Bit Z-Buffer (Depth Buffer) */
    8,                                /* Some Stencil Buffer */
    0,                                /* No Auxiliary Buffer */
    PFD_MAIN_PLANE,                   /* Main Drawing Layer */
    0,                                /* Reserved */
    0, 0, 0                           /* Layer Masks Ignored */
  };     

  HDC hdc = GetDC(hwnd);
  int PixelFormat = ChoosePixelFormat(hdc, &pfd);
  if (PixelFormat == 0) {
     return FALSE ;
  }

  BOOL bResult = SetPixelFormat(hdc, PixelFormat, &pfd);
  if (bResult==FALSE) {
     return FALSE ;
  }

  SetClientSize( hwnd, 256, 256 );
  ShowWindow( hwnd, SW_SHOWNORMAL );

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


More information about the cairo mailing list