Диспетчер задач & quot; Перейти к & quot; не работает должным образом в приложении DirectX 8 на Windows 7

Диспетчер задач «Переключиться на» не работает должным образом с приложением DirectX 8 в Windows 7

Привет! У меня очень специфическая и странная проблема.
Моя игра использует 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();
}
}
}

Функция Render имеет несколько основных функций, таких как:

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

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

//...
}

В полноэкранном режиме, когда приложение теряет фокус (по Alt + Tab, Windows Button, Ctrl + Shift + Esc и т. Д.), Оно просто минимизируется, остается в панели задач и не использует никаких ресурсов. Нет проблем. Затем я могу активировать его, используя Alt + Tab или нажав на значок панели задач. Также работает отлично: приложение активирует и сбрасывает устройство Direct3D в полноэкранном режиме.
Но использование функции «Переключить на» в диспетчере задач приводит к странной вещи: окно моего приложения разворачивается, а затем внезапно снова сворачивается!
Я попытался проанализировать ввод сообщений. Похоже, мое окно получает деактивирующий массаж сразу после сообщения об активации. Like Task Manager активирует мое приложение и снова его деактивирует.

Сначала я попробовал

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;
};

//...
}
}

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]