お世話になっております。
ポップアップメニューの項目にチェック状態を設定しているのですが、うまく記憶させる(次回開くときに反映されている)方法がわかりません。どんな処理が不足しているのかご教示いただけますと幸いです。
void COcxCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
HMENU hmenu = ::LoadMenu((HINSTANCE)::GetWindowLong(this->GetSafeHwnd(), GWL_HINSTANCE), MAKEINTRESOURCE(IDR_MENU1));
HMENU hmenuPopup = ::GetSubMenu(hmenu, 0);
::ClientToScreen(this->GetSafeHwnd(), &point);
::TrackPopupMenu(hmenuPopup, TPM_LEFTALIGN, point.x, point.y, 0, this->GetSafeHwnd(), NULL);
::DestroyMenu(hmenu);
COleControl::OnRButtonDown(nFlags, point);
}
/// m_checked は、BOOL型のCOcxCtrlメンバー変数
void COcxCtrl::OnPopupCheck()
{
HMENU hmenu = ::LoadMenu((HINSTANCE)::GetWindowLong(this->GetSafeHwnd(), GWL_HINSTANCE), MAKEINTRESOURCE(IDR_MENU1));
HMENU hmenuPopup = ::GetSubMenu(hmenu, 0);
UINT state = ::GetMenuState(hmenu, IDM_POPUP_CHECK, MF_BYCOMMAND);
ASSERT(state != 0xFFFFFFFF);
if (state & MF_CHECKED){
m_checked = false;
MessageBox(_T("F"));
}
else{
m_checked = true;
MessageBox(_T("T"));
}
::CheckMenuItem(hmenu, IDM_POPUP_CHECK, MF_BYCOMMAND | (m_checked ? (MF_CHECKED) : (MF_UNCHECKED)));
}
常にチェックが入り(メッセージボックスでは F が毎度表示)、MF_UNCHECKEDを設定しているにもかかわらず、次回開くときにチェックが入っています。プログラミングの間違いで論理が変なのかと思い、上記コードのMF_CHECKEDをMF_UNCHECKEDにしてもチェックはついたまま。プロパティでCheckedをFalseに指定すると、今度は何をしてもチェックは入りません。
だいぶ以前にしたときには出来たのですが、コードはすっかり忘れてしまい、何がおかしいのか思い当たらず困ってしまいました。
何かご指摘いただけますと助かります。
追記
該当メニュー項目プロパティのCheckedをFalseにすると、::CheckMenuItem() の戻り値は 0 です。
>::CheckMenuItem(hmenu, ...
を
>::CheckMenuItem(hmenuPopup, ...
としてみましたが、同じでした。
再追記
GetMenuItemInfoやSetMenuItemInfoを利用しても、変化ありませんでした(エラーにもなりません)
void COcxCtrl::OnPopupCheck()
{
HMENU hmenu = ::LoadMenu((HINSTANCE)::GetWindowLong(this->GetSafeHwnd(), GWL_HINSTANCE), MAKEINTRESOURCE(IDR_MENU1));
HMENU hmenuPopup = ::GetSubMenu(hmenu, 0);
MENUITEMINFO menuItemInfo;
::ZeroMemory(&menuItemInfo, sizeof(menuItemInfo));
menuItemInfo.cbSize = sizeof(menuItemInfo);
menuItemInfo.fMask = MIIM_STATE;
DWORD d = ::GetMenuItemInfo(hmenu, IDM_POPUP_CHECK, false, &menuItemInfo);
DWORD e = ::GetLastError();
menuItemInfo.fMask = MIIM_STATE;
menuItemInfo.fState |= MF_CHECKED;
DWORD dw = ::SetMenuItemInfo(hmenu, IDM_POPUP_CHECK, false, &menuItemInfo);
DWORD ee = ::GetLastError();
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
check解決した方法
0
お陰様で、自己解決しました。
毎度 LoadMenu で生成をしてしまっていては、チェック状態は記憶されないようです。
ウインドウ生成時にLoadMenuしたハンドルを保持して、これを操作することで、うまくチェック状態を保持することが出来ました。
親ウインドウのポップアップメニューであれば、SetMenu でウインドウとメニューを結び付け、適宜 GetMenu 経由で操作できますが、子ウインドウ(コントロール)の場合 SetMenu は使えない(エラーコード 1436)ので、ハンドルをメンバー変数として保持することにしました。
WM_CREATE メッセージが飛んできたら LoadMenu でメニューを読み込んでハンドルをメンバー変数に保持、WM_DESTROY メッセージで DestroyMenu を呼び出してメニューハンドルを破棄、ポップアップメニュー表示などのときにはメンバー変数に保持しているハンドルを操作します。
class COcxCtrl : public COleControl
{
//...
HMENU m_hMenu = NULL;
//...
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
//...
}
int COcxCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
m_hMenu = ::LoadMenu((HINSTANCE)::GetWindowLong(this->GetSafeHwnd(), GWL_HINSTANCE), MAKEINTRESOURCE(IDR_MENU1));
return 0;
}
void COcxCtrl::OnDestroy()
{
if (m_hMenu != NULL)
::DestroyMenu(m_hMenu);
COleControl::OnDestroy();
}
void COcxCtrl::OnPopupCheck()
{
//...
MENUITEMINFO menuItemInfo;
::ZeroMemory(&menuItemInfo, sizeof(menuItemInfo));
menuItemInfo.cbSize = sizeof(menuItemInfo);
menuItemInfo.fMask = MIIM_STATE;
if (::GetMenuItemInfo(m_hMenu, IDM_POPUP_CHECK, false, &menuItemInfo))
{
if (menuItemInfo.fState & MF_CHECKED)
{
//...
menuItemInfo.fState &= ~MF_CHECKED;
}
else
{
//...
menuItemInfo.fState |= MF_CHECKED;
}
::SetMenuItemInfo(m_hMenu, IDM_POPUP_CHECK, false, &menuItemInfo);
}
//...
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
CheckMenuItemではなくSetMenuItemInfoを使ってみたらどうでしょうか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる