Как я могу исправить проблему с фокусом окна? - PullRequest
2 голосов
/ 31 мая 2010

У меня очень неприятная ошибка в приложении, над которым я работаю.Предполагается, что подпрограмма что-то делает в одном окне, а затем возвращает фокус к другому в конце метода, но когда я начал использовать большой набор данных на днях, фокус перестал возвращаться в конце.Я прошел по коду по одной строке за раз, и ошибки прекратились.Итак, я полагаю, что это вопрос времени.Я прослеживаю до тех пор, пока не найду виновника.Вызов ShellExecute (...), который завершает редактор изображений, который я использую.(http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx)

Теперь, если я пройду мимо этого вызова и продолжу запуск программы, все работает нормально, но если я просто пройду мимо этой строки, произойдет ошибка. Как это может быть? Iвызвать метод SetFocus () в самом конце этого метода. Разве программа не должна нажимать на это, несмотря ни на что?

Это все очень расстраивает ...

Ответы [ 2 ]

4 голосов
/ 31 мая 2010

Первое, что должно быть ясно, это то, что вызовы Win32 API, которые связаны с окнами / сообщениями / фокусом и т. Д. не не зависят от времени. Каждый поток имеет свою собственную подсистему окна / обмена сообщениями, здесь нет условий гонки.

То, что вы описываете, является чем-то другим. Вы фактически запускаете другой процесс (приложение), который работает одновременно с вашим. Обратите внимание, что ShellExecute является асинхронной функцией. Он возвращается сразу после создания процесса, и теперь ваше приложение и созданный вами процесс запускаются одновременно.

Теперь, поскольку только одно окно в системе может иметь фокус за раз - очень вероятно, что процесс, который вы создали, просто крадет у вас фокус. Чтобы избежать этого - сначала нужно дождаться окончания работы этого процесса, и только затем восстановить фокус на вашем окне и продолжить работу.

Для этого вам нужно получить дескриптор созданного процесса и вызвать для него функцию ожидания Win32. ShellExecute не возвращает вам дескриптор созданного процесса. Однако ShellExecuteEx - делает. Кстати, он также позволяет вам запустить процесс с инструкцией, чтобы он не отображал пользовательский интерфейс, если это то, что вам нужно.

Вы должны написать это так:

SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpFile = L"notepad.exe";
sei.nShow = SW_SHOWNORMAL; // or SW_HIDE if you don't want to show it

if (ShellExecuteEx(&sei))
{
    // wait for completion
    WaitForSingleObject(sei.hProcess, INFINITE);
    CloseHandle(sei.hProcess);
}

Это должно быть полезно

P.S. Конечно, вы должны закрыть дескриптор созданного процесса. То есть CloseHandle должен вызываться после WaitForSingleObject.

0 голосов
/ 31 мая 2010

Как вы говорите, проблема звучит как проблема синхронизации.

Я не знаком с функцией ShellExecute, но со страницы, на которую вы ссылались:

"Поскольку ShellExecute может делегировать выполнение расширениям Shell (источникам данных, обработчикам контекстного меню, реализациям глаголов), которые активируются с помощью объектной модели компонентов (COM), COM следует инициализировать перед вызовом ShellExecute. Для некоторых расширений Shell требуется один COM квартира типа (СТА). "

Может быть, это связано?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...