質問編集履歴

18

あああ

2018/01/24 06:08

投稿

notgoodpg
notgoodpg

スコア37

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
- if (cWnd == NULL) throw std::exception("cant find calc.");
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
- catch(std::exception e){
121
+ if (hMen == NULL) {
120
-
122
+
121
- MessageBox(CString(e.what()), NULL, 0);
123
+ MessageBox(_T("この電卓、メニューバーのウィンドウハンドラがないぞ・・・"), NULL, 0);
122
124
 
123
125
  return;
124
126
 
125
127
  }
126
128
 
127
- cWnd->SetForegroundWindow();
129
+
128
-
129
- // メニューバーを操作
130
+
130
-
131
- HWND hWnd = ::FindWindow(prgClsNm, prgNm);
132
-
133
- HMENU hMen = ::GetMenu(hWnd);
131
+ MENUITEMINFO mii;
134
-
135
- if(hMen == NULL)return; // メニューバーが無ければここで抜け
132
+
136
-
137
-
138
-
139
- MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(&V"));
133
+ if (GetSubMenuInfo(hWnd, hMen, &mii, _T("表示(&V")) == FALSE) return;
140
-
134
+
141
- mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P) Alt+")); // *これ、デバッガから適当にコピーしたけど\tとか含んでるのでクソめんどくさい文字列
135
+ if (GetSubMenuInfo(hWnd, mii.hSubMenu, &mii, _T("プログラマ(&P) Alt+")) == FALSE) return;
142
-
136
+
143
- ::SendMessage(hWnd, WM_COMMAND, mii.wID, 0);
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
- MENUITEMINFO CUIAutoDlg::GetSubMenuInfo(const HWND winHnd,const HMENU menHnd,const CString menTitle)
145
+ BOOL CUIAutoDlg::GetSubMenuInfo(const HWND winHnd,const HMENU menHnd, MENUITEMINFO* mii,const CString menTitle) {
152
-
153
- {
146
+
154
-
155
- if (menHnd == NULL) return MENUITEMINFO();
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
- mii.fMask = MIIM_STRING; // メニュー項目の文字列を取得するよう設定
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.dwTypeData = NULL;
161
+ mii->fMask = MIIM_STRING;
184
-
185
- mii.dwTypeData = &buffer[0]; // バッファのアドレスを与える
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
- mii.wID = -1;
163
+ mii->cch = 0;
198
-
199
- if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue; // この実行でIDを取得
164
+
200
-
201
- // サブメニューのウィンドウハンドラを取得
202
-
203
- mii.fMask = MIIM_SUBMENU; // サブメニューのウィンドウハンドラを取得するよう変更
204
-
205
- mii.hSubMenu = NULL;
206
-
207
- if (::GetMenuItemInfo(menHnd, i, 1, &mii) == 0) continue;
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 mii;
197
+ return TRUE;
212
198
 
213
199
  }
214
200
 
215
201
  }
216
202
 
217
- return MENUITEMINFO();
203
+ return FALSE;
218
204
 
219
205
  }
220
206
 

17

ちょっと直した

2018/01/24 06:08

投稿

notgoodpg
notgoodpg

スコア37

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

更新のメッセージを入れ忘れた

2018/01/24 05:40

投稿

notgoodpg
notgoodpg

スコア37

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

まとめました

2018/01/24 05:30

投稿

notgoodpg
notgoodpg

スコア37

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

質問をちょっと修正

2018/01/24 05:28

投稿

notgoodpg
notgoodpg

スコア37

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

何度も直して申し訳ない

2018/01/24 04:56

投稿

notgoodpg
notgoodpg

スコア37

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(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0); // 表示を選ぼうとしているが出来てない
121
+ ::SendMessage(hWnd, WM_COMMAND, mii.wID, 0); // 表示を選ぼうとしているが出来てない
122
122
 
123
123
  mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(&P"));
124
124
 
125
- ::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0); // まず表示を選ばないとこれも意味が無い
125
+ ::SendMessage(hWnd, WM_COMMAND, mii.wID, 0); // まず表示を選ばないとこれも意味が無い
126
126
 
127
127
  }
128
128
 

12

試したこと を更新し忘れていたので更新。

