简介:Notepad++ v8.6.6 源代码包面向希望深入理解成熟文本编辑器实现原理的开发者、Windows 程序设计学习者及教学研究人员。资源基于 Windows API 与 Scintilla 编辑控件构建,涵盖语法高亮定义、插件加载与管理、多文档界面等核心模块,适合具备一定 C++ 基础、想研究编辑器架构或定制自有版本的中高级开发者。压缩包共约 2000 个文件,体积 11.48MB,以 h 头文件、hpp、cpp、cxx 等 C++ 源码为主体,辅以 ico、bmp、png 等界面资源,xml、properties、styled、folded 等语法与配置定义,以及 py、rb、lua、pl 等多语言脚本和 rc、mak、vcxproj 等构建文件,目录结构完整。目前已有 877 人学习下载。通过研读可掌握 Windows 消息处理机制、Scintilla 接口调用与事件扩展、插件通信机制,并借鉴大文件打开优化与内存管理思路,对教学研究或自研编辑器均有参考价值。
1. 拿到 Notepad++ v8.6.6 源码之后:一个 Windows 桌面文本编辑器的完整编译链路
很多人第一次拿到 Notepad++ v8.6.6 源代码时,第一反应是「这不就是个记事本吗,能有多复杂」。真把压缩包解开、打开解决方案文件那一刻,才会发现这是一个用 C++ 写、依赖 Scintilla 编辑控件、跑在 Win32 API 上的完整桌面应用,光工程配置就够看半天。它解决的核心问题很具体:你想改一个菜单项、加一个语法高亮规则、换掉某个插件的加载逻辑,或者单纯想搞清楚一个成熟 Windows 编辑器是怎么组织的,就必须从源码编译开始。这篇文章面向的是愿意动手的开发者——不管你是刚接触 Win32 编程的新手,还是想给编辑器做二次开发的老手,下面这套从环境准备到编译排错的路径都能直接照着走。
2. 编译环境怎么搭:工具链选型和依赖关系
2.1 为什么是 Visual Studio 而不是别的
Notepad++ 的官方工程文件是.sln加.vcxproj格式,这是 Visual Studio 的原生工程格式。你当然可以尝试用 CMake 重新组织,但那是另一项工作量,而且会丢掉官方工程里已经配好的预处理器宏、字符集设置和链接选项。常见做法是直接用 Visual Studio 打开,让 IDE 帮你处理这些配置。
版本选择上有个实际约束:Notepad++ v8.x 系列用的是较新的 C++ 标准库特性,同时 Scintilla 组件对 Windows SDK 版本有要求。我一般会选 Visual Studio 2022 社区版,配合 Windows 10 或 11 SDK。如果你手头只有 2019,多数情况下也能编译,但可能遇到个别标准库头文件缺失的报错,那时候再补装对应组件即可。
安装 Visual Studio 时,工作负载要勾选「使用 C++ 的桌面开发」,右侧的安装细节里确认这几项:
- MSVC v143 生成工具(或与你 VS 版本对应的工具集)
- Windows 10/11 SDK
- C++ ATL(Notepad++ 部分模块用到)
- C++ MFC(某些对话框资源依赖)
少装 ATL 或 MFC 是新手最常见的翻车点,报错信息往往指向某个atlbase.h找不到,看起来像源码问题,其实是组件没装。
2.2 源码目录结构先看懂再动手
解压后的目录大致是这样几块:
| 目录/文件 | 作用 |
|---|---|
PowerEditor/src/ | Notepad++ 主程序源码,核心逻辑都在这里 |
PowerEditor/visual.net/ | Visual Studio 工程文件所在位置 |
scintilla/ | Scintilla 编辑控件源码,独立子项目 |
lexilla/ | 词法分析器集合,负责各种语言的语法高亮 |
boostregex/ | 正则表达式相关依赖 |
主程序并不直接包含 Scintilla 的全部实现,而是通过工程引用把 Scintilla 编译成静态库再链接进来。这意味着你不能只编译主工程,必须让解决方案一次性构建所有依赖项目。打开.sln之后,解决方案资源管理器里会看到多个项目,正确的做法是右键解决方案选「生成解决方案」,而不是单独生成某一个项目。
2.3 第一次编译的完整命令路径
如果你习惯命令行,也可以用 MSBuild 来构建。先找到 VS 自带的开发者命令提示符,或者手动调用:
:: 进入 VS 安装目录下的 MSBuild :: 路径按你的实际安装位置调整 "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" ^ "PowerEditor\visual.net\notepadPlus.sln" ^ /p:Configuration=Release ^ /p:Platform=x64 ^ /m这段命令的含义逐项说明:/p:Configuration=Release指定发布配置,调试阶段可以换成Debug;/p:Platform=x64指定 64 位平台,Notepad++ 同时支持 Win32 和 x64,选哪个取决于你的目标;/m开启多核并行编译,能明显缩短构建时间。第一次编译建议先用 Debug 配置,因为出错时调试信息更完整。
编译成功后,输出文件通常在PowerEditor\bin.x64\或对应的bin\目录下,会看到notepad++.exe以及一堆语言配置文件。直接双击运行,如果闪退,多半是缺少某个运行时 DLL 或者配置文件路径不对。
提示:首次编译前把杀毒软件的实时扫描暂时关掉,MSBuild 频繁读写中间文件时容易被拦截,表现为编译卡死或随机报文件占用。
3. 源码里几个关键模块:改哪里、怎么改
3.1 Scintilla 与 Lexilla 的分工
Scintilla 负责编辑器的底层能力:文本缓冲区、光标、选区、滚动、撤销重做。Lexilla 负责词法分析,也就是把文本切成关键字、注释、字符串这些 token,再交给 Scintilla 上色。两者是分离的,这个设计意味着你加一门新语言的语法高亮,主要工作在 Lexilla 侧,不需要动 Scintilla 核心。
具体到代码,lexilla/lexers/目录下每个Lex*.cxx文件对应一种语言。比如你想给某个自定义配置格式加高亮,可以复制一个结构相近的 lexer 文件作为模板,改掉关键字表和状态机逻辑,然后在lexilla/src/Lexilla.cxx里注册这个新 lexer。注册这一步容易漏,漏了之后编译能过,但运行时编辑器根本找不到你的 lexer。
3.2 主程序里菜单和命令的响应链
Notepad++ 的菜单项定义在资源文件.rc里,命令 ID 定义在menuCmdID.h之类的头文件中,响应函数则在主窗口类里通过消息映射关联。想加一个菜单项,需要同时改三处:资源文件加菜单文本和 ID、头文件加 ID 宏定义、消息映射里加处理函数。只改资源文件不改消息映射,菜单能显示但点了没反应,这是很典型的「看起来对但就是不动」的问题。
3.3 插件接口的加载时机
Notepad++ 的插件是 DLL 形式,主程序启动时扫描插件目录并加载。源码里插件管理相关的逻辑集中在PowerEditor/src/PluginsManager.cpp一类文件中。如果你在调试插件加载问题,可以在加载函数入口下断点,观察 DLL 路径拼接是否正确、导出函数是否按约定命名。插件 DLL 必须导出特定的函数名,名字不对会被静默跳过,不报错,只是插件列表里看不到。
4. 编译和运行阶段的避坑清单
4.1 报错「无法打开包括文件 atlbase.h」
现象:编译刚开始就报找不到 ATL 相关头文件。原因:Visual Studio 安装时没有勾选 C++ ATL 组件。解决:打开 Visual Studio Installer,修改当前安装,在单个组件里搜索 ATL 并勾选安装,重启 VS 后重新编译。
4.2 链接阶段报大量 LNK2019 未解析外部符号
现象:编译通过,链接时报一堆找不到符号。原因:通常是 Scintilla 或 Lexilla 子项目没有先编译成功,或者平台配置不一致(主工程 x64 而子项目 Win32)。解决:确认解决方案配置管理器里所有项目的平台设置一致,然后清理解决方案重新完整生成。
4.3 编译成功但运行闪退
现象:exe 生成了,双击一闪而过。原因:常见的是工作目录不对,程序找不到语言配置文件或主题文件。解决:不要直接双击 bin 目录下的 exe,而是从 VS 里按 F5 启动,或者把 exe 放到包含完整配置文件的目录下运行。用调试器启动还能直接看到崩溃时的调用栈。
4.4 改了源码但行为没变化
现象:明明改了代码重新编译,运行结果和之前一样。原因:MSBuild 的增量编译有时没检测到某些头文件变更,或者你改的文件根本不在当前编译的配置里。解决:先「清理解决方案」再「重新生成解决方案」,确认输出目录的时间戳确实更新了。另外检查你改的是不是被条件编译宏排除掉的代码分支。
4.5 中文路径导致编译异常
现象:源码放在含中文的路径下,编译报奇怪的编码错误。原因:部分构建脚本和工具链对非 ASCII 路径处理不完善。解决:把源码移到纯英文、无空格的路径下,比如D:\dev\notepad-src\,这是最省事的做法。
5. 从能编译到能改:一个具体的小改动练手
5.1 修改默认字体大小
找到主程序里初始化编辑器样式的代码,通常在窗口创建后设置 Scintilla 属性的位置。搜索类似SCI_STYLESETSIZE的调用,把默认字号值改掉。改完重新编译,启动后新建文档就能看到效果。这个改动足够小,适合验证整条编译链路是否真的通了。
5.2 加一条自定义语法高亮规则
在 Lexilla 里找一个简单的 lexer 文件,复制一份改名,修改关键字列表,然后在 Lexilla 注册表和 Notepad++ 的语言配置里各加一条对应项。语言配置是 XML 格式,放在PowerEditor/bin/langs.xml一类文件里。这一步涉及跨模块改动,能跑通说明你对整个工程结构已经有基本把握。
5.3 验证改动是否生效的检查点
编译产物时间戳是否更新、运行后行为是否变化、调试器里断点是否命中你改的那行代码。三个检查点都过了,才算真正改成功。只看到编译通过就以为改好了,是新手最容易踩的坑。
6. 进阶:调试技巧和二次开发的边界
调试一个成熟的 Win32 应用,光靠打印日志效率很低。我一般会在关键路径上直接下断点,比如窗口过程函数、命令分发函数、插件加载函数。Visual Studio 的调用栈窗口和监视窗口配合用,能快速定位问题出在哪一层。如果崩溃发生在 Scintilla 内部,先确认是不是自己传入了非法参数,多数崩溃根源在调用方而不是控件本身。
二次开发有几个现实边界要知道。第一,Notepad++ 的插件接口是稳定的,但主程序内部函数没有导出,想直接调用主程序内部逻辑基本不可行,正确做法是通过插件接口或者自己维护一个分支。第二,升级源码版本时,你改过的文件可能和官方更新冲突,建议把自己的改动集中放在少数几个文件里,并且用版本控制工具管理,方便合并。第三,发布自己编译的版本涉及许可证合规问题,动手前先看清楚源码附带的许可证条款。
一个我养成的习惯:每次改源码前先完整编译一次原始版本,确认基线是通的,再开始改。这样一旦出问题,能立刻判断是自己改坏的还是环境本来就有问题。这个习惯帮我省下过很多排查时间。希望帮到你。
本文还有配套的精品资源,点击获取