我正在尝试创build一个半透明像素的非矩形窗口。 该图像不是来自PNG,而是使用GDI +调用即时绘制的。
我创build窗口如下:
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,L"User Interface",WS_VISIBLE,CW_USEDEFAULT,640,480,HWND_DESKTOP,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,&blend,ULW_ALPHA)) { throw GetLastError(); } ReleaseDC(HWND_DESKTOP,scrndc); gfx.ReleaseHDC(gfxdc); }
注释代码块将Bitmap对象保存到PNG中,我只是为了确认位图是否正确绘制而编写的。
Linux串行IO – 在两个线程之间分割Tx和Rx?
在Linux上以相反顺序接收的实时信号
在自定义libc中实现线程本地存储
没有错误发生,但是屏幕上的结果不是我的意图。 而不是一个很好的50%透明的绿色广场,我得到一个几乎看不见的白色正方形:
。
另一个奇怪的是,窗口上的点击落在下面的任何东西,尽pipe它稍微可见…
我在这里做错了什么?
linux内核中的时间戳错误?
read()失败,地址错误,valgrind显示Syscall参数读取(buf)指向无法寻址的字节(s)
如何在Linux内核中打印当前线程堆栈跟踪?
我可以发送SIGCONT到正在运行的进程吗?
为什么我的Perl TCP服务器脚本挂着很多的TCP连接?
通过重写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.bottom - r.top); HBITMAP oldbmp = (HBITMAP)SelectObject(memdc,bmp); Graphics gfx(memdc); Rect rect(r.left,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,memdc,ULW_ALPHA)) { throw GetLastError(); } SelectObject(memdc,oldbmp); DeleteObject(bmp); DeleteDC(memdc); ReleaseDC(HWND_DESKTOP,scrndc); }
可能不是最有效的方法,但它的工作原理。 可能可能会使HBITMAP,memdc和Graphics对象保持更长的时间。 想象这个是留给读者的一个练习。 ;)
UpdatelayeredWindow()的源位图必须与屏幕兼容,否则你的视觉效果是依赖于硬件的。 GDI和GDIplus似乎可以绘制到任何位图,但bitblt操作通常不能处理不同(即不兼容)的格式。 原因是速度。
不幸的是,Windows文档没有很清楚地指出这些事实。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。