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

时间:2010-02-26 18:26:39

标签: c# interop

所以,我认为这很简单,而且,我错了。以下是该问题的简要说明:

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

这有时会起作用,但是如果我非常快地点击图标,我实际上会捕获任务栏而不是前景窗口。我不知道为什么会发生这种情况(我明白任务栏是一个窗口,我不明白为什么有时它似乎在我点击之前在MouseMove中有焦点),而且我没有运气使用EnumWindows方法同样,可能是因为我不完全理解它是如何工作的。

看起来,如果我能够仅使用窗口句柄获得每个窗口的z位置,那么使用EnumWindows解决这个问题就很容易了。然而,我还没有找到一种方法来做到这一点。

所以,我问你们;你会如何写一个方法来可靠地定位前景窗口,因为它当时可能没有焦点?要么我的google-fu失败了,要么关于这方面的信息很少。提前谢谢。

2 个答案:

答案 0 :(得分:1)

任务栏与任何前景窗口一样有效。单击它时,它将暂时为前景窗口。如果单击“开始”并按Escape键,它将成为前景窗口,直到您单击它为止。

<击> 你可以使用GetWindow和HWND_NEXT传递任务栏的窗口句柄。

没关系,因为任务栏是最顶层的窗口,GetWindow(或GetNextWindow等)将以不同的方式运行。我建议重新审视EnumWindows解决方案,这可能是你最好的选择。

答案 1 :(得分:0)

如果您想要快照的表单与链接到任务栏的表单相同,那么您实际上不需要使用GetforegroundWindow。只需使用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 ); 

螺纹脾脏给窗口足够的时间来到Z阶的顶部。