If the application supports more than one type of document, then the framework gets the names of the supported document types from the document templates and displays them in a list in the File New dialog box.
如上述,我在InitInstance里面new了两个CMultiDocTemplate,他们对应各自的view,frame,相同的doc,可是在程序开始的时候都会弹出一个对话框要我选择show哪一套frame(如引述),我想去掉它,然后框架出来时就是我想指定的哪一套template。望指教!谢!

解决方案 »

  1.   


    RE:  tyanpro (皮)
    1. 在CMDIApp::InitInstance()注意,第二个pDocTemplate不要AddDocTenplate.
    sample:
      CMultiDocTemplate* pDocTemplate;
    pDocTemplate = new CMultiDocTemplate(
    IDR_MDITYPE,
    RUNTIME_CLASS(CMDIDoc),
    RUNTIME_CLASS(CChildFrame), // custom MDI child frame
    RUNTIME_CLASS(CMDIView));
    AddDocTemplate(pDocTemplate); m_pTemplate2 = new CMultiDocTemplate(
    IDR_MDITYPE2,
    RUNTIME_CLASS(CMDIDoc2),
    RUNTIME_CLASS(CChildFrame2),
    RUNTIME_CLASS(CMDIView2)); // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
    return FALSE;
    m_pMainWnd = pMainFrame;
    2. 然后,在你需要改变DocTemplate时,再用以下方法(在CMainFrame中响应): CMDIChildWnd * pActiveChild = MDIGetActive();
    CDocument * pDocument;
    if(pActiveChild == NULL || 
                (pDocument = pActiveChild->GetActiveDocument () ) == NULL )
    {
            AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
        return;
    } CDocTemplate * pTemplate = ((CMDIApp*)AfxGetApp())->m_pTemplate2;  CFrameWnd * pFrame = pTemplate->CreateNewFrame(pDocument,pActiveChild);
    if(pFrame == NULL)
    {
        AfxMessageBox("Failed to create new frame\n");
        return;
    }
    pTemplate->InitialUpdateFrame(pFrame,pDocument);
    最后,推荐你仔细看看後俊杰的《深入浅出mfc》,里面有详细介绍。
      

  2.   

    在if (!ProcessShellCommand(cmdInfo))
    return FALSE;
    的前边加上这一段就可以了。
    if(cmdInfo.m_nShellCommand==CCommandLineInfo::FileNew)
    {
    cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing;
    }
      

  3.   

    据说这样也行,我没试:在初始化中,你会看到下列代码,把它们注解或删除那么对话框就不会出现了    // Parse command line for standard shell commands, DDE, file open
        /*CCommandLineInfo cmdInfo;
        ParseCommandLine(cmdInfo);    // Dispatch commands specified on the command line
        if (!ProcessShellCommand(cmdInfo))
            return FALSE;
        */
      

  4.   

    RE:guanjinke,qfly 
    二位的方法其实是一个效果!但是它并不能开始就初始化出我想要的一套frame!
    感谢freeshoot(巴蒂刘)指点,你的方法令我大开眼界!我会试一试的,
    不知道你看过BCMenu这个类的Demo没有,他没有用你说的这种方法,但是可以实现,我一时还没有找出为什么,望指点讨论
      

  5.   

    是的,不过我无意与guanjinke(纶巾客)兄重复,不知你有没有注意到回复时间相同,也就是说我回复时没有看到guanjinke(纶巾客)兄已回复。这里有一篇古老的文章,论及这方面,你可以参考在VC++ 中 使用MFC实现MDI界面 
       ● 吴 道 威   MDI (Multiple Document Interface) 是Windows 界 面 的 一 种 规 范, 它 建 立 多 个 窗 口 来 浏 览 文 档 数 据, 如Windows 中 的Program Manager 等 都 是 按MDI 规 范 实 现 的。 在 实 际 工 程 软 件 开 发 中, 许 多 程 序 员 将 其 作 为 一 种 实 现 多 窗 口 的 标 准 方 法。 微 软 基 础 类 库(Microsoft Foundation Class Library, 简 称MFC 库), 是 微 软 公 司 为 方 便Windows 程 序 开 发 所 提 供 的 一 个 功 能 强 大 的 通 用 类 库。MFC 的 核 心 是 以 类 的 形 式 封 装 了 大 量Windows API。 在 可 视 化 编 程 语 言VC++ 下 应 用MFC 是 目 前 开 发Windows 程 序 最 方 便 的 途 径 之 一。VC++ 提 供 的 各 种 开 发 工 具 如AppWizard、ClassWizard 和App Studio, 可 以 建 立 起 具 备 基 本 功 能 的Windows 框 架 程 序(Framework)。 而 程 序 员 所 需 要 做 的 工 作 就 是 将 自 己 特 有 的 代 码 填 入 到 框 架 程 序 中 去, 从 而 极 大 地 减 少 了 用 户 界 面 编 程 的 工 作 量, 加 快 了 开 发 速 度。 关 于MDI 的 标 准 开 发 方 法 可 参 考 一 般 的Windows 编 程 书 籍, 本 文 将 介 绍 利 用MFC 实 现MDI 界 面。   MFC 2.0 以 上 版 本 支 持“ 文 档/ 浏 览 视 窗”(Document/View) 结 构 模 式。 由 文 档 负 责 管 理 数 据, 浏 览 视 窗 负 责 数 据 显 示 及 与 用 户 的 交 互, 从 而 实 现 了 数 据 与 界 面 的 分 离, 使 整 个 程 序 设 计 更 具 规 范 化、 模 块 化。MFC 中,“ 文 档” 由 类CDocument 及 其 派 生 类 实 现( 简 称Doc 类);“ 浏 览 视 窗” 由 类CView 及 其 派 生 类 实 现 ( 简 称View 类)。 二 者 都 包 含 于 应 用 程 序 的 框 架 窗 口 中, 并 由 其 管 理。 使 用 单 文 档 时, 框 架 窗 口 由 类CFrameWnd 及 其 派 生 类 实 现; 使 用 多 文 档 时, 框 架 窗 口 是 利 用 类CMDIFrameWnd 和CMDIChildWnd 实 现。 由 文 档 模 板 将 文 档、 浏 览 窗 口 和 框 架 窗 口 三 者 联 系 起 来。    当 程 序 员 在App Wizard 的Option 选 项 中 选 择 Multiple Document Interface 时,MFC 构 架 程 序(Framework) 将 自 动 生 成 实 现MDI 基 本 功 能 的 代 码。 类CMDIFrameWnd 负 责 整 个 应 用 程 序 的 主 框 架 窗 口; 类CMDIChildWnd 实 现MDI 的 子 窗 口 框 架, 它 不 带 菜 单 项, 而 与 主 框 架 窗 口 共 享 菜 单。 主 框 架 窗 口 依 据 当 前 激 活 的 子 窗 口 自 动 更 换 菜 单 项。CView 则 负 责MDI 子 窗 口 客 户 区 中 显 示 的 具 体 内 容。 例 如,App Wizard 的 以M01 为Project 名 建 立 的 构 架 程 序(framework) 中 包 括 一 些 基 本 类: 主 框 架 窗 口CMainFrame: 派 生 自CMDIFrameWnd; 文 档CM01Doc : 派 生 自CDocument; 浏 览 窗 口CM01View: 派 生 自CView; 其 中CM01Doc、CM01View 和CMDIChildWnd 由 多 文 档 模 板CMultiDocTemplate 联 系 在 一 起。 在CM01App::InitInstance() 函 数 中 代 码 如 下:   BOOL CM01App::InitInstance()   {   ......    CMultiDocTemplate* pDocTemplate;    // CMultiDocTemplate 用 于MDI 文 档    pDocTemplate = new CMultiDocTemplate(    IDR_M01TYPE,// 资 源 标 识    RUNTIME_CLASS(CM01Doc),    // 文 档 类    RUNTIME_CLASS(CMDIChildWnd),    // 标 准MDI 子 窗 口 框 架    RUNTIME_CLASS(CM01View));    // 浏 览 视 窗 类    AddDocTemplate(pDocTemplate);    // 为 整 个 应 用 程 序 添 加 新 模 板   ......   }    此 时, 数 据Doc 类 仅 与 一 种View 类 相 关 联,MDI 每 个 子 窗 口 显 示 的 内 容 是 一 致 的。 如 果 用 户 希 望 不 同 的 子 窗 口 显 示 不 同 的 文 档, 则 需 要 分 别 建 立 新 的 资 源 项、 新 的 文 档 类、 新 的View 类, 并 且 用 新 模 板 将 他 们 与CMDIChildWnd 联 系 起 来 即 可。MFC 框 架 程 序 将 复 杂 的 消 息 发 送 和 接 收 机 制 隐 藏 起 来, 自 动 实 现 子 窗 口 的 调 度 安 排。 程 序 员 只 需 设 定 自 己 的 数 据, 并 在 各 个View 中 重 载OnDraw() 函 数, 完 成 所 需 的 绘 制。    然 而 在 实 际 开 发 应 用 程 序 中, 常 常 希 望 对 某 一 类 数 据 进 行 不 同 方 式 的 显 示, 既 可 观 察 数 值, 又 可 有 图 形 显 示。 这 就 要 求 同 一 种Doc 类 与 多 个View 类 相 关 联, 而 每 个View 类 对 应 一 个 不 同 的MDI 子 窗 口。CMultiDocTemplate 的 典 型 用 法 是 建 立 独 立 的 文 档 结 构 和View 对 象。 而 下 面CMultiDocTemplate 将 使 用 同 一 文 档 和 多 个View 类。   (1) 用ClassWizard 建 立 一 新 的View 类:CM02View。   (2) 建 立 新 模 板:   CMultiDocTemplate* pDocTemplate02=new CMultiDocTemplate(    IDR_M01TYPE, // 使 用 同 一 资 源    RUNTIME_CLASS(CM01Doc), // 同 一 文 档    RUNTIME_CLASS(CMDIChildWnd), // 标 准MDI 子 窗 口 框 架    RUNTIME_CLASS(CM02View)); // 新View    然 后 使 用CApp::AddDocTemplate 函 数 添 加 新 模 板。    如 果 此 时 仍 然 在CM01App::InitInstance() 函 数 中 添 加 新 模 板, 则 构 架 程 序 会 错 误 地 认 为 程 序 支 持 两 种 文 档 类 型, 从 而 在 编 译 产 生 的EXE 文 件 执 行 时 弹 出 对 话 框, 要 求 用 户 选 择 文 档 类 型。 而 实 际 上 两 种 文 档 类 型 是 一 样 的。    为 避 免 此 种 情 况, 可 使 用MFC 开 发 者 建 议 的 方 法: 在 前 例 情 况 下, 首 先, 应 在App Studio 中 将 字 串 资 源IDR_M01TYPE 复 制 为 一 个 新 字 串 资 源IDR_M02TYPE。 然 后, 删 去 字 串 资 源IDR_M02TYPE 中 第 二 个\n 后 的 字 符 串M01 Document( 该 字 串 即 为CDocTemplate::fileNewName 项)。 之 后, 用 新 资 源IDR_M02TYPE 来 建 立 第 二 个 模 板。 这 样 编 译 的EXE 文 件 将 不 会 弹 出 对 话 框。 在 研 究MFC 的 源 码 之 后, 发 现 之 所 以 弹 出 文 档 类 型 对 话 框, 是 由 于CM01App::InitInstance() 函 数 中 调 用 了OnFileNew() 函 数。OnFileNew() 函 数 检 查 文 档 模 板 数 量; 当 不 止 一 个 模 板 时, 则 弹 出 对 话 框; 待 用 户 选 择 之 后, 按 所 选 的 文 档 类 型 建 立MDI 窗 口。 由 于 删 去 了 第 二 个 模 板 的fileNewName 项, 无 法 显 示 文 档 类 型, 就 自 动 停 止 对 话 框, 而 将 第 一 种 类 型 作 为 缺 省 文 档 类 型 建 立MDI 窗 口。    在 工 程 应 用 程 序 中,OnFileNew() 函 数 一 般 只 在 程 序 初 始 化 时 调 用 一 次( 至 于 菜 单File |New 的 响 应, 用 户 可 接 管 处 理), 所 以 可 以 不 在CMyApp::InitInstance() 函 数 中 添 加 新 文 档 模 板, 躲 过OnFileNew() 函 数 的 检 查, 而 在 需 要 的 时 候 添 加 所 需 的 文 档 模 板, 建 立 新 的 子 窗 口。 这 样 既 避 免 了 文 档 类 型 对 话 框, 又 不 必 增 加 字 串 资 源。    一 种 简 单 的 例 子 如 下: 第 一 个 子 窗 口 仍 由 构 架 程 序 自 动 建 立; 设 定 一 个 新 的 菜 单 项“ 新 窗 口(NewWindow)”, 在CMainFrame 中 处 理 该 菜 单 消 息, 消 息 响 应 函 数 中 显 示 第 二 个 子 窗 口。   void CMainFrame::OnNewWindow()   {    // 添 加 新 的 文 档 模 板    static CMultiDocTemplate* pDocTemplate_New;    static BOOL bChildCreated=FALSE;    // 标 志, 新 窗 口 是 否 建 立; 如 已 建, 将 不 重 建    if(bChildCreated==FALSE)    {    pDocTemplate_New = new CMultiDocTemplate(    IDR_M01TYPE, // 使 用 同 一 资 源    RUNTIME_CLASS(CM01Doc),    RUNTIME_CLASS(CMDIChildWnd),    // 标 准MDI 子 窗 口 框 架    RUNTIME_CLASS(CM02View));    AfxGetApp()->AddDocTemplate(pdocTemplate_New);    // 创 建 新 的 子 窗 口    CMDIChildWnd* pMDIActive = MDIGetActive(); // 获 得 当 前 活 动 子 窗 口 的 指 针    CMpvDoc* pDoc = (CMpvDoc*)pMDIActive->GetActiveDocument(); // 获 得 文 档 指 针    CMDIChildWnd* pNewFrame=(CMDIChildWnd*) (pDocTemplate_New ->CreateNewFrame(pDoc, NULL));   // 建 立 新 的 框 架 窗 口    if (pNewFrame == NULL)    {    AfxMessageBox(" 新 窗 口 不 能 建 立",MB_OK,0);    return; // not created    }   pDocTemplate_New ->InitialUpdateFrame(pNewFrame, pDoc); // 显 示 窗 口   MDITile(MDITILE_HORIZONTAL); // 将 多 个 窗 口 平 铺   bChildCreated=TRUE;   }    不 同 的View 在OnDraw() 函 数 中 有 各 自 的 绘 制 代 码, 当 数 据 更 新 时, 只 要 调 用CDocument::UpdateAllViews() 函 数, 即 可 更 新 全 部 的MDI 子 窗 口。