==================================声明==================================

本文原创,转载在正文中显要的注明作者和出处,并保证文章的完整性。

未经作者同意请勿修改(包括本声明),保留法律追究的权利。

未经作者同意请勿用于出版、印刷或学术引用。

本文不定期修正完善,为保证内容正确,建议移步原文处阅读。

本文链接:http://www.cnblogs.com/wlsandwho/p/4282242.html

=======================================================================

水平太低了,在青岛找个称心的工作,难——真的是不开空调啊,猎头怎么不信我呢!(这个梗请点我点我

这么晚了,还是写个博客看会儿书再睡觉吧,人丑就要多……

=======================================================================

先创建一个MFC程序。

工程创建完后,编译运行一下,看看默认是什么样子。如下图。

点击窗口-新建窗口(N),效果如图:

可以看到,两个窗口都是一样的。

=======================================================================

下面,就要开始魔改了。

=======================================================================

添加一个对话框资源,ID命名为IDD_FORMVIEW1。

给刚添加的资源添加类,CFV1,其基类为CFormView。

添加对IDC_BUTTON1的消息处理函数。

  1. void CFV1::OnBnClickedButton1()
  2. {
  3. // TODO: 在此添加控件通知处理程序代码
  4. MessageBox(TEXT(""),TEXT("CFV1"),MB_OK);
  5. }

同样的步骤,再添加CFV2和对IDD_FORMVIEW2中IDC_BUTTON1的消息处理函数。

  1. void CFV2::OnBnClickedButton1()
  2. {
  3. // TODO: 在此添加控件通知处理程序代码
  4. MessageBox(TEXT(""),TEXT("CFV2"),MB_OK);
  5. }

在TestMDIWLS.h中添加头文件

  1. #include "FV1.h"
  2. #include "FV2.h"

=======================================================================

到这里,让我们暂停一下。下面要进入重点了。

=======================================================================

对模板的注册是在CTestMDIWLSApp::InitInstance中实现的,下面是MFC的MDI中原有的代码。

  1. // CTestMDIWLSApp 初始化
  2.  
  3. BOOL CTestMDIWLSApp::InitInstance()
  4. {
  5. // 如果一个运行在 Windows XP 上的应用程序清单指定要
  6. // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
  7. //则需要 InitCommonControlsEx()。否则,将无法创建窗口。
  8. INITCOMMONCONTROLSEX InitCtrls;
  9. InitCtrls.dwSize = sizeof(InitCtrls);
  10. // 将它设置为包括所有要在应用程序中使用的
  11. // 公共控件类。
  12. InitCtrls.dwICC = ICC_WIN95_CLASSES;
  13. InitCommonControlsEx(&InitCtrls);
  14.  
  15. CWinAppEx::InitInstance();
  16.  
  17. // 初始化 OLE 库
  18. if (!AfxOleInit())
  19. {
  20. AfxMessageBox(IDP_OLE_INIT_FAILED);
  21. return FALSE;
  22. }
  23.  
  24. AfxEnableControlContainer();
  25.  
  26. EnableTaskbarInteraction();
  27.  
  28. // 使用 RichEdit 控件需要 AfxInitRichEdit2()
  29. // AfxInitRichEdit2();
  30.  
  31. // 标准初始化
  32. // 如果未使用这些功能并希望减小
  33. // 最终可执行文件的大小,则应移除下列
  34. // 不需要的特定初始化例程
  35. // 更改用于存储设置的注册表项
  36. // TODO: 应适当修改该字符串,
  37. // 例如修改为公司或组织名
  38. SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
  39. LoadStdProfileSettings(); // 加载标准 INI 文件选项(包括 MRU)
  40.  
  41. InitContextMenuManager();
  42.  
  43. InitKeyboardManager();
  44.  
  45. InitTooltipManager();
  46. CMFCToolTipInfo ttParams;
  47. ttParams.m_bVislManagerTheme = TRUE;
  48. theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
  49. RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
  50.  
  51. // 注册应用程序的文档模板。文档模板
  52. // 将用作文档、框架窗口和视图之间的连接
  53. CMultiDocTemplate* pDocTemplate;
  54. pDocTemplate = new CMultiDocTemplate(IDR_TestMDIWLSTYPE,
  55. RUNTIME_CLASS(CTestMDIWLSDoc),
  56. RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
  57. RUNTIME_CLASS(CTestMDIWLSView));
  58. if (!pDocTemplate)
  59. return FALSE;
  60. AddDocTemplate(pDocTemplate);
  61.  
  62. // 创建主 MDI 框架窗口
  63. CMainFrame* pMainFrame = new CMainFrame;
  64. if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
  65. {
  66. delete pMainFrame;
  67. return FALSE;
  68. }
  69. m_pMainWnd = pMainFrame;
  70. // 仅当具有后缀时才调用 DragAcceptFiles
  71. // 在 MDI 应用程序中,这应在设置 m_pMainWnd 之后立即发生
  72.  
  73. // 分析标准 shell 命令、DDE、打开文件操作的命令行
  74. CCommandLineInfo cmdInfo;
  75. ParseCommandLine(cmdInfo);
  76.  
  77. // 调度在命令行中指定的命令。如果
  78. // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
  79. if (!ProcessShellCommand(cmdInfo))
  80. return FALSE;
  81. // 主窗口已初始化,因此显示它并对其进行更新
  82. pMainFrame->ShowWindow(m_nCmdShow);
  83. pMainFrame->UpdateWindow();
  84.  
  85. return TRUE;
  86. }

注意这一块代码:(我手工对齐了一下)

  1. // 注册应用程序的文档模板。文档模板
  2. // 将用作文档、框架窗口和视图之间的连接
  3. CMultiDocTemplate* pDocTemplate;
  4. pDocTemplate = new CMultiDocTemplate(IDR_TestMDIWLSTYPE,
  5.                     RUNTIME_CLASS(CTestMDIWLSDoc),
  6.                     RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
  7.                     RUNTIME_CLASS(CTestMDIWLSView));
  8. if (!pDocTemplate)
  9. return FALSE;
  10. AddDocTemplate(pDocTemplate);

这里我们需要做的就是new一个自己新建的CFV,然后把它加入文档模板。

所以先再分析下CMultiDocTemplate(...)函数

  1. CMultiDocTemplate(
  2. UINT nIDResource,
  3. CRuntimeClass* pDocClass,
  4. CRuntimeClass* pFrameClass,
  5. CRuntimeClass* pViewClass
  6. );

后三个参数一目了然,形参自注释。

要注意的是第一个参数:UINT nIDResource

MSDN中这样说的:

  1. nIDResource
  2.  
  3. Specifies the ID of the resources used with the document type. This may include menu, icon, accelerator table, and string resources.
  4.  
  5. The string resource consists of up to seven substrings separated by the '\n' character (the '\n' character is needed as a place holder if a substring is not included; however, trailing '\n' characters are not necessary); these substrings describe the document type. For information on the substrings, see CDocTemplate::GetDocString. This string resource is found in the application's resource file. For example:
  6.  
  7. // MYCALC.RC
  8.  
  9. STRINGTABLE PRELOAD DISCARDABLE
  10.  
  11. BEGIN
  12.  
  13. IDR_SHEETTYPE "\nSheet\nWorksheet\nWorksheets (*.myc)\n.myc\n MyCalcSheet\nMyCalc Worksheet"
  14.  
  15. END
  16.  
  17. Note that the string begins with a '\n' character; this is because the first substring is not used for MDI applications and so is not included. You can edit this string using the string editor; the entire string appears as a single entry in the String Editor, not as seven separate entries.
  18.  
  19. For more information about these resource types, see Resource Editors.

在这里最简单的方式就是在IDE里查找原来的IDR_TestMDIWLSTYPE所对应的字符串,然后模仿着修改。

我尝试了下直接用Sting_Table添加,并修改了一个字符串的部分字段(AAAA和BBBB),另一个未变,以便观察效果。(大晚上的我要是愿意看英文我早就去看美剧了。)

下面是在rc文件中的编码。(新手不要手工编辑,相关资料参见MSDN和罗云彬的汇编书,PS:典藏版亚马逊有售哦!)

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // String Table
  4. //
  5.  
  6. STRINGTABLE
  7. BEGIN
  8. IDP_OLE_INIT_FAILED "OLE 初始化失败。请确保 OLE 库是正确的版本。"
  9. IDR_CFV1_TYPE "\nAAAA\nBBBB\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  10. IDR_CFV2_TYPE "\nTestMDIWLS\nTestMDIWLS\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  11. END
  12.  
  13. STRINGTABLE
  14. BEGIN
  15. IDR_MAINFRAME "TestMDIWLS"
  16. IDR_TestMDIWLSTYPE "\nTestMDIWLS\nTestMDIWLS\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  17. ID_WINDOW_MANAGER "窗口(&W)..."
  18. END
  19.  
  20. STRINGTABLE
  21. BEGIN
  22. AFX_IDS_APP_TITLE "TestMDIWLS"
  23. AFX_IDS_IDLEMESSAGE "就绪"
  24. END

可以看到13-18行是MFC自带的,我们手工添加的是7-11中的9、10两行。

根本就没有MSDN上面说的那个PRELOAD DISCARDABLE。看来不预加载也没问题啊。当然这是猜测,可能是资源太小了。

=======================================================================

看完刚才的资料,可以尝试着添加文档模板了。当然要是有闲心情——现在是深夜,不管你有没有,我反正没有——可以看下

https://msdn.microsoft.com/zh-cn/library/2b4xctyw%28v=vs.100%29.aspx和https://msdn.microsoft.com/zh-cn/library/feh4ww6k%28v=vs.100%29.aspx

=======================================================================

现在我们添加模板文档。先添加一个试试。

  1. // 注册应用程序的文档模板。文档模板
  2. // 将用作文档、框架窗口和视图之间的连接
  3. CMultiDocTemplate* pDocTemplate;
  4. pDocTemplate = new CMultiDocTemplate(IDR_TestMDIWLSTYPE,
  5. RUNTIME_CLASS(CTestMDIWLSDoc),
  6. RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
  7. RUNTIME_CLASS(CTestMDIWLSView));
  8. if (!pDocTemplate)
  9. return FALSE;
  10. AddDocTemplate(pDocTemplate);
  11.  
  12. //////////////////////////////////////////////////////////////////////////
  13. //by wls 20150209 22:17:50
  14. pDocTemplate = new CMultiDocTemplate(IDR_CFV1_TYPE,
  15. RUNTIME_CLASS(CTestMDIWLSDoc),
  16. RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
  17. RUNTIME_CLASS(CFV1));
  18. if (!pDocTemplate)
  19. return FALSE;
  20. AddDocTemplate(pDocTemplate);
  21.  
  22. //////////////////////////////////////////////////////////////////////////

编译、运行,效果:

注意这里是TestMDIWLS和BBBB。

点击BBBB确定后:

这里是AAAA1。

点击按钮1后:

现在就可以更改String_Table里的东西了。我手工改,毕竟编辑器有点蹩脚。

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // String Table
  4. //
  5.  
  6. STRINGTABLE
  7. BEGIN
  8. IDP_OLE_INIT_FAILED "OLE 初始化失败。请确保 OLE 库是正确的版本。"
  9. IDR_CFV1_TYPE "\nCFV1的FormView视图\nCFV1\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  10. IDR_CFV2_TYPE "\nCFV2的FormView视图\nCFV2\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  11. END

再添加上CFV2:

  1. //////////////////////////////////////////////////////////////////////////
  2. //by wls 20150209 22:17:50
  3. pDocTemplate = new CMultiDocTemplate(IDR_CFV1_TYPE,
  4. RUNTIME_CLASS(CTestMDIWLSDoc),
  5. RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
  6. RUNTIME_CLASS(CFV1));
  7. if (!pDocTemplate)
  8. return FALSE;
  9. AddDocTemplate(pDocTemplate);
  10.  
  11. pDocTemplate = new CMultiDocTemplate(IDR_CFV2_TYPE,
  12. RUNTIME_CLASS(CTestMDIWLSDoc),
  13. RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
  14. RUNTIME_CLASS(CFV2));
  15. if (!pDocTemplate)
  16. return FALSE;
  17. AddDocTemplate(pDocTemplate);
  18.  
  19. //////////////////////////////////////////////////////////////////////////

编译运行:

点击CFV1后确定:

点击新建,点击CFV2后确定:

发现确实是创建了2个模板。

=======================================================================

现在问题来了,如何让程序一开始运行时,就打开了2个模板?毕竟让用户自己手工点击,99.999%是会有问题的。

=======================================================================

让我们来回忆一下,我们是如何创建模板窗口的?第一个是程序默认给出的选择框。没错。

那第二个呢?第二个是我们手工点击的新建!而且出来的是一模一样的选择框!

现在我们要做的就是先看看这个点击新建的响应函数是怎样的。

=======================================================================

下面是MDI中默认的响应函数的映射宏:

  1. // CTestMDIWLSApp
  2.  
  3. BEGIN_MESSAGE_MAP(CTestMDIWLSApp, CWinAppEx)
  4. ON_COMMAND(ID_APP_ABOUT, &CTestMDIWLSApp::OnAppAbout)
  5. // 基于文件的标准文档命令
  6. ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
  7. ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
  8. // 标准打印设置命令
  9. ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
  10. END_MESSAGE_MAP()

可以看到第6行:

  1. ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)

