我正在尝试创建一个半透明像素的非矩形窗口。图像不是来自PNG,而是使用GDI +调用即时绘制。
我按如下方式创建窗口:
WNDCLASSEX wc = WNDCLASSEX();
wc.cbSize = sizeof(wc);
HINSTANCE instance = GetModuleHandle(nullptr);
std::wstring classname(L"gditest ui window class");
if (!GetClassInfoEx(instance, classname.c_str(), &wc)) {
//wc.cbSize;
//wc.style = CS_DROPSHADOW;
wc.lpfnWndProc = process_messages;
//wc.cbClsExtra;
//wc.cbWndExtra;
wc.hInstance = instance;
wc.hIcon;
wc.hCursor = LoadCursor(0, IDC_ARROW);
//wc.hbrBackground;
//wc.lpszMenuName;
wc.lpszClassName = classname.c_str();
wc.hIconSm;
if (!RegisterClassEx(&wc))
throw GetLastError();
}
m_window = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED,
classname.c_str(), L"User Interface",
WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
HWND_DESKTOP, 0, instance, this);
if (!m_window)
throw GetLastError();
update_window();
update_window()函数如下所示:
void user_interface::update_window()
{
RECT r;
GetClientRect(m_window, &r);
Bitmap buf(r.right - r.left, r.bottom - r.top, PixelFormat32bppARGB);
Graphics gfx(&buf);
Rect rect(r.left, r.top, r.right - r.left, r.bottom - r.top);
SolidBrush b(Color(0x7f00ff00));
gfx.FillRectangle(&b, rect);
/* CLSID clsid;
UINT numbytes = 0, numenc = 0;
GetImageEncodersSize(&numenc, &numbytes);
std::vector<char> encoders(numbytes, 0);
ImageCodecInfo *encoderptr = (ImageCodecInfo *)&encoders[0];
GetImageEncoders(numenc, numbytes, encoderptr);
clsid = encoderptr[4].Clsid;
buf.Save(L"test.png", &clsid);
*/
HDC gfxdc = gfx.GetHDC();
HDC scrndc = GetDC(HWND_DESKTOP);
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
POINT src = POINT(), dst;
SIZE size;
GetWindowRect(m_window, &r);
dst.x = r.left;
dst.y = r.top;
size.cx = buf.GetWidth();
size.cy = buf.GetHeight();
if (!UpdateLayeredWindow(m_window, scrndc, &dst, &size, gfxdc, &src, 0, &blend, ULW_ALPHA)) {
throw GetLastError();
}
ReleaseDC(HWND_DESKTOP, scrndc);
gfx.ReleaseHDC(gfxdc);
}
注释的代码将Bitmap对象保存到PNG,我只是为了确认位图是否正确绘制而写的。
没有错误发生,但屏幕上的结果不是我想要的。我得到一个几乎看不见的白色方块,而不是一个漂亮的50%透明绿色方块:。
另一个奇怪的事情是,窗户上的点击会落到下面的任何地方,尽管它稍微可见......
我在这里做错了什么?
答案 0 :(得分:0)
通过重写update_window()方法来管理自己解决这个问题:
void user_interface::update_window()
{
RECT r;
GetClientRect(m_window, &r);
HDC scrndc = GetDC(HWND_DESKTOP);
HDC memdc = CreateCompatibleDC(scrndc);
HBITMAP bmp = CreateCompatibleBitmap(scrndc, r.right - r.left, r.bottom - r.top);
HBITMAP oldbmp = (HBITMAP)SelectObject(memdc, bmp);
Graphics gfx(memdc);
Rect rect(r.left, r.top, r.right - r.left, r.bottom - r.top);
SolidBrush b(Color(0x7f00ff00));
gfx.FillRectangle(&b, rect);
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
POINT src = POINT(), dst;
SIZE size;
size.cx = r.right - r.left;
size.cy = r.bottom - r.top;
GetWindowRect(m_window, &r);
dst.x = r.left;
dst.y = r.top;
if (!UpdateLayeredWindow(m_window, scrndc, &dst, &size, memdc, &src, 0, &blend, ULW_ALPHA)) {
throw GetLastError();
}
SelectObject(memdc, oldbmp);
DeleteObject(bmp);
DeleteDC(memdc);
ReleaseDC(HWND_DESKTOP, scrndc);
}
可能不是最有效的方法,但它有效。可能会将HBITMAP,memdc和Graphics对象保持更长时间。弄清楚这个是留给读者的练习。 ;)
答案 1 :(得分:0)
UpdateLayeredWindow()的源位图必须与屏幕兼容,否则您的视觉结果与硬件有关。 GDI和GDIplus似乎能够绘制到任何位图,但bitblt操作通常不能处理不同的(即不兼容的)格式。原因是速度。
不幸的是,Windows文档并没有非常清楚地指出这些事实。