我试图创建一个半透明的弹出窗口,用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);
}
截图
当弹出窗口超出显示边框时,透明度正常:http://clip2net.com/s/5IHCI3
我还想在二级显示器上发布它如何工作的截图,但我不能因为代表而将图像直接发布到SO。想象一下它就像它在二级屏幕截图上一样好。
谢谢。