代码之家  ›  专栏  ›  技术社区  ›  Ed Swangren

如何在前景窗口没有焦点时可靠地找到它

  •  6
  • Ed Swangren  · 技术社区  · 14 年前

    所以,我觉得这很简单,我错了。以下是问题的简化描述:

    我正在为我们的制造人员编写一个小应用程序,当他们单击系统托盘中的应用程序图标时,它将抓取整个桌面以及前台窗口的屏幕截图。目前,我正在NotifyIcon的MouseMove事件中使用Win32方法“getforegroundindow”来保存前台窗口句柄,并在Click事件中拍摄屏幕截图。

    似乎,如果我能够得到每个窗口的z位置只使用窗口句柄,这将是一个很容易解决的问题使用枚举窗口。然而,我还没有找到一种方法来做到这一点。

    所以,我问你们;考虑到前景窗口当时可能没有焦点,您将如何编写一个方法来可靠地定位前景窗口?不是我的googlefu让我失望了,就是这方面的信息太少了。提前谢谢。

    2 回复  |  直到 14 年前
        1
  •  1
  •   Josh    14 年前

    任务栏和任何一个前台窗口一样有效。当您单击它时,它将暂时成为前景窗口。例如,如果您单击“开始”并按Escape,它将是前台窗口,直到您单击“关闭”为止。

    你可以用 GetWindow HWND\u下一次传入任务栏的窗口句柄。

    不过,由于任务栏是最上面的窗口,GetWindow(或GetNextWindow等)的操作方式会有所不同。我建议你重游 EnumWindows 这可能是你最好的选择。

        2
  •  0
  •   JDMX    14 年前

    如果要为其创建快照的窗体与链接到任务栏的窗体相同,则确实不需要使用getforegroughindow。只需使用Form.hWnd并将其传递到获取快照的函数中。您可能需要通过调用

    [DllImport( "user32.dll" )]
    public static extern IntPtr SetForegroundWindow( IntPtr hWnd );
    

    [DllImport( "user32.dll" )]
    public static extern bool BringWindowToTop( HandleRef hWnd );
    

    如果你想要整个桌面,那么你可能只需要加入一个Thread.Sleep来确保前台窗口在获得桌面快照之前已经足够到达顶端。

    把我评论中的src放在这里是为了更好的打印

    [DllImport( "user32.dll" )]
    public static extern IntPtr GetForegroundWindow();
    
    [DllImport( "user32.dll" )] 
    public static extern IntPtr GetActiveWindow(); 
    
    // this or the next line not both
    IntPtr curWindow = GetActiveWindow(); 
    IntPtr curWindow = GetForegroundWindow(); 
    
    BringWindowToTop( window ); 
    System.Threading.Thread.Sleep( 500 ); 
    

    线程spleep给窗口足够的时间到达Z顺序的顶部。