DirectX を使用して自分自身に物をレンダリングする半透明のポップアップ ウィンドウを作成しようとしています。
問題は、レンダリングが有効になっている場合にのみ背景が再描画されないことです。再描画は、更新時 (つまり、ポップアップ ウィンドウの背後にあるテキスト エディターで行を選択したとき) にのみ発生します。
ウィンドウがセカンダリ モニターに移動すると、魔法が始まります。そこでは大丈夫です。透明度は完璧に機能し、背景は常に再描画されます。また、ポップアップが表示枠の外に出ると、透明度が機能し始めます。(以下のスクリーンショット。)
OS は、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/5IHAyQ
ポップアップが表示枠の外にある場合、透明度は問題ありません: http://clip2net.com/s/5IHCI3
また、セカンダリモニターでの動作のスクリーンショットを投稿したかったのですが、担当者のために SO に直接画像を投稿することもできません。2番目のスクリーンショットのように、それで問題ないと想像してみてください.
ありがとうございました。