質問編集履歴

2

動いたソースを追加

2018/01/26 05:54

投稿

notgoodpg
notgoodpg

スコア37

test CHANGED
File without changes
test CHANGED
@@ -1,3 +1,9 @@
1
+ ### まとめ
2
+
3
+ - UI Automationでボタンのクリックまで出来る
4
+
5
+ - 最初のハンドラを取得するところもUI Automationで出来る
6
+
1
7
  ### 前提・実現したいこと
2
8
 
3
9
  VC++でUI Automationを使いボタンコントロールをクリックする処理を行いたい。
@@ -36,7 +42,7 @@
36
42
 
37
43
  ### 該当のソースコード
38
44
 
39
-
45
+ 2018 0126 動いた 過去のソースは編集履歴を参照してください
40
46
 
41
47
  ```c++
42
48
 
@@ -94,13 +100,27 @@
94
100
 
95
101
  // 1のボタンを探してくる
96
102
 
103
+ IUIAutomationElement *clickElement = NULL;
104
+
97
- HWND hwndBtn = GetHWNDByName(autoMaster, treeWalker, autElm, L"1");
105
+ if (GetUIAutomationElementFromChildrenByName(autoMaster, treeWalker, autElm, L"1", clickElement) != S_OK) {
106
+
107
+ MessageBox(_T("control not found!"));
108
+
109
+ return;
110
+
111
+ }
98
112
 
99
113
  // 押す
100
114
 
115
+ IUnknown *btn;
116
+
101
- if(hwndBtn != NULL) ::SendMessage(hwndBtn, BM_CLICK, 0, 0);
117
+ clickElement->GetCurrentPattern(UIA_InvokePatternId, &btn);
118
+
102
-
119
+ ((IUIAutomationInvokePattern *)btn)->Invoke();
120
+
103
- // 後片付け
121
+ btn->Release();
122
+
123
+
104
124
 
105
125
  autElm->Release();
106
126
 
@@ -108,80 +128,74 @@
108
128
 
109
129
  autoMaster->Release();
110
130
 
131
+
132
+
111
- CoUninitialize();
133
+ CoUninitialize();}
134
+
135
+
136
+
137
+ BOOL CUIAutoDlg::GetUIAutomationElementFromChildrenByName(IUIAutomation *autoMaster,
138
+
139
+ IUIAutomationTreeWalker *treeWalker, IUIAutomationElement *uiaElement,
140
+
141
+ const BSTR windowName, IUIAutomationElement *& distElement)
142
+
143
+ {
144
+
145
+ IUIAutomationElement *childElm = NULL;
146
+
147
+ // 子コントロールからさがす
148
+
149
+ if (treeWalker->GetFirstChildElement(uiaElement, &childElm) != S_OK) {
150
+
151
+ return S_FALSE; // 子がない
152
+
153
+ }
154
+
155
+ IUIAutomationElement *nextChildElm = NULL;
156
+
157
+ UIA_HWND hwnd = NULL;
158
+
159
+ while (childElm) {
160
+
161
+ BSTR tempWindowName;
162
+
163
+ childElm->get_CurrentName(&tempWindowName);
164
+
165
+
166
+
167
+ if (_tcscmp( tempWindowName, windowName) == 0) {
168
+
169
+ // Nameが一致するコントロールを見つけた
170
+
171
+ SysFreeString(tempWindowName); // 用済み
172
+
173
+ distElement = childElm;
174
+
175
+ return S_OK; //hwnd; // UIA_HWNDはHWNDじゃない!
176
+
177
+ }
178
+
179
+ SysFreeString(tempWindowName); // 用済み
180
+
181
+ // 孫以下のウィドウは再起で処理
182
+
183
+ if (GetUIAutomationElementFromChildrenByName(autoMaster, treeWalker, childElm, windowName, distElement) == S_OK) return S_OK;
184
+
185
+ treeWalker->GetNextSiblingElement(childElm, &nextChildElm);
186
+
187
+
188
+
189
+ childElm->Release(); // 用済み
190
+
191
+ childElm = nextChildElm;
192
+
193
+ }
194
+
195
+ return S_FALSE; // nameの該当するコントロールが無い
112
196
 
113
197
  }
114
198
 
115
-
116
-
117
- HWND CUIAutoDlg::GetHWNDByName( IUIAutomation *autoMaster, IUIAutomationTreeWalker *treeWalker,
118
-
119
- IUIAutomationElement *uiaElement, const BSTR windowName)
120
-
121
- {
122
-
123
- IUIAutomationElement *childElm = NULL;
124
-
125
- treeWalker->GetFirstChildElement(uiaElement, &childElm);
126
-
127
-
128
-
129
- IUIAutomationElement *nextChildElm = NULL;
130
-
131
- UIA_HWND hwnd = NULL;
132
-
133
- while (childElm) {
134
-
135
- BSTR tempWindowName;
136
-
137
- childElm->get_CurrentName(&tempWindowName);
138
-
139
-
140
-
141
- if (tempWindowName == windowName) {
142
-
143
- // Nameが一致するコントロールを見つけた
144
-
145
- SysFreeString(tempWindowName); // 用済み
146
-
147
-
148
-
149
- childElm->get_CurrentNativeWindowHandle(&hwnd);
150
-
151
-
152
-
153
- childElm->Release(); // 用済み
154
-
155
-
156
-
157
- return hwnd; // UIA_HWNDはHWNDじゃない!
158
-
159
- }
160
-
161
- SysFreeString(tempWindowName); // 用済み
162
-
163
-
164
-
165
- treeWalker->GetNextSiblingElement(childElm, &nextChildElm);
166
-
167
- childElm->Release(); // 用済み
168
-
169
- childElm = nextChildElm;
170
-
171
-
172
-
173
- hwnd = GetHWNDByName(autoMaster, treeWalker, childElm, windowName);// 孫以下のウィドウは再起で処理
174
-
175
- if (hwnd != NULL) return hwnd; // UIA_HWNDはHWNDじゃない!
176
-
177
- }
178
-
179
-
180
-
181
- return NULL;
182
-
183
- }
184
-
185
199
  ```
