Win32: Bring a window to top

2019-01-08 21:49发布

I have a Windows program which has two 2 windows in it:

hwnd (main interface)

hwnd2 (toplevel window, no parent, created by hwnd)

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 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.

(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 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.)

(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.)

(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.)

I found the reason, which is because of Direct Show. I use multithread to execute it, and then the problem's solved. But...why??

This problem can be resolved by using PostMessage (rather than SendMessage).

7条回答
劳资没心,怎么记你
2楼-- · 2019-01-08 22:05

//work great!

Var
 WndHandle:HWND;

begin
 WndHandle :=FindWindowEx(0,0,nil,'Calculator');
 PostMessage(WndHandle,WM_SHOWWINDOW,SW_RESTORE,0);
 SetForegroundWindow(WndHandle);
end; 
查看更多
仙女界的扛把子
3楼-- · 2019-01-08 22:11

Have you tried SetActiveWindow()?

查看更多
再贱就再见
4楼-- · 2019-01-08 22:13

SwitchToThisWindow works best for me.

查看更多
爷的心禁止访问
5楼-- · 2019-01-08 22:17

SwitchToThisWindow() is not deprecated at all.
I use it for 14 years in production environment.
See Windows source code and you will see it's called everywhere...

查看更多
叼着烟拽天下
6楼-- · 2019-01-08 22:17

After many tries and errors.I found following solution to this problem:

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);
//redraw to prevent the window blank.
RedrawWindow(hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN );

The hwnd is your windows HWND . Please do not just copy and paste. You also need use GetLastError to check api error after every api call.

I have confirm following result on my win7:

  • Can restore minimize window and no error return.
  • If the window already top, the window title will blink and no error return.
  • If the window has closed, it will return the error "0x578 Invalid window handle."
  • It can bring the window to the top on all not top-most window and no error return.(For example it will behind the top-most taskmanager)
  • It do not make the window top-most. The user can make other window on top of it.
查看更多
太酷不给撩
7楼-- · 2019-01-08 22:28

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_NOSIZE | SWP_NOMOVE);
    ::SetForegroundWindow(m_hWnd);
    ::AttachThreadInput(dwCurID, dwMyID, FALSE);
    ::SetFocus(m_hWnd);
    ::SetActiveWindow(m_hWnd);
查看更多
登录 后发表回答