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