任务管理器的“切换到”在Windows 7上的DirectX 8应用程序上无法正常工作

时间:2013-11-27 11:10:33

标签: c++ windows-7 directx taskmanager

任务管理器的“切换到”在Windows 7上与DirectX 8应用程序无法正常工作

嗨!我有一个非常具体和奇怪的问题。 我的游戏正在使用DirectX 8.主循环看起来像这样:

while( WM_QUIT != msg.message  )
{
    if(IsIconic(m_hWnd))
    {
        if(GetMessage( &msg, NULL, 0U, 0U))
        {
            // Translate and dispatch the message
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }
    else
    {
        // Use PeekMessage() if the app is active, so we can use idle time to
        // render the scene. Else, use GetMessage() to avoid eating CPU time.
        if(PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE))
        {
            // Translate and dispatch the message
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
        {
            m_pGame->Render();
        }
    }
}

渲染功能有一些基本功能:

void CGame::Render()
{
    //...

    HRESULT hr = m_pD3DDevice->TestCooperativeLevel();
    if(hr == D3DERR_DEVICENOTRESET)
        Reset();
    else if( SUCCEEDED( hr ) )
    {
        // Render
        //...
    }

    //...
}

在全屏模式下,当应用程序失去焦点时(通过Alt + Tab,Windows按钮,Ctrl + Shift + Esc等),它只会最小化,保留在任务栏中并且不使用任何资源。没问题。然后我可以使用Alt + Tab或单击任务栏图标来激活它。也很完美:应用程序激活并全屏重置Direct3D设备。 但使用任务管理器的“切换到”功能会导致奇怪的事情:我的应用程序窗口展开,然后突然最小化! 我试图分析消息输入。看起来我的窗口在激活消息之后接收停用按摩。就像任务管理器一样,激活我的应用程序并再次停用它。

首先我试过

LockSetForegroundWindow(LSFW_LOCK);

它有助于主板集成GPU速度慢的机器,但奇怪的是它对GPU速度更快的机器没有帮助。有时候它有效。但大多数时候它没有。

然后我尝试使用SetForegroundWindow强制将窗口置于前台:

DWORD dwTimeout;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &dwTimeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0);
SetForegroundWindow(hWindow);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)dwTimeout, 0);
LockSetForegroundWindow(LSFW_LOCK);

没有用,所以我尝试了另一个黑客:

HWND hCurrWnd;
int iMyTID;
int iCurrTID;
hCurrWnd = GetForegroundWindow();
iMyTID   = GetCurrentThreadId();
iCurrTID = GetWindowThreadProcessId(hCurrWnd,0);
AttachThreadInput(iMyTID, iCurrTID, TRUE);
SetForegroundWindow(hWindow);
AttachThreadInput(iMyTID, iCurrTID, FALSE);
LockSetForegroundWindow(LSFW_LOCK);

不工作。

为什么任务经理行为如此奇怪?我还能做什么?

/////////////////////////////////////////////// //// UPPDATE +解。

所以,我解决了这个问题,虽然我完全不明白为什么它会起作用。 我找到了两个解决方案。它们中的每一个都适用于特定的计算机组。一个用于较旧和较弱的计算机(或较旧的操作系统,如WindowsXP),另一个用于具有更快视频卡和Windows 7的更高级计算机。我设法联合这两个解决方案,现在我的游戏响应“切换到”没有问题。

对于较旧和较弱的计算机,我只将LockSetForegroundWindow(LSFW_LOCK)置于关键位置,如主循环开始之前和WM_ACTIVATE消息中。

对于速度更快的计算机,我只需要调整窗口大小(使其变小),并在停用时调用WindowsUpdate。当我的窗口再次激活设备重置时,在设备重置期间,我只需自动恢复窗口的全屏大小。

LRESULT APIENTRY WndProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_ACTIVATE:
            if((LOWORD(wParam)==WA_ACTIVE)||(LOWORD(wParam)==WA_CLICKACTIVE))
        {
            if(m_pGame->m_bFullScreen)
                LockSetForegroundWindow(LSFW_LOCK);
            break;
        }
            else
            {
            if(m_pGame->m_bFullScreen)
            {
                SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,
                    128,64,SWP_NOMOVE);
                UpdateWindow(hWnd);
            };
            break;
        };

         //...
        }
}

0 个答案:

没有答案