zoukankan      html  css  js  c++  java
  • SetForegroundWindow的正确用法2

    http://www.cnblogs.com/ziwuge/archive/2012/01/06/2315342.html

     MSDN:http://msdn.microsoft.com/en-us/library/ms633539(v=VS.85).aspx 下面是谷歌翻译,有些语句不是很流畅。

      SetForegroundWindow函数将创建指定的窗口,并激活到前台窗口的线程 。键盘输入窗口,并为用户更改不同的视觉线索。该系统分配一个优先略高前景的窗口,比它其他线程创建的线程。
    语法
      BOOL SetForegroundWindow(       
            HWND  HWND );
    参数
    HWND
      [in]应该被激活,并带到前景的窗口句柄。
    返回值
      如果窗口被带到前台,返回值为非零。
      如果窗口不带到前景,返回值是零。
    备注
      Windows 98/Me系统限制哪些进程可以设置前台窗口。一个进程可以设置前台窗口,仅当下列条件之一为真 :
        这个过程是前台进程。
        这个过程是由前台进程的开始。
        过程中收到的最后一个输入事件。
        没有前台进程。
        前台进程正在被调试。
        前景不被锁定(见LockSetForegroundWindow)。
        前景锁定超时已过期(看到SPI_GETFOREGROUNDLOCKTIMEOUTSystemParametersInfo)。
        Windows 2000/XP的:没有菜单处于活动状态。
      这一变化,应用程序不能强制一个窗口到前台,而用户是另一个窗口的工作。相反,前台和后台的Windows激活窗口( SetActiveWindow)和调用函数通知用户 。然而,在Microsoft Windows 98和Windows Millennium Edition(Windows Me)中,如果一个nonforeground线程调用SetForegroundWindow,并通过一个没有被调用线程创建的窗口的句柄,窗口不闪现在任务栏上。SetForegroundWindow行为相同的,因为它没有在Windows 95和Microsoft Windows NT 4.0,安装应用程序时,更改前景色锁超时值 。这可以从下面的函数调用设置或安装应用程序:

    SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);

      这种方法允许在Windows 98/Windows Me和Windows 2000/Windows XPSetForegroundWindow行为作为Windows 95和Windows NT 4.0相同,分别为所有应用程序,。安装应用程序,这样做是使用户是不会改变的行为感到惊讶的用户发出警告。在Windows上的Windows 2000和Windows XP,调用失败,除非调用线程可以改变前台窗口,因此必须从一个安装或修补应用程序调用。欲了解更多信息,请参阅前景和背景窗口

      一个过程,可以设置前台窗口可以使另一个进程通过调用前台窗口AllowSetForegroundWindow功能。dwProcessId所指定的过程中失去了到前台窗口设置下一次输入用户生成的能力,除非输入是在这个过程中,或在下一次进程调用AllowSetForegroundWindow,除非指定过程。
      前台进程可以禁用调用SetForegroundWindow调用的LockSetForegroundWindow函数。

     

      保证SetForegroundWindow成功
      在SetForegroundWindow之前比较早的时候(比如main函数里)调用一下以下代码:

    DWORD dwTimeout = -1;  
    SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&dwTimeout, 0);
    if (dwTimeout >= 100) {
    SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
    }
    复制代码
    HWND hForeWnd = NULL; 
    HWND hWnd= FindWindow(NULL, "");
    DWORD dwForeID;
    DWORD dwCurID;

    hForeWnd = GetForegroundWindow();
    dwCurID = GetCurrentThreadId();
    dwForeID = GetWindowThreadProcessId( hForeWnd, NULL );
    AttachThreadInput( dwCurID, dwForeID, TRUE);
    ShowWindow( hWnd, SW_SHOWNORMAL );
    SetWindowPos( hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE );
    SetWindowPos( hWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE );
    SetForegroundWindow( hWnd );
    AttachThreadInput( dwCurID, dwForeID, FALSE);
    复制代码

      第一段代码:
        后果是如果执行到if里面的语句,会因为user profile的更改回写和WM_SETTINGCHANGE的广播而导致这个API调用本身卡两三秒。
      第二段代码: 
        设置当前某窗口为当前窗口,有几个步骤要做: 
        1.得到窗口句柄FindWindow 
        2.切换键盘输入焦点AttachThreadInput 
        3.显示窗口ShowWindow(有些窗口被最小化/隐藏了) 
        4.更改窗口的Zorder,SetWindowPos使之最上,为了不影响后续窗口的Zorder,改完之后,再还原 
        5.最后SetForegroundWindow 

      想必看到上述代码就明白了这个函数失败的原因了吧。

    【参考资料 感谢作者】
    1、VC++ SetForegroundWindow 
    2、保证SetForegroundWindow成功
    3、讨论一下,如何确保SetForegroundWindow()成功???????

  • 相关阅读:
    关于MOTO E2
    Visual Studio 2008 SDK 1.1 Beta 发布
    开始了新的工作
    C# 2.0 的"语法多义性"
    最近画的框架草图
    SQL数据库向ORACLE迁移注意事项
    C#中很多新的特性,提供了更好的“即兴编程”的能力。
    看了点lua相关的东西,有点想法不知能否实现?先记下来慢慢思考。
    读《企业应用架框模式》
    porting cinvoke1.0 to E2 (armlinux)
  • 原文地址:https://www.cnblogs.com/carl2380/p/2534560.html
Copyright © 2011-2022 走看看