質問編集履歴
18
あああ
test
CHANGED
File without changes
|
test
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
- Win32APIでフォームアプリのメニューバーを選択したいときは`SendMessage(hWnd, WM_COMMAND, 選択したいメニュー項目のID, 0);`
|
4
4
|
|
5
|
-
- 選択したいメニュー項目のIDは、`GetMenuItemInfo`関数を使うが、**なんとこの関数、引数のMENUITEMINFO構造体のfTypeに指定した一項目ずつしか情報を取ってこない。**
|
5
|
+
- 選択したいメニュー項目のIDは、`GetMenuItemInfo`関数を使うが、**なんとこの関数、引数の`MENUITEMINFO`構造体の`fType`に指定した一項目ずつしか情報を取ってこない。**
|
6
|
-
|
6
|
+
|
7
|
-
- なのでほしい情報が集まるまでfTypeを変更しつつ何度も`GetMenuItemInfo`を投げなくてはならない。
|
7
|
+
- なのでほしい情報が集まるまで`fType`を変更しつつ何度も`GetMenuItemInfo`を投げなくてはならない。
|
8
8
|
|
9
9
|
- `GetMenuItemInfo`は`MENUITEMINFO`にうまく情報を入れられなかった場合は0を返すので条件分岐はする。
|
10
10
|
|
@@ -90,57 +90,51 @@
|
|
90
90
|
|
91
91
|
// 2018 0124 1430 これで動くはず 修正前の内容は編集履歴をご確認ください
|
92
92
|
|
93
|
+
// 2018 0124 1500 これを直してる場合じゃない 修正前の内容は編集履歴をご確認ください
|
94
|
+
|
93
95
|
```c++
|
94
96
|
|
95
97
|
void CUIAutoDlg::OnBnClickedOk()
|
96
98
|
|
97
99
|
{
|
98
100
|
|
99
|
-
// TODO: ここにコントロール通知ハンドラー コードを追加します。
|
100
|
-
|
101
|
-
// 電卓のウィンドウを最善面に移動
|
102
|
-
|
103
|
-
const CString prgNm = _T("電卓");
|
104
|
-
|
105
|
-
const CString prgClsNm = _T("CalcFrame");
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
CWnd* cWnd = FindWindow(prgClsNm, prgNm);
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
try {
|
114
|
-
|
115
|
-
|
101
|
+
HWND hWnd = ::FindWindow(_T("CalcFrame"), _T("電卓"));
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
if (hWnd == NULL) {
|
106
|
+
|
107
|
+
MessageBox(_T("電卓が閉じてるとかそういう理由でウィンドウハンドラが取れなかった"), NULL, 0);
|
108
|
+
|
109
|
+
return;
|
116
110
|
|
117
111
|
}
|
118
112
|
|
113
|
+
|
114
|
+
|
115
|
+
::SetForegroundWindow(hWnd);
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
HMENU hMen = ::GetMenu(hWnd); // cWnd->GetMenu();
|
120
|
+
|
119
|
-
|
121
|
+
if (hMen == NULL) {
|
120
|
-
|
122
|
+
|
121
|
-
MessageBox(
|
123
|
+
MessageBox(_T("この電卓、メニューバーのウィンドウハンドラがないぞ・・・"), NULL, 0);
|
122
124
|
|
123
125
|
return;
|
124
126
|
|
125
127
|
}
|
126
128
|
|
127
|
-
|
129
|
+
|
128
|
-
|
129
|
-
|
130
|
+
|
130
|
-
|
131
|
-
HWND hWnd = ::FindWindow(prgClsNm, prgNm);
|
132
|
-
|
133
|
-
|
131
|
+
MENUITEMINFO mii;
|
134
|
-
|
135
|
-
|
132
|
+
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
133
|
+
if (GetSubMenuInfo(hWnd, hMen, &mii, _T("表示(&V")) == FALSE) return;
|
140
|
-
|
134
|
+
|
141
|
-
|
135
|
+
if (GetSubMenuInfo(hWnd, mii.hSubMenu, &mii, _T("プログラマ(&P) Alt+")) == FALSE) return;
|
142
|
-
|
136
|
+
|
143
|
-
::
|
137
|
+
::PostMessage(hWnd, WM_COMMAND, mii.wID, 0);
|
144
138
|
|
145
139
|
}
|
146
140
|
|
@@ -148,73 +142,65 @@
|
|
148
142
|
|
149
143
|
// 目的の項目の情報をMENUITEMINFOとして返す
|
150
144
|
|
151
|
-
|
145
|
+
BOOL CUIAutoDlg::GetSubMenuInfo(const HWND winHnd,const HMENU menHnd, MENUITEMINFO* mii,const CString menTitle) {
|
152
|
-
|
153
|
-
|
146
|
+
|
154
|
-
|
155
|
-
if (menHnd == NULL) return
|
147
|
+
if (menHnd == NULL) return FALSE;
|
148
|
+
|
149
|
+
|
150
|
+
|
156
|
-
|
151
|
+
mii->cbSize = sizeof(MENUITEMINFO);
|
157
|
-
|
158
152
|
|
159
153
|
int menuCnt = ::GetMenuItemCount(menHnd);
|
160
154
|
|
161
|
-
std::wstring buffer;
|
155
|
+
std::wstring buffer;
|
162
|
-
|
163
|
-
MENUITEMINFO mii;
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
mii.cbSize = sizeof(MENUITEMINFO); // 構造体サイズらしい。なんとなく初期化
|
168
|
-
|
169
|
-
|
170
156
|
|
171
157
|
for (int i = 0; i < menuCnt; ++i) {
|
172
158
|
|
173
|
-
//
|
159
|
+
// 文字列取得
|
174
|
-
|
175
|
-
|
160
|
+
|
176
|
-
|
177
|
-
mii.cch = 0; // 文字列長を一旦0で初期化
|
178
|
-
|
179
|
-
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行で文字列長を取得
|
180
|
-
|
181
|
-
buffer.resize(mii.cch); // バッファサイズの指定
|
182
|
-
|
183
|
-
mii
|
161
|
+
mii->fMask = MIIM_STRING;
|
184
|
-
|
185
|
-
|
162
|
+
|
186
|
-
|
187
|
-
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行で文字列を取得
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
if (mii.dwTypeData == menTitle) { // 項目名を比較(完全一致じゃ書きづらくて仕方が無いので.Contains相当のロジックを組まなくては)
|
192
|
-
|
193
|
-
// メニュー項目のIDを取得
|
194
|
-
|
195
|
-
mii.fMask = MIIM_ID; // メニュー項目のIDを取得するよう変更
|
196
|
-
|
197
|
-
|
163
|
+
mii->cch = 0;
|
198
|
-
|
199
|
-
|
164
|
+
|
200
|
-
|
201
|
-
// サブメニューのウィンドウハンドラを取得
|
202
|
-
|
203
|
-
mii.fMask = MIIM_SUBMENU; // サブメニューのウィンドウハンドラを取得するよう変更
|
204
|
-
|
205
|
-
mii.hSubMenu = NULL;
|
206
|
-
|
207
|
-
|
165
|
+
if (::GetMenuItemInfo(menHnd, i, 1, mii) == 0) continue;
|
166
|
+
|
208
|
-
|
167
|
+
buffer.resize(mii->cch);
|
168
|
+
|
209
|
-
|
169
|
+
mii->dwTypeData = NULL;
|
170
|
+
|
210
|
-
|
171
|
+
mii->dwTypeData = &buffer[0];
|
172
|
+
|
173
|
+
if (::GetMenuItemInfo(menHnd, i, 1, mii) == 0) continue;
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
if (mii->dwTypeData == menTitle) {
|
178
|
+
|
179
|
+
// ID取得
|
180
|
+
|
181
|
+
mii->fMask = MIIM_ID;
|
182
|
+
|
183
|
+
mii->wID = -1;
|
184
|
+
|
185
|
+
if (::GetMenuItemInfo(menHnd, i, 1, mii) == 0) continue;
|
186
|
+
|
187
|
+
// サブメニューハンドラ取得
|
188
|
+
|
189
|
+
mii->fMask = MIIM_SUBMENU;
|
190
|
+
|
191
|
+
mii->hSubMenu = NULL;
|
192
|
+
|
193
|
+
if (::GetMenuItemInfo(menHnd, i, 1, mii) == 0) continue;
|
194
|
+
|
195
|
+
|
196
|
+
|
211
|
-
return
|
197
|
+
return TRUE;
|
212
198
|
|
213
199
|
}
|
214
200
|
|
215
201
|
}
|
216
202
|
|
217
|
-
return
|
203
|
+
return FALSE;
|
218
204
|
|
219
205
|
}
|
220
206
|
|
17
ちょっと直した
test
CHANGED
File without changes
|
test
CHANGED
@@ -2,13 +2,19 @@
|
|
2
2
|
|
3
3
|
- Win32APIでフォームアプリのメニューバーを選択したいときは`SendMessage(hWnd, WM_COMMAND, 選択したいメニュー項目のID, 0);`
|
4
4
|
|
5
|
-
- 選択したいメニュー項目のIDは、`GetMenuItemInfo`関数を使うが、**なんとこの関数、fTypeに指定した一項目ずつしか情報を取ってこない。**
|
5
|
+
- 選択したいメニュー項目のIDは、`GetMenuItemInfo`関数を使うが、**なんとこの関数、引数のMENUITEMINFO構造体のfTypeに指定した一項目ずつしか情報を取ってこない。**
|
6
|
-
|
6
|
+
|
7
|
-
- なのでほしい情報が集まるまでfTypeを変更しつつ何度も`GetMenuItemInfo`を投げ
|
7
|
+
- なのでほしい情報が集まるまでfTypeを変更しつつ何度も`GetMenuItemInfo`を投げなくてはならない。
|
8
8
|
|
9
9
|
- `GetMenuItemInfo`は`MENUITEMINFO`にうまく情報を入れられなかった場合は0を返すので条件分岐はする。
|
10
10
|
|
11
|
-
- MFCの`C~Dlg`クラスでは**Win32APIに呼びかける関数を使おうとするとマクロで別の処理に切り替わり**ます。とりあえず`::`を使って名前空間を明示的に指定す
|
11
|
+
- MFCの`C~Dlg`クラスでは**Win32APIに呼びかける関数を使おうとするとマクロで別の処理に切り替わり**ます。とりあえず`::`を使って名前空間を明示的に指定することでどうにか目的の関数を呼べるようになる。
|
12
|
+
|
13
|
+
[GetMenuItemInfo(MSDN)](https://msdn.microsoft.com/ja-jp/library/cc364689.aspx)
|
14
|
+
|
15
|
+
[MSDNのサイトで不足情報はここ参照](http://chokuto.ifdef.jp/urawaza/struct/MENUITEMINFO.html)
|
16
|
+
|
17
|
+
|
12
18
|
|
13
19
|
###前提・実現したいこと
|
14
20
|
|
16
更新のメッセージを入れ忘れた
test
CHANGED
File without changes
|
test
CHANGED
@@ -82,6 +82,8 @@
|
|
82
82
|
|
83
83
|
// 2018 0124 1105 メニューに表示されいる文字列は取得できました 修正前の内容は編集履歴をご確認ください
|
84
84
|
|
85
|
+
// 2018 0124 1430 これで動くはず 修正前の内容は編集履歴をご確認ください
|
86
|
+
|
85
87
|
```c++
|
86
88
|
|
87
89
|
void CUIAutoDlg::OnBnClickedOk()
|
15
まとめました
test
CHANGED
File without changes
|
test
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
###まとめ
|
2
|
+
|
3
|
+
- Win32APIでフォームアプリのメニューバーを選択したいときは`SendMessage(hWnd, WM_COMMAND, 選択したいメニュー項目のID, 0);`
|
4
|
+
|
5
|
+
- 選択したいメニュー項目のIDは、`GetMenuItemInfo`関数を使うが、**なんとこの関数、fTypeに指定した一項目ずつしか情報を取ってこない。**
|
6
|
+
|
7
|
+
- なのでほしい情報が集まるまでfTypeを変更しつつ何度も`GetMenuItemInfo`を投げる。
|
8
|
+
|
9
|
+
- `GetMenuItemInfo`は`MENUITEMINFO`にうまく情報を入れられなかった場合は0を返すので条件分岐はする。
|
10
|
+
|
11
|
+
- MFCの`C~Dlg`クラスでは**Win32APIに呼びかける関数を使おうとするとマクロで別の処理に切り替わり**ます。とりあえず`::`を使って名前空間を明示的に指定すればどうにか呼べます。
|
12
|
+
|
1
13
|
###前提・実現したいこと
|
2
14
|
|
3
15
|
MFCから他のアプリケーションのメニューバーを操作したい。
|
@@ -118,11 +130,9 @@
|
|
118
130
|
|
119
131
|
MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(&V"));
|
120
132
|
|
133
|
+
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P) Alt+")); // *これ、デバッガから適当にコピーしたけど\tとか含んでるのでクソめんどくさい文字列
|
134
|
+
|
121
|
-
::SendMessage(hWnd, WM_COMMAND, mii.wID, 0);
|
135
|
+
::SendMessage(hWnd, WM_COMMAND, mii.wID, 0);
|
122
|
-
|
123
|
-
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P"));
|
124
|
-
|
125
|
-
::SendMessage(hWnd, WM_COMMAND, mii.wID, 0); // まず表示を選ばないとこれも意味が無い
|
126
136
|
|
127
137
|
}
|
128
138
|
|
@@ -152,14 +162,14 @@
|
|
152
162
|
|
153
163
|
for (int i = 0; i < menuCnt; ++i) {
|
154
164
|
|
165
|
+
// メニュー項目の文字列を取得
|
166
|
+
|
155
167
|
mii.fMask = MIIM_STRING; // メニュー項目の文字列を取得するよう設定
|
156
168
|
|
157
169
|
mii.cch = 0; // 文字列長を一旦0で初期化
|
158
170
|
|
159
171
|
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行で文字列長を取得
|
160
172
|
|
161
|
-
|
162
|
-
|
163
173
|
buffer.resize(mii.cch); // バッファサイズの指定
|
164
174
|
|
165
175
|
mii.dwTypeData = NULL;
|
@@ -170,13 +180,25 @@
|
|
170
180
|
|
171
181
|
|
172
182
|
|
173
|
-
if (mii.dwTypeData == menTitle) {
|
183
|
+
if (mii.dwTypeData == menTitle) { // 項目名を比較(完全一致じゃ書きづらくて仕方が無いので.Contains相当のロジックを組まなくては)
|
184
|
+
|
185
|
+
// メニュー項目のIDを取得
|
174
186
|
|
175
187
|
mii.fMask = MIIM_ID; // メニュー項目のIDを取得するよう変更
|
176
188
|
|
177
189
|
mii.wID = -1;
|
178
190
|
|
179
|
-
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行でIDを取得
|
191
|
+
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行でIDを取得
|
192
|
+
|
193
|
+
// サブメニューのウィンドウハンドラを取得
|
194
|
+
|
195
|
+
mii.fMask = MIIM_SUBMENU; // サブメニューのウィンドウハンドラを取得するよう変更
|
196
|
+
|
197
|
+
mii.hSubMenu = NULL;
|
198
|
+
|
199
|
+
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue;
|
200
|
+
|
201
|
+
|
180
202
|
|
181
203
|
return mii;
|
182
204
|
|
14
質問をちょっと修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -56,9 +56,9 @@
|
|
56
56
|
|
57
57
|
ですがどうも動いている様子がありませんので質問を
|
58
58
|
|
59
|
-
MENUITEMINFOの取得方法
|
59
|
+
- MENUITEMINFOの取得方法
|
60
|
-
|
60
|
+
|
61
|
-
メニューバーの項目の選択方法
|
61
|
+
- メニューバーの項目の選択方法(SendMessageで何のコマンドを利用すればよいか)
|
62
62
|
|
63
63
|
に変え、引き続きお知恵をお貸しいただけますようお願いいたします。
|
64
64
|
|
13
何度も直して申し訳ない
test
CHANGED
File without changes
|
test
CHANGED
@@ -118,11 +118,11 @@
|
|
118
118
|
|
119
119
|
MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(&V"));
|
120
120
|
|
121
|
-
::SendMessage(
|
121
|
+
::SendMessage(hWnd, WM_COMMAND, mii.wID, 0); // 表示を選ぼうとしているが出来てない
|
122
122
|
|
123
123
|
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P"));
|
124
124
|
|
125
|
-
::SendMessage(
|
125
|
+
::SendMessage(hWnd, WM_COMMAND, mii.wID, 0); // まず表示を選ばないとこれも意味が無い
|
126
126
|
|
127
127
|
}
|
128
128
|
|
12
試したこと を更新し忘れていたので更新。
test
CHANGED
File without changes
|
test
CHANGED
@@ -196,7 +196,9 @@
|
|
196
196
|
|
197
197
|
###試したこと
|
198
198
|
|
199
|
-
現状の方法で改善の方向性が見出せないため他の方法を探してみています。
|
199
|
+
~~現状の方法で改善の方向性が見出せないため他の方法を探してみています。~~
|
200
|
+
|
201
|
+
`wID`として取得できた値で`WM_COMMAND`以外のコマンドをいろいろ`SendMessage`してみています。
|
200
202
|
|
201
203
|
以前の質問でUI Automationを教えていただいており、これを用いる方法は現在調査中です
|
202
204
|
|
11
コピーし忘れ部分を修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -80,7 +80,13 @@
|
|
80
80
|
|
81
81
|
// 電卓のウィンドウを最善面に移動
|
82
82
|
|
83
|
+
const CString prgNm = _T("電卓");
|
84
|
+
|
83
|
-
|
85
|
+
const CString prgClsNm = _T("CalcFrame");
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
CWnd* cWnd = FindWindow(prgClsNm, prgNm);
|
84
90
|
|
85
91
|
|
86
92
|
|
@@ -102,19 +108,21 @@
|
|
102
108
|
|
103
109
|
// メニューバーを操作
|
104
110
|
|
105
|
-
HWND hWnd = ::FindWindow(
|
111
|
+
HWND hWnd = ::FindWindow(prgClsNm, prgNm);
|
106
|
-
|
112
|
+
|
107
|
-
HMENU hMen = ::GetMenu(hWnd);
|
113
|
+
HMENU hMen = ::GetMenu(hWnd);
|
108
|
-
|
114
|
+
|
109
|
-
if(hMen == NULL)return; // ここで抜け
|
115
|
+
if(hMen == NULL)return; // メニューバーが無ければここで抜け
|
110
|
-
|
111
|
-
|
116
|
+
|
117
|
+
|
112
118
|
|
113
119
|
MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(&V"));
|
114
120
|
|
121
|
+
::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0); // 表示を選ぼうとしているが出来てない
|
122
|
+
|
115
123
|
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P"));
|
116
124
|
|
117
|
-
::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0);
|
125
|
+
::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0); // まず表示を選ばないとこれも意味が無い
|
118
126
|
|
119
127
|
}
|
120
128
|
|
10
MENUITEMINFOを取得する処理が動いたのでコードを修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -26,7 +26,9 @@
|
|
26
26
|
|
27
27
|
→SendMessageで選択を実行
|
28
28
|
|
29
|
+
```
|
30
|
+
|
29
|
-
|
31
|
+
~~という流れで処理を行おうとしたのですがdwTypeDataと項目名を比較しようとすると~~
|
30
32
|
|
31
33
|
```0x000007FEEA1F8F22(ucrtbased.dll)で例外がスローされました
|
32
34
|
|
@@ -34,30 +36,42 @@
|
|
34
36
|
|
35
37
|
この例外のハンドラーがある場合は、プログラムを安全に実行できます。
|
36
38
|
|
37
|
-
```と例外が投げられます。(文字列の先頭アドレスが指定されないからでしょうか)
|
39
|
+
```~~と例外が投げられます。(文字列の先頭アドレスが指定されないからでしょうか)
|
38
40
|
|
39
41
|
HMENUをデバッガで確認すると`<メモリを読み取れません>`と表示されており
|
40
42
|
|
41
|
-
たしかに処理できそうに見えません。
|
43
|
+
たしかに処理できそうに見えません。~~
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
|
45
|
+
|
46
|
+
|
45
|
-
そこで、HMENUを正しく取得する方法
|
47
|
+
~~そこで、HMENUを正しく取得する方法
|
46
48
|
|
47
49
|
もしくはHMENUを利用するほかに他のアプリケーションのメニューバーを操作する方法
|
48
50
|
|
49
51
|
をご教授いただきたいです。
|
50
52
|
|
51
|
-
よろしくお願いいたします。
|
53
|
+
よろしくお願いいたします。~~
|
54
|
+
|
55
|
+
上記の打ち消し線部の問題が解決すれば目的の動作を達成すると思っていました。
|
56
|
+
|
57
|
+
ですがどうも動いている様子がありませんので質問を
|
58
|
+
|
59
|
+
MENUITEMINFOの取得方法
|
60
|
+
|
61
|
+
メニューバーの項目の選択方法
|
62
|
+
|
63
|
+
に変え、引き続きお知恵をお貸しいただけますようお願いいたします。
|
52
64
|
|
53
65
|
|
54
66
|
|
55
67
|
###該当のソースコード
|
56
68
|
|
57
|
-
```ここに言語を入力
|
58
|
-
|
59
69
|
// 2018 0123 1727 ご指摘を受けて修正 修正前の内容は編集履歴をご確認ください
|
60
70
|
|
71
|
+
// 2018 0124 1105 メニューに表示されいる文字列は取得できました 修正前の内容は編集履歴をご確認ください
|
72
|
+
|
73
|
+
```c++
|
74
|
+
|
61
75
|
void CUIAutoDlg::OnBnClickedOk()
|
62
76
|
|
63
77
|
{
|
@@ -96,9 +110,9 @@
|
|
96
110
|
|
97
111
|
// ところが上のチェックをパスしたにもかかわらず次の処理で例外を投げている
|
98
112
|
|
99
|
-
MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(V
|
113
|
+
MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(&V"));
|
100
|
-
|
114
|
+
|
101
|
-
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(P
|
115
|
+
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P"));
|
102
116
|
|
103
117
|
::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0);
|
104
118
|
|
@@ -112,41 +126,57 @@
|
|
112
126
|
|
113
127
|
{
|
114
128
|
|
129
|
+
if (menHnd == NULL) return MENUITEMINFO();
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
int menuCnt = ::GetMenuItemCount(menHnd);
|
134
|
+
|
135
|
+
std::wstring buffer; // メニュー表示文字列受け取りバッファ
|
136
|
+
|
115
137
|
MENUITEMINFO mii;
|
116
138
|
|
139
|
+
|
140
|
+
|
117
|
-
i
|
141
|
+
mii.cbSize = sizeof(MENUITEMINFO); // 構造体サイズらしい。なんとなく初期化
|
142
|
+
|
143
|
+
|
118
144
|
|
119
145
|
for (int i = 0; i < menuCnt; ++i) {
|
120
146
|
|
121
|
-
mii.fMask = MIIM_
|
147
|
+
mii.fMask = MIIM_STRING; // メニュー項目の文字列を取得するよう設定
|
122
|
-
|
123
|
-
|
148
|
+
|
124
|
-
|
125
|
-
mii.cch = 0; //
|
149
|
+
mii.cch = 0; // 文字列長を一旦0で初期化
|
150
|
+
|
126
|
-
|
151
|
+
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行で文字列長を取得
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
buffer.resize(mii.cch); // バッファサイズの指定
|
156
|
+
|
157
|
+
mii.dwTypeData = NULL;
|
158
|
+
|
159
|
+
mii.dwTypeData = &buffer[0]; // バッファのアドレスを与える
|
160
|
+
|
127
|
-
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0)
|
161
|
+
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行で文字列を取得
|
162
|
+
|
163
|
+
|
164
|
+
|
128
|
-
|
165
|
+
if (mii.dwTypeData == menTitle) {
|
166
|
+
|
129
|
-
|
167
|
+
mii.fMask = MIIM_ID; // メニュー項目のIDを取得するよう変更
|
168
|
+
|
169
|
+
mii.wID = -1;
|
170
|
+
|
171
|
+
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行でIDを取得?
|
172
|
+
|
173
|
+
return mii;
|
130
174
|
|
131
175
|
}
|
132
176
|
|
133
|
-
|
134
|
-
|
135
|
-
// if (mii.fType != MIIM_STRING) continue; // ご指摘を受けて修正 *取り急ぎ
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
if (mii.dwTypeData == menTitle) { // ここでエラー dwTypeDataの指すポインタが<読み取れません>になっている
|
140
|
-
|
141
|
-
// メニュー項目が目的のものなら返す
|
142
|
-
|
143
|
-
return mii;
|
144
|
-
|
145
|
-
}
|
146
|
-
|
147
177
|
}
|
148
178
|
|
149
|
-
return MENUITEMINFO();
|
179
|
+
return MENUITEMINFO();
|
150
180
|
|
151
181
|
}
|
152
182
|
|
9
コードを慎重に見直し
test
CHANGED
File without changes
|
test
CHANGED
@@ -118,11 +118,21 @@
|
|
118
118
|
|
119
119
|
for (int i = 0; i < menuCnt; ++i) {
|
120
120
|
|
121
|
+
mii.fMask = MIIM_FTYPE; // 追記
|
122
|
+
|
123
|
+
mii.fType = MFT_STRING; // 追記
|
124
|
+
|
125
|
+
mii.cch = 0; // 追記
|
126
|
+
|
121
|
-
::GetMenuItemInfo(menHnd, i, 1, &mii)
|
127
|
+
if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) {
|
128
|
+
|
129
|
+
continue; // 取得失敗なら以下の処理は飛ばす
|
130
|
+
|
131
|
+
}
|
122
132
|
|
123
133
|
|
124
134
|
|
125
|
-
if (mii.fType != MIIM_STRING) continue; // ご指摘を受けて修正 *取り急ぎ
|
135
|
+
// if (mii.fType != MIIM_STRING) continue; // ご指摘を受けて修正 *取り急ぎ
|
126
136
|
|
127
137
|
|
128
138
|
|
@@ -142,6 +152,8 @@
|
|
142
152
|
|
143
153
|
```
|
144
154
|
|
155
|
+
[GetMenuItemInfo(MSDN)](https://msdn.microsoft.com/ja-jp/library/cc364689.aspx)とか[MENUITEMINFOについて解説してるサイト](http://chokuto.ifdef.jp/urawaza/struct/MENUITEMINFO.html)を見ながら修正
|
156
|
+
|
145
157
|
|
146
158
|
|
147
159
|
###試したこと
|
8
ちょっと修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -122,6 +122,10 @@
|
|
122
122
|
|
123
123
|
|
124
124
|
|
125
|
+
if (mii.fType != MIIM_STRING) continue; // ご指摘を受けて修正 *取り急ぎ
|
126
|
+
|
127
|
+
|
128
|
+
|
125
129
|
if (mii.dwTypeData == menTitle) { // ここでエラー dwTypeDataの指すポインタが<読み取れません>になっている
|
126
130
|
|
127
131
|
// メニュー項目が目的のものなら返す
|
7
ご指摘を受けて修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -56,13 +56,15 @@
|
|
56
56
|
|
57
57
|
```ここに言語を入力
|
58
58
|
|
59
|
+
// 2018 0123 1727 ご指摘を受けて修正 修正前の内容は編集履歴をご確認ください
|
60
|
+
|
59
61
|
void CUIAutoDlg::OnBnClickedOk()
|
60
62
|
|
61
63
|
{
|
62
64
|
|
63
65
|
// TODO: ここにコントロール通知ハンドラー コードを追加します。
|
64
66
|
|
65
|
-
// 電卓の
|
67
|
+
// 電卓のウィンドウを最善面に移動
|
66
68
|
|
67
69
|
CWnd* cWnd = FindWindow(_T("CalcFrame"), _T("電卓"));
|
68
70
|
|
@@ -82,21 +84,21 @@
|
|
82
84
|
|
83
85
|
}
|
84
86
|
|
85
|
-
|
86
|
-
|
87
87
|
cWnd->SetForegroundWindow();
|
88
88
|
|
89
89
|
// メニューバーを操作
|
90
90
|
|
91
|
+
HWND hWnd = ::FindWindow(_T("CalcFrame"), _T("電卓"));
|
92
|
+
|
91
|
-
HMENU hMen = ::GetMenu(
|
93
|
+
HMENU hMen = ::GetMenu(hWnd); // HMENUの中身が本当に無いならNULLが返るので
|
92
94
|
|
93
95
|
if(hMen == NULL)return; // ここで抜けるはず
|
94
96
|
|
95
97
|
// ところが上のチェックをパスしたにもかかわらず次の処理で例外を投げている
|
96
98
|
|
97
|
-
MENUITEMINFO mii = GetSubMenuInfo(
|
99
|
+
MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(V)"));
|
98
100
|
|
99
|
-
mii = GetSubMenuInfo(
|
101
|
+
mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(P)"));
|
100
102
|
|
101
103
|
::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0);
|
102
104
|
|
6
泣き言を消しました
test
CHANGED
File without changes
|
test
CHANGED
@@ -142,9 +142,7 @@
|
|
142
142
|
|
143
143
|
現状の方法で改善の方向性が見出せないため他の方法を探してみています。
|
144
144
|
|
145
|
-
以前の質問でUI Automationを教えていただいており、これを用いる方法は現在調査中です
|
145
|
+
以前の質問でUI Automationを教えていただいており、これを用いる方法は現在調査中です
|
146
|
-
|
147
|
-
|
148
146
|
|
149
147
|
###補足情報(言語/FW/ツール等のバージョンなど)
|
150
148
|
|
5
文面を少し修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -44,7 +44,9 @@
|
|
44
44
|
|
45
45
|
そこで、HMENUを正しく取得する方法
|
46
46
|
|
47
|
-
もしくはHMENUを利用するほかに他のアプリケーションのメニューバーを操作する方法
|
47
|
+
もしくはHMENUを利用するほかに他のアプリケーションのメニューバーを操作する方法
|
48
|
+
|
49
|
+
をご教授いただきたいです。
|
48
50
|
|
49
51
|
よろしくお願いいたします。
|
50
52
|
|
@@ -118,7 +120,7 @@
|
|
118
120
|
|
119
121
|
|
120
122
|
|
121
|
-
if (mii.dwTypeData == menTitle) { // ここでエラー
|
123
|
+
if (mii.dwTypeData == menTitle) { // ここでエラー dwTypeDataの指すポインタが<読み取れません>になっている
|
122
124
|
|
123
125
|
// メニュー項目が目的のものなら返す
|
124
126
|
|
@@ -138,9 +140,9 @@
|
|
138
140
|
|
139
141
|
###試したこと
|
140
142
|
|
141
|
-
他の方法を探してみています
|
143
|
+
現状の方法で改善の方向性が見出せないため他の方法を探してみています。
|
142
144
|
|
143
|
-
|
145
|
+
以前の質問でUI Automationを教えていただいており、これを用いる方法は現在調査中です。__にほんごの資料が少なく難航してます__
|
144
146
|
|
145
147
|
|
146
148
|
|
4
タグの整理整頓と少し修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -90,7 +90,7 @@
|
|
90
90
|
|
91
91
|
if(hMen == NULL)return; // ここで抜けるはず
|
92
92
|
|
93
|
-
// ところが上のチェックをパスしたにもかかわらず次の処理
|
93
|
+
// ところが上のチェックをパスしたにもかかわらず次の処理で例外を投げている
|
94
94
|
|
95
95
|
MENUITEMINFO mii = GetSubMenuInfo(cWnd->GetSafeHwnd(), hMen, _T("表示(V)"));
|
96
96
|
|
@@ -114,7 +114,7 @@
|
|
114
114
|
|
115
115
|
for (int i = 0; i < menuCnt; ++i) {
|
116
116
|
|
117
|
-
::GetMenuItemInfo(menHnd, i, 1, &mii);
|
117
|
+
::GetMenuItemInfo(menHnd, i, 1, &mii); // MENUITEMINFOの取り方に間違いがある?
|
118
118
|
|
119
119
|
|
120
120
|
|
3
ちょっとだけ追加
test
CHANGED
File without changes
|
test
CHANGED
@@ -70,8 +70,6 @@
|
|
70
70
|
|
71
71
|
if (cWnd == NULL) throw std::exception("cant find calc.");
|
72
72
|
|
73
|
-
|
74
|
-
|
75
73
|
}
|
76
74
|
|
77
75
|
catch(std::exception e){
|
@@ -82,13 +80,17 @@
|
|
82
80
|
|
83
81
|
}
|
84
82
|
|
83
|
+
|
84
|
+
|
85
85
|
cWnd->SetForegroundWindow();
|
86
86
|
|
87
87
|
// メニューバーを操作
|
88
88
|
|
89
|
-
HMENU hMen = ::GetMenu(cWnd->GetSafeHwnd()); //
|
89
|
+
HMENU hMen = ::GetMenu(cWnd->GetSafeHwnd()); // HMENUの中身が本当に無いならNULLが返るので
|
90
90
|
|
91
|
+
if(hMen == NULL)return; // ここで抜けるはず
|
91
92
|
|
93
|
+
// ところが上のチェックをパスしたにもかかわらず次の処理に進み例外を投げている
|
92
94
|
|
93
95
|
MENUITEMINFO mii = GetSubMenuInfo(cWnd->GetSafeHwnd(), hMen, _T("表示(V)"));
|
94
96
|
|
@@ -102,9 +104,9 @@
|
|
102
104
|
|
103
105
|
// 目的の項目の情報をMENUITEMINFOとして返す
|
104
106
|
|
105
|
-
MENUITEMINFO CUIAutoDlg::GetSubMenuInfo(const HWND winHnd,const HMENU menHnd,const CString menTitle)
|
107
|
+
MENUITEMINFO CUIAutoDlg::GetSubMenuInfo(const HWND winHnd,const HMENU menHnd,const CString menTitle)
|
106
108
|
|
107
|
-
|
109
|
+
{
|
108
110
|
|
109
111
|
MENUITEMINFO mii;
|
110
112
|
|
@@ -116,11 +118,7 @@
|
|
116
118
|
|
117
119
|
|
118
120
|
|
119
|
-
if (mii.dwTypeData == NULL) continue;
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
if (mii.dwTypeData == menTitle) { // ここでエラー
|
121
|
+
if (mii.dwTypeData == menTitle) { // ここでエラー マトモに文字列があればLPTSTRとCStringの比較でエラーは起きない
|
124
122
|
|
125
123
|
// メニュー項目が目的のものなら返す
|
126
124
|
|
@@ -129,8 +127,6 @@
|
|
129
127
|
}
|
130
128
|
|
131
129
|
}
|
132
|
-
|
133
|
-
|
134
130
|
|
135
131
|
return MENUITEMINFO(); // 目的の項目が見つからなければ空の構造体を返す
|
136
132
|
|
2
処理の流れに不足があったので追加
test
CHANGED
File without changes
|
test
CHANGED
@@ -21,6 +21,8 @@
|
|
21
21
|
→HMENUからMENUITEMINFOを取得
|
22
22
|
|
23
23
|
→dwTypeDataから項目名"プログラマ"と合致するかチェック
|
24
|
+
|
25
|
+
→メニューバーのプログラマ(P)の項目のIDを取得
|
24
26
|
|
25
27
|
→SendMessageで選択を実行
|
26
28
|
|
1
未検証のIDチェックをそのまま載せちゃってたので削除(ていうか条件も < 0 だな・・・ま逆・・・
test
CHANGED
File without changes
|
test
CHANGED
@@ -90,11 +90,7 @@
|
|
90
90
|
|
91
91
|
MENUITEMINFO mii = GetSubMenuInfo(cWnd->GetSafeHwnd(), hMen, _T("表示(V)"));
|
92
92
|
|
93
|
-
if (mii.wID >= 0)return;
|
94
|
-
|
95
93
|
mii = GetSubMenuInfo(cWnd->GetSafeHwnd(), mii.hSubMenu, _T("プログラマ(P)"));
|
96
|
-
|
97
|
-
if (mii.wID >= 0)return;
|
98
94
|
|
99
95
|
::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0);
|
100
96
|
|