使用的是CWinAppEx的OnFileNew函数。显然MFC框架的代码是最好不修改的,只能自己模仿CWinAppEx的OnFileNew函数写一个自己的实现,姑且叫OnFileNewWLS吧。

在动手前,先看看OnFileNew是如何实现的:

  1. /////////////////////////////////////////////////////////////////////////////
  2. // WinApp features for new and open
  3.  
  4. void CWinApp::OnFileNew()
  5. {
  6. if (m_pDocManager != NULL)
  7. m_pDocManager->OnFileNew();
  8. }

那CDocManager的实现呢?如下:

  1. void CDocManager::OnFileNew()
  2. {
  3. if (m_templateList.IsEmpty())
  4. {
  5. TRACE(traceAppMsg, , "Error: no document templates registered with CWinApp.\n");
  6. AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
  7. return;
  8. }
  9.  
  10. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
  11. if (m_templateList.GetCount() > )
  12. {
  13. // more than one document template to choose from
  14. // bring up dialog prompting user
  15. CNewTypeDlg dlg(&m_templateList);
  16. INT_PTR nID = dlg.DoModal();
  17. if (nID == IDOK)
  18. pTemplate = dlg.m_pSelectedTemplate;
  19. else
  20. return; // none - cancel operation
  21. }
  22.  
  23. ASSERT(pTemplate != NULL);
  24. ASSERT_KINDOF(CDocTemplate, pTemplate);
  25.  
  26. pTemplate->OpenDocumentFile(NULL);
  27. // if returns NULL, the user has already been alerted
  28. }

