問題描述
我有一個 Windows 程序,其中有兩個 2 個窗口:
I have a Windows program which has two 2 windows in it:
hwnd (main interface)
hwnd2 (toplevel window, no parent, created by hwnd)
當我雙擊hwnd時,我需要hwnd2彈出并顯示一些數據,所以我使用這個函數將hwnd2帶到頂部:
When I double click on hwnd, I need hwnd2 to pop up and show some data, so I use this function to bring hwnd2 to top:
BringWindowToTop(hwnd2);
hwnd2 被帶到了頂部,但有一點很奇怪.當我再次點擊 hwnd2 時,hwnd(主界面)再次自動彈出.我嘗試使用以下函數來解決此問題,但它們都不起作用.
hwnd2 is brought to top, but there is one thing odd. When I click on hwnd2 again, hwnd (main interface) pops itself up again automatically. I tried to use the following function to solve this problem, but non of them works.
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);
我該如何解決這個問題?提前致謝.
How could I solve this problem? Thanks in advance.
(回復aJ,hwnd2沒有父級,因為它需要是一個頂層窗口,所以它可以在其他窗口的前面/后面)
(for replying to aJ, hwnd2 doesn't have parent because it needs to be a toplevel window so it can be in front/back of other windows)
(hwnd2 是一個媒體播放器,由多個窗口組成,其中一個窗口用于視頻顯示,另外兩個軌跡欄控件用于進度條和音量條,一個用于控制面板的工具欄控件.)
(hwnd2 is a media player which is composed of several windows, one of the windows is for video dispaly, two other trackbar controls for progress bar and volume bar, one Toolbar control for control panel.)
(有一個這個可能有幫助,無論我點擊hwnd2的哪個窗口,hwnd都會自動彈出,就像鼠標在Z-order中的hwnd頂部"一樣,包括菜單欄和非客戶區,等)
(There is one this might help, no matter which window I click on hwnd2, hwnd pops up automatically as loong as "the mouse is on top of hwnd in Z-order", including menu bar and non-client area, etc.)
(這個媒體播放器是用Direct Show寫的.我使用IVideoWindow::put_Owner把視頻窗口作為視頻所有者,Direct Show內部創建了一個子視頻窗口作為視頻窗口的子窗口.除了這個子窗口我看不到源代碼的視頻窗口,我在hwnd2中沒有看到任何可疑的東西.)
(This media player is writen in Direct Show. I use IVideoWindow::put_Owner to put video window as the video owner, Direct Show internally creates a sub-video window as a child of the video window. Except for this sub-video window which I can't see the source code, I don't see any thing suspicious in hwnd2.)
我找到了原因,是因為Direct Show.我使用多線程執行它,然后問題解決了.但是……為什么??
I found the reason, which is because of Direct Show. I use multithread to execute it, and then the problem's solved. But...why??
這個問題可以通過使用 PostMessage(而不是 SendMessage)來解決.
This problem can be resolved by using PostMessage (rather than SendMessage).
推薦答案
試試這個,據說來自M$
try this,it is said coming from 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_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
::SetForegroundWindow(m_hWnd);
::SetFocus(m_hWnd);
::SetActiveWindow(m_hWnd);
::AttachThreadInput(dwCurID, dwMyID, FALSE);
為了把一個窗口帶到頂部,你應該得到你的窗口句柄,線程句柄,在前臺的windows線程句柄
In order to bring a window to top, you should get your window handle,thread handle, the windows thread handle who is in foreground
然后我們將我們的線程附加到前臺窗口線程并通過AttachThreadInput獲取輸入,然后我們設置我們的窗口z順序到最頂層,然后將其 z 順序恢復為正常,調用 SetForegroundWindow,SetFocus,SetActiveWindow 以確保我們的窗口位于頂部并處于活動狀態并具有焦點
then we attach our thread to foreground window thread and get input by AttachThreadInput, then we set our window z order to topmost and then restore its z order to normal, call SetForegroundWindow,SetFocus,SetActiveWindow to make sure our window is brought to top and is active and have focus
然后從舊的前臺窗口線程中分離輸入隊列,使我們的線程成為唯一捕獲輸入事件的線程
then deattach the input queue from the old foreground window thread, make our thread the only one who capture the input events
那為什么要調用AttachThreadInput,是因為
So why should We call AttachThreadInput, it is because
SetFocus 將鍵盤焦點設置到指定的窗口.窗戶必須是附加到調用線程的消息隊列.
SetFocus sets the keyboard focus to the specified window. The window must be attached to the calling thread's message queue.
AttachThreadInput 有什么作用?
What does AttachThreadInput do?
AttachThreadInput 函數可用于允許一組線程共享相同的輸入狀態.通過共享輸入狀態,線程分享他們的活動窗口概念.通過這樣做,一個線程總是可以激活另一個線程的窗口.這個功能也是用于共享焦點狀態、鼠標捕獲狀態、鍵盤狀態、以及由不同線程創建的窗口之間的窗口 Z 順序狀態其輸入狀態是共享的.
The AttachThreadInput function can be used to allow a set of threads to share the same input state. By sharing input state, the threads share their concept of the active window. By doing this, one thread can always activate another thread's window. This function is also useful for sharing focus state, mouse capture state, keyboard state, and window Z-order state among windows created by different threads whose input state is shared.
我們使用 SetWindowPos 將窗口帶到最頂層,如果窗口隱藏,則使用 SWP_HIDEWINDOW 顯示窗口
We use SetWindowPos to bring the windows to topmost and show the window if the window is hidding by using SWP_HIDEWINDOW
SetWindowPos 函數改變一個窗口的大小、位置和 Z 順序子窗口、彈出窗口或頂級窗口.這些窗戶是訂購的根據他們在屏幕上的外觀.最上面的窗口獲得最高等級,是 Z 順序中的第一個窗口
SetWindowPos function changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order
如果你的問題是你的窗口也被最小化了,你應該在最后添加一行代碼
If your problem is your window is also minimized , you should add one line code to the end
ShowWindow(m_hWnd, SW_RESTORE);
這篇關于Win32:將窗口置于頂部的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!