////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // This function is not used by the sample, but it shows an alternative approach to building up // the cache of hyperlinks. Depending on the action taken by the target app when providing data // to be stored in the cache of results, different approaches taken by the UIA client can have // different performance benefits. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void BuildListOfHyperlinksFromWindowInternalAlternateApproach(bool fSearchLinkChildren) { // If we're already building up a list of links, ignore this request to refresh the list. // (A shipping app might consider queueing this request in order to refresh the list again // once the in-progress refreshing action is complete.) if (_fRefreshInProgress) { return; } _fRefreshInProgress = true; // First build a cache request in the same way as done elsewhere in the sample. // This means that for each element returned following the search, they will // have their name, bounding rect and Invoke pattern cached. IUIAutomationCacheRequest cacheRequest = _automation.CreateCacheRequest(); cacheRequest.AddProperty(_propertyIdName); cacheRequest.AddProperty(_propertyIdBoundingRectangle); cacheRequest.AddPattern(_patternIdInvoke); // At this point elsewhere in the sample, we specified that we only wanted data // for the hyperlink elements (and optionally their children) cached. In this // approach here, we will say that we want data for ALL descendants of the // found elements cached. cacheRequest.TreeScope = TreeScope.TreeScope_Descendants; // Now create a property condition as we've done elsewhere, to say that we're only // interested in elements which are in the Control view and are hyperlinks. IUIAutomationCondition conditionControlView = _automation.ControlViewCondition; IUIAutomationCondition conditionHyperlink = _automation.CreatePropertyCondition(_propertyIdControlType, _controlTypeIdHyperlink); IUIAutomationCondition condition = _automation.CreateAndCondition(conditionControlView, conditionHyperlink); // Now unlike steps we took elsewhere, specify that the cache request should // have an additional filter of the property condition we just created. cacheRequest.TreeFilter = condition; // Elsewhere in the sample, we called FindAllBuildCache(). This returned an array of hyperlink // elements with their data cached, (and optinally their children with cache data too.) This // CacheLinksFromWindow() function takes a different approach. The element that is returned // from the call to BuildUpdatedCache() below is the browser element with some data cached. // But the returned element will have an array of cached child elements, and each of those // elements will by the hyperlinks we need. So the cache request here has specified through // its tree filter that we're only interest in hyperlinks, whereas elsewhere in this sample, // we supplied that condition in the search call we made. How much difference this makes to // the performance of calls depends on the action taken by the target application. // *** Note, using this appoach, we can't also cache data for the direct children of the // hyperlinks as we did elsewhere in the sample. So whether this approach is practical // depends on the needs of the client application. // Note that with a property conditions, it's not possible to request that the set of elements // returned from a search are all elements which have a control type of hyperlink OR whose parent // has a control type of hyperlink. // Get a handle to the window of interest. IntPtr hwnd = Win32.FindWindow(strBrowserWindowClass, null); if (hwnd != IntPtr.Zero) { IUIAutomationElement elementBrowser = _automation.ElementFromHandleBuildCache(hwnd, cacheRequest); if (elementBrowser != null) { _linkItems.Clear(); IUIAutomationElementArray arrayChildren = elementBrowser.GetCachedChildren(); if (arrayChildren != null) { int cElements = arrayChildren.Length; // Process each returned hyperlink element. for (int idxElement = 0; idxElement < cElements; idxElement++) { IUIAutomationElement elementChild = arrayChildren.GetElement(idxElement); // Take the same action elsewhere in the sample to present the hyperlink // in the sample app UI. string strLinkName = GetCachedDataFromElement(elementChild, fSearchLinkChildren); if (strLinkName != null) { strLinkName = strLinkName.Trim(); LinkItem item = new LinkItem(); item.linkName = strLinkName; item.element = elementChild; _linkItems.Add(item); } } // Notify the main UI thread that a list of links is ready for processing. Do not block in this call. _listViewLinks.BeginInvoke(_UIUpdateDelegate, _linkItems); } } } // Allow another refresh to be performed now. _fRefreshInProgress = false; }