看完了这些,我们就知道如何实现自己的OnFileNewWLS了,这是我的代码,仅供参考。

  1. void CTestMDIWLSApp::OnFileNewWLS()
  2. {
  3. CDocTemplate* pTemplate = NULL;
  4.  
  5. POSITION pos = GetFirstDocTemplatePosition();
  6. while(pos)
  7. {
  8. pTemplate = GetNextDocTemplate(pos);
  9.  
  10. ASSERT(pTemplate != NULL);
  11. ASSERT_KINDOF(CDocTemplate, pTemplate);
  12.  
  13. pTemplate->OpenDocumentFile(NULL);
  14. }
  15. }

不要忘了修改映射宏。

  1. // CTestMDIWLSApp
  2.  
  3. BEGIN_MESSAGE_MAP(CTestMDIWLSApp, CWinAppEx)
  4. ON_COMMAND(ID_APP_ABOUT, &CTestMDIWLSApp::OnAppAbout)
  5. // 基于文件的标准文档命令
  6. //ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
  7. ON_COMMAND(ID_FILE_NEW, &CTestMDIWLSApp::OnFileNewWLS)
  8. ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
  9. // 标准打印设置命令
  10. ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
  11. END_MESSAGE_MAP()

编译链接看效果:

注意到三个模板都实现了,但是界面有卡顿。

