我对 Winapi 窗口有疑问。我有一个应用程序,它可能(但不一定)以全屏模式启动,如果是这样,在切换到全屏之前我不能显示一个空窗口。所以,我正在做的是:
- 创建窗口
称呼
ShowWindow(HWnd, SW_HIDE); UpdateWindow(HWnd);
从文件中读取设置
重置 D3D 渲染器、调整窗口、可能切换到全屏并调用
SetWindowPos(HWnd, HWND_NOTOPMOST, posx, posy,sizex, sizey, SWP_SHOWWINDOW); ShowWindow(HWnd, SW_SHOW);
在全屏模式下一切都很好,但是当应用程序以窗口模式启动时,根本就没有窗口——CreateWindowEx
返回正确的窗口句柄,应用程序在后台运行,一切正常,但找不到窗口。我忘记了什么?
编辑
好的,有些进展。原来 D3D 渲染器重置例程中的 SetWindowPos 没有被调用。我解决了这个问题,现在出现了新问题 - 窗口是它应该在的地方,但它是完全透明的,除了光标之外,客户区什么都没有显示。
在全屏模式下一切正常。如果应用程序以全屏模式启动并且用户切换到窗口模式,一切都很好。
edit2
好的,我设法找到了窗口中没有渲染任何内容的原因 -IDirect3DDevice9::BeginScene
方法返回D3DERR_INVALIDCALL
,所以显然重置 D3D 渲染器有问题。
void VD3D9Renderer::Reset(bool windowed, ulong width, ulong height)
{
for (size_t i=0; i<Fonts.size(); i++)
Fonts[i]->Font->OnLostDevice();
if (FontMgr)
FontMgr->OnLostDevice();
for (VMap<VString, VD3D9Texture*>::iterator it = TextureMap.begin(); it != TextureMap.end(); it++)
{
VD3D9Texture* tex = it->second;
if (tex && tex->IsRenderTarget())
tex->TexturePtr->Release();
}
D3DD->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &BackBufferColor);
D3DD->GetDepthStencilSurface(&BackBufferDepthStencil);
if (BackBufferColor) BackBufferColor->Release();
if (BackBufferDepthStencil) BackBufferDepthStencil->Release();
bool change_fs = (windowed==true && D3DPP.Windowed == FALSE) || (windowed==false && D3DPP.Windowed == TRUE) ? true : false;
D3DPP.Windowed = windowed;
if (width) D3DPP.BackBufferWidth = width;
if (height) D3DPP.BackBufferHeight = height;
D3DD->Reset(&D3DPP);
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = D3DPP.BackBufferWidth;
rc.bottom = D3DPP.BackBufferHeight;
if (change_fs)
{
if(D3DPP.Windowed)
{
DWORD style = GetWindowLong(HWnd, GWL_STYLE);
DWORD exstyle = GetWindowLong(HWnd, GWL_EXSTYLE);
style = WS_CAPTION | WS_SYSMENU;
exstyle = 0;
int posx = (GetSystemMetrics(SM_CXSCREEN) - (rc.right-rc.left)) >> 1;
int posy = 0;
AdjustWindowRectEx(&rc, style, false, exstyle);
SetWindowLong(HWnd, GWL_STYLE, style);
SetWindowLong(HWnd, GWL_EXSTYLE, exstyle);
if(!SetWindowPos(HWnd, HWND_NOTOPMOST, posx, posy, rc.right, rc.bottom, SWP_SHOWWINDOW))
{
DWORD error = GetLastError();
VLog("Error in SetWindowPos: %u\n", error);
}
ShowWindow(HWnd, SW_SHOW);
}
else
{
DWORD style = GetWindowLong(HWnd, GWL_STYLE);
DWORD exstyle = GetWindowLong(HWnd, GWL_EXSTYLE);
style = WS_POPUP;
exstyle = 0;
int posx = (GetSystemMetrics(SM_CXSCREEN) - (width)) >> 1;
int posy = 0;
SetWindowLong(HWnd, GWL_STYLE, style);
SetWindowLong(HWnd, GWL_EXSTYLE, exstyle);
if(!SetWindowPos(HWnd, HWND_NOTOPMOST, posx, posy, rc.right, rc.bottom, SWP_SHOWWINDOW))
{
DWORD error = GetLastError();
VLog("Error in SetWindowPos: %u\n", error);
}
ShowWindow(HWnd, SW_SHOW);
}
}
else
{
if (rc.right > 0 && rc.bottom > 0)
{
DWORD style = GetWindowLong(HWnd, GWL_STYLE);
AdjustWindowRect(&rc, style, false);
int posx = (GetSystemMetrics(SM_CXSCREEN) - (rc.right-rc.left)) >> 1;
int posy = 0;
if(!SetWindowPos(HWnd, HWND_NOTOPMOST, posx, posy, rc.right, rc.bottom, SWP_SHOWWINDOW))
{
DWORD error = GetLastError();
VLog("Error in SetWindowPos: %u\n", error);
}
//SetWindowPos(HWnd, HWND_NOTOPMOST, posx, posy, rc.right, rc.bottom, SWP_SHOWWINDOW);
ShowWindow(HWnd, SW_SHOW);
}
}
for (VMap<VString, VD3D9Texture*>::iterator it = TextureMap.begin(); it != TextureMap.end(); it++)
{
VD3D9Texture* tex = it->second;
if (tex && tex->IsRenderTarget())
D3DD->CreateTexture(tex->Width, tex->Height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &tex->TexturePtr, NULL);
}
for (size_t i=0; i<Fonts.size(); i++)
Fonts[i]->Font->OnResetDevice();
if (FontMgr)
FontMgr->OnResetDevice();
ResetDeviceState();
}