0

半透明のピクセルで四角形以外のウィンドウを作成しようとしています。画像は 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% 透明の緑色の四角形の代わりに、かろうじて見える白い四角形が表示されますスクリーンショット

もう1つの奇妙なことは、ウィンドウをクリックすると、その下にあるものに落ちることです.

ここで何が間違っていますか?

4

2 に答える 2

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 オブジェクトをより長く保持できます。これを理解することは、読者の演習として残されています。;)

于 2013-01-15T08:34:13.137 に答える