是时候表演真正的记性了!

手工修改String_Table。拆分第一个。添加PRELOAD DISCARDABLE。

  1. STRINGTABLE
  2. BEGIN
  3. IDP_OLE_INIT_FAILED "OLE 初始化失败。请确保 OLE 库是正确的版本。"
  4. END
  5.  
  6. STRINGTABLE PRELOAD DISCARDABLE
  7. BEGIN
  8. IDR_TestMDIWLSTYPE "\nTestMDIWLS\nTestMDIWLS\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  9. IDR_CFV1_TYPE "\nCFV1的FormView视图\nCFV1\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  10. IDR_CFV2_TYPE "\nCFV2的FormView视图\nCFV2\n\n\nTestMDIWLS.Document\nTestMDIWLS.Document"
  11. END
  12.  
  13. STRINGTABLE
  14. BEGIN
  15. IDR_MAINFRAME "TestMDIWLS"
  16. ID_WINDOW_MANAGER "窗口(&W)..."
  17. END

可能是心理效果,我感觉略微快了那么一点点。(处女座请自重。)

=======================================================================

下面屏蔽各种新建按钮,防止创建过多的模板视图。

更改之前的OnFileNewWLS代码,利用局部Static变量。

  1. void CTestMDIWLSApp::OnFileNewWLS()
  2. {
  3. static BOOL bNew=FALSE;
  4.  
  5. if (bNew==FALSE)
  6. {
  7. bNew=TRUE;
  8.  
  9. CDocTemplate* pTemplate = NULL;
  10.  
  11. POSITION pos = GetFirstDocTemplatePosition();
  12. while(pos)
  13. {
  14. pTemplate = GetNextDocTemplate(pos);
  15.  
  16. ASSERT(pTemplate != NULL);
  17. ASSERT_KINDOF(CDocTemplate, pTemplate);
  18.  
  19. pTemplate->OpenDocumentFile(NULL);
  20. }
  21. }
  22. }

