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