186
200
 
187
201
  一応、`GetHWNDByName`の戻り値をNULLにして一旦動かしてみてはいます。

1

なんかすごい事になってたので修正

2018/01/26 05:54

投稿

notgoodpg
notgoodpg

スコア37

test CHANGED
File without changes
test CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  [以前の質問](https://teratail.com/questions/110070)でボタンのテキストが空になっていることが判明し、そのボタンを判別する手段としてUI Autmationを教えていただきました。
12
12
 
13
- なんとかボタンの特定までは行き着けのですが、特定したボタンをクリックする事が出来ずにいます。
13
+ なんとかボタンの特定までは行き着けそうなのですが、特定したボタンをクリックする事が出来ずにいます。
14
14
 
15
15
 
16
16
 
@@ -26,7 +26,7 @@
26
26
 
27
27
 
28
28
 
29
- SendMessageでBN_CLICKを送出することでボタンを押す
29
+ SendMessageでBM_CLICKを送出することでボタンを押す
30
30
 
31
31
  ```という流れで実現できるかなと思いながらコードを作っています。
32
32
 
@@ -38,12 +38,154 @@
38
38
 
39
39
 
40
40
 
41
- ```ここに言語名を入力
41
+ ```c++
42
+
42
-
43
+ void CUIAutoDlg::UseUIAutomation() {
44
+
45
+ // COM初期化
46
+
47
+ if( CoInitialize(NULL) != S_OK){
48
+
49
+ MessageBox(_T("CoInitialize stuck!"));
50
+
43
- ソースコード
51
+ return;
52
+
53
+ }
54
+
55
+ // IUIAutmation初期化
56
+
57
+ IUIAutomation *autoMaster;
58
+
59
+ if (HRESULT h = CoCreateInstance(__uuidof(CUIAutomation), NULL,
60
+
61
+ CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&autoMaster)) != S_OK)
62
+
63
+ {
64
+
65
+ MessageBox(_T("CoCreateInstance stuck!"));
66
+
67
+ return;
68
+
69
+ }
70
+
71
+ // TreeWalker初期化
72
+
73
+ IUIAutomationTreeWalker *treeWalker;
74
+
75
+ autoMaster->get_ContentViewWalker(&treeWalker);
76
+
77
+ // 電卓のIUIAutomationElement取得
78
+
79
+ IUIAutomationElement *autElm = NULL;
80
+
81
+ HWND h = ::FindWindow(_T("CalcFrame"), _T("電卓"));
82
+
83
+ if(autoMaster->ElementFromHandle(h, &autElm)){
84
+
85
+ MessageBox(_T("ElementFromHandle stuck!"));
86
+
87
+ return;
88
+
89
+ }
90
+
91
+
92
+
93
+ autElm->SetFocus();
94
+
95
+ // 1のボタンを探してくる
96
+
97
+ HWND hwndBtn = GetHWNDByName(autoMaster, treeWalker, autElm, L"1");
98
+
99
+ // 押す
100
+
101
+ if(hwndBtn != NULL) ::SendMessage(hwndBtn, BM_CLICK, 0, 0);
102
+
103
+ // 後片付け
104
+
105
+ autElm->Release();
106
+
107
+ treeWalker->Release();
108
+
109
+ autoMaster->Release();
110
+
111
+ CoUninitialize();
112
+
113
+ }
114
+
115
+
116
+
117
+ HWND CUIAutoDlg::GetHWNDByName( IUIAutomation *autoMaster, IUIAutomationTreeWalker *treeWalker,
118
+
119
+ IUIAutomationElement *uiaElement, const BSTR windowName)
120
+
121
+ {
122
+
123
+ IUIAutomationElement *childElm = NULL;
124
+
125
+ treeWalker->GetFirstChildElement(uiaElement, &childElm);
126
+
127
+
128
+
129
+ IUIAutomationElement *nextChildElm = NULL;
130
+
131
+ UIA_HWND hwnd = NULL;
132
+
133
+ while (childElm) {
134
+
135
+ BSTR tempWindowName;
136
+
137
+ childElm->get_CurrentName(&tempWindowName);
138
+
139
+
140
+
141
+ if (tempWindowName == windowName) {
142
+
143
+ // Nameが一致するコントロールを見つけた
144
+
145
+ SysFreeString(tempWindowName); // 用済み
146
+
147
+
148
+
149
+ childElm->get_CurrentNativeWindowHandle(&hwnd);
150
+
151
+
152
+
153
+ childElm->Release(); // 用済み
154
+
155
+
156
+
157
+ return hwnd; // UIA_HWNDはHWNDじゃない!
158
+
159
+ }
160
+
161
+ SysFreeString(tempWindowName); // 用済み
162
+
163
+
164
+
165
+ treeWalker->GetNextSiblingElement(childElm, &nextChildElm);
166
+
167
+ childElm->Release(); // 用済み
168
+
169
+ childElm = nextChildElm;
170
+
171
+
172
+
173
+ hwnd = GetHWNDByName(autoMaster, treeWalker, childElm, windowName);// 孫以下のウィドウは再起で処理
174
+
175
+ if (hwnd != NULL) return hwnd; // UIA_HWNDはHWNDじゃない!
176
+
177
+ }
178
+
179
+
180
+
181
+ return NULL;
182
+
183
+ }
44
184
 
45
185
  ```
46
186
 
187
+ 一応、`GetHWNDByName`の戻り値をNULLにして一旦動かしてみてはいます。
188
+
47
189
 
48
190
 
49
191
  ### 試したこと
@@ -58,6 +200,10 @@
58
200
 
59
201
  ### 補足情報(FW/ツールのバージョンなど)
60
202
 
61
-
203
+ - Windows7/64bit SP1
62
-
204
+
63
- ここにより詳細な情報を記載してください。
205
+ - VisualStudio2015SP
206
+
207
+ - VC++/MFC
208
+
209
+ - UI Automation