1 '************************************************************************************************
3 ' File: ListFragment.vb
5 ' Description: Implements a UI Automation provider for a custom list control.
7 ' See ProviderForm.cs for a full description of this sample.
10 ' This file is part of the Microsoft Windows SDK Code Samples.
12 ' Copyright (C) Microsoft Corporation. All rights reserved.
14 ' This source code is intended only as a supplement to Microsoft
15 ' Development Tools and/or on-line documentation. See these other
16 ' materials for detailed information regarding Microsoft code samples.
18 ' THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
19 ' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 ' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
23 '***********************************************************************************************
26 Imports System
.Collections
.Generic
28 Imports System
.Drawing
29 Imports System
.Windows
.Forms
30 Imports System
.Windows
.Automation
.Provider
31 Imports System
.Windows
.Automation
32 Imports System
.Collections
33 Imports System
.Threading
38 Public Class ListProvider
39 Implements IRawElementProviderFragmentRoot
, ISelectionProvider
40 ' Control that contains the list.
41 Private OwnerListControl
As CustomListControl
42 ' Window handle of the control.
43 Private WindowHandle
As IntPtr
49 ''' <param name="control">
50 ''' The control for which this object is providing UI Automation functionality.
52 Public Sub New(ByVal control
As CustomListControl
)
53 OwnerListControl
= control
54 WindowHandle
= control
.Handle
58 #Region
"IRawElementProviderSimple Members"
62 ''' Retrieves the object that supports the specified control pattern.
64 ''' <param name="patternId">The pattern identifier</param>
66 ''' The supporting object, or null if the pattern is not supported.
68 Public Function GetPatternProvider(ByVal patternId
As Integer) As Object _
69 Implements IRawElementProviderFragment
.GetPatternProvider
70 If patternId
= SelectionPatternIdentifiers
.Pattern
.Id
Then
75 End Function 'GetPatternProvider
80 ''' Gets provider property values.
82 ''' <param name="propertyId">The property identifier.</param>
83 ''' <returns>The value of the property.</returns>
84 Public Function GetPropertyValue(ByVal propertyId
As Integer) As Object _
85 Implements IRawElementProviderFragment
.GetPropertyValue
87 If propertyId
= AutomationElementIdentifiers
.ControlTypeProperty
.Id
Then
88 Return ControlType
.List
.Id
89 ' It is necessary to supply a value for IsKeyboardFocusable in a Windows Forms control,
90 ' because this value cannot be discovered by the HWND host provider. This is not
91 ' necessary for a Win32 provider.
92 ElseIf propertyId
= AutomationElementIdentifiers
.IsKeyboardFocusableProperty
.Id
Then
94 ElseIf propertyId
= AutomationElementIdentifiers
.FrameworkIdProperty
.Id
Then
99 End Function 'GetPropertyValue
102 ''' Gets the host provider.
105 ''' Fragment roots return their window providers; most others return null.
108 ReadOnly
Property HostRawElementProvider() As IRawElementProviderSimple _
109 Implements IRawElementProviderSimple
.HostRawElementProvider
111 Return AutomationInteropProvider
.HostProviderFromHandle(WindowHandle
)
116 ''' Gets provider options.
118 ReadOnly
Property ProviderOptions() As ProviderOptions _
119 Implements IRawElementProviderSimple
.ProviderOptions
121 Return ProviderOptions
.ServerSideProvider
126 Private Members
As IRawElementProviderSimple
129 #Region
"IRawElementProviderFragment Members" '
132 ''' Gets the bounding rectangle.
135 ''' Fragment roots should return an empty rectangle. UI Automation will get the rectangle
136 ''' from the host control (the HWND in this case).
138 Public ReadOnly
Property BoundingRectangle() As System
.Windows
.Rect _
139 Implements IRawElementProviderFragment
.BoundingRectangle
142 Return System
.Windows
.Rect
.Empty
147 ''' Gets the root of this fragment.
150 Public ReadOnly
Property FragmentRoot() As IRawElementProviderFragmentRoot _
151 Implements IRawElementProviderFragment
.FragmentRoot
159 ''' Gets any fragment roots that are embedded in this fragment.
161 ''' <returns>Null in this case.</returns>
162 Public Function GetEmbeddedFragmentRoots() As IRawElementProviderSimple() _
163 Implements IRawElementProviderFragment
.GetEmbeddedFragmentRoots
166 End Function 'GetEmbeddedFragmentRoots
170 ''' Gets the runtime identifier of the UI Automation element.
172 ''' <returns>Fragment roots return null.</returns>
173 Public Function GetRuntimeId() As Integer() _
174 Implements IRawElementProviderFragmentRoot
.GetRuntimeId
177 End Function 'GetRuntimeId
181 ''' Navigates to adjacent elements in the UI Automation tree.
183 ''' <param name="direction">Direction of navigation.</param>
184 ''' <returns>The element in that direction, or null.</returns>
185 ''' <remarks>The provider only returns directions that it is responsible for.
186 ''' UI Automation knows how to navigate between HWNDs, so only the custom item
187 ''' navigation needs to be provided.
189 Public Function Navigate(ByVal direction
As NavigateDirection
) _
190 As IRawElementProviderFragment _
191 Implements IRawElementProviderFragment
.Navigate
193 If direction
= NavigateDirection
.FirstChild
Then
194 Return GetProviderForIndex(0)
195 ElseIf direction
= NavigateDirection
.LastChild
Then
196 Return GetProviderForIndex((OwnerListControl
.ItemCount
- 1))
200 End Function 'Navigate
204 ''' Responds to a client request to set the focus to this control.
206 ''' <remarks>Setting focus to the control is handled by the parent window.</remarks>
207 Public Sub SetFocus() _
208 Implements IRawElementProviderFragment
.SetFocus
210 Throw
New Exception("The method is not implemented.")
216 #Region
"IRawElementProviderFragmentRoot Members"
218 Private Delegate
Function PointToClientDelegate(ByVal point
As System
.Drawing
.Point
) As System
.Drawing
.Point
221 ''' Gets the child element at the specified point.
223 ''' <param name="x">Distance from the left of the application window.</param>
224 ''' <param name="y">Distance from the top of the application window.</param>
225 ''' <returns>The provider for the element at that point.</returns>
226 Public Function ElementProviderFromPoint(ByVal x
As Double, ByVal y
As Double) _
227 As IRawElementProviderFragment _
228 Implements IRawElementProviderFragmentRoot
.ElementProviderFromPoint
230 Dim index
As Integer = -1
231 Dim screenPoint
As System
.Drawing
.Point
= New System
.Drawing
.Point(CInt(x
), CInt(y
))
233 ' Call PointToClient by delegation to avoid clashing with UI thread.
234 Dim conversionDelegate
As PointToClientDelegate
= _
235 New PointToClientDelegate(AddressOf OwnerListControl
.PointToClient
)
236 Dim result
As Object = OwnerListControl
.Invoke(conversionDelegate
, screenPoint
)
237 Dim clientPoint
As System
.Drawing
.Point
= CType(result
, System
.Drawing
.Point
)
239 index
= OwnerListControl
.ItemIndexFromPoint(clientPoint
)
243 Return GetProviderForIndex(index
)
244 End Function 'ElementProviderFromPoint
249 ''' Returns the child element that is selected when the list gets focus.
251 ''' <returns>The selected item.</returns>
252 Function GetFocus() As IRawElementProviderFragment _
253 Implements IRawElementProviderFragmentRoot
.GetFocus
255 Dim index
As Integer = OwnerListControl
.SelectedIndex
256 Return GetProviderForIndex(index
)
257 End Function 'IRawElementProviderFragmentRoot.GetFocus
261 #Region
"ISelectionProvider Members" '
264 ''' Specifies whether selection of more than one item at a time is supported.
267 Public ReadOnly
Property CanSelectMultiple() As Boolean _
268 Implements ISelectionProvider
.CanSelectMultiple
277 ''' Returns the UI Automation provider for the selected list items.
279 ''' <returns>The selected items.</returns>
280 ''' <remarks>Because this is a single-selection list box,
281 ''' only one item is returned.</remarks>
282 Public Function GetSelection() As IRawElementProviderSimple() _
283 Implements ISelectionProvider
.GetSelection
285 Dim index
As Integer = OwnerListControl
.SelectedIndex
286 Return New IRawElementProviderSimple() {GetProviderForIndex(index
)}
288 End Function 'GetSelection
291 ''' Specifies whether the list must have an item selected at all times.
293 ''' <returns>True if selection is required.</returns>
294 Public ReadOnly
Property IsSelectionRequired() As Boolean _
295 Implements ISelectionProvider
.IsSelectionRequired
304 #Region
"Helper methods"
307 ''' Gets the UI Automation provider for the item at the specified index.
309 ''' <param name="index">Index of the item.</param>
310 ''' <returns>The provider object, or null if the index is out of range.</returns>
311 Public Function GetProviderForIndex(ByVal index
As Integer) _
312 As IRawElementProviderFragment
314 Dim OwnerCustomListItemCount
As Integer = OwnerListControl
.ItemCount
- 1
315 If index
< 0 OrElse index
> OwnerCustomListItemCount
Then
318 Return CType(Me.OwnerListControl
.GetItem(index
).Provider
, IRawElementProviderFragment
)
319 End Function 'GetProviderForIndex
323 #Region
"UI Automation Event Handlers"
326 ''' Responds to a focus change by raising an event.
328 ''' <param name="listItem">The item that has received focus.</param>
329 Public Shared
Sub OnFocusChange(ByVal listItem
As CustomListItem
)
331 If AutomationInteropProvider
.ClientsAreListening
Then
332 Dim args
As New AutomationEventArgs( _
333 AutomationElementIdentifiers
.AutomationFocusChangedEvent
)
334 AutomationInteropProvider
.RaiseAutomationEvent( _
335 AutomationElementIdentifiers
.AutomationFocusChangedEvent
, _
336 listItem
.Provider
, args
)
339 End Sub 'OnFocusChange
342 ''' Responds to a selection change by raising an event.
344 ''' <param name="listItem">The item that has been selected.</param>
345 Public Shared
Sub OnSelectionChange(ByVal listItem
As CustomListItem
)
346 If AutomationInteropProvider
.ClientsAreListening
Then
347 Dim args
As New AutomationEventArgs( _
348 SelectionItemPatternIdentifiers
.ElementSelectedEvent
)
349 AutomationInteropProvider
.RaiseAutomationEvent( _
350 SelectionItemPatternIdentifiers
.ElementSelectedEvent
, _
351 listItem
.Provider
, args
)
354 End Sub 'OnSelectionChange
358 ''' Responds to an addition to the UI Automation tree structure by raising an event.
360 ''' <param name="list">
361 ''' The list to which the item was added.
364 ''' For the runtime Id of the item, pass 0 because the provider cannot know
365 ''' what its actual runtime Id is.
367 Public Shared
Sub OnStructureChangeAdd(ByVal list
As CustomListControl
)
368 If AutomationInteropProvider
.ClientsAreListening
Then
369 Dim fakeRuntimeId(1) As Integer
371 Dim args
As New StructureChangedEventArgs( _
372 StructureChangeType
.ChildrenBulkAdded
, fakeRuntimeId
)
373 AutomationInteropProvider
.RaiseStructureChangedEvent( _
374 CType(list
.Provider
, IRawElementProviderSimple
), args
)
377 End Sub 'OnStructureChangeAdd
381 ''' Responds to a removal from the UI Automation tree structure by raising an event.
383 ''' <param name="list">
384 ''' The list from which the item was removed.
387 ''' For the runtime Id of the list, pass 0 because the provider cannot know
388 ''' what its actual runtime ID is.
390 Public Shared
Sub OnStructureChangeRemove(ByVal list
As CustomListControl
)
391 If AutomationInteropProvider
.ClientsAreListening
Then
392 Dim fakeRuntimeId(1) As Integer
394 Dim args
As New StructureChangedEventArgs( _
395 StructureChangeType
.ChildrenBulkRemoved
, fakeRuntimeId
)
396 AutomationInteropProvider
.RaiseStructureChangedEvent( _
397 CType(list
.Provider
, IRawElementProviderSimple
), args
)
400 End Sub 'OnStructureChangeRemove
404 End Class
'ListProvider