Создайте экземпляр WordPad и перенесите его в верхний z-порядок, все из приложения не переднего плана - PullRequest
1 голос
/ 10 февраля 2020

Я работаю с голосовым программным обеспечением (Dragon от Nuance или, может быть, Windows Распознавание речи (еще не пробовал)).

В процессе работы пользователь (я) выдает голосовую команду, чтобы что-то произошло. Для этого вопроса я пытаюсь написать код, который запускает простое приложение, такое как блокнот или WordPad, чтобы оно могло получать диктовку. Другая форма голосовой команды переключает приложения, чтобы вывести фоновое приложение (почта, браузер, электронная таблица и т. Д. c.) На передний план, чтобы оно могло принимать голосовой ввод. Таким образом, это не сценарий «кражи фокуса»; он управляется пользователем, но от микрофона, а не от клавиатуры или мыши.

У меня есть приложение C# (назовем его Creator), которое создает новый процесс, который запускает WordPad. Я хочу, чтобы вновь созданный экземпляр WordPad отображался в верхнем окне на экране, как если бы он был создан из меню «Пуск».

Все работает нормально, если приложение Creator является приложением переднего плана при создании процесса WordPad. В этом случае экземпляр WordPad появляется над процессом Creator в Z-порядке, как и ожидалось.

Однако, если окно Creator не является окном переднего плана, когда оно создает процесс и экземпляр WordPad, вновь созданный WordPad Экземпляр не появляется в верхней части Z-порядка. Он появляется в верхней части окна Создателя, но ниже любых других windows, которые были выше процесса Создателя в Z-порядке во время создания процесса WordPad.

Я прочитал много постов и перепробовал многие последовательности и варианты SetForegroundWindow, SetWindowPos, ShowWindow, WindowRestore и Focus, но безуспешно. Вновь созданный экземпляр WordPad всегда создается над окном Создателя, но под всеми windows в верхней части окна Создателя.

Что я делаю не так?

var proc = Process.Start(WordPadExepath);
if (proc != null) {
    // no permutation of these calls works reliably
    // rarely and randomly, the WordPad instance sometimes appears on top
    ShowWindow (proc.Handle, 1);
    Win32.SetForegroundWindow(proc.Handle);
    WinFuns.WindowRestore(new WindowHandle(proc.Handle));
    SetWindowPos (proc.Handle, new IntPtr(0), 0, 0, 0, 0, 3);
}

Я понимаю проблема кражи фокуса, и один из комментаторов ниже предоставил полезную ссылку на один из старых постов Чена. Тем не менее, голосовое программное обеспечение Dragon как-то делает то, что я хочу Приложение «DragonBar» всегда находится над всеми остальными windows, но позволяет мне перемещать фокус и переключать приложения с помощью мыши. (Правильно ли сделать вывод, что нахождение сверху не зависит от приложения на переднем плане?)

На данный момент я могу получить голосовой запрос пользователя в своем приложении. У меня вопрос: как я могу реализовать запрос пользователя на запуск нового процесса (и WordPad) и вывести их на первый план из моего маленького приложения Creator? Пока мое приложение Creator является приложением переднего плана / верхнего уровня, когда я получаю запрос пользователя, все в порядке. Но если я получаю голосовой запрос, когда Creator не является приложением переднего плана, я не могу сделать то, что запросил пользователь. Спасибо.

1 Ответ

0 голосов
/ 12 февраля 2020

Сначала убедитесь, что процесс имеет разрешение на активацию переднего плана для текущего окна переднего плана.

Согласно документу SetForegroundWindow,

A Процесс может установить окно переднего плана, только если выполняется одно из следующих условий:

  • Процесс является процессом переднего плана.
  • Процесс был запущен процессом переднего плана.
  • Процесс получил последнее входное событие.
  • Нет процесса переднего плана.
  • Процесс отлаживается.
  • Процесс переднего плана не является современным приложением или начальный экран.
  • Передний план не заблокирован (см. LockSetForegroundWindow).
  • Истекло время ожидания блокировки переднего плана (см. SPI_GETFOREGROUNDLOCKTIMEOUT в SystemParametersInfo).
  • Меню не отображаются active.

Second, Process.Handle не дескриптор окна, вы можете попробовать использовать свойство Process.MainWindowHandle.

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

Вы можете обратиться к следующему документу:

Отправка локального уведомления о тостах с рабочего стола C# apps

...