您已经了解了如何使用EnumChildWindows 获取子窗口句柄以与GetClassName 关联。
所以我会建议你另一种方法,使用UI Automation。
它可能不太为人所知,但在这种情况下,它非常简单,并且可以简化此任务。
您只需要知道要枚举其子窗口的主窗口的句柄,并使用 LINQ 的 .Where() 或 .FirstOrDefault() 方法过滤子窗口的集合 (AutomationElementCollection)。
请注意,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 侧日历对象的屏幕边界。
它可能没有那么有用,但它是一种展示如何使用这些类来解析/检查进程主窗口的 UI 元素的方法。
这是结果:
主日历窗口更易于识别和捕获。
所有日历类名称都以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
这是结果: