透明窗口使背景不重绘(winxp)

时间:2013-09-09 15:30:56

标签: c++ winapi directx transparency wxwidgets

我试图创建一个半透明的弹出窗口,用DirectX渲染自己的东西。

问题是只有在启用渲染时,背景才会重绘自身。重绘只在更新时发生(即当我在弹出窗口后面的文本编辑器中选择一行时)。

当我的窗口移动到辅助监视器时,

Magic开始了。一切都还好。透明度完美,背景不断重绘。此外,如果弹出窗口超出显示边界,则透明度开始起作用。 (截图如下。)

操作系统是带有DirectX 9.0c的Windows XP SP3和带有最新驱动程序的NVIDIA显卡。

我还在几个不同的视频卡上测试了Win Vista和Win 7上的程序。效果很好。

创建窗口

m_popup = new popup(__("pew!"), wxPoint(600, 330), wxSize(250, 250));
m_popup->Show(true);
m_popup->SetWindowStyle(wxSTAY_ON_TOP);
m_popup->SetTransparent(150);
SetTopWindow(m_popup);

来自wxWidgets的透明度代码(2.8.12)

    bool wxTopLevelWindowMSW::SetTransparent(wxByte alpha)
    {
        typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD);
        static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL;
        if ( pSetLayeredWindowAttributes == NULL )
        {
            wxDynamicLibrary dllUser32(_T("user32.dll"));
            pSetLayeredWindowAttributes = (PSETLAYEREDWINDOWATTR)
            dllUser32.GetSymbol(wxT("SetLayeredWindowAttributes"));
        }
    if ( pSetLayeredWindowAttributes == NULL )
        return false;

    LONG exstyle = GetWindowLong(GetHwnd(), GWL_EXSTYLE);

    // if setting alpha to fully opaque then turn off the layered style
    if (alpha == 255)
    {
        SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle & ~WS_EX_LAYERED);
        Refresh();
        return true;
    }

    // Otherwise, set the layered style if needed and set the alpha value
    if ((exstyle & WS_EX_LAYERED) == 0 )
        SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle | WS_EX_LAYERED);
        // ^ this line seems to cause the problem
        // (tried to make the window transparent manually without wxWidgets' help)

    return pSetLayeredWindowAttributes(GetHwnd(), 0, (BYTE)alpha, LWA_ALPHA) != 0;
    }

DirectX初始化

    m_d3d = Direct3DCreate9(D3D_SDK_VERSION);
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
    d3dpp.BackBufferWidth = g_size;
    d3dpp.BackBufferHeight = g_size;

    m_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_d3ddev);

    CUSTOMVERTEX vertices[] =
    {
    { 320.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(150, 255, 150, 150), },
    { 520.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(150, 150, 255, 150), },
    { 120.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_ARGB(150, 150, 150, 255), },
    };
    m_d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
                           0,
                           CUSTOMFVF,
                           D3DPOOL_MANAGED,
                           &v_buffer,
                           NULL);

    VOID* pVoid;

    v_buffer->Lock(0, 0, (void**)&pVoid, 0);
    memcpy(pVoid, vertices, sizeof(vertices));
    v_buffer->Unlock();

渲染

    if (m_render)
    {
            m_d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(150, 150, 150, 200), 1.0f, 0);
            m_d3ddev->BeginScene();
            m_d3ddev->SetFVF(CUSTOMFVF);
            m_d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
            m_d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
            m_d3ddev->EndScene();
            m_d3ddev->Present(NULL, NULL, NULL, NULL);
    }

截图

  1. 透明度失败:http://clip2net.com/s/5IHAyQ

  2. 当弹出窗口超出显示边框时,透明度正常:http://clip2net.com/s/5IHCI3

  3. 我还想在二级显示器上发布它如何工作的截图,但我不能因为代表而将图像直接发布到SO。想象一下它就像它在二级屏幕截图上一样好。

    谢谢。

    部分已解决,请参阅评论。

0 个答案:

没有答案