Windows 编程: 将目标窗口显示在最顶端

Posted 轩辕泪1020

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows 编程: 将目标窗口显示在最顶端相关的知识,希望对你有一定的参考价值。

1. [BUG Backgroud]

  1. 使用SetForegroundWindow(hwnd) 不能将目标窗口弹到顶端.
  2. Win7 中使用WIN键后出现的BUG.

最终成功测试代码:

BOOL MyClass::PutMyWindowToTop(
) 
  OutputDebugString("In function PutMyWindowToTop!");
  HWND hwnd = FindWindow(NULL, L"MyWindow");
  if (hwnd == NULL) 
      OutputDebugString("Failed to get hwnd of MyWindow!");
      return FALSE;
   else 
      OutputDebugString("Success get hwnd of MyWindow before switch to window");
  
  if (!::IsWindow(hwnd)) 
      OutputDebugString("hwnd is not a valid window's handler!");
      return FALSE;
  
  try 
      DWORD lock_timeout = 0;
      DWORD lock_timeout_after = 0;
      HWND  current_hwnd = ::GetForegroundWindow();
      DWORD dw_this_tid = ::GetCurrentThreadId();
      DWORD dw_current_tid = ::GetWindowThreadProcessId(current_hwnd, 0);
      if (dw_this_tid != dw_current_tid) 
          ::AttachThreadInput(dw_this_tid, dw_current_tid, TRUE);

          ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &lock_timeout, 0);
          if (lock_timeout >= 100) 
             ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
             if (0 == ::AllowSetForegroundWindow(dw_this_tid)) 
                 OutputDebugString("Failed to AllowSetForegoundWindow!");
              else 
                 OutputDebugString("Successed in AllowSetForegoundWindow!");
             
             ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &lock_timeout_after, 0);
          
      
      char temp_s[60] =  0 ;
      sprintf(temp_s, "lock_timeout: %u, after: %u", lock_timeout, lock_timeout_after);
      OutputDebugString(temp_s);
      //Test SetWindows position.
      if (0 == ::ShowWindow(hwnd, SW_SHOWNORMAL)) 
          OutputDebugString("ShowWindow return window was previously hidden!");
       else 
          OutputDebugString("ShowWindow return window was previously visible!");
      
      if (0 == ::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)) 
          OutputDebugString("SetWindowPos first time was failed!");
       else 
          OutputDebugString("SetWindowPos first time was succeed!");
      
      if (0 == ::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)) 
          OutputDebugString("SetWindowPos second time was failed!");
       else 
          OutputDebugString("SetWindowPos second time was succeed!");
      
      
      if (0 == ::SetForegroundWindow(hwnd)) 
          OutputDebugString("Failed to set this window to foreground!");
       else 
          OutputDebugString("Success in set this window to foreground!");
      

      if (dw_this_tid != dw_current_tid) 
          ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (PVOID)lock_timeout, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
          ::AttachThreadInput(dw_this_tid, dw_current_tid, FALSE);
      
   catch (...) 
      OutputDebugString("Failed to put MyWindow window to top!");
  

  OutputDebugString("End function PutMyWindowToTop!");

  return TRUE;

2. 最终分析

SetForegroundWindow 其实并不进行窗口z-order 次序的更改, 它所做的事就是像人一样在任务栏上点击了一下程序. https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setforegroundwindow

通过最后的调试结果来看, 设置不设置Foreground time out 参数对结果没有影响. 相应的代码可以去掉. 这个感觉是个老问题, 在论坛上找到了好多的讨论, 但是并不知道为什么. 这个还得大神来.

另外: SetActiveWindow是干什么的? 获取输入队列?

related website:

  1. 将后台窗口激活到前台的方法(使用AttachThreadInput和SetForegroundWindow两个API)–>这个在大多数情况下都是可以的, 但是在少数特定情况下不知道为什么不可以.
  2. SetForegroundWindow的正确用法 --> 就是按照这个来的, 恕我愚钝, 没有看出来原因.
  3. SetForegroundWindow、SetActiveWindow、SetFocus 如何将一个某个窗口提到最顶层

3. others:

  1. 在pdf, EXCEL 文件中设置超链接时, 路径上不能有#字符.
  2. CSDN的MarkDown 编辑界面好用了一些, 但是为什么代码段用黑色背景, 感觉不配啊! (虽然我在编辑代码的时候用黑色的! 哼!)

以上是关于Windows 编程: 将目标窗口显示在最顶端的主要内容,如果未能解决你的问题,请参考以下文章

Windows API一日一练 38 SetWindowPos函数

如何将window.open弹出的窗口总在最前显示

vue在路由跳转时,如何让跳转的页面显示在最顶端

Android 项目必备(四十二)-->Android 多窗口模式

wpf 只让窗口保留一个,并在最前显示

取消google浏览器在最前端显示