MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单
  5Z6Aj0LQwRjK 2023年12月10日 47 0


更改快捷键后不生效的问题

问题原因: 创建项目时选择 “使用菜单栏和工具栏”

MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单_菜单栏

使用这种方式创建的应用程序,会将其应用信息,如菜单等资源记录在注册表中,每次启动时从注册表加载,会忽略代码中的修改,导致出现在程序中修改了菜单却无效的问题。

如何区分项目是使用哪种菜单? “经典菜单"还是"菜单和工具栏”?

看APP继承类,“经典菜单”继承CWinApp

MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单_菜单栏_02

“菜单和工具栏”继承“”CWinAppEx

MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单_工具栏_03

解决办法:
在App类中添加: ExitInstance 实现,如1

int CMFCApplication1App::ExitInstance() {
    AfxOleTerm(FALSE);
    this->CleanState();       //清空注册表信息  
    return CWinAppEx::ExitInstance();
}

上下文菜单

(经典菜单)

上下文菜单,或者称之为"右键菜单",这种菜单一般是在单击鼠标右键时弹出。制作弹出菜单步骤:

新建菜单资源

MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单_App_04

在应用初始化时加载菜单资源

BOOL Cdraw3View::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: 在此处通过修改
    //  CREATESTRUCT cs 来修改窗口类或样式
    m_DrawMenu.LoadMenu(IDR_MENU1);
    return CView::PreCreateWindow(cs);
}

在点击右键时显示菜单

void Cdraw3View::OnRButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CMenu* pPopup = m_DrawMenu.GetSubMenu(0);
    //转换成屏幕坐标(反方向也可以转换)
    ClientToScreen(&point);
    pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTALIGN, point.x, point.y, this);

    CView::OnRButtonDown(nFlags, point);
}

知识点:
1.屏幕坐标和客户区坐标

(菜单和工具栏)

新建项目时“菜单和工具栏”

MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单_菜单栏_05

app类中的初始化

BOOL CcontentMenuApp::InitInstance(){
    ...
    InitContextMenuManager();
    ...
}

app类的PreLoadState,加载菜单资源

void CcontentMenuApp::PreLoadState()
{
    BOOL bNameValid;
    CString strName;
    bNameValid = strName.LoadString(IDS_EDIT_MENU);
    ASSERT(bNameValid);
    GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
}

显示弹出菜单

void CcontentMenuView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
    theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}

通过代码修改菜单栏

"经典菜单"类型项目,使用代码修改菜单栏(增加,插入,删除)

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){
    ...
    CMenu menu;
    menu.CreateMenu();
    menu.AppendMenu(MF_STRING, 111, _T("Hello"));
    menu.AppendMenu(MF_STRING, 112, _T("World"));
    menu.AppendMenu(MF_STRING, 113, _T("Other"));

    GetMenu()->AppendMenu(MF_POPUP, (UINT)menu.m_hMenu, _T("Test"));
    menu.Detach();
    ...
}

"使用菜单和工具栏"类型项目,修改使用代码修改菜单栏

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){
    ...
    CMenu menu;
    menu.CreatePopupMenu();
    menu.AppendMenu(MF_STRING, ID_MSG_LINE, _T("画线"));
    menu.AppendMenu(MF_STRING, ID_MSG_RECT, _T("画矩形"));
    menu.AppendMenu(MF_STRING, ID_MSG_ELLIPSE, _T("画椭圆"));
    menu.AppendMenu(MF_STRING, ID_MSG_PEN, _T("画笔"));

    CMenu* mu = CMenu::FromHandle(GetMenuBar()->GetDefaultMenu());
    mu->AppendMenu(MF_POPUP, (UINT)menu.m_hMenu, _T("Test"));
    menu.Detach();
    ...
}

知识点: 窗口类,窗口对象,窗口
窗口类: C++类,如CWnd, CView
窗口对象: 由窗口类生成的C++对象,如CWnd对象,CView对象等
窗口: Win32底层结构:WNDCLASS, 大多用HWND(窗口句柄)表示

关系:
1.每个窗口对象都包含一个窗口
2.窗口对象使用Create方法创建窗口,在Create方法中将窗口对象与窗口进行绑定
3.窗口对象与窗口的生命周期不同,并不同生共死

MFC框架理论

关键类

CWinApp: MFC应用程序抽象,管理Document Template

CFrameWnd: 框架窗口,负责创建应用主窗口,含标题栏,菜单栏,工具栏,状态栏等

CView: 负责展示应用数据,View其实是一个没有边框的窗口, 客户区

CDocument: 负责存储应用数据

CDocTemplate:Document Template: 隐藏Boss, 负责管理MainFrame,View和Document

MFC---更改快捷键/菜单后不生效的问题与通过代码修改菜单_mfc_06

BOOL Cdraw3App::InitInstance(){
    ...
    // 注册应用程序的文档模板。  文档模板
    // 将用作文档、框架窗口和视图之间的连接
    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(Cdraw3Doc),
        RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
        RUNTIME_CLASS(Cdraw3View));
    if (!pDocTemplate)
        return FALSE;
    AddDocTemplate(pDocTemplate);
    ...
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月10日 0

暂无评论

推荐阅读
5Z6Aj0LQwRjK