简介:BCGControlBar Pro 15.1 是一套面向 MFC 开发者的高级界面扩展库,旨在用现成的工具栏、菜单、Docking 窗格、图表与日历等组件,快速构建现代化 Windows 桌面程序;随包附带完整源代码,适合需要深度定制 UI 或研究底层实现的中高级开发者。压缩包共 2153 个文件,资源包约 6.82MB,其中 1258 个 PNG 与 64 个 BMP 提供全套界面图标,330 个 H 与 305 个 CPP 构成核心实现,DSP、VCProj、SLN、VCXProj 等工程文件覆盖多版本 Visual Studio 编译配置,另有 RC 资源脚本与 C 辅助文件,便于直接加载工程。该版本不含集成向导、帮助文档或示例工程,因此使用者需具备 MFC 基础,并自行查阅周边资料上手。已有 139 人学习下载,可用于研究高级工具栏绘制、多面板布局管理、主题切换及图标资源组织方式;对希望摆脱黑盒调用的开发者,也可逐行走查源码,掌握界面框架的组织脉络,为二次开发提供可靠蓝本。
1. BCGControlBar Pro 15.1:老 MFC 界面的一次全面翻新
BCGControlBar Pro 15.1 是一个经典的 MFC 界面扩展库版本,解决的是 Windows 桌面程序里最普遍的老问题:MFC 自带的菜单、工具栏和对话框外观停留在上个时代的视觉风格,而业务逻辑短期还不能迁移到新框架。它的价值在于用相对小的改动,让原有 C++ 代码得到现代办公软件风格的功能区、可停靠窗格、主题皮肤和更顺手的操作体验。适合接手存量 MFC 工程的开发者,特别是那些还在 VS2015 / VS2017 环境里维护代码的团队。15.1 这个版本号之所以被反复检索,是因为它对应一批仍在服役的老工程,换主框架时重建资源的代价最小,大家留下的踩坑记录也相对完整。
2. 选型与集成:先回答“这个版本能不能接进我的工程”
在写一行代码之前,先把一个工程特征理清楚:编译器版本。15.1 是在 VS2015 成为主流的阶段发布的稳定分支,对 VS2008 到 VS2015 的 toolset 有明确适配,后续在 VS2017 的若干更新环境下也能通过编译。这里的“适配”指的是库内部针对各个编译器的版本检查分支都做了处理,而不是简单地拿一套源码硬编译。如果工程已经换到更新的 VS 版本,强行用 15.1 会导致 BCG 头文件与标准库头文件之间的检查不一致,报错位置往往藏在 BCG 自己的头文件里,修改成本高,不如直接评估新版本库。所以先说结论:还在 VS2015/VS2017 的团队合适,已经换了新编译器的团队不建议为了省成本而硬上 15.1。
2.1 版本与编译器:为什么 15.1 和 VS2015/VS2017 是常见组合
选型时不只需要看编译器,还要核对目标系统和字符集。目标 Windows 系统在 Win7 / Win10 上都有广泛部署,15.1 对这两代系统的兼容没有明显差异,但如果是更早的 XP,就需要看看官方支持列表中是否包含,旧版本库在 XP 上通常还有遗留问题。字符集则更关键:15.1 时代主流工程基本都是 Unicode,如果还在用 ANSI 编译,BCG 的字符串接口几乎处处会报类型不匹配。实际处理顺序是先切换字符集、再引入库,这样报错会集中在统一的位置,而不是散落在几十个控件文件里。
另一个容易被忽略的点是主框架窗口基类。如果工程里大量使用 CFrameWnd / CMDIFrameWnd,替换成 BCG 提供的 CBCGPFrameWnd / CBCGPMDIFrameWnd 时,所有 Create 调用和消息映射要一起检查。只改继承声明不够,因为 BCG 框架类在创建过程中要做资源状态切换和视觉管理器匹配,这些逻辑都在基类的 OnCreate 内部完成,子类如果不把原先的创建流程调整好,窗口能出来但会出现工具栏尺寸不对、停靠区域布局紊乱之类的问题。
2.2 静态库与动态库:链接方式影响后续维护成本
接入 BCGControlBar Pro 15.1 的第二步是确定链接方式。通常有两种做法:静态链接到 BCG 静态库,或者链接对应的 DLL 版本。对存量工程来说,我一般优先选静态链接,理由是部署简单——目标机器不需要额外分发 BCG 运行时 DLL,也不会出现不同机器装了不同版本动态库而互相干扰的情况。代价是可执行文件体积明显增加,一个原本只有几 MB 的主程序,加上 BCG 后可能膨胀到几十 MB;在以几十个 DLL 模块组成的大型系统里,这个体积增长会进一步传递到内存占用。
动态链接的好处是升级时不用重新编译全部工程,替换 DLL 即可。负面问题也同样明显:运行时版本必须严格匹配。开发机的库版本和部署机的运行时版本不一致时,启动阶段就会出现断言或控件创建失败,这类问题编译期完全看不出来,只在运行现场暴露,定位时像在查玄学。所以我通常的建议是:内部工具类工程可以用动态链接,对外交付的桌面产品一律静态链接。链接方式决定了你要写进工程里的条件编译宏,中途切换会带来一轮编译错误,这个决定要在集成最开始定下来,后面不要反复横跳。
下面是我实际做判断时参考的对比表:
| 对比维度 | 静态链接 | 动态链接 |
|---|---|---|
| 部署复杂度 | 只交付 exe 即可 | 需要带对应版本的运行时 DLL |
| 升级库版本 | 需要重编全部工程 | 替换 DLL 即可 |
| 体积与内存 | exe 更大,独立占用内存 | 多进程共享一份 DLL,整体内存更省 |
| 版本冲突风险 | 低 | 高,版本不一致时运行期崩溃 |
如果做一个由多个独立小工具组成的工具包,静态链接会让每个小工具都携带一份 BCG 代码,内存浪费明显;这种情况可以考虑统一改用动态链接。如果是一个以模块化 DLL 方式发布的大型系统,主框架和子模块最后打成一个安装包,静态链接的一致性优势就体现出来了。
2.3 最小接入流程:引入头文件、替换基类、配置链接
接入过程通常分三步:设置包含目录和库目录、在预编译头里引入 BCG 头文件、替换主框架窗口基类。以静态链接为例,典型的配置如下:
// stdafx.h —— 预编译头中加入 BCG 头文件 #define BCG_CONTROL_BAR_PRO_VERSION 15.1 #include "BCGCBPro.h" // BCG 库总入口 #include "BCGCBProVisualManager.h" // 视觉管理器(主题相关)这两行要放在 MFC 标准头文件之后,顺序乱了会出现大量重复定义编译错误。BCGCBPro.h 是 BCG 的总入口,必须最先被包含;BCGCBProVisualManager.h 是为后续换主题预留的,如果第一步只做功能区,可以不包含,但写了没副作用。版本宏不写也可以,但写上有助于让头文件内置的版本检查逻辑按 15.1 走,避免预编译头缓存旧版本信息。
工程设置上要同步改三处:一是“VC++ 目录”里的包含目录加上 BCG 的 include 路径;二是“链接器 常规 附加库目录”指向对应静态库路径;三是“预处理器定义”里确认有 _UNICODE;UNICODE。第三项我在实际项目中遇到过几次,因为某个成员新建工程时没带这个宏,编译期报错非常分散,字符串接口全部失效。如果遇到类似情况,先回去检查这个定义,能省半小时。
主框架窗口基类和功能区创建的代码如下:
// MainFrm.h class CMainFrame : public CBCGPMDIFrameWnd { public: CBCGPRibbonBar m_wndRibbonBar; CBCGPStatusBar m_wndStatusBar; }; // MainFrm.cpp int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CBCGPMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // 创建功能区并加载 Ribbon 资源 if (!m_wndRibbonBar.Create(this)) return -1; if (!m_wndRibbonBar.LoadFromResource(IDR_RIBBON)) { TRACE(_T("Ribbon 资源加载失败\n")); return -1; } return 0; }这里的 Create 必须在框架窗口的 OnCreate 阶段调用,滞后到窗口建立之后就会挂载失败。LoadFromResource 的参数是 Ribbon 资源 ID,资源本身由 BCG 的 Ribbon 资源编辑器生成;虽然有办法直接读 XML,但不推荐纯手写,编辑器会自动完成命令 ID 映射,手写漏一处就要排查很久。
这里还涉及应用类的初始化。如果工程原本的 App 类是从 CWinApp 派生,最少也应在 InitInstance 里调用一次 CBCGPWorkspace::InitInstance,让 BCG 的全局状态建立起来。不做这一步,后期会出现工具栏位图丢失、图标加载失败这类看起来毫无关联的故障。我见过一个案例,界面大部分能显示,但某一个图标总是白色方块,折腾半天才发现是初始化顺序问题。
做完这三步,工程应当能编译通过并在主窗口顶部出现一个空功能区。编译如果报错集中在 C6064 之类警告,先把“将警告视为错误”关掉再观察;如果报成片链接错误,优先检查静态库文件是否匹配 Debug / Release 配置。BCG 的 Debug 库和 Release 库文件名后缀不同,混用是典型的翻车现场之一。
3. 功能区与停靠窗格:把界面骨架搭起来
功能区是 BCGControlBar Pro 15.1 中使用最多的部件,替代传统菜单和工具栏。它的创建顺序是:先创建 CBCGPRibbonBar 对象,再加载 Ribbon 资源,最后让主框架完成布局注入。顺序颠倒会导致两种典型异常:只 LoadFromResource 不 Create,运行时断言失败或得到空白窗口;只 Create 不加载资源,功能区是空壳,页签和按钮全部缺失。所以任何时候,先把控件对象 Create 成功,再去 LoadFromResource。
3.1 Ribbon 栏的创建流程与资源加载顺序
Ribbon 资源包含若干个 Category(分类页),每个 Category 下有若干 Panel(面板),面板里放 Button、CheckBox、Edit 等命令项。每个命令项绑定一个命令 ID,消息路由沿用 MFC 的 ON_COMMAND 映射,Click 事件照样走原有处理函数。这点对外层业务代码很友好,原本写好的 OnFileSave 之类函数可以原样保留,只需把工具栏按钮 ID 换成功能区命令 ID。也是因为这一点,BCG 才被称为“存量工程友好”——界面层变了,业务层的消息处理逻辑不用动。
资源编辑器的使用顺序通常是这样:新建 Ribbon 资源 → 创建第一个 Category → 在 Category 下添加 Panel → 往 Panel 里放命令按钮 → 为按钮指定命令 ID 和图标 → 保存并编译资源。这个顺序不要跳,跳了会出现在编辑器里看着正常、运行时按钮缺失的情况。保存后生成的二进制资源要确认已经嵌入到工程资源中,方法是在资源视图里找到对应的 Ribbon 分类,而不是只看磁盘上有没有这个文件。
如果 LoadFromResource 返回 FALSE,需要分两类排查:一是资源 ID 写错,二是资源文件里保存的 Ribbon 版本与当前库版本不一致。后一种通常发生在多人协作时,某位成员用不同版本的 BCG 编辑器保存过资源文件。现象是编辑器里打开正常,运行时一片空白。解决方式是统一团队里的 BCG 版本,并把 Ribbon 资源重新保存一遍。
在 MDI 工程中,主框架换成 CBCGPMDIFrameWnd 后,文档子窗口通常不需要替换。只要停靠窗格和主框架用了 BCG 类,就能实现大部分现代界面效果。如果希望子窗口本身也具备功能区,就要把子窗口基类改成对应的 BCG 子窗口类,不过这种做法在 15.1 下会带来更复杂的消息路由和管理状态,除非业务确实需要,否则不建议一开始就做。
3.2 可停靠窗格的创建与 Dock 布局
停靠窗格对应传统 MFC 里的 ControlBar,但 CBCGPDockingControlBar 在行为上更接近现代桌面软件:可以拖拽、停靠、自动隐藏,还可以悬浮成为独立小窗口。创建窗格的典型写法如下:
// MainFrm.h class CMainFrame : public CBCGPMDIFrameWnd { public: CBCGPDockingControlBar m_wndOutput; CListBox m_wndOutputList; // 窗格内的子控件 }; // MainFrm.cpp if (!m_wndOutput.Create( _T("输出"), // 窗格标题 this, // 父窗口 CRect(0, 0, 300, 200), // 初始尺寸 CBRS_LEFT | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY, AFX_CBRS_FLOAT)) // 支持悬浮 { return -1; } m_wndOutput.DockToFrameWindow(CBRS_BOTTOM, this); m_wndOutputList.Create( WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT, CRect(0, 0, 0, 0), &m_wndOutput, 1);Create 里的停靠风格标志是控制行为的关键。CBRS_LEFT/CBRS_RIGHT/CBRS_TOP/CBRS_BOTTOM 决定初始停靠方向;CBRS_GRIPPER 决定标题栏上是否显示可拖拽的把手,没有这个标志窗格会“拖不动”;CBRS_FLOAT 表示允许窗格脱离主框架独立悬浮。DockToFrameWindow 的第二个参数必须传主框架 this,传成文档类或视图类都不会成功,这也是新手常问“为什么停靠没反应”的原因之一。
窗格内的子控件用 WS_CHILD | WS_VISIBLE 创建,父窗口指向停靠窗格本身。子控件尺寸在 Dock 布局之后会被自动重排,所以 Create 里的矩形只是占位,不需要按最终像素精确设计。很多人在这里费心计算矩形,最后发现 Dock 之后还是被重排,不如省下这部分时间。
3.3 命令 ID 与消息路由:把业务代码接入新界面
功能区按钮不会自动调用业务逻辑,需要命令 ID 和 ON_COMMAND 映射正确对应。在编辑器里,按钮有两个关键字段:命令 ID 和图标。程序里对应的消息映射写在主框架类中:
BEGIN_MESSAGE_MAP(CMainFrame, CBCGPMDIFrameWnd) ON_COMMAND(ID_VIEW_OUTPUT, &CMainFrame::OnViewOutput) END_MESSAGE_MAP() void CMainFrame::OnViewOutput() { // 显示或隐藏输出窗格 ShowControlBar(&m_wndOutput, !m_wndOutput.IsVisible(), FALSE, FALSE); }ShowControlBar 是 BCG 框架提供的方法,四个参数分别是目标窗格、显隐状态、是否延迟布局、是否强制显示。这里的 FALSE, FALSE 是保守写法——不延迟,也不强制更新,窗口显示状态由正常 MFC 布局流程处理。如果命令 ID 映射不上,按钮点击后什么都不会发生。排查时先在处理函数入口加输出日志,别直接断言,因为很多按钮的点击会被 BCG 的消息路由提前拦截。日志能快速区分是消息没进入框架,还是进入了框架但没有匹配到处理函数。
如果旧工程原本有菜单和工具栏,在迁移过程中让功能区与旧菜单并存是常见状态。此时要记得,菜单的更新命令 UI 消息同样作用于功能区按钮,二者共用一套命令状态机制。所以不要让旧工具栏和功能区同时创建同一命令的按钮,否则一个界面里会出现两个“启用/禁用”来源,逻辑混乱且难调试。我的做法是迁移期间暂时保留旧工具栏但隐藏它,而不是直接删除代码,这样随时可以回退对比行为差异。
4. 外观定制:主题、视觉管理器与几个必调参数
功能区、停靠窗格在默认状态下已经可以工作,但很多团队接受不了默认外观,尤其是业务系统希望贴近现代办公软件。BCGControlBar Pro 15.1 将外观统一交给视觉管理器(Visual Manager)处理,功能区的按钮、停靠窗格的标题栏、状态栏颜色都来自同一个视觉管理器实例,修改时不用一个个控件去调颜色。
4.1 视觉管理器:换肤不是换颜色,而是换绘制策略
公共配置方法是应用初始化阶段设置一次:
CBCGPVisualManager::SetDefaultManager( RUNTIME_CLASS(CBCGPVisualManagerVS2012));SetDefaultManager 传入一个运行时类指针,指定视觉管理器类。BCG 提供多套内置主题:2007 蓝渐变、2010 渐变、VS2012 扁平深色、接近系统原生的 Windows 风格等。选 VS2012 风格时界面立即变成深色扁平化按钮,菜单项间距收紧;选 2010 风格则保留渐变色。这个设置对之后创建的所有窗口生效,不需要在每个窗格上重复设置。
内置视觉管理器类通常按视觉效果和应用场景来选择,以下是我常用的几个:
| 视觉管理器类 | 风格 | 适用场景 |
|---|---|---|
| CBCGPVisualManagerOffice2007 | 2007 渐变风格 | 商务管理类系统 |
| CBCGPVisualManagerVS2012 | 深色扁平、紧凑 | 工具类软件、开发者工具 |
| CBCGPVisualManagerWindows | 接近系统原生 | 老平台兼容、无边框窗口 |
需要注意:如果工程里同时存在原生 MFC 的 CFrameWnd 子类窗口和 BCG 的 CBCGPFrameWnd 子类窗口,视觉管理器只对后者生效。很多人运行后看到“只换了一半皮肤”,原因就是还有一批窗口没有继承 BCG 窗口基类。解决方法是把老窗口基类逐个改造,或者在迁移前统一窗口基类,把这类半换肤状态尽快消掉。
4.2 功能区按钮布局:大图标、小图标与折叠模式
功能区上的按钮默认显示大图标和文本,实际工程常要根据分辨率调整。控制点有两个:Ribbon 资源编辑器里的按钮属性,和运行时布局模式:
// 运行时切换功能区布局模式 m_wndRibbonBar.SetLayoutMode( BCGP_RIBBON_LAYOUT_MINIMIZED);BCGP_RIBBON_LAYOUT_MINIMIZED 会把功能区折叠成一条窄栏,鼠标点击时才展开,类似现代办公软件的折叠模式。对垂直分辨率有限的窗口作用明显。展开模式下还可以把某个 Panel 的按钮设为“仅图标”或“仅文本”,在编辑器里逐项配置即可。
需要注意,运行时动态调整的布局在窗口尺寸变化时可能被重置。如果要做自适应布局,应该在 OnSize 里重新调用布局相关的方法,而不是依赖功能区内部的默认自适应逻辑。在 15.1 上,功能区对 DPI 变化响应也不算理想,从 100% 缩放到 125% 缩放时按钮可能错位,此时需要显式强制一次布局更新。这类问题在项目演示时最容易暴露,属于“实际用得着、但文档不会强调”的参数。
4.3 自定义视觉管理器的边界与图标暗坑
BCGControlBar Pro 15.1 对图标有明确要求:小图标建议 16x16,大图标建议 32x32,推荐 PNG 而不是 ICO。ICO 在传统工具栏里没问题,但在功能区上经常出现边缘锯齿和透明通道丢失,256 色以下的老式 ICO 尤其严重。另一个是图标资源 ID 不能重复;不同命令指向同一个图标 ID 时,功能区上只能显示同一张图,用户区分不开按钮,误点概率上升。
在皮肤定制上要克制。不建议重写视觉管理器的全部虚函数,绘制方法非常多,遗漏某个分支就会出现“按钮正常但下拉箭头异常”“窗口正常但分隔条异常”这类局部怪异现象。正确做法是继承现成的视觉管理器类,只重写少量方法:
class CMyVisualManager : public CBCGPVisualManagerVS2012 { public: virtual void OnFillRibbonPanel( CDC* pDC, CBCGPRibbonPanel* pPanel, CRect rect); };只重写 OnFillRibbonPanel 控制面板背景。其余绘制逻辑全部交给父类,这样既能做颜色变化,又不会破坏按钮状态反馈、下拉箭头等细节。如果改完外观和预期不符,优先检查是不是覆盖了过多方法,而不是去调整某一处颜色值。
一个相关技巧:变更视觉管理器后,如果功能区出现绘制残留,可以先隐藏功能区再重新显示。处理方式是调用 Reset 方法重建内部缓存。这在 15.1 中属于已知的缓存不一致场景,处理起来比强制重画整个窗口更可控。
5. BCGControlBar Pro 15.1 集成避坑:5 个高频排查记录
这一节集中写我在实操中真正遇到过、并且反复被队友问到的坑。每条按现象、原因、解决来写,方便直接对照。
5.1 链接报错一堆 LNK2019,代码却看起来没问题
现象:头文件包含没报错,链接阶段出现十几条 unresolved external symbol,集中在 BCG 相关类。
原因:BCG 的 Debug 和 Release 静态库是不同的文件,把 Debug 工程链到 Release 库,全部 BCG 符号解析失败;字符集不一致也会导致字符串接口全部解析失败。
解决:分别配置 Debug / Release 的库目录和附加依赖,确认文件后缀与配置匹配;预处理器定义里显式加入 _UNICODE;UNICODE。改完后清理一遍 .pch 和 .idb 再重新编译,避免旧的预编译信息继续生效。
5.2 功能区折叠后无法展开
现象:功能区正常显示,点击折叠箭头后收起,但再次点击没有反应。
原因:常见于切换到自定义视觉管理器时,与折叠状态相关的命中测试方法被覆盖或没有正确处理,折叠后点击区域计算错误,鼠标虽然点在箭头上,但命中测试认为不在可交互区域。
解决:先换回内置视觉管理器测试,如果能正常展开,再排查自定义类里与 Ribbon 交互区域相关的方法。只保留颜色和绘制类重写,不碰区域计算类方法。如果必须重写命中测试,要在新版本头文件中确认方法签名没有变化,避免覆盖失效。
5.3 停靠窗格拖动后出现黑块
现象:停靠窗格拖动时,主框架与窗格交界处出现黑色区域,拖动结束后慢慢消失。
原因:BCG 对窗格做了双缓冲绘制,但窗格内嵌的原生 MFC 控件(如 CListBox)继续执行默认背景擦除,擦除时机与窗格重绘不同步,产生黑块。
解决:在窗格类和子控件的 OnEraseBkgnd 中直接返回 TRUE,不做默认擦除。如果子控件本身需要画背景,把背景绘制逻辑移到 OnPaint 中完成。需要特别注意的是,某些控件库会拦截 OnEraseBkgnd,直接返回 TRUE 可能反而导致重叠区域绘制异常,此时应改用透明控件或自绘子控件。
5.4 发布到旧版系统后功能区字体异常
现象:开发机正常,用户机器上按钮文字变成宋体,字号和行距都变了,Ribbon 排版错乱。
原因:BCG 默认跟随系统 UI 字体,开发机有现代中文字体,用户机器未安装同名字体,系统回退到默认中文字体,导致按钮尺寸和布局全变。
解决:应用初始化时指定界面字体:
CBCGPWorkspace::SetRegFont( _T("Microsoft YaHei"), FONT_ROLE_MAINUI);同时确认目标机器确实安装了对应字体,或者安装包附带字体并完成注册。这类字体问题属于最容易忽略的运行时问题,因为开发机上往往覆盖不了全部用户环境。
5.5 从旧版工程拷贝代码后出现“版本检查失败”断言
现象:旧工程从 14.x 拷贝代码升级到 15.1,编译通过,运行时弹出版本检查断言。
原因:BCG 头文件里有版本检查宏,旧工程的预编译头缓存了旧版本常量,库文件是 15.1,二者不一致触发断言。断言位置通常在 BCG 某个初始化函数内部,堆栈看起来像是在正常流程里突然终止。
解决:删除工程 Debug / Release 目录下的 .pch 和 .idb 文件,重新预编译整个工程;如果工程里混用了其他 BCG 包装库,同步替换到对应版本。这个问题的本质是预编译头缓存,清理掉就正常,不需要改任何代码。
6. 一个值得养成的习惯:先跑模板工程,再整合存量代码
给这次集成留下一个最值得用的习惯:不要直接在存量工程里写 BCG 控件代码,先跑通一个独立的小模板工程。
具体做法是:新建一个空白 MFC 单文档工程,按第 2 章的步骤接入 15.1,添加功能区资源和两个停靠窗格,编译运行确认功能正常,然后把它保存为一个可复用的模板。后续需要添加“属性网格”“任务面板”“自定义状态栏”这些控件时,先在模板里实现并验证,再把代码粘贴到存量工程。这样做最大的好处是分离问题:出错时,你能明确判断是 BCG 配置的问题,还是存量业务代码拦截了消息。
这套流程同样适用于视觉管理器定制。模板工程可以快速验证主题效果,不用反复重启大型存量程序。每次新需求进来时,先花半小时在模板里跑一下相关控件接口,心里有底后再进入正式代码。
保持定期复查自己编写的视觉管理器重写方法也很重要。BCG 的版本升级后,部分绘制方法的签名可能变化,一次复制粘贴会覆盖不到正确的方法,界面局部不绘制。用类向导重新生成覆盖声明,比手工照抄旧代码更稳妥,也能顺便检查签名是否匹配。
我自己在这类界面库上最大的体会是:真正费时间的从来不是某个控件不会用,而是“代码已经改好了但资源没更新”和“链接库版本放错了”这两类环境问题。在模板工程里提前排掉环境因素,迁移速度至少能快出一倍。希望这套方法帮到你。
本文还有配套的精品资源,点击获取