1 #include <windows.h>
2 #include <servprov.h>
3 #include "wordbyauto.hh"
4 #include "uiauto.hh"
5 
6 #include <cstdio>
7 #include "gddebug.hh"
8 
9 class GDAutomationClient {
10 public:
11     GDAutomationClient();
12     ~GDAutomationClient();
13     bool getWordAtPoint( POINT pt );
getText()14     WCHAR *getText() { return buffer; }
15 private:
16     WCHAR buffer[256];
17     IUIAutomation *pGDAutomation;
18     IUIAutomationTreeWalker *pTree;
19 };
20 
21 GDAutomationClient gdAuto;
22 
GDAutomationClient()23 GDAutomationClient::GDAutomationClient()
24 {
25 HRESULT hr;
26     CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
27     hr = CoCreateInstance( CLSID_CUIAutomation , NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, (void**)&pGDAutomation );
28     if( hr != S_OK ) pGDAutomation = NULL;
29     pTree = NULL;
30     if( pGDAutomation != NULL )
31         hr = pGDAutomation->get_RawViewWalker( &pTree );
32     memset( buffer, 0, sizeof(buffer) );
33 }
34 
~GDAutomationClient()35 GDAutomationClient::~GDAutomationClient()
36 {
37     if( pTree != NULL ) pTree->Release();
38     if( pGDAutomation != NULL ) pGDAutomation->Release();
39     CoUninitialize();
40 }
41 
getWordAtPoint(POINT pt)42 bool GDAutomationClient::getWordAtPoint( POINT pt )
43 {
44 HRESULT hr;
45 IUIAutomationTextPattern *pTextPattern;
46 IUIAutomationTextRange *pTextRange;
47 IUIAutomationElement *pElement, *pParent;
48 BSTR bstr;
49 RECT r = { 0, 0, 0, 0 };
50 bool bGoUp;
51 
52     GD_DPRINTF("\nEntering getWordAtPoint\n");
53 
54     if( pGDAutomation == NULL ) return false;
55 
56     buffer[0] = 0;
57     pElement = NULL;
58     hr = pGDAutomation->ElementFromPoint( pt, &pElement );
59     GD_DPRINTF("ElementFromPoint return hr=%08lX, ptr=%p\n", hr, pElement);
60     if( hr != S_OK || pElement == NULL )
61         return false;
62 
63     pTextPattern = NULL;
64     bGoUp = false;
65     while( pElement != NULL ) {
66         hr = pElement->GetCurrentPatternAs( UIA_TextPatternId, IID_IUIAutomationTextPattern, (void**)&pTextPattern );
67         if( hr == S_OK && pTextPattern != NULL )
68             break;
69         if( pTree == NULL ) {
70             pElement->Release();
71             return false;
72         }
73         pParent = NULL;
74         hr = pTree->GetParentElement( pElement, &pParent );
75         pElement->Release();
76         pElement = pParent;
77         bGoUp = TRUE;
78     }
79     if( pElement == NULL )
80         return false;
81 
82     if( !bGoUp ) {
83         hr = pElement->get_CurrentBoundingRectangle( &r );
84         if( hr == S_OK) {
85             pt.x -= r.left;
86             pt.y -= r.top;
87         }
88     }
89     pElement->Release();
90 
91     pTextRange = NULL;
92     hr = pTextPattern->RangeFromPoint( pt, &pTextRange );
93     pTextPattern->Release();
94     if( hr != S_OK || pTextRange == NULL )
95         return false;
96 
97     hr = pTextRange->ExpandToEnclosingUnit( TextUnit_Word );
98     if( hr == S_OK) {
99         hr = pTextRange->GetText( 255, &bstr );
100         if (hr == S_OK) {
101             wsprintfW( buffer, L"%s", (LPCWSTR)bstr );
102             SysFreeString( bstr );
103         }
104     }
105     pTextRange->Release();
106 
107     return ( buffer[0] != 0 );
108 }
109 
gdGetWordAtPointByAutomation(POINT pt)110 WCHAR *gdGetWordAtPointByAutomation( POINT pt )
111 {
112     if( gdAuto.getWordAtPoint( pt ) ) return gdAuto.getText();
113     else return NULL;
114 }
115