I have a multi-monitor, multi-full screen dx9 device setup that need to work hand-in-hand with another process. This other process can make the dx9 app minimize so it can take the active foreground window... and when it's done, it signals the dx9 app (via local telnet) to recover itself and become active again.
My finished product needs to accomplish this procedurally, as in I cannot use any input devices to either alt-tab or click the dx9 app in taskbar with mouse. When I try to do it procedurally, the different recovery code I've tried has managed to create two different outcomes.
- The dx9 app does maximize, and recovers... but when I click the screen, if any windows are behind the game it immediately loses focus, as if the dx9 app is only rendering overtop the other windows but not actually there.
- Or, the game comes back up, but shows only a white screen and the device is reports 'D3DERR_DEVICELOST', and never makes it to 'D3DERR_DEVICENOTRESET'... but if you actually click the screen it receives the input properly and plays the game.
I'm almost certain I'm freeing all the dx resources that I need to be, and that it's got to be some sort of focus issue.
I'm also aware that AllowSetForegroundWindow(), needs to present in the other process to be able to give up focus, and it is being called.
The dx9 app is a fairly large engine, so posting the code is a concise matter will be difficult, below is the general idea of things:
All code is from dx9 app:
//
// A message comes in whether to minimize/maximize
if(m_bMinimize)
{
LOG("minimize!");
ShowWindow(deviceRef.GetWnd(), SW_MINIMIZE);//SW_HIDE);
}
else
{
LOG("MAXIMIZE!");
ShowWindow(deviceRef.GetWnd(), SW_SHOWNORMAL);
SetForegroundWindow(deviceRef.GetWnd());
}
The below function CheckDevice() is called at the beginning of the render thread loop. It returns whether or not the device is okay.
// Returns true if it's okay to render
bool LtGRenderThread::CheckDevice()
{
if(m_bLostDevice)
{
int j = 0;
for(j = 0; j < m_iNumDevices; j++) //for(int j = m_iNumDevices-1; j >= 0; --j)
{
HRESULT result = m_pDevices[j].m_pD3DDevice->TestCooperativeLevel();
if(FAILED(result))
{
if(D3DERR_DEVICENOTRESET == result)
{
HRESULT result2 = m_pDevices[j].m_pD3DDevice->Reset(&m_pDevices[j].m_tPresentParams);
if(FAILED(result2))
{
LOGF("Device %i: reset failed: %u", LOG_NORMAL, j, result2); }
else
{
LOGF("Device %i: Reset successful...", LOG_NORMAL, j);
}
}
break;
}
else
LOGF("DEVICE %i has recovered!", LOG_TODO, j);
}
if(j == m_iNumDevices)
{
LOG("Reloading all vRAM...");
for(j = 0; j < m_iNumDevices; j++)
{
m_pDevices[j].OnResetDevice();
}
// Tell Update thread that we need to reset the device
m_MsgManRef.MarkFlag(MSGMAN_ResetDevice);
m_bLostDevice = false;
}
}
else
{
for(int j = 0; j < m_iNumDevices; j++)
{
HRESULT result = m_pDevices[j].m_pD3DDevice->TestCooperativeLevel();
if(FAILED(result) || m_pDevices[j].IsForceReset())
{
LOG("A device has been lost! (Or forced to reset)");
m_bLostDevice = true;
// Clear out all DX resources
for(int i = 0; i < m_iNumDevices; i++)
m_pDevices[i].OnLostDevice();
m_MsgManRef.MarkFlag(MSGMAN_LostDevice);
break;
}
}
}
return !m_bLostDevice;
}
I'm pretty sure no one is going to respond to this mess. But I'll just try to be hopeful that someone has some experience in doing something similar to this. Thanks for reading.