news 2026/10/6 13:58:44

Notepad++ v8.6.6 源码构建与二次开发实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Notepad++ v8.6.6 源码构建与二次开发实战指南

简介:Notepad++ v8.6.6 源代码是一份面向进阶开发者的学习型资源,适合希望通过真实项目理解 Windows 原生文本编辑器实现原理的程序员,也适合作为软件工程课程或源码分析项目的参考。该版本基于 Windows API 和 Scintilla 文本编辑控件构建,核心覆盖语法高亮规则文件、插件管理器、消息处理与多文档界面等机制,能帮助读者搞懂轻量级编辑器如何实现高效响应与多语言支持。压缩包内共 2000 个文件,以 h/hpp/cpp/cxx 等 C++ 源码为主,并包含 xml/styled/folded 语法定义、ico/bmp 界面图标以及多平台构建脚本,总大小约 11.48MB,目录结构完整,便于按模块检索。已有 877 人学习下载。通过对照源码可重点研究 Scintilla 的调用与事件扩展、插件加载通信、折叠与自动完成实现,以及 v8.6.6 在内存管理和用户体验上的细节改进,为自行开发插件、二次定制或深入研究 Windows 程序设计打下扎实基础。

1. Notepad++ v8.6.6 源代码:一份能编译、能改动、能学习的 GPL 项目

手头只有一个装好的 notepad++.exe,遇到一个诡异 bug 时只能干瞪眼:菜单行为不对,想加个快捷键,找不到配置项,想给右键菜单加个入口,翻遍偏好设置也没有——这时候你会特别想要源代码。Notepad++ v8.6.6 源代码就是这条退路:它不是一个“看看架构”的阅读材料,而是一份能本地编译出可运行 exe、能定位问题、能按自己需求改功能的完整原生 Windows 工程。它基于 Scintilla 编辑组件,整体以 GPL v3 协议发布,面向三类人:想自己构建最新稳定版而不是到处找安装包的人,想二次开发插件或改界面的人,以及想读一份大型原生 Win32 应用源码来提升 C++ 功力的人。这篇笔记从拉取源码开始,一路讲到构建、读码、踩坑和进阶改造,全部是实操路径。

2. 把 v8.6.6 源码拿到本地:仓库结构、版本核对与两种获取方式

2.1 源码仓库长什么样:PowerEditor 主目录与 Scintilla 组件

Notepad++ 的源码托管在官方 GitHub 仓库中,仓库名就是 notepad-plus-plus。整个工程不是一个单一项目文件,而是由几块拼起来的:主程序逻辑、编辑器内核、插件接口、安装脚本和测试用例。第一次进去最容易懵的是看到一堆目录,不知道入口在哪。

常见做法是先认清两个核心目录。PowerEditor 是主程序的家:src 下是 C++ 源码,visualstudio 下是 Visual Studio 解决方案,installer 下是安装包制作脚本,themes、localization 这些是资源目录。另一个必须认识的是 Scintilla,它不属于 Notepad++ 团队,而是一个独立的开源编辑控件库,Notepad++ 的编辑区就是它。v8.6.6 源码里把 Scintilla 一并放进仓库,是为了保证构建时可复现——你不需要另外去下载匹配版本的 Scintilla。

先拉一次仓库看结构,建议用下面命令:

git clone --depth 1 --branch v8.6.6 https://github.com/notepad-plus-plus/notepad-plus-plus.git cd notepad-plus-plus ls

这里--depth 1表示只拉最新一条提交,不带历史记录,省流量也省时间;--branch v8.6.6直接切到对应版本标签。如果你只是要编译这个版本,浅克隆足够。克隆完成后ls能看到上面说的 PowerEditor、Scintilla 等目录。真正的“源代码管理”从这里开始:之后每次想升级到更新版本,不用重新下载 zip,直接git fetch再切 tag 就行。

2.2 用 git 拉取指定版本:tag 核对与 zip 快照的区别

如果你不想装 git,或者只需要一次性查代码,GitHub 页面上的 “Download ZIP” 也能拿到 v8.6.6 的完整源码快照。这个方式胜在简单,但有两个明显短板:一是没有版本历史,二是不方便对比 v8.6.5 到 v8.6.6 到底改了哪些文件。对只想编译的人来说无所谓,对想跟踪上游修复的人来说就差很多。