下面要屏蔽新建窗口按钮

在rc文件中有这么一行

  1. ID_WINDOW_NEW "为活动文档打开另一个窗口\n新建窗口"

所以需要屏蔽的就是对ID_WINDOW_NEW的响应,所以添加第10行代码,重写自己的响应函数。

  1. // CMainFrame
  2.  
  3. IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWndEx)
  4.  
  5. BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
  6. ON_WM_CREATE()
  7. ON_COMMAND(ID_WINDOW_MANAGER, &CMainFrame::OnWindowManager)
  8. ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
  9. ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
  10. ON_COMMAND(ID_WINDOW_NEW,&CMainFrame::OnWindowNewWLS)
  11. END_MESSAGE_MAP()

OnWindowsWLS的实现:

  1. void CMainFrame::OnWindowNewWLS()
  2. {
  3. //no op
  4. }

现在已经能够在运行时一次性创建3个视图,并且不再创建额外的视图。

=======================================================================

既然能且只能创建3个视图,那么就不需要在选项卡上显示表示实例数目的阿拉伯字母了。

  1. BOOL CTestMDIWLSDoc::OnNewDocument()
  2. {
  3. if (!CDocument::OnNewDocument())
  4. return FALSE;
  5.  
  6. // TODO: 在此添加重新初始化代码
  7. // (SDI 文档将重用该文档)
  8. CString strTitle=GetTitle();
  9. strTitle=strTitle.Left(strTitle.GetLength()-);
  10. SetTitle(strTitle);
  11.  
  12. return TRUE;
  13. }

效果:

=======================================================================

下面要做的就是屏蔽彩色选项卡的关闭按钮。

那么这个一直被我称为选项卡/标签页的东西到底是什么呢?使用Spy++查看下。

显示的是TabWnd,那么是一个类似Tab窗口的东西。这些都在CMainFrame::OnCreate里有初始化设置。

