title: Drawing a window with a standard frame and transparent contents
body: <p>For <a href="http://x.cygwin.com/docs/man1/xtow.1.html">xtow</a>, I want to draw a top-level window with the standard non-client area and the client area filled with a bitmap which has an alpha channel.</p>
  
  <p>I now discover the way I have implemented this works on Windows 7, but doesn't render correctly on Windows 8.1, leaving behind images of the window contents when it is moved or maximized.</p>
  
  <p>To investigate, I made a simple test program <a href="https://github.com/jon-turney/windows8-alpha-drawing-test/blob/master/alpha-test.cc">alpha-test</a>, which </p>
  
  <ul>
  <li>Uses DwmEnableBlurBehindWindow() to set a non-intersecting blur region, so that alpha values in the window are honoured, without blur.</li>
  <li>Uses BitBlt() to copy a bitmap with alpha into it.</li>
  </ul>
  
  <pre class="lang-c prettyprint-override"><code>//
  // g++ alpha-test.cc -o alpha-test -mwindows -lgdiplus -ldwmapi
  //
  
  #define  _WIN32_WINNT 0x0600
  
  #include &lt;assert.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;windows.h&gt;
  #include &lt;gdiplus.h&gt;
  #include &lt;dwmapi.h&gt;
  
  int width = 360;
  int height = 360;
  HBITMAP hBitmap;
  
  LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    switch (message)
      {
      case WM_PAINT:
        {
          PAINTSTRUCT ps;
          HDC hdcUpdate = BeginPaint(hWnd, &amp;ps);
  
          RECT rc;
          GetClientRect(hWnd, &amp;rc);
          HBRUSH hbrush = CreateSolidBrush(RGB(0,0,0));
          FillRect(hdcUpdate, &amp;rc, hbrush);
          DeleteObject(hbrush);
  
          HDC hdcMem = CreateCompatibleDC(hdcUpdate);
          HBITMAP hbmpold = (HBITMAP)SelectObject(hdcMem, hBitmap);
  
          if (!BitBlt(hdcUpdate, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, hdcMem, 0, 0, SRCCOPY))
            {
              printf("BitBlt failed: 0x%08x\n", (int)GetLastError());
            }
  
          SelectObject(hdcMem, hbmpold);
          DeleteDC(hdcMem);
  
          EndPaint(hWnd, &amp;ps);
        }
        return 0;
  
      case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
  
      default:
        return DefWindowProc(hWnd, message, wParam, lParam);
      }
  }
  
  int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
  {
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&amp;gdiplusToken, &amp;gdiplusStartupInput, NULL);
  
    LPCTSTR szWindowClass = "TransparentClass";
  
    // Register class
    WNDCLASSEX wcex = {0};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = NULL;
    wcex.hbrBackground  = (HBRUSH)CreateSolidBrush(0x00000000);
    RegisterClassEx(&amp;wcex);
  
    // Create window
    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW,
                               szWindowClass,
                               "Transparent Window",
                               WS_OVERLAPPED | WS_SYSMENU,
                               CW_USEDEFAULT, CW_USEDEFAULT, width, height,
                               NULL, NULL, hInstance, NULL);
  
    Gdiplus::Bitmap *m_pImage = Gdiplus::Bitmap::FromFile(L"sample.png", FALSE);
    Gdiplus::Color bg(0,0,0,0);
    m_pImage-&gt;GetHBITMAP(bg, &amp;hBitmap);
    assert(hBitmap);
  
    DWM_BLURBEHIND blurBehind = { 0 };
    blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    blurBehind.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
    blurBehind.fEnable = TRUE;
    blurBehind.fTransitionOnMaximized = FALSE;
    DwmEnableBlurBehindWindow(hWnd, &amp;blurBehind);
    DeleteObject(blurBehind.hRgnBlur);
  
    ShowWindow(hWnd, SW_SHOW);
  
    // Main message loop
    MSG msg;
    while (GetMessage(&amp;msg, NULL, 0, 0))
      {
        TranslateMessage(&amp;msg);
        DispatchMessage(&amp;msg);
      }
  
    return (int)msg.wParam;
  }
  </code></pre>
  
  
  
  <p>Is this really broken? How can I fix my code? Is this a Windows bug/limitation?</p>
  
  <p>Is there another way to achieve my goal of drawing a bitmap with alpha into a window with a border?</p>
  
  <p><strong>Update:</strong>
  I did some tests using Direct2D and Direct3D to fill the client area with the
  bitmaps, but they mis-rendered in the same way.</p>