拉完代码后必须做一次版本核对,否则很容易出现“以为在 v8.6.6 上改代码,实际切错分支”的翻车现场。核对命令很简单:

git describe --tags git log -1 --oneline

git describe --tags会输出当前 HEAD 最近的标签名,比如v8.6.6。如果输出的是v8.6.5-xxx,说明你不在目标版本上。git log -1 --oneline显示最近一条提交,可以和你拿到的发布说明对照提交时间。这一步千万别跳——我在帮同事排查时遇到过好多次,对方信誓旦旦说“源码是 8.6.6”,一查 tag 停在半年前,问题自然是已经修过的旧 bug。

提示:浅克隆(--depth 1)只有一个提交,想看 v8.6.6 和 v8.6.5 的差异,需要去掉 --depth 重新完整克隆,或者把浅克隆的深度加大。临时想对比,也可以只拉两个 tag:git fetch --depth 1 origin tag v8.6.5。

3. 从源码构建 Notepad++:工具链、完整流程与产物识别

3.1 构建前要装齐的依赖:VS、Boost、GnuWin32 与 Python

Notepad++ 是原生 Windows 应用,构建工具链以 Visual Studio 为核心,但完整构建不止需要 VS。下面这张表是我每次在干净机器上从零构建前对照检查的清单,按“缺了会怎样”排了优先级。

依赖用途是否必需缺失时的典型表现
Visual Studio 2022/2019,勾选“使用 C++ 的桌面开发”编译主程序与插件必需找不到 MSBuild、cl.exe
Windows SDK(随 VS 安装)系统头文件与库必需一堆 windows.h 相关报错
Boost C++ 库字符串处理、文件系统等必需找不到 boost 头文件
GnuWin32 的 make构建 Scintilla 组件必需make 不是内部或外部命令
Python 3部分生成步骤/脚本常见做法脚本运行失败或跳过
HTML Help Workshop生成 chm 帮助文档可选文档相关目标跳过即可

这里最容易踩的第一个坑是 Boost 版本。Notepad++ 官方构建文档会写一个推荐的 Boost 版本,不是“越新越好”。新版本 Boost 偶尔会调整头文件布局或内部接口,直接导致编译中断。我一般会先按 BUILD 文档指定的大版本装,比如 1.8x 系列,然后把 Boost 根目录放到一个稳定路径,方便设置环境变量。GnuWin32 则相对冷门,它是 Windows 上运行 GNU make 的经典方案,构建 Scintilla 时会被预构建事件调用。

3.2 用命令行编译:从零到产出 notepad++.exe

依赖装齐后,最稳的做法是打开 “x64 Native Tools Command Prompt for VS 2022”,这个终端会把 MSBuild、cl.exe 等工具链环境都配好,避免你自己拼 PATH。然后进入源码目录执行构建:

cd notepad-plus-plus\PowerEditor\visualstudio msbuild PowerEditor.sln /p:Configuration=Release /p:Platform=x64 /m -verbosity:minimal

/p:Configuration=Release指定发布版,比 Debug 版体积小、行为更接近官方;/p:Platform=x64指定 64 位目标,如果你的系统是 32 位或要兼容老旧机器,改成 Win32;/m是多核并行编译,能明显缩短时间。-verbosity:minimal让输出只显示错误和关键信息,不然刷屏能刷到怀疑人生。

首次构建耗时大概几分钟到十几分钟,取决于机器核数和磁盘速度。见到Build succeeded后,在PowerEditor\bin\Release(也可能是PowerEditor\bin下按平台分子目录,具体看解决方案输出路径设置)找 notepad++.exe。这里有个很多新手会忽略的点:编译产物不只是那一个 exe,而是整整一个目录。直接把 exe 拖到桌面双击,十有八九起不来,因为旁边的 SciLexer.dll、plugins、themes、localization 都是运行时依赖。

3.3 构建输出与常见产物:哪个 exe 才是你要的

构建完成后你手里其实多了一整棵可运行目录,对照下面这个清单认识它们:

