qq_41945416 2025-10-31 22:08 采纳率: 90.6%
浏览 4
已结题

关于mfc多文档编程的问题

img

如图所示,这是mfc多文档编程的演示程序 打红框的这个标题栏是由谁负责?

1.1 这个窗口是非模态的 可为什么我看不到向导写的 打开非模态窗口的那些代码呢?
1.2 这些子窗口 包括标题栏,由哪个类负责?CDemoView吗? 还是 CChildFrame? 还是 CMainFrame?
1.3 虽然我没有找到向导写的 打开非模态窗口的代码,但是我意外发现 菜单栏 新建窗口的 ID 为 ID_WINDOW_NEW,能多次打开子窗口 和这个有关系吗 ? 按道理来说应该像button一样 一个id对应一个消息处理函数才能正常工作,可为什么这里只需要填对微软要求填写的id,不用映射消息处理函数也能正常打开子窗口呢?就像按钮id IDOK和IDCANCEL一样,为什么不用映射消息处理函数,只要填对id也能正常工作?微软这是怎么做到的?我们也可以这样做吗?
1.4 如果我要用常规的 在按钮button里写代码的方式 打开这样的子窗口,代码应该怎么写?

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-31 22:12
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:别害怕犯错,错误是成长的必经之路。
    .

    根据你的问题,我来逐一解答MFC多文档编程中的相关问题:

    1.1 红框标题栏的负责类

    红框中的标题栏实际上是由CChildFrame类负责的。在多文档界面(MDI)中:

    • CMainFrame:负责主框架窗口,包含菜单栏、工具栏、状态栏
    • CChildFrame:负责子窗口框架,包含子窗口的标题栏、系统菜单、最大化/最小化按钮等
    • CDemoView:负责视图区域的内容显示

    1.2 非模态窗口代码的隐藏机制

    你看不到显式的非模态窗口创建代码,是因为MFC框架在内部自动处理了这些操作。具体机制如下:

    // MFC框架内部的处理流程大致如下:
    BOOL CWinApp::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
    {
        // 当检测到标准命令ID时,框架会自动处理
        if (nID == ID_WINDOW_NEW) {
            CMDIFrameWnd* pFrame = (CMDIFrameWnd*)AfxGetMainWnd();
            pFrame->MDICreate(); // 内部创建新的MDI子窗口
            return TRUE;
        }
    }
    

    1.3 标准命令ID的自动处理机制

    为什么ID_WINDOW_NEW不需要显式消息映射?

    这是因为MFC框架内置了对标准命令ID的默认处理:

    // 在MFC框架中预定义的标准命令处理
    BEGIN_MESSAGE_MAP(CMDIFrameWnd, CFrameWnd)
        ON_COMMAND(ID_WINDOW_NEW, &CMDIFrameWnd::OnWindowNew)
        ON_COMMAND(ID_WINDOW_CASCADE, &CMDIFrameWnd::OnWindowCascade)
        ON_COMMAND(ID_WINDOW_TILE_HORZ, &CMDIFrameWnd::OnWindowTileHorz)
        // ... 其他标准窗口命令
    END_MESSAGE_MAP()
    

    我们也可以实现类似机制:

    // 1. 定义自定义命令ID
    #define ID_MY_CUSTOM_COMMAND 0x8000
    
    
    // 2. 在消息映射中添加默认处理
    BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
        ON_COMMAND(ID_MY_CUSTOM_COMMAND, &CMyFrame::OnMyCustomCommand)
    END_MESSAGE_MAP()
    
    
    // 3. 实现默认处理函数
    void CMyFrame::OnMyCustomCommand()
    {
        // 自定义的默认处理逻辑
        AfxMessageBox(_T("自定义命令被执行"));
    }
    

    1.4 在按钮中手动创建子窗口的代码

    如果你想在按钮点击事件中手动创建MDI子窗口,可以这样写:

    // 在某个按钮的点击事件处理函数中
    void CYourView::OnButtonCreateWindow()
    {
        // 获取主框架窗口
        CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
        if (!pMainFrame) return;
        
        // 获取MDIClient窗口
        CMDIClientWnd* pMDIClient = pMainFrame->GetMDIClient();
        if (!pMDIClient) return;
        
        // 创建文档模板(通常已经在App类的InitInstance中注册)
        CMultiDocTemplate* pDocTemplate = ((CYourApp*)AfxGetApp())->m_pYourDocTemplate;
        
        // 创建新的文档、框架窗口和视图
        CDocument* pDoc = pDocTemplate->CreateNewDocument();
        if (pDoc) {
            CFrameWnd* pFrame = pDocTemplate->CreateNewFrame(pDoc, NULL);
            if (pFrame) {
                pDocTemplate->InitialUpdateFrame(pFrame, pDoc);
            }
        }
    }
    

    或者更简单的方式:

    // 直接发送命令消息模拟菜单操作
    void CYourView::OnButtonCreateWindow()
    {
        // 直接触发ID_WINDOW_NEW命令
        AfxGetMainWnd()->SendMessage(WM_COMMAND, ID_WINDOW_NEW);
    }
    

    总结:

    • MDI子窗口的标题栏由CChildFrame负责
    • 标准命令ID由MFC框架自动处理,无需显式映射
    • 可以通过发送标准命令或手动创建文档/框架来打开新窗口
    • 自定义标准命令需要继承框架类并重写消息映射
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月9日
  • 已采纳回答 11月1日
  • 创建了问题 10月31日