Für xtow möchte ich ein Top-Level-Fenster mit dem Standard-Nicht-Client-Bereich und dem Client-Bereich mit einer Bitmap, die einen Alpha-Kanal enthält, zeichnen.Zeichnen eines Fensters mit einem Standardrahmen und transparentem Inhalt
entdecke ich jetzt so, wie ich umgesetzt haben, das funktioniert auf Windows 7, aber nicht korrekt dargestellt auf Windows 8.1, hinter Bildern des Fensterinhaltes zu verlassen, wenn er bewegt wird oder maximiert.
Um zu untersuchen, habe ich ein einfaches Testprogramm alpha-test, das
- DwmEnableBlurBehindWindow Verwendet() eine nicht schneidende Unschärfe Region zu setzen, so dass die Alpha-Werte im Fenster geehrt werden, ohne Unschärfe.
- Verwendet BitBlt() eine Bitmap mit alpha hinein zu kopieren.
//
// g++ alpha-test.cc -o alpha-test -mwindows -lgdiplus -ldwmapi
//
#define _WIN32_WINNT 0x0600
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <gdiplus.h>
#include <dwmapi.h>
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, &ps);
RECT rc;
GetClientRect(hWnd, &rc);
HBRUSH hbrush = CreateSolidBrush(RGB(0,0,0));
FillRect(hdcUpdate, &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, &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(&gdiplusToken, &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(&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->GetHBITMAP(bg, &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, &blurBehind);
DeleteObject(blurBehind.hRgnBlur);
ShowWindow(hWnd, SW_SHOW);
// Main message loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Ist das wirklich kaputt? Wie kann ich meinen Code reparieren? Ist das ein Windows-Bug/Einschränkung?
Gibt es einen anderen Weg, um mein Ziel zu erreichen, der mit einer Grenze ein Bitmap mit Alpha in ein Fenster zu zeichnen?
Update: ich einige Tests haben Direct2D und Direct3D mit den Clientbereich mit den Bitmaps zu füllen, aber sie in der gleichen Art und Weise mis gemacht.
Vielleicht vermisse ich etwas, aber ich denke, dass Fenster, die mit UpdateLayeredWindow gezeichnet werden, keinen Rahmen bekommen, Das macht es für meine Zwecke ein bisschen ein Nichtstarter, es sei denn, es gibt einen Weg um das ... – jturney
@jturney Beachten Sie, dass Sie in Windows 8 den 'WS_EX_LAYERED'-Stil in einem untergeordneten Fenster verwenden können, so dass Sie wahrscheinlich tun könnten dies mit zwei Codepfaden, unter Verwendung Ihrer vorhandenen Methode für Windows 7 und früher. Sind Sie sicher, dass Sie das in Windows 7 nicht können? (Ich habe nie versucht, einen der Rahmenstile im Fenster zu aktivieren, wenn ich das in der Vergangenheit getan habe) –