先看看MDI原有的代码:

  1. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2. {
  3. if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -)
  4. return -;
  5.  
  6. BOOL bNameValid;
  7. // 基于持久值设置视觉管理器和样式
  8. OnApplicationLook(theApp.m_nAppLook);
  9.  
  10. CMDITabInfo mdiTabParams;
  11. mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // 其他可用样式...
  12. mdiTabParams.m_bActiveTabCloseButton = TRUE; // 设置为 FALSE 会将关闭按钮放置在选项卡区域的右侧
  13. mdiTabParams.m_bTabIcons = FALSE; // 设置为 TRUE 将在 MDI 选项卡上启用文档图标
  14. mdiTabParams.m_bAutoColor = TRUE; // 设置为 FALSE 将禁用 MDI 选项卡的自动着色
  15. mdiTabParams.m_bDocumentMenu = TRUE; // 在选项卡区域的右边缘启用文档菜单
  16. EnableMDITabbedGroups(TRUE, mdiTabParams);
  17.  
  18. m_wndRibbonBar.Create(this);
  19. m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
  20.  
  21. if (!m_wndStatusBar.Create(this))
  22. {
  23. TRACE0("未能创建状态栏\n");
  24. return -; // 未能创建
  25. }
  26.  
  27. CString strTitlePane1;
  28. CString strTitlePane2;
  29. bNameValid = strTitlePane1.LoadString(IDS_STATUS_PANE1);
  30. ASSERT(bNameValid);
  31. bNameValid = strTitlePane2.LoadString(IDS_STATUS_PANE2);
  32. ASSERT(bNameValid);
  33. m_wndStatusBar.AddElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE1, strTitlePane1, TRUE), strTitlePane1);
  34. m_wndStatusBar.AddExtendedElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE2, strTitlePane2, TRUE), strTitlePane2);
  35.  
  36. // 启用 Visual Studio 2005 样式停靠窗口行为
  37. CDockingManager::SetDockingMode(DT_SMART);
  38. // 启用 Visual Studio 2005 样式停靠窗口自动隐藏行为
  39. EnableAutoHidePanes(CBRS_ALIGN_ANY);
  40.  
  41. // 启用增强的窗口管理对话框
  42. EnableWindowsDialog(ID_WINDOW_MANAGER, ID_WINDOW_MANAGER, TRUE);
  43.  
  44. // 将文档名和应用程序名称在窗口标题栏上的顺序进行交换。这
  45. // 将改进任务栏的可用性,因为显示的文档名带有缩略图。
  46. ModifyStyle(, FWS_PREFIXTITLE);
  47.  
  48. return ;
  49. }

没错,就是CMDITabInfo!找到她了!

10-16是对彩色的选项卡进行的设置。想要屏蔽关闭按钮,要修改为:

  1. CMDITabInfo mdiTabParams;
  2. mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // 其他可用样式...
  3. //mdiTabParams.m_bActiveTabCloseButton = TRUE; // 设置为 FALSE 会将关闭按钮放置在选项卡区域的右侧
  4. mdiTabParams.m_bTabCloseButton=FALSE;
  5. mdiTabParams.m_bTabIcons = FALSE; // 设置为 TRUE 将在 MDI 选项卡上启用文档图标
  6. mdiTabParams.m_bAutoColor = TRUE; // 设置为 FALSE 将禁用 MDI 选项卡的自动着色
  7. mdiTabParams.m_bDocumentMenu = TRUE; // 在选项卡区域的右边缘启用文档菜单
  8. EnableMDITabbedGroups(TRUE, mdiTabParams);

这样,就完成了。

=======================================================================

网上有关禁用MDI选项卡关闭按钮的文章,大多抄袭自MSDN的这篇文档http://support.microsoft.com/kb/201553/zh-cn

但是,不适用于VS2010下使用Office风格的MDI程序——该文档只更新到2006年11月21日。

=======================================================================

本文一步一步的解析实现,故暂不提供示例工程源代码。

