Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 绘制部分透明的GDI+;使用UpdateLayeredWindow将位图设置为无边框窗口_C++_Windows_Gdi+ - Fatal编程技术网

C++ 绘制部分透明的GDI+;使用UpdateLayeredWindow将位图设置为无边框窗口

C++ 绘制部分透明的GDI+;使用UpdateLayeredWindow将位图设置为无边框窗口,c++,windows,gdi+,C++,Windows,Gdi+,我试图创建一个具有半透明像素的非矩形窗口。图像不是来自PNG,而是使用GDI+调用动态绘制的 我按如下方式创建窗口: WNDCLASSEX wc = WNDCLASSEX(); wc.cbSize = sizeof(wc); HINSTANCE instance = GetModuleHandle(nullptr); std::wstring classname(L"gditest ui window class"); if (!GetClassInfoEx(instance, classna

我试图创建一个具有半透明像素的非矩形窗口。图像不是来自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);
}
void用户界面::更新窗口()
{
矩形r;
GetClientRect(m_窗口和r);
位图buf(右-左,右下-右上,像素格式32bppargb);
图形gfx(&buf);
Rect Rect(右左,右上,右右-右左,右下-右上);
SolidBrush b(颜色(0x7f00ff00));
gfx.FillRectangle(&b,rect);
/*CLSID-CLSID;
UINT numbytes=0,numen=0;
GetImageEncodersSize(&numenc,&numbytes);
std::矢量编码器(numbytes,0);
ImageCodecInfo*编码器=(ImageCodecInfo*)和编码器[0];
GetImageEncoder(numenc、numbytes、Encoder);
clsid=编码器RPTR[4]。clsid;
buf.Save(L“test.png”和&clsid);
*/
HDC gfxdc=gfx.GetHDC();
HDC scrndc=GetDC(HWND_桌面);
混合功能混合;
blend.BlendOp=AC\u SRC\u OVER;
blend.BlendFlags=0;
blend.SourceConstantAlpha=255;
blend.AlphaFormat=AC_SRC_ALPHA;
点src=点(),dst;
大小;
GetWindowRect(m_窗口和r);
dst.x=右左;
dst.y=r.top;
size.cx=buf.GetWidth();
size.cy=buf.GetHeight();
if(!UpdateLayeredWindow(m_窗口、scrndc和dst、大小、gfxdc和src、0和混合、ULW_ALPHA)){
抛出GetLastError();
}
ReleaseDC(HWND_桌面,scrndc);
gfx.ReleaseHDC(gfxdc);
}
注释后的代码将位图对象保存到PNG中,我编写PNG只是为了确认位图绘制正确

没有错误发生,但是屏幕上的结果不是我想要的。我得到的不是一个50%透明的绿色正方形,而是一个几乎看不见的白色正方形:

另一件奇怪的事情是,点击窗户会穿透到下面的任何东西,即使它稍微可见


我做错了什么?

通过重写update\u 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和图形对象保留更长时间。这一点留给读者做练习

UpdateLayeredWindow()的源位图必须与屏幕兼容,否则视觉效果取决于硬件。GDI和GDIplus似乎能够绘制到任何位图中,但bitblt操作通常无法处理不同的(即不兼容的)格式。原因是速度。 不幸的是,Windows文档并没有很清楚地指出这些事实