我需要截屏捕获多窗口应用程序的特定窗口。 一个很好的例子:我使用两个窗口(邮件和日历)运行OUTLOOK。 当我使用Process.GetProcessesByName(ApplicationToWatch).FirstOrDefault()时,我当然会获得“第一个”窗口。如何访问“第二个”窗口或后续窗口? (有趣的是,这里有一个FirstOrDefault,但没有其他方法可以得到别的东西-我很明显缺少了一些东西。)
答案 0 :(得分:1)
您已经掌握了如何使用EnumChildWindows与GetClassName关联的子窗口句柄的说明。
因此,我将为您提出另一种使用UI Automation的方法。
它可能不太知名,但是在这种情况下,它非常简单,可以简化此任务。
您只需要知道主窗口的句柄,就可以使用LINQ的AutomationElementCollection或.Where()方法枚举并过滤其子窗口的集合(.FirstOrDefault())。 br />
请注意,UI自动化枚举不如EnumChildWindows
完整。同样,在某些情况下,返回的类名称可能与特定UI元素的实际类名称不同。
但是这些可能是您不感兴趣的UI元素。
要获取Outlook
主窗口的句柄,我们照常使用Process.GetProcessesByName()。
然后使用AutomationElement.FromHandle()方法获取自动化元素。
要查找特定的子元素,我们可以使用此主要自动化元素(源引用).FindAll()方法,并根据需要使用.Where()
过滤返回的集合,以定义子集合-或.FirstOrDefault()
,以获得特定元素类或句柄(或其他已知细节)的引用。
这些方法展示了如何拍摄Outlook
的侧面“日历”面板和“主日历”窗口的屏幕截图。
使用code already discussed in your previous question拍摄所选屏幕边界的实际屏幕截图。
此代码需要添加对以下内容的引用:
UIAutomationClient
UIAutomationTypes
WindowsBase
Imports System.Diagnostics
Imports System.Drawing
Imports System.Windows.Automation
Dim OutLookProc As Process = Process.GetProcessesByName("OUTLOOK").FirstOrDefault()
Dim MainElement As AutomationElement = AutomationElement.FromHandle(OutLookProc.MainWindowHandle)
Dim SmallCalendar As AutomationElement =
MainElement.FindAll(TreeScope.Subtree, Automation.RawViewCondition).
OfType(Of AutomationElement)().
FirstOrDefault(Function(elm) elm.Current.Name.Contains("NUIDocument") AndAlso
(Not String.IsNullOrEmpty(elm.Current.AutomationId)))
Dim CalendarNavigator As AutomationElement =
MainElement.FindAll(TreeScope.Subtree, Automation.RawViewCondition).
OfType(Of AutomationElement)().
FirstOrDefault(Function(elm) elm.Current.ClassName.Contains("TreeDisplayNode"))
If SmallCalendar IsNot Nothing Then
Dim SmallCalendarHeight As Integer = CInt(CalendarNavigator.Current.BoundingRectangle.Y -
SmallCalendar.Current.BoundingRectangle.Y)
Dim CalLocation As Point = New Point(CInt(SmallCalendar.Current.BoundingRectangle.Location.X),
CInt(SmallCalendar.Current.BoundingRectangle.Location.Y))
Dim CalSize As Size = New Size(CInt(SmallCalendar.Current.BoundingRectangle.Width), SmallCalendarHeight)
Dim SmallCalendarBounds As Rectangle = New Rectangle(CalLocation, CalSize)
SmallCalendarBounds.Inflate(-20, 0)
'CopyFormScreen() the SmallCalendarBounds rectangle. Inflate as needed
End If
这部分代码计算Outlook侧面Calendar对象的屏幕边界。
可能没有那么有用,但是它是一种显示如何使用这些类来解析/检查流程主窗口的UI元素的方法。
这是结果:
“主日历”窗口更易于识别和捕获。
所有Calendars类的名称都以ViewWnd
结尾,因此,无论选择/使用哪种日历,您始终可以很容易地识别它。
Dim LargeCalendar As AutomationElement =
MainElement.FindAll(TreeScope.Descendants, Automation.RawViewCondition).
OfType(Of AutomationElement)().
FirstOrDefault(Function(elm) elm.Current.ClassName.Contains("ViewWnd"))
If LargeCalendar IsNot Nothing Then
Dim LCalLocation As Point = New Point(CInt(LargeCalendar.Current.BoundingRectangle.Location.X),
CInt(LargeCalendar.Current.BoundingRectangle.Location.Y))
Dim LCalSize As Size = New Size(CInt(LargeCalendar.Current.BoundingRectangle.Width),
CInt(LargeCalendar.Current.BoundingRectangle.Height))
Dim LargeCalendarBounds As Rectangle = New Rectangle(LCalLocation, LCalSize)
End If
这是结果:
答案 1 :(得分:0)
这应该有帮助:
获取窗口位置:
How to get and set the window position of another application in C#
获取窗口句柄:
Get Application's Window Handles
将另一个应用程序带到前面:
您可以尝试这些技巧,然后从屏幕上复制。