2018/01/24 02:39

投稿

notgoodpg
notgoodpg

スコア37

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

コピーし忘れ部分を修正

2018/01/24 02:27

投稿

notgoodpg
notgoodpg

スコア37

test CHANGED
File without changes
test CHANGED
@@ -80,7 +80,13 @@
80
80
 
81
81
  // 電卓のウィンドウを最善面に移動
82
82
 
83
+ const CString prgNm = _T("電卓");
84
+
83
- CWnd* cWnd = FindWindow(_T("CalcFrame"), _T("電卓"));
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(_T("CalcFrame"), _T("電卓"));
111
+ HWND hWnd = ::FindWindow(prgClsNm, prgNm);
106
-
112
+
107
- HMENU hMen = ::GetMenu(hWnd); // HMENUの中身が本当に無いならNULLが返るので
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を取得する処理が動いたのでコードを修正

2018/01/24 02:13

投稿

notgoodpg
notgoodpg

スコア37

test CHANGED
File without changes
test CHANGED
@@ -26,7 +26,9 @@
26
26
 
27
27
  →SendMessageで選択を実行
28
28
 
29
+ ```
30
+
29
- ```という流れで処理を行おうとしたのですがdwTypeDataと項目名を比較しようとすると
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
- int menuCnt = ::GetMenuItemCount(menHnd);
141
+ mii.cbSize = sizeof(MENUITEMINFO); // 構造体サイズらしい。なんとなく初期化
142
+
143
+
118
144
 
119
145
  for (int i = 0; i < menuCnt; ++i) {
120
146
 
121
- mii.fMask = MIIM_FTYPE; // 追記
147
+ mii.fMask = MIIM_STRING; // メニュー項目の文字列を取得するよう設定
122
-
123
- mii.fType = MFT_STRING; // 追記
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
- continue; // 取得失敗なら以下の処理は飛ば
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

コードを慎重に見直し

2018/01/24 02:05

投稿

notgoodpg
notgoodpg

スコア37

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); // MENUITEMINFOの取り方に間違いがある?
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

ちょっと修正

2018/01/24 01:25

投稿

notgoodpg
notgoodpg

スコア37

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

ご指摘を受けて修正

2018/01/24 00:15

投稿

notgoodpg
notgoodpg

スコア37

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
- // 電卓のCWnd取得
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(cWnd->GetSafeHwnd()); // HMENUの中身が本当に無いならNULLが返るので
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(cWnd->GetSafeHwnd(), hMen, _T("表示(V)"));
99
+ MENUITEMINFO mii = GetSubMenuInfo(hWnd , hMen, _T("表示(V)"));
98
100
 
99
- mii = GetSubMenuInfo(cWnd->GetSafeHwnd(), mii.hSubMenu, _T("プログラマ(P)"));
101
+ mii = GetSubMenuInfo(hWnd ,mii.hSubMenu, _T("プログラマ(P)"));
100
102
 
101
103
  ::SendMessage(cWnd->GetSafeHwnd(), WM_COMMAND, mii.wID, 0);
102
104
 

6

泣き言を消しました

2018/01/23 08:28

投稿

notgoodpg
notgoodpg

スコア37

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

文面を少し修正

2018/01/23 07:47

投稿

notgoodpg
notgoodpg

スコア37

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) { // ここでエラー マトモに文字列があればLPTSTRとCString比較でエラーは起きない
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
- なお、以前の質問でUI Automationを教えていただいており、これを用いる方法は現在調査中です。
145
+ 以前の質問でUI Automationを教えていただいており、これを用いる方法は現在調査中です。__にほんごの資料が少なく難航してます__
144
146
 
145
147
 
146
148
 

4

タグの整理整頓と少し修正

2018/01/23 07:46

投稿

notgoodpg
notgoodpg

スコア37

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

ちょっとだけ追加

2018/01/23 07:27

投稿

notgoodpg
notgoodpg

スコア37

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()); // cWnd->GetMenu();
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

処理の流れに不足があったので追加

2018/01/23 06:20

投稿

notgoodpg
notgoodpg

スコア37

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 だな・・・ま逆・・・

2018/01/23 05:07

投稿

notgoodpg
notgoodpg

スコア37

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