Приложение минимизирует запоздало при нажатии показать рабочий стол / свернуть все - PullRequest
0 голосов
/ 04 июня 2019

У меня довольно большое приложение с несколькими потоками (например, поток рендеринга Opengl) и графическим интерфейсом пользователя.При нажатии кнопки сворачивания в строке заголовка приложение быстро закрывается.Однако при нажатии Показать рабочий стол на панели задач Windows или при нажатии Win + D или Win + M приложение минимизируется с запозданием (через несколько секунд).

Я искал (довольно большую) базу кода для вхождения SC_MINIMIZE,W_MINIMIZE и такие безуспешно.Я также приостановил выполнение после нажатия кнопки «Показать рабочий стол», чтобы проверить, не заблокированы ли некоторые потоки, но не смог найти никаких проблем (но мне не хватает моих навыков отладки в области многопоточности).В любом случае, быстрое сворачивание из строки заголовка доказывает, что это возможно.

Я пытаюсь лучше понять проблему: что происходит по-другому, когда команда минимизации поступает извне приложения?Откуда эти команды поступают в приложение MFC?

Я ожидаю, что приложение быстро свернется при нажатии Показать рабочий стол на панели задач или при нажатии win + D или win + M.Однако он минимизируется с запозданием.

Дополнительная информация:

CFrameWnd :: ActivateFrame (nCmdShow) вызывается только один раз при запуске приложения.

Вот созданиепоток рендеринга:

m_threadObject = new MyRenderThread();

// If the thread is currently running, return error 
if( m_threadObject ->getCurrentStatus() != Stopped )
    return false;

m_threadObject ->setCurrentStatus( Initialized );
m_threadObject ->setContinueFlag( true );

// Create the thread
m_threadObject ->handle = AfxBeginThread(_sgThreadInternal::ThreadProc, (void*)m_threadObject);

// if the creation failed, reset status, and return error
if( m_threadObject ->handle == NULL )
{
    m_threadObject ->setCurrentStatus( Stopped );
    return false;
}

// if the wait flag is set, wait for the status to change
if( waitFlag )
{
    while( m_threadObject ->getCurrentStatus() == Initialized )
    {
        sgThread::sleep(1);
    }
}

Обмен данными между потоками происходит путем отправки событий туда и обратно, например:

MyRenderThread::sendEvent([this, name]()
{
    if (!this->load(name))
    {
        this->unload();
    }
} );

Но я не уверен, что проблема заключается в потоках.Я обнаружил, что обработчик сообщений OnSysCommand () вызывается при нажатии кнопки свертывания, но не при нажатии кнопки «Показать рабочий стол».В тестовом приложении, которое я создал, OnSysCommand () вызывается при нажатии кнопки «Показать рабочий стол».

Обновление Moar:

Мое приложение даже должным образом свернуто, если вы создаете другое приложение, повторяете все окна с помощью EnumWindows () и отправляете

::SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);

, используя окно моего приложенияhandle.

Похоже, только рабочий стол показывает, Win + D и Win + M заблокированы.

1 Ответ

0 голосов
/ 21 июня 2019

Я нашел этот код:

BOOL CMyApplicationApp::OnIdle(LONG lCount)
{
    CWinApp::OnIdle(lCount);

    [...]

    ::Sleep(5);
    if(m_mainFrame->IsIconic())
    {
        ::Sleep(100);
    }

    ::SwitchToThread();

    return TRUE;
}

Чтение о CWinApp :: OnIdle () в документации убедило меня, что бит с sleep () был излишним. Я предполагаю, что оригинальный разработчик хотел сохранить циклы процессора или что-то в этом роде. Как только я удалил код, приложение быстро свернется.

...