魔改——MFC MDI程序 定制 文档模板 运行时全部打开 禁用关闭按钮的更多相关文章

  1. 魔改——MFC SDI程序 转换为 MDI程序

    ==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...

  2. 1、创建MFC应用程序——单个文档

    文件——新建——项目——MFC应用程序 运行即可. [菜单栏单击事件] 视图——其他窗口——资源视图,双击Menu中的IDR_MAINFRAM,打开菜单栏.在主菜单栏输入“显示你好”. “显示你好”处 ...

  3. permission 文档 翻译 运行时权限

    文档位置:API24/guide/topics/security/permissions.html  System Permissions 系统权限 Android is a privilege-se ...

  4. VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)

    VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)-软件开发-鸡啄米 http://www.jizhuomi.com/software/141.html   上一讲中讲了VS20 ...

  5. C++MFC编程笔记day05 文档类-单文档和多文档应用程序

    文档类 1 相关类    CDocument类-父类是CCmdTarget类,所以,文档类也能够处理菜单等               命令消息. 作用保存和管理数据.    注意事项:怎样解决断言错 ...

  6. 微信小程序入门文档

    一 基本介绍 微信专门为小程序开发了一个ide叫做微信开发者工具 最新一版的微信开发者工具,把微信公众号的调试开发工作也集成了进去,可以更换开发模式. https://mp.weixin.qq.com ...

  7. “Word自动更改后的内容保存到通用文档模板上。是否加载该模板?“的解决办法

    在win7系统下,Word2010出现了不能正常关闭.打开一个已有word文档,点击右上角关闭按钮后,先提示"word已停止工作,windows正在检查该问题的解决方案",随后提示 ...

  8. Java中常用到的文件操作那些事(一)——替换doc文档模板,生成真实合同案例

    工作中,我们时常会遇到一些操作文件的操作,比如在线生成合同模板,上传/下载/解析Excel,doc文档转为pdf等操作.本文就已工作中遇到的在线生成合同为例,简要地介绍一种文档替换写法. 本文目的:给 ...

  9. Pycharm文档模板变量

    点击这里查看JetBrains官方英文源文件 本篇Blog只是搬运外加大概翻译一下. File template variables A file template can contain varia ...

随机推荐

  1. 6/13 sprint2 看板和燃尽图的更新

  2. ASP.NET中使用DropDownList实现无刷新二级联动详细过程

    Demo.sql create table Car( [id] int identity, ) not null, ) not null ) go insert into Car ([brand],[ ...

  3. GridView如何实现双击行进行编辑,更新

    虽然标题是原创,但是其实主要的思想呢还是接见了晓风残月的思路,今天在晓风残月的博客上看到了如何利用GridView来实现双击进行编辑.我决定动手实现一下,由于还没有实现双击进行更改操作,所以顺便就把这 ...

  4. C# 通过自定义特性 实现根据实体类自动创建数据库表

    .Net新手通常容易把属性(Property)跟特性(Attribute)搞混,其实这是两种不同的东西 属性指的类中封装的数据字段:而特性是对类.字段.方法和属性等元素标注的声明性信息 如下代码(Id ...

  5. jQquery.validate自定义规则的使用案例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 【Unity】13.2 通过Lighting Window设置相关参数

    分类:Unity.C#.VS2015 创建日期:2016-05-19 一.简介 Unity 5.3.4的Lighting Window有3个选项卡:Object.Scene.Lightmaps. 二. ...

  7. Scala on Visual Studio Code

    Download and install Scala Download a scala installation package from here. Then install it. Linux s ...

  8. springMVC图片文件上传功能的实现

    在工程依赖库下添加文件上传jar包 commons-fileupload-1.2.2.jar commons-io-2.4.jar 2.jsp页面设置form表单属性enctype 在表单中上传图片时 ...

  9. C#生成条形码 Code128算法

    条形有很多种,Code128是比较常用的一种,是一种高密度条码, CODE128 码可表示从 ASCII 0 到ASCII 127 共128个字符,故称128码.其中包含了数字.字母和符号字符. Co ...

  10. jQuery pgwslideshow 空间相册

    一个响应式相册插件,你可以自定义幻灯片最大高度,滑动效果,是否显示控制按钮,自动轮播或间隔时间. pgwslideshow相册插件有以下特点    支持响应式    支持桌面和移动设备    代码简单 ...