Win32: Верните окно вверх
У меня есть программа Windows, в которой есть два окна:
hwnd (main interface)
hwnd2 (toplevel window, no parent, created by hwnd)
Когда я дважды нажимаю на hwnd, мне нужно, чтобы hwnd2 всплывал и показывал некоторые данные, поэтому я использую эту функцию для вывода hwnd2 в начало:
BringWindowToTop(hwnd2);
hwnd2 доведено до вершины, но есть одна вещь нечетная. Когда я снова нажимаю hwnd2, hwnd (основной интерфейс) автоматически появляется автоматически.
Я попытался использовать следующую функцию для решения этой проблемы, но не работает.
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
//doesn't work
BringWindowToTop(hwnd2); //This is the function brings hwnd2 to top
SetForegroundWindow(hwnd2); //doesn't work
SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
//doesn't work
SetWindowPos(hwnd2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
// hwnd2 "always" on top, not what I want
SetActiveWindow(hwnd2); // doesn't work too (for replying to Magnus Skog, thanks)
SwitchToThisWindow(hwnd2, TRUE);// got the same problem with BringWindowToTop function
SwitchToThisWindow(hwnd2, FALSE);
Как я могу решить эту проблему?
Спасибо заранее.
(для ответа на aJ, hwnd2 не имеет родительского элемента, поскольку он должен быть оконным окном, чтобы он мог находиться в передней/задней части других окон)
(hwnd2 - медиаплеер, состоящий из нескольких окон, одно из окон - для видеодисплеирования, два других элемента управления трекбарами для индикатора выполнения и строки тома, один элемент панели управления для панели управления.)
(Возможно, это может помочь, независимо от того, какое окно я нахожу на hwnd2, hwnd появляется автоматически, поскольку "мышь находится поверх hwnd в Z-порядке", включая панель меню и неклиентскую область, и др.)
(Этот медиаплеер записывается в Direct Show.Я использую IVideoWindow:: put_Owner для размещения видеоокна в качестве владельца видео, Direct Show внутренне создает окно суб-видео в качестве дочернего объекта видео-окна. За исключением этого суб- видео, которое я не вижу в исходном коде, я не вижу ничего подозрительного в hwnd2.)
Я нашел причину, которая вызвана Direct Show. Я использую multithread для его выполнения, а затем проблема решена. Но... почему??
Эта проблема может быть решена с помощью PostMessage (а не SendMessage).
Ответы
Ответ 1
попробуйте это, говорят, что он приходит из M $
HWND hCurWnd = ::GetForegroundWindow();
DWORD dwMyID = ::GetCurrentThreadId();
DWORD dwCurID = ::GetWindowThreadProcessId(hCurWnd, NULL);
::AttachThreadInput(dwCurID, dwMyID, TRUE);
::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
::SetForegroundWindow(m_hWnd);
::AttachThreadInput(dwCurID, dwMyID, FALSE);
::SetFocus(m_hWnd);
::SetActiveWindow(m_hWnd);
Ответ 2
Оба отлично работают:
::SetForegroundWindow(wnd)
или
::SetWindowPos(m_hWnd, // handle to window
HWND_TOPMOST, // placement-order handle
0, // horizontal position
0, // vertical position
0, // width
0, // height
SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE// window-positioning options
);
Но помните, что последнее устанавливает окно всегда сверху.
Ответ 3
SwitchToThisWindow работает лучше всего для меня.
Ответ 4
Вы пробовали SetActiveWindow()?
Ответ 5
SwitchToThisWindow() не устарел вообще.
Я использую его в течение 14 лет в производственной среде.
Смотрите исходный код Windows, и вы увидите, что он называется везде...
Ответ 6
После многих попыток и ошибок я нашел следующее решение этой проблемы:
SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); // restore the minimize window
SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE);
RedrawWindow(hwnd,nil,0,RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN ); // redraw to prevent the window blank.
Хунд - это ваши окна HWND. Пожалуйста, не копируйте и не вставляете. Вам также нужно использовать GetLastError
для проверки ошибки api после каждого вызова api.
Я подтверждаю следующий результат на моей win7:
- Можно восстановить окно минимизации и не возвращать ошибку.
- Если окно уже вернулось, заголовок окна будет мигать, и ошибка не вернется.
- Если окно закрыто, оно вернет ошибку "0x578 Недопустимый дескриптор окна".
- Он может вывести окно вверху всего не самого верхнего окна и не возвращать ошибку (например, он будет за главным менеджером задач)
- Это не делает окно самым большим. Пользователь может сделать другое окно поверх него.
Ответ 7
//отлично работает!
Var
WndHandle:HWND;
begin
WndHandle :=FindWindowEx(0,0,nil,'Calculator');
PostMessage(WndHandle,WM_SHOWWINDOW,SW_RESTORE,0);
SetForegroundWindow(WndHandle);
end;