0

我试图创建一个半透明的弹出窗口,它使用 DirectX 在自身上呈现内容。

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

当我的窗口移动到辅助监视器时,魔术就开始了。那里一切正常。透明效果完美,背景不断重绘。此外,如果弹出窗口超出显示边框透明度开始工作。(下面的屏幕截图。)

操作系统是带有 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

我还想发布它在辅助监视器上如何工作的屏幕截图,但我不能因为代表而直接将图像发布到 SO。试想一下,它就像在辅助屏幕截图上一样。

谢谢你。

部分解决,见评论。

4

0 回答 0