Как заставить мое приложение выйти вперед и сфокусироваться? - PullRequest
7 голосов
/ 27 марта 2009

Я работаю над приложением, которое оказывается начальной загрузкой для установщика, над которым я тоже работаю. Приложение выполняет несколько вызовов MSI, чтобы получить информацию, которая мне нужна для создания мастера, который является главным окном моего приложения, которое вызывает окно прогресса, которое открывается во время сбора информации, а затем исчезает, как только это будет сделано. Затем мастер настроен и запущен. Моя проблема в том, что мастер (производный от CPropertySheet) не хочет выходить на передний план и быть активным приложением, а я не добавляю в него некоторые вызовы.

Я решил проблему с выводом на первый план с помощью следующего кода в моем методе OnInitDialog ():

SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // force window to top
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // lose the topmost status that the previous line gave us

Моя проблема в том, что я до сих пор не выяснил, как заставить окно самостоятельно активироваться (т.е. сделать себя тем, кто имеет фокус). SetFocus () не будет работать в этом контексте. Мне нужно что-то, что приведет окно к вершине Z-порядка и активирует его, желательно в минимально возможном количестве вызовов.

Я предполагаю, что окно прогресса, открываемое в начале вызовами MSI, приводит к тому, что главное окно испортилось, но у меня нет способа предотвратить появление этого окна. Кроме того, не имеет смысла скрывать это, потому что оно позволяет пользователю узнать, что происходит, прежде чем появится главное окно.

Ответы [ 4 ]

9 голосов
/ 20 декабря 2013

Андрей не совсем прав. Windows действительно очень старается не дать вам украсть фокус, но это возможно, используя следующий метод.

  1. Присоединить к нити окна, которое в данный момент имеет фокус.
  2. Поместите ваше окно в фокус.
  3. Отсоединить от нити.

И код для этого будет выглядеть примерно так:

DWORD dwCurrentThread = GetCurrentThreadId();
DWORD dwFGThread      = GetWindowThreadProcessId(GetForegroundWindow(), NULL);


AttachThreadInput(dwCurrentThread, dwFGThread, TRUE);

// Possible actions you may wan to bring the window into focus.
SetForegroundWindow(hwnd);
SetCapture(hwnd);
SetFocus(hwnd);
SetActiveWindow(hwnd);
EnableWindow(hwnd, TRUE);

AttachThreadInput(dwCurrentThread, dwFGThread, FALSE);

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

8 голосов
/ 27 марта 2009

Вы не можете украсть фокус. Период.

См. Эту старую новинку статьи:

https://blogs.msdn.microsoft.com/oldnewthing/20090220-00/?p=19083

0 голосов
/ 27 марта 2009

Вы обнаружите, что у BringWindowToTop или SetForegroundWindow есть требования, которые должны быть выполнены, прежде чем окно будет фактически перемещено вперед на все другие окна (приложения). Если они не выполнены, Windows будет мигать только значок приложения на панели задач. Эта статья предлагает способ обойти это, но, как указывает 1800 ИНФОРМАЦИЯ, это не рекомендуется. Я полагаю, вам просто нужно это принять.

0 голосов
/ 27 марта 2009

не работает ShowWindow (youwindow, SW_SHOWNORMAL)? -don

...