路径/文件作用
notepad++.exe主程序入口
SciLexer.dllScintilla 编辑控件运行时,缺了它编辑器区空白
plugins/ 目录插件存放处,自带部分官方插件
themes/ 目录配色主题
localization/ 目录多语言翻译文件

官方安装包的原理,就是把这一整套目录打包成安装器。你完全可以把构建出来的bin目录直接当一个免安装版用——这就是网上常见的 notepad++ zip 绿色版的来源。与其下载别人打的绿色包,不如自己构建一份,至少能确认文件来源和版本。如果发现程序启动后菜单还是英文、语言切换无效,优先检查 localization 是否在 exe 同级目录下。

提示:Debug 版和 Release 版的行为在一些场景下会不一样,尤其是涉及优化和计时的地方。排查崩溃、内存问题时可以用 Debug 版,日常使用和性能验证请用 Release 版。

4. 读懂这版源码的三个入口:启动流程、Scintilla 与插件协议

4.1 从 WinMain 跟到主窗口:消息循环与 NppData

构建跑通只是开始,真正的价值在于改源码。第一次读 Notepad++ 源码,不建议从某个功能菜单开始追,那会陷进调用链深坑。先找三个入口,把骨架立起来。

第一个入口是 WinMain。它在 PowerEditor/src 下的主程序文件里。你可以在这个函数里看到整个应用的启动顺序:解析命令行参数、初始化 Scintilla 窗口、创建主窗口、注册并加载插件、进入消息循环。Windows 原生程序的脉搏就是消息循环,Notepad++ 的很多行为——比如切主题、改语言、插件回调——都能在消息处理里找到对应分支。

插件拿到的 NppData 结构体也在这个阶段成型。它其实不是复杂对象,就是四个窗口句柄打包在一起:

struct NppData { HWND _nppHandle; // 主窗口句柄 HWND _scintillaMainHandle; // 当前文档的编辑区句柄 HWND _scintillaSecondHandle; // 分栏后的第二个编辑区句柄 HWND _pluginHandle; // 插件自己的窗口句柄 };

读到这里,很多让人觉得“黑匣子”的事情就通了:插件之所以能操作当前文档,全程只需要拿_scintillaMainHandle去发 Windows 消息,并不需要什么秘密接口。这也是 Notepad++ 插件协议能保持几十年兼容的底气。

4.2 Scintilla 封装层:编辑器的核心边界

第二个入口是 Scintilla。Notepad++ 自己不实现文本渲染、光标管理、语法高亮这些底层的活,全交给 Scintilla。源码里你会频繁看到SendMessage调用,目标就是编辑区句柄。学习这套接口的节奏,重点不是记住每个 SCI 消息号,而是理解三个门类:

