问题描述
我有一个 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:将窗口置于顶部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!