1
2 #include "studiox_includes.h"
3 #include "uiautomation.h"
4 #include "resource_item_provider.h"
5 #include "resource_view_provider.h"
6
7 ///////////////////////////////////////////////////////////////////////////////
resource_view_provider(resource_view * pControl)8 resource_view_provider::resource_view_provider(resource_view* pControl)
9 {
10 m_refCount = 1;
11 m_pResViewControl = pControl;
12 m_resViewControlHwnd = pControl->GetSafeHwnd();
13 }
14
15 ///////////////////////////////////////////////////////////////////////////////
~resource_view_provider()16 resource_view_provider::~resource_view_provider()
17 {
18 }
19
20 ///////////////////////////////////////////////////////////////////////////////
21 // IUnknown implementation.
22 //
23 ///////////////////////////////////////////////////////////////////////////////
IFACEMETHODIMP_(ULONG)24 IFACEMETHODIMP_(ULONG) resource_view_provider::AddRef()
25 {
26 return InterlockedIncrement(&m_refCount);
27 }
28
29 ///////////////////////////////////////////////////////////////////////////////
IFACEMETHODIMP_(ULONG)30 IFACEMETHODIMP_(ULONG) resource_view_provider::Release()
31 {
32 long val = InterlockedDecrement(&m_refCount);
33 if (val == 0)
34 {
35 delete this;
36 }
37 return val;
38 }
39
40 ///////////////////////////////////////////////////////////////////////////////
QueryInterface(REFIID riid,void ** ppInterface)41 IFACEMETHODIMP resource_view_provider::QueryInterface(REFIID riid, void** ppInterface)
42 {
43 if (riid == __uuidof(IUnknown)) *ppInterface = static_cast<IRawElementProviderSimple*>(this);
44 else if (riid == __uuidof(IRawElementProviderSimple)) *ppInterface = static_cast<IRawElementProviderSimple*>(this);
45 else if (riid == __uuidof(IRawElementProviderFragment)) *ppInterface = static_cast<IRawElementProviderFragment*>(this);
46 else if (riid == __uuidof(IRawElementProviderFragmentRoot)) *ppInterface = static_cast<IRawElementProviderFragmentRoot*>(this);
47 else if (riid == __uuidof(ISelectionProvider)) *ppInterface = static_cast<ISelectionProvider*>(this);
48 else
49 {
50 *ppInterface = NULL;
51 return E_NOINTERFACE;
52 }
53 (static_cast<IUnknown*>(*ppInterface))->AddRef();
54 return S_OK;
55 }
56
57
58 ///////////////////////////////////////////////////////////////////////////////
59 // IRawElementProviderSimple implementation
60 //
61 // Implementation of IRawElementProviderSimple::get_ProviderOptions.
62 // Gets UI Automation provider options.
63 //
64 ///////////////////////////////////////////////////////////////////////////////
get_ProviderOptions(ProviderOptions * pRetVal)65 IFACEMETHODIMP resource_view_provider::get_ProviderOptions(ProviderOptions* pRetVal)
66 {
67 *pRetVal = ProviderOptions_ServerSideProvider;
68 return S_OK;
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////
72 // Implementation of IRawElementProviderSimple::get_PatternProvider.
73 // Gets the object that supports ISelectionPattern.
74 //
75 ///////////////////////////////////////////////////////////////////////////////
GetPatternProvider(PATTERNID patternId,IUnknown ** pRetVal)76 IFACEMETHODIMP resource_view_provider::GetPatternProvider(PATTERNID patternId, IUnknown** pRetVal)
77 {
78 *pRetVal = NULL;
79 if (patternId == UIA_SelectionPatternId)
80 {
81 *pRetVal = static_cast<IRawElementProviderSimple*>(this);
82 AddRef();
83 }
84 return S_OK;
85 }
86
87 ///////////////////////////////////////////////////////////////////////////////
88 // Implementation of IRawElementProviderSimple::get_PropertyValue.
89 // Gets custom properties.
90 //
91 ///////////////////////////////////////////////////////////////////////////////
GetPropertyValue(PROPERTYID propertyId,VARIANT * pRetVal)92 IFACEMETHODIMP resource_view_provider::GetPropertyValue(PROPERTYID propertyId, VARIANT* pRetVal)
93 {
94 if (propertyId == UIA_LocalizedControlTypePropertyId)
95 {
96 pRetVal->vt = VT_BSTR;
97 pRetVal->bstrVal = SysAllocString(L"resource tree");
98 }
99 else if (propertyId == UIA_ControlTypePropertyId)
100 {
101 pRetVal->vt = VT_I4;
102 pRetVal->lVal = UIA_TreeControlTypeId;
103 }
104 else if (propertyId == UIA_IsKeyboardFocusablePropertyId)
105 {
106 pRetVal->vt = VT_BOOL;
107 pRetVal->boolVal = VARIANT_TRUE;
108 }
109 else
110 {
111 pRetVal->vt = VT_EMPTY;
112 }
113 return S_OK;
114 }
115
116 ///////////////////////////////////////////////////////////////////////////////
117 // Implementation of IRawElementProviderSimple::get_HostRawElementProvider.
118 // Gets the default UI Automation provider for the host window. This provider
119 // supplies many properties.
120 //
121 ///////////////////////////////////////////////////////////////////////////////
get_HostRawElementProvider(IRawElementProviderSimple ** pRetVal)122 IFACEMETHODIMP resource_view_provider::get_HostRawElementProvider(IRawElementProviderSimple** pRetVal)
123 {
124 if (m_resViewControlHwnd == NULL)
125 {
126 return UIA_E_ELEMENTNOTAVAILABLE;
127 }
128 HRESULT hr = UiaHostProviderFromHwnd(m_resViewControlHwnd, pRetVal);
129 return hr;
130 }
131
132 ///////////////////////////////////////////////////////////////////////////////
133 // IRawElementProviderFragment implementation
134 //
135 // Implementation of IRawElementProviderFragment::Navigate.
136 // Enables UI Automation to locate the element in the tree.
137 // Navigation to the parent is handled by the host window provider.
138 //
139 ///////////////////////////////////////////////////////////////////////////////
Navigate(NavigateDirection direction,IRawElementProviderFragment ** pRetVal)140 IFACEMETHODIMP resource_view_provider::Navigate(NavigateDirection direction, IRawElementProviderFragment** pRetVal)
141 {
142 resource_item* pDest = NULL;
143 IRawElementProviderFragment* pFrag = NULL;
144
145 switch (direction)
146 {
147 case NavigateDirection_FirstChild:
148 pDest = m_pResViewControl->GetResTree()->GetRoot();
149
150 if (pDest)
151 {
152 pDest = pDest->NavigateFirst();
153 }
154 break;
155
156 case NavigateDirection_LastChild:
157 pDest = m_pResViewControl->GetResTree()->GetRoot();
158
159 if (pDest)
160 {
161 pDest = pDest->NavigateLast();
162 }
163 break;
164 }
165
166 if (pDest)
167 {
168 pFrag = pDest->GetResItemProvider();
169 }
170
171 if (pFrag != NULL)
172 {
173 pFrag->AddRef();
174 }
175 *pRetVal = pFrag;
176 return S_OK;
177 }
178
179 ///////////////////////////////////////////////////////////////////////////////
180 // Implementation of IRawElementProviderFragment::GetRuntimeId.
181 // UI Automation gets this value from the host window provider, so supply NULL here.
182 //
183 ///////////////////////////////////////////////////////////////////////////////
GetRuntimeId(SAFEARRAY ** pRetVal)184 IFACEMETHODIMP resource_view_provider::GetRuntimeId(SAFEARRAY** pRetVal)
185 {
186 *pRetVal = NULL;
187 return S_OK;
188 }
189
190 ///////////////////////////////////////////////////////////////////////////////
191 // Implementation of IRawElementProviderFragment::get_BoundingRectangle.
192 //
193 // Retrieves the screen location and size of the control. Controls hosted in
194 // Win32 windows can return an empty rectangle; UI Automation will
195 // retrieve the rectangle from the HWND provider. However, the method is
196 // implemented here so that it can be used by the list items to calculate
197 // their own bounding rectangles.
198 //
199 // UI Spy uses the bounding rectangle to draw a red border around the element.
200 //
201 ///////////////////////////////////////////////////////////////////////////////
get_BoundingRectangle(UiaRect * pRetVal)202 IFACEMETHODIMP resource_view_provider::get_BoundingRectangle(UiaRect* pRetVal)
203 {
204 RECT rect;
205 m_pResViewControl->GetClientRect(&rect);
206 m_pResViewControl->ClientToScreen(&rect);
207
208 pRetVal->left = rect.left;
209 pRetVal->top = rect.top;
210 pRetVal->width = rect.right - rect.left;
211 pRetVal->height = rect.bottom - rect.top;
212 return S_OK;
213 }
214
215 ///////////////////////////////////////////////////////////////////////////////
216 // Implementation of IRawElementProviderFragment::GetEmbeddedFragmentRoots.
217 // Retrieves other fragment roots that may be hosted in this one.
218 //
219 ///////////////////////////////////////////////////////////////////////////////
GetEmbeddedFragmentRoots(SAFEARRAY ** pRetVal)220 IFACEMETHODIMP resource_view_provider::GetEmbeddedFragmentRoots(SAFEARRAY** pRetVal)
221 {
222 *pRetVal = NULL;
223 return S_OK;
224 }
225
226 ///////////////////////////////////////////////////////////////////////////////
227 // Implementation of IRawElementProviderFragment::SetFocus.
228 // Responds to the control receiving focus through a UI Automation request.
229 // For HWND-based controls, this is handled by the host window provider.
230 //
231 ///////////////////////////////////////////////////////////////////////////////
SetFocus()232 IFACEMETHODIMP resource_view_provider::SetFocus()
233 {
234 return S_OK;
235 }
236
237 ///////////////////////////////////////////////////////////////////////////////
238 // Implementation of IRawElementProviderFragment::get_FragmentRoot.
239 // Retrieves the root element of this fragment.
240 //
241 ///////////////////////////////////////////////////////////////////////////////
get_FragmentRoot(IRawElementProviderFragmentRoot ** pRetVal)242 IFACEMETHODIMP resource_view_provider::get_FragmentRoot(IRawElementProviderFragmentRoot** pRetVal)
243 {
244 *pRetVal = static_cast<IRawElementProviderFragmentRoot*>(this);
245 AddRef();
246 return S_OK;
247 }
248
249 ///////////////////////////////////////////////////////////////////////////////
250 // IRawElementProviderFragmentRoot implementation
251 //
252 // Implementation of IRawElementProviderFragmentRoot::ElementProviderFromPoint.
253 // Retrieves the IRawElementProviderFragment interface for the item at the specified
254 // point (in client coordinates).
255 // UI Spy uses this to determine what element is under the cursor when Ctrl is pressed.
256 //
257 ///////////////////////////////////////////////////////////////////////////////
ElementProviderFromPoint(double x,double y,IRawElementProviderFragment ** pRetVal)258 IFACEMETHODIMP resource_view_provider::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment** pRetVal)
259 {
260 POINT pt;
261 pt.x = (LONG)x;
262 pt.y = (LONG)y;
263
264 m_pResViewControl->ScreenToClient(&pt);
265 resource_tree* pResTree = m_pResViewControl->GetResTree();
266 resource_item* pRoot = pResTree->GetRoot();
267
268 if (!pRoot)
269 {
270 return NULL;
271 }
272
273 resource_item* pItem = pResTree->FindItem(pRoot, pt);
274
275 if (pItem == NULL)
276 {
277 return NULL;
278 }
279
280 resource_item_provider *pItemProvider = pItem->GetResItemProvider();
281
282 if (pItemProvider != NULL)
283 {
284 *pRetVal = static_cast<IRawElementProviderFragment*>(pItemProvider);
285 pItemProvider->AddRef();
286 }
287 else
288 {
289 *pRetVal = NULL;
290 }
291 return S_OK;
292 }
293
294 ///////////////////////////////////////////////////////////////////////////////
295 // Implementation of IRawElementProviderFragmentRoot::GetFocus.
296 // Retrieves the provider for the list item that is selected when the control gets focus.
297 //
298 ///////////////////////////////////////////////////////////////////////////////
GetFocus(IRawElementProviderFragment ** pRetVal)299 IFACEMETHODIMP resource_view_provider::GetFocus(IRawElementProviderFragment** pRetVal)
300 {
301 *pRetVal = NULL;
302 resource_item* pSelectItem = m_pResViewControl->GetCurrentItem();
303 if (pSelectItem)
304 {
305 resource_item_provider* pItemProvider = pSelectItem->GetResItemProvider();
306
307 if (pItemProvider != NULL)
308 {
309 pItemProvider->AddRef();
310 *pRetVal = pItemProvider;
311 }
312 }
313 return S_OK;
314 }
315
316 ///////////////////////////////////////////////////////////////////////////////
317 // ISelectionProvider implementation
318 //
319 // Implementation of ISelectionProvider::GetSelection.
320 // Gets the provider(s) for the items(s) selected in the list box.
321 // In this case, only a single item can be selected.
322 //
323 ///////////////////////////////////////////////////////////////////////////////
GetSelection(SAFEARRAY ** pRetVal)324 IFACEMETHODIMP resource_view_provider::GetSelection(SAFEARRAY** pRetVal)
325 {
326 SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
327 resource_item* pSelectItem = m_pResViewControl->GetCurrentItem();
328
329 if (pSelectItem)
330 {
331 resource_item_provider* pItemProvider = pSelectItem->GetResItemProvider();
332 if (pItemProvider != NULL)
333 {
334 LONG i = 0;
335 SafeArrayPutElement(psa, &i, pItemProvider);
336 }
337 }
338 *pRetVal = psa;
339 return S_OK;
340 }
341
342 ///////////////////////////////////////////////////////////////////////////////
343 // Implementation of ISelectionProvider::get_CanSelectMultiple.
344 //
345 ///////////////////////////////////////////////////////////////////////////////
get_CanSelectMultiple(BOOL * pRetVal)346 IFACEMETHODIMP resource_view_provider::get_CanSelectMultiple(BOOL* pRetVal)
347 {
348 *pRetVal = FALSE;
349 return S_OK;
350 }
351
352 ///////////////////////////////////////////////////////////////////////////////
353 // Implementation of ISelectionProvider::get_IsSelectionRequired.
354 //
355 ///////////////////////////////////////////////////////////////////////////////
get_IsSelectionRequired(BOOL * pRetVal)356 IFACEMETHODIMP resource_view_provider::get_IsSelectionRequired(BOOL* pRetVal)
357 {
358 *pRetVal = TRUE;
359 return S_OK;
360 }
361
362