  • 文本操作类:SCI_GETTEXT、SCI_SETTEXT、SCI_GETCURRENTPOS
  • 样式与高亮类:SCI_STYLESETFONT、SCI_SETLEXER
  • 标记与折叠类:SCI_MARKERADD、SCI_FOLDALL

下面是一段常见的按语言名切换语法高亮的代码:

LRESULT msgRes = SendMessage(hScintilla, SCI_SETLEXER, SCLEX_CPP, 0); if (msgRes == 0) { SendMessage(hScintilla, SCI_SETKEYWORDS, 0, (LPARAM)"int char float if else while return"); }

逻辑说明:第一行把 Scintilla 的 lexer 切到 C++ 模式,第二行把关键字列表传给分词器。参数里SCLEX_CPP是 Scintilla 预定义的语言枚举值,SCI_SETKEYWORDS的wParam=0表示设置第 0 组关键字,不同语言可以分多组。实际使用时,你还会配合 SCI_STYLESETFONT 设置字体、SCI_STYLESETFORE 设置前景色,才能做出完整高亮效果。想验证效果,直接用 PowerShell 发消息不现实,最方便的是写一个几十行的 C++ 小程序,加载 Scintilla 窗口后再发消息。

4.3 插件协议与 Python Script:最小插件骨架

第三个入口是插件协议。Notepad++ 的插件本质是一个动态库,导出几个特定函数让主程序调用。读懂这个协议,你就能给自己写任何自定义功能。核心是四个导出函数,新版插件还要提供卸载入口:

extern "C" __declspec(dllexport) void setInfo(NppData nppData); extern "C" __declspec(dllexport) const TCHAR* getName(); extern "C" __declspec(dllexport) FuncItem* getFuncsArray(int* nbF); extern "C" __declspec(dllexport) void beNotified(SCNotification* notify);

逻辑说明:setInfo在主程序加载插件时调用一次,NppData 在这里被保存为全局变量;getName返回插件显示名;getFuncsArray返回一个功能菜单项数组,每个 FuncItem 对应菜单里的一行;beNotified用于接收编辑事件通知,比如 SCI 的 SCN_MODIFIED。

很多不写 C++ 的人会问:那我用 Python Script 插件不行吗?当然行,notepad++ 插件 python script 用法已经很成熟,适合自动化日常操作,比如批量转码、正则处理、文件头插入。但它运行在插件提供的脚本环境里,拿不到主程序内部数据结构,只能操作编辑区。想改菜单、想拦截主程序行为、想优化性能,还是得回到 C++ 插件这层。我的建议是:轻量自动化用 Python Script,正式功能开发直接写 C++ 插件。

5. 源码构建避坑排查:五个高频问题的现象、原因与解决

5.1 现象一:msbuild 报错找不到 Boost 头文件

现象:编译执行到一半,输出大量C1083: 无法打开包括文件: "boost/...",整个 C++ 项目直接失败。原因基本是 Boost 没装,或者装了但 Visual Studio 不知道上哪儿找。解决方式分两步:先确认 Boost 确实存在,再把路径告诉编译器。命令行下最直接的是建一个环境变量:

$env:BOOST_ROOT = "C:\local\boost_1_84_0" $env:PATH = "$env:BOOST_ROOT\lib64-msvc-14.3;$env:PATH"

说明:BOOST_ROOT是 Boost 官方推荐的变量名,Visual Studio 的工程属性里通常会引用它来拼 include 路径。如果你的 VS 版本是 2022,对应工具集是 v143,Boost 预编译库目录可能是lib64-msvc-14.3或lib64-msvc-14.2,按实际装到的目录写。设置后重启命令行再编译,注意环境变量只在当前会话生效。

5.2 现象二:构建过程中提示 make 不是内部或外部命令

现象:前几步好好的,一到 Scintilla 相关目标就停住,提示找不到 make。原因:Notepad++ 解决方案的预构建事件会调用 GNU make 来编 Scintilla,Windows 系统本身不带 make,需要另外装 GnuWin32。解决:下载 GnuWin32 的安装包,装完把C:\Program Files (x86)\GnuWin32\bin加入系统 PATH。装完在任意终端敲make --version,能输出版本号就说明环境通了。这个问题的隐蔽点在于:不是每次构建都会触发,只有 Scintilla 需要重编时才会调用 make,所以有的人第一次能过、第二次就挂。

5.3 现象三:编译成功但 notepad++.exe 启动报 0xc000007b

现象:构建显示成功,双击 exe 弹出“应用程序无法正常启动 0xc000007b”,或者一闪而过。原因大多数是两种:一是把 exe 单独拷出来了,旁边的 SciLexer.dll 没跟上;二是构建的 x64 版本和你系统的运行环境不匹配,比如 64 位 exe 加载了 32 位 DLL。解决:先不要拷贝,直接在构建输出目录里运行;确认 SciLexer.dll 和 exe 在同一个目录;再用依赖查看器确认加载的 DLL 位数一致。这条是最常见的“编译成功但没法跑”翻车点,遇到时先怀疑缺文件,再怀疑位数。

5.4 现象四:自编译版本被杀毒软件或 SmartScreen 拦截

现象:源码构建的 exe 第一次运行,Windows Defender 提示检测到风险,或者 SmartScreen 显示“已阻止此应用”。原因:自编译的 exe 没有正规代码签名,数字签名是空的,加上行为特征与官方版不完全一致,容易被启发式引擎误报。解决:开发机器上把构建目录加入 Defender 排除项,或者临时关闭实时防护,跑通后再打开。如果要分发给团队或用户,就该考虑购买代码签名证书了。这条算不上源码 bug,但第一次自编译的人十有八九遇到,别慌着怀疑自己代码有毒。

5.5 现象五:基于源码改动后二次分发,GPL v3 合规红线模糊

现象:你改了源码、编译出自己的版本,打算发给同事或放内网共享,但不知道该附什么东西。原因:Notepad++ 以 GPL v3 协议发布,GPL 要求分发二进制时同时提供对应源代码,或者提供书面的源码获取说明。解决:改过的源码和构建配置一起放在项目仓库里;分发时把仓库地址或源码包路径写清楚;不要混淆“绿色版”和“闭源修改版”——绿色版只改了分发形态,源码照样要公开。另外,修改版不要继续冒充官方版本,名称和图标最好区分开,这是基本尊重。

6. 吃透源码后的进阶路径:改版本号、自构建绿色版、验证发布

编译、阅读、排错之后,真正让这份源码产生价值的是改完还能用。我建议从最小改造开始验证你的工具链:在源码里搜版本号资源文件,通常是以 .rc 结尾的资源脚本,搜8,6,6或8.6.6字样,把它改成你的自定义版本号,比如8,6,6,100,重新编译。改完在 exe 属性-详细信息里能看到版本号变化,说明源码改动到构建产物的链路是通的。这一步虽小,但它是所有后续二次开发的地基。

更实用的一条路径是维护自己的免安装构建。网上经常有人找 notepad++ zip 绿色版,其实最干净的做法是自己构建后压缩 bin 目录,加一个 setup 脚本用来写右键菜单和文件关联。这样每次官方发新版本,你只要把新 tag 拉下来重编一遍,就能得到内部统一版本的发行包,比下载别人打的包放心得多。

最后不要忽略验证。每次构建完,我至少跑一遍冒烟清单:启动程序、打开一个 5 万行的日志文件、切换两三种语言高亮、加载 Python Script 插件、执行一次简单替换、正常退出。这套流程五分钟不到,能拦住大半发版事故。我踩过的最大教训是图省事只跑 Debug 版验证,结果给同事的 Release 版在退出时偶发崩溃——从那以后,验证一律用 Release,发布之前还要专门测一次退出路径。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 13:58:44

绩效管理指标体系设计全流程:从战略解码到落地的进阶指南

管理咨询项目里,绩效管理体系设计是被客户点名率最高的需求之一。但我做了这么多年咨询,见过太多企业把“做绩效”等同于“定指标、打分、发奖金”,方案做得漂漂亮亮,落地三个月就变形。这篇就当是给刚入行或者正在往进阶走的咨询…

作者头像 李华
网站建设 2026/10/6 13:58:44

Go泛型深度解析:类型参数、约束与性能实践

今天这篇是《每日一Go》系列的第33篇,也是我私心觉得整个 Go 深入系列里最容易被低估的一篇:泛型。Go 1.18 发布泛型到现在已经过了一轮大版本迭代,社区的风向也从“这玩意儿到底有没有用”变成了“这玩意儿到底怎么用才对”。如果你还停留在…

作者头像 李华
网站建设 2026/10/6 13:58:44

用Python构建FVTracker:基金估值偏差跟踪工具实战

每天下午两三点,我都要打开基金App,盯一眼盘中估值,再翻到昨晚公布的实际净值,心算一下两者差了百分之几。做这事时间长了,手算速度倒是练出来了,时间也悄悄耗掉了。后来干脆用Python写了个小工具&#xff…

作者头像 李华
网站建设 2026/10/6 13:58:23

从HTTP到Express:路由与中间件原理及工程实践

1. 内容整体设计与思路拆解 凡是写过原生 Node.js 接口的人,应该都有过这种体验:用 http.createServer 创建一个服务,然后对着 req.url 做字符串判断,再手工设置响应头,把返回数据 JSON.stringify 之后塞进 res…

作者头像 李华
网站建设 2026/10/6 13:56:43

LinearLayout 布局优化:layout_weight、gravity 与嵌套性能避坑指南

做了这么多年 Android,如果让我选一个"看起来最简单、实际最容易出问题"的控件,LinearLayout 一定排在前面。几乎每个人写的第一个布局都是它:拖两个按钮,设一个 android:orientation"horizontal" &#xf…

作者头像 李华