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
            );

Но помните, что последнее устанавливает окно всегда сверху.

Ответ 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;