简介:Codejock.Xtreme.Toolkit.Pro.v15.3.1 是一套功能全面的 MFC 界面组件库,涵盖命令栏、主题皮肤、网格、日期选择器、对话框等众多高级控件,适合使用 Visual Studio 2017 进行 Windows 桌面应用界面开发的 C++ 开发者。包内以完整源码为核心,已将解决方案中的 32 位与 64 位工程属性全部调整为 VS2017 工程格式,打开 .sln 即可直接编译,免去手工迁移工程、配置附加 include 目录和链接库的繁琐环节,对熟悉 MFC 的开发者十分友好。压缩包内共 4654 个文件,整体约 80.08MB,其中以 2673 个 png、675 个 h、573 个 cpp、410 个 rc 为主:png、bmp、cur、ico 等为界面图标和皮肤素材,h 与 cpp 构成控件核心实现,rc 为资源定义脚本,sln、vcxproj 与 filters 组织工程结构,方便按模块检索、学习和二次开发。同时附带已编译好的 debug 与 release 动态库和静态库,例如 ToolkitPro1531vc150.lib、ToolkitPro1531vc150.dll 及其 D 版本,可在不编译源码的情况下直接链接使用,也可按业务需求修改源码后重新生成指定库版本。已有 995 人学习下载,对于需要快速集成 Codejock 控件、研究界面库源码实现或为旧项目适配 VS2017 的开发者来说,是一份实用且省时的资源。
1. 还在用原生控件撑门面的 MFC 程序,是时候换个活法了
如果你的工作流里还躺着十几年前留下的 MFC 代码,或者你正准备在新项目里用 MFC 快速交付一个 Windows 桌面客户端,那么“界面丑、控件老、客户嫌弃”这三座大山你一定不陌生。Codejock Xtreme Toolkit Pro v15.3.1 这个 VS2017 版本,就是冲着解决这个问题去的:它是一套庞大的 MFC 界面库,提供从 Ribbon 工具栏、Visual Studio 风格停靠窗格、属性网格到皮肤引擎、图表、语法编辑等一整套现成控件。简单说,装上它,你的 MFC 程序能直接换上 Office 2016 那种现代外观,不用自己从零画按钮和重绘窗口。
这篇文章不会去复述官方文档,而是从一个实际做 MFC 维护和二次开发的工程师视角,把这套库在 VS2017 环境下从安装、编译、接入到发布的全过程拆开讲。你会看到具体的编译配置、链接时玄学般的错误怎么排查,以及那些藏在文档角落里的关键参数。如果你正打算给老项目换肤,或者新项目想用 MFC 但不想让 UI 拖后腿,这篇实战笔记应该能帮你少走不少弯路。
2. 拿到安装包之后:先搞清 v15.3.1 在 VS2017 下的家底
2.1 解压与目录结构:别急着双击 Setup.exe
很多第一次接触 Codejock 的人,习惯性双击根目录下的 Setup.exe,结果装完发现 VS2017 里死活找不到库文件和头文件。这个版本有些特别,下载回来的压缩包解压后,你会看到一个 Sources 目录和一个 Redistributable 目录,前者是完整的源码和工程文件,后者是编译好的 DLL 和静态库。我一般不会直接跑安装程序,而是把整个解压目录放到一个固定路径,比如D:\Codejock\Xtreme Toolkit Pro v15.3.1,这样后续升级或换机器时,路径一致,不用改工程配置。
进入 Sources 目录后,你会看到按功能模块划分的子文件夹,比如ToolkitPro、Chart、DockingPane、PropertyGrid等,每个模块下都有对应的.sln或.vcxproj工程文件。这里有个关键点:v15.3.1 是较早支持 VS2017 的版本线,它的工程文件默认是用 VS2015 生成的,但 VS2017 打开时会自动做平台工具集升级。如果你在 VS2017 里打开解决方案时遇到“需要安装 VS2015 工具集”的提示,不用慌,直接在属性页里把平台工具集改成Visual Studio 2017 (v141)即可。
2.2 编译选项:Debug 与 Release 必须分开编,混用必翻车
Codejock 的库分为静态库和动态库两种使用方式,这个选择会直接影响你后续的链接配置。动态库方式(使用_XTP_DLL宏)会生成一堆 DLL,发布时得带上;静态库方式(默认不定义_XTP_DLL)则是把代码编进你的 exe 里,发布包更干净,但编译时间会明显变长。我一般倾向用静态库,尤其是做内部工具或交付给客户时,少一堆 DLL 就少一堆“运行库缺失”的售后问题。
打开Sources\ToolkitPro\ToolkitPro.vcxproj这个工程,在属性管理器里新建两个配置:Debug_Static和Release_Static。需要改的其实就几个地方:字符集选“使用多字节字符集”还是“Unicode”?这里我强烈建议直接用 Unicode,Codejock v15.3.1 对 Unicode 的支持已经很成熟,而且你新写的代码也应该是宽字符的。然后就是运行库,Debug 用/MTd,Release 用/MT,前提是你自己的工程也用的是静态运行库。如果你主程序用的是/MD,那这里就得改成/MDd和/MD,两边必须对齐,否则链接期会报一堆libcmt.lib和libcmtd.lib冲突之类的错。
编译顺序也有讲究。Codejock 模块之间有依赖关系,手动一个个点编译容易漏。我一般直接在 Solution 层级选择“生成解决方案”,让 VS 自己处理依赖顺序。第一次全量编译 Release_Static 大概需要 10 到 20 分钟,中途如果报错,多半是 Windows SDK 版本问题——把目标平台版本改成你机器上实际安装的,比如 10.0.17763.0,基本能过。
2.3 环境变量与头文件搜索路径:一劳永逸的配置法
编译完库之后,就是配置你的主工程引用这些库了。网上很多教程让你在每个工程里手动加附加包含目录和附加库目录,这样做在工程少的时候没什么,但工程一多,维护起来想死的心都有。更稳妥的做法是:新建一个系统环境变量,比如命名为CODjOCK_ROOT,值指向你的解压目录。
然后在 VS2017 里,打开“属性管理器”,找到你的工程配置,在“VC++ 目录”的“包含目录”里加上$(CODjOCK_ROOT)\Sources,在“库目录”里加上$(CODjOCK_ROOT)\Sources\ToolkitPro\Lib。后续不管换机器还是换版本,只要改一个环境变量就行。这一步做完,你的工程就能找到所有头文件和 .lib 文件了。注意,如果你用的是动态库方式,库目录还要加上$(CODjOCK_ROOT)\Redistributable\VC150之类的路径,具体看你编译出来的输出目录在哪。
3. 让代码跑起来:从初始化到弹出第一个 Ribbon 窗口
3.1 初始化 Toolkit Pro:App 模块里的三行关键代码
头文件和库路径配好之后,代码层面的接入很简单,但顺序不能乱。在你要使用 Codejock 控件的那个 MFC 对话框或框架窗口的OnInitDialog或OnCreate里,首先要调用初始化函数。对于 v15.3.1,你需要包含对应的头文件,然后调用XTPInitToolkit()。这个函数会完成库内部的资源加载和公共控件注册,不调它就直接创建控件,轻则控件样式不对,重则直接断言崩溃。
// 在你的 MFC 应用类或主窗口 .cpp 文件头部 #include "XTPToolkitPro.h" // 主头文件,包含绝大多数控件的声明 // 在 CWinApp::InitInstance 中,创建任何窗口之前 BOOL CMyApp::InitInstance() { // 初始化 Toolkit Pro 运行环境 if (!XTPInitToolkit()) { AfxMessageBox(_T("Toolkit Pro 初始化失败,请检查运行环境。")); return FALSE; } // 允许使用 Visual Studio 风格的视觉主题(皮肤引擎) XTPSkinManager()->SetCurrentSkin(_T("Office2016")); // 其余 MFC 初始化代码... }逻辑说明:XTPInitToolkit()是进入 Codejock 世界的钥匙,它会注册窗口类、加载内部资源,并初始化皮肤引擎的底层。XTPSkinManager()返回的是一个全局皮肤管理器对象指针,SetCurrentSkin接受一个皮肤名称字符串,像Office2016、Office2013、VS2015这些都是内置的。参数说明:皮肤名称字符串必须和库内置的皮肤资源名字完全一致,大小写敏感,写错了不会报编译错,运行时会静默失败,窗口看起来还是老样子。如果你不想用皮肤,只是想要控件,那可以不调用SetCurrentSkin,但 Ribbon 这类高级控件一般会依赖皮肤引擎来渲染,建议还是开启。
3.2 创建一个 Ribbon 风格的 MainFrame:替换你的 CMainFrame 基类
这是最直观能看到效果的一步。传统 MFC 的CMainFrame继承自CFrameWnd,你要换成 Codejock 提供的CXTPRibbonFrameWnd。这个类已经实现了 Ribbon 界面所需的框架逻辑,你只需要在里面加入 Ribbon 控件并填充选项卡。
// MainFrm.h 的关键改动 #include "XTPRibbonFrameWnd.h" // Ribbon 框架窗口基类 class CMainFrame : public CXTPRibbonFrameWnd { DECLARE_DYNCREATE(CMainFrame) public: CMainFrame(); // 其余成员函数保持不变 }; // MainFrm.cpp 中 OnCreate 的关键改动 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // 先调用基类 OnCreate,完成框架窗口创建工作 if (CXTPRibbonFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // 获取 Ribbon 控件指针 CXTPRibbonBar* pRibbon = GetRibbonBar(); // 添加一个名为“文件”的选项卡 CXTPRibbonTab* pTabHome = pRibbon->AddCategory(_T("文件")); // 添加一个面板(组) CXTPRibbonGroup* pGroupFile = pTabHome->AddGroup(_T("常用操作")); // 向组里添加一个按钮 CXTPRibbonButton* pBtnNew = (CXTPRibbonButton*)pGroupFile->AddButton( ID_FILE_NEW, _T("新建"), NULL, 0); // 再添加一个大按钮用于打开文件 CXTPRibbonButton* pBtnOpen = (CXTPRibbonButton*)pGroupFile->AddButton( ID_FILE_OPEN, _T("打开"), NULL, 1); return 0; }逻辑说明:CXTPRibbonFrameWnd是 v15.3.1 里 Ribbon 框架的入口,GetRibbonBar()返回它内部维护的CXTPRibbonBar指针。AddCategory对应 Ribbon 里的一个顶级选项卡,AddGroup对应选项卡里的一个面板,AddButton则是在面板里放按钮。参数说明:AddButton的第一个参数是命令 ID,通常是你在资源文件里定义好的菜单或按钮 ID,这样按钮点击后会自动路由到你的消息处理函数;第三个参数可以传一个CXTPImageManager图标对象,传NULL就先用默认样式(纯文字按钮)。第四个参数是按钮样式标志,0表示常规按钮,1表示大按钮,视觉差异挺大,可以按需挑。
编译运行,如果你的主窗口继承了CXTPRibbonFrameWnd,并且初始化代码都写了,你应该能看到一个带 Office 2016 风格的 Ribbon 界面。如果编译报错说CXTPRibbonFrameWnd未定义,回头检查头文件路径和宏定义_XTP_STATIC_LIB,静态链接时必须定义这个宏,否则链接器找不到实现。
3.3 控件工具箱:停靠窗格与属性网格的搭配用法
Ribbon 只是门面,真正提升开发效率的是停靠窗格和属性网格。做工具软件的人都知道,左边一个树形列表、右边一个属性面板,这种布局能省无数对话框。Codejock 的CXTPDockingPaneManager让这个布局的实现变得很粗暴。
// 在 CMainFrame 中声明停靠管理器和属性网格 #include "XTPDockingPaneManager.h" #include "XTPPropertyGrid.h" // 在 OnCreate 里,创建 Ribbon 之后 // 获取停靠窗格管理器并创建布局 CXTPDockingPaneManager* pPaneManager = GetDockingPaneManager(); // 创建一个左停靠的树形视图窗格 CXTPDockingPane* pTreePane = pPaneManager->CreatePane( 1, _T("资源树"), CRect(0, 0, 200, 300), xtpPaneDockLeft); // 创建一个底部停靠的输出窗格 CXTPDockingPane* pOutputPane = pPaneManager->CreatePane( 2, _T("输出"), CRect(0, 0, 200, 100), xtpPaneDockBottom); // 让树形窗格默认显示 pPaneManager->ShowPane(pTreePane); pPaneManager->ShowPane(pOutputPane); // 将已有的 CFormView 或 CWnd 视图关联到窗格 // 通常你在 DocTemplate 里给 View 指定了 CChildView,这里需要替换逻辑说明:CreatePane的参数从左到右依次是窗格 ID(自定义)、标题、初始位置矩形、停靠方向。xtpPaneDockLeft和xtpPaneDockBottom是枚举值。重要的是,如果你用的是 SDI 程序,每个窗格都要关联一个实际窗口视图,这步经常有人忘了做,结果窗格空荡荡,鼠标点不动。常见做法是在OnCreate里先创建好CView的实例,再用pPane->Attach(CWnd*)把视图挂上去。
参数说明:窗格 ID 不能重复,建议从 100 开始递增,避开和命令 ID 冲突。CRect里的宽高只是初始值,用户拖动窗格边框后会被记住。如果你希望启动时布局是固定的,可以调用pPaneManager->SetDockState()加载之前保存的布局二进制数据,这功能对提升用户体验很有帮助。
4. 皮肤引擎与视觉主题:换肤不是换个颜色那么简单
4.1 皮肤文件格式与加载方式:内置皮肤与外部皮肤的区别
Codejock 的皮肤系统很强大,它不只是换颜色,而是重新绘制所有 MFC 标准控件以及 Codejock 自家控件。v15.3.1 内置了 Office 2016、Office 2013、Office 2010、VS 2015、Windows 10 等十几种主题。你可以在XTPSkinManager上直接指定名字,也可以加载外部.ini或.utheme文件。负载均衡和性能上,内置皮肤是编译进库里的,加载速度最快;外部皮肤文件适合做换肤商城,但要注意版权,官方提供的.utheme文件只能用于自家程序发布。
// 从外部文件加载皮肤 CString strSkinPath = _T(".\\Skins\\MyCompany.utheme"); if (XTPSkinManager()->LoadSkin(strSkinPath)) { XTPSkinManager()->ApplySkin(); } else { TRACE(_T("皮肤文件加载失败,使用默认皮肤。\n")); XTPSkinManager()->SetCurrentSkin(_T("Office2016")); }逻辑说明:LoadSkin加载文件到内存,ApplySkin应用到当前所有窗口。注意,加载皮肤必须在至少一个窗口创建之后调用,否则没有 HWND 可以刷新。参数说明:路径支持相对路径和绝对路径,但发布时最稳妥是把皮肤文件放在 exe 同目录的子文件夹里,避免用户改目录导致路径失效。
4.2 高 DPI 与缩放:老库在新屏幕下最头疼的坑
v15.3.1 发布那几年,4K 屏还不像现在这么普及,所以它对高 DPI 的支持是有的,但不完美。如果你的程序跑在 150% 缩放的屏幕上,你会发现 Codejock 的工具栏图标有点糊,或者 Ribbon 文字被截断。这不是库坏了,而是你没有告诉 Windows 你的程序支持 DPI 感知。
// 在 App 的 InitInstance 最开头加上 // 告诉系统当前程序是 DPI Aware 的,禁用虚拟化 ::SetProcessDPIAware(); // 或者更推荐的方式:在项目清单里声明 // 打开 Visual Studio 的“清单工具”->“输入和输出”->“DpiAwareness” // 值设为 "PerMonitorHighDPIAware"逻辑说明:如果不调用SetProcessDPIAware,Windows 会把你的程序当成不支持 DPI,然后整体做位图拉伸,后果就是界面模糊。这个 API 必须在任何窗口创建前调用,放在InitInstance第一行。参数说明:PerMonitorHighDPIAware是最理想的,程序能感知每个显示器不同的缩放比例,但 v15.3.1 对 Per-Monitor V2 的支持有已知的绘制问题,如果你用的显卡驱动比较激进,可能会看到工具栏闪现黑块。我的建议是:对于这个版本,用System DPI Aware就够了,两个显示器的缩放如果不同,界面会有点小瑕疵,但至少不会糊成一片。
4.3 自定义配色:把公司主色调进 Ribbon 和停靠窗格
内置皮肤的颜色是一整套的,但公司往往想在自己的产品里突出品牌色。Codejock提供了XTPSkinManager()->GetColorSet()接口,你可以修改里面特定项的颜色值。
// 获取当前皮肤的调色板 XTPColorSet* pColorSet = XTPSkinManager()->GetColorSet(); // 修改 Ribbon 高亮背景色,参数是 RGB 值 pColorSet->SetColor(XTPColorSet::TabHighlightText, RGB(255, 255, 255)); pColorSet->SetColor(XTPColorSet::TabHighlight, RGB(0, 160, 233)); // 改完以后要强制刷新皮肤 XTPSkinManager()->RefreshAllWindows();逻辑说明:XTPColorSet定义了大量颜色语义项,比如TabHighlight是选项卡高亮时的背景色,GroupCaption是面板标题文字色,ButtonPressed是按钮按下状态色。直接改内存调色板是即时生效的,不用重新编译皮肤文件。参数说明:这个改动是运行时态的,不会写回.utheme文件。如果你要把这套配色固化下来,可以在程序启动时读取一个配置文件,把颜色值填进去,这样市场部的人可以自己调色,不用找你重新编译发版。
5. License 机制与部署注意:为什么换了台电脑就提示未授权
5.1 开发授权与运行授权的差异:理解 _XTP_LICENSE 宏
这是很多团队从试用转正时踩坑最多的地方。你在一台机器上编译好的程序,拷贝到另一台干净的机器上运行,如果安装包不带授权信息,程序启动时 Codejock 会弹出一个关于版权的对话框或者直接退出。原因是,Codejock 在编译库时嵌入了授权验证代码,它区分“开发模式”和“部署模式”。
现象:程序在开发机上跑得好好的,复制到客户电脑上报错,提示需要注册或激活。
原因:Codejock 的授权验证绑定的是编译环境。在开发机上,它知道你装了正版授权(安装时写入了注册表或 license 文件),所以链接进 exe 的是评估版逻辑或带授权宏的版本。而部署到没有安装 Codejock 的机器时,exe 里的验证代码发现没有有效的授权签名,就罢工了。
解决:你需要使用官方提供的“Deployment Kit”或“Redistributable”授权文件。具体做法是在编译你的 Release 工程时,在预处理定义里加入_XTP_LICENSE宏,并把它指向一个授权文件的路径。这个路径通常是一个.lic文件,可以从 Codejock 官网账户里下载。
// 在 VS2017 中:项目属性 -> C/C++ -> 预处理器 -> 预定义 // 添加以下宏(假设 lic 文件放在工程目录下) _XTP_LICENSE="$(ProjectDir)Codejock.lic"逻辑说明:这个宏告诉链接器把授权文件的内容编译进最终 exe。这样一来,目标机器上就不需要安装任何 Codejock 组件,exe 自己就能通过授权校验。参数说明:$(ProjectDir)是 VS 宏,会自动替换成当前工程目录,这样源码在不同机器间同步时不用改绝对路径。Codejock.lic文件要确保存在于指定位置,建议在工程里把它设为“文件”类型,并设置“复制到输出目录”,但前提是它只在编译时需要。注意:这个 .lic 文件是有配额的,不能随意在公网传播。
5.2 运行时 DLL 清单:静态库也逃不过的发布陷阱
虽然前面我推荐用静态库,但v15.3.1里的某些模块,尤其是图表和语法编辑,静态编译后 exe 体积会瞬间增大几十 MB,而且部分功能(比如打印预览)依赖系统组件,静态编译反而可能出问题。如果你最终选择了动态库方式,发布时一定要带上Redistributable目录下的全部 DLL,一个都不能少。
现象:程序在客户机器上启动,双击没反应,事件查看器里报缺少ToolkitPro1503.dll之类的错误。
原因:Codejock 的 DLL 命名包含版本号,且内部有依赖链,你主程序只链接了最外层的 DLL,它内部还调用更底层模块的 DLL,你把外层的拷过去了,内层的没拷。
解决:不要手动一个个拷,而是用 VS2017 的“生成事件”脚本,在编译后自动复制所有需要的内容。我一般会在工程属性 -> 生成事件 -> 后期生成事件命令行里加上一行xcopy /y /d "$(CODjOCK_ROOT)\Redistributable\*.dll" "$(OutDir)"。这样每次编译完,所有 DLL 会自动齐刷刷地出现在输出目录。你需要确认Redistributable目录下的 DLL 和你编译库时选择的字符集(Unicode/多字节)和模式(Debug/Release)一一对应,文件名后缀可能有d表示 Debug 版,拷贝时别拿错了。
5.3 静默授权验证失败:排查和兜底策略
有些特殊场景,比如客户电脑没有管理员权限,或者杀毒软件拦了 Codejock 的授权验证,程序会启动失败。这种时候,最直接的兜底策略是在InitInstance里捕获授权验证的返回值,并给出明确的错误提示,而不是让程序默默消失。
// 检查授权状态 if (!XTPToolkitPro_IsRegistered()) { AfxMessageBox(_T("本程序需要有效的 Codejock 授权才能运行。\n") _T("请联系技术支持获取授权文件。"), MB_ICONERROR); return FALSE; }逻辑说明:XTPToolkitPro_IsRegistered()是 v15.3.1 提供的一个全局函数,用来查询当前运行环境是否通过了授权校验。如果返回 FALSE,直接退出并提示是成本最低的方案,至少用户知道发生了什么,而不是以为程序坏了。参数说明:这个函数在 Debug 版本下一般都返回 TRUE,因为调试器环境识别为开发授权;只有在 Release 且没有正确嵌入 .lic 时才可能返回 FALSE,所以别在 Debug 下测这个逻辑,测不出来。要想彻底测试部署环境,得在一台没装过 Codejock 的虚拟机里跑 Release 版本。
6. 性能调优与进阶配置:把 Toolkit Pro 的能力阈值再顶高一点
6.1 控件加速:关闭不需要的动画和阴影
Ribbon 界面默认带着动画效果,在配置低的机器上(比如客户的 POS 机),这些动画会让界面卡顿。v15.3.1 支持通过XTPSkinManager()调整渲染选项,关闭动画能显著提升响应速度。
// 关闭 Ribbon 菜单动画 XTPSkinManager()->SetTheme(_T(""), NULL); XTPSkinManager()->GetSkinOptions()->m_bDisableAnimation = TRUE; // 关闭窗口阴影(部分经典主题下阴影性能开销大) XTPSkinManager()->GetSkinOptions()->m_bDropShadow = FALSE;参数说明:m_bDisableAnimation设为 TRUE 后,菜单展开和 Ribbon 选项卡切换会变成瞬切。m_bDropShadow控制窗口阴影,在远程桌面场景下,阴影容易渲染异常,关掉能减少绘制工作量。这些选项在InitInstance里设置一次,程序生命周期内都有效。
6.2 消息过滤:避免控件内部消息干扰你的业务逻辑
Codejock 的控件在处理鼠标交互时会发送大量自定义通知消息。如果你在主窗口里用ON_MESSAGE处理了所有消息,容易误拦截控件内部的广播。我看过有同事把WM_XTP_THEMECHANGED当成业务消息处理,结果界面刷新数据错乱。
正确姿势是:使用 Codejock 提供的消息映射宏,只捕获你关心的通知。例如 Ribbon 按钮点击,你不需要处理底层的鼠标消息,只要给对应的命令 ID 添加ON_COMMAND处理函数即可。属性网格的值修改,响应的消息映射是ON_NOTIFY(XTP_PGN_PROPERTYCHANGED, IDC_PROPERTY_GRID, &CMainFrame::OnPropertyGridChanged)。这里面XTP_PGN_PROPERTYCHANGED是属性网格特有的改动通知,不会和其他空间冲突。
6.3 界面状态持久化的最佳实践:用户改好的布局要记得存
停靠窗格用户拖拽过的位置、大小、隐藏状态,这些配置如果不保存,下次启动就回到初始布局,用户会骂人的。v15.3.1 提供了CXTPDockingPaneManager::SaveState()和LoadState()。在CMainFrame的OnDestroy里保存,在OnCreate里加载。唯一要小心的是加载时机:必须在所有窗格和视图创建完成后调用,否则会因句柄无效崩溃。
// 保存布局到注册表或文件 void CMainFrame::OnDestroy() { // 保存停靠窗格布局 GetDockingPaneManager()->SaveState(_T("Software\\MyCompany\\MyApp\\DockingLayout")); CXTPRibbonFrameWnd::OnDestroy(); } // 加载布局:放在 OnCreate 里所有窗格创建之后 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // ... 创建 Ribbon、创建窗格、关联视图 ... // 最后加载上次保存的布局 GetDockingPaneManager()->LoadState(_T("Software\\MyCompany\\MyApp\\DockingLayout")); return 0; }参数说明:SaveState接受一个注册表路径,也可以是文件路径。如果是注册表路径,注意要用反斜杠分隔完整路径,系统会以当前用户身份写入 HKCU 下。这里有个血泪教训:如果路径包含中文或者特殊字符,Release 版可能写入失败但不报错,导致布局永远存不下来。我的习惯是只用英文加反斜杠,而且不要以反斜杠结尾。
6.4 关于 v15.3.1 与 VS2017 的一个收尾心得
写到这,这套工具的核心用法基本盘了一遍。说实话,即使到了今天,MFC 搭配这套 Toolit Pro,仍然是 Windows 企业级桌面应用里效率最高的组合之一。你不需要懂现代 UI 框架的状态管理和虚拟 DOM,只要把 C++ 逻辑写好,界面部分交给它,一个月搞定一个像模像样的工具软件不是空话。但前提是,第一遍编译配置必须一次做对,后面就全是幸福时光。我手里的老项目换到这个版本后,客户反馈的“界面丑、不专业”这类声音基本绝迹。希望这篇笔记能帮你把这条路走顺,也希望你上手时少踩我当年踩过的那些坑。
本文还有配套的精品资源,点击获取