1、Notepad++介绍
Notepad++是一个台湾人使用C++开发的开源免费的文本编辑器,它是一个多国语言版的编辑器,包含简体中文,使用它可以方便地编辑C、C++、Java、C#、XML、HTML、PHP、CSS等等纯文本文件,支持正则搜索、文件夹搜索、编码转换、文件比较等,可以媲美UltraEdit;关键的支持插件开发。
官方网站的地址是:http://notepad-plus-plus.org/
Sourceforge地址:http://sourceforge.net/apps/mediawiki/notepad-plus
另外,Npp是基于开源控件Scintilla 开发的。
Scintilla官网地址:http://www.scintilla.org/
2、Notepad++插件实现
之前开发的一个自动测试的项目,由于各种流程、界面以及报告都是以XML脚本的方式定义的,项目实施时需要经常编辑脚本,就个实施工程师推荐这个小巧方便的编辑工具,评价还不错。
最近实施的一个项目中需要把大量的格式不一致的excel和word文档编辑成项目格式的XML文档,一个一个的编辑实在麻烦、工作量大,为了减轻实施的工作量,决定给Notepad++开发一个插件。
在Sourceforge中,相关文档已经详细的说明了插件开发的方式,基本都是英文的。Npp提供了对多种语言开发的插件的支持,包括C#、VC++/MFC、DELPHI等。看了C#的比较麻烦,MFC的简单易开发,就选了用VC做。
插件开发说明地址:
http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Plugin_Resources
其中有plus-demo可下载,详细介绍页面地址:
http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Plugin_Development
主要Scintilla控件接口介绍页面:
http://www.scintilla.org/ScintillaDoc.html
插件接入方式主要是消息和函数指针。主要包含四个头文件:Notepad_plus_msgs.h(npp消息定义)、menuCmdID.h(菜单项ID定义)、 Scintilla.h(Scintilla控件消息定义)、PluginDefinition.h(插件接口定义);
插件接口定义如下:
// Copyright (C)2003 Don HO <donho@altern.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H
#include <windows.h>
#include " NppPlugin_Scintilla.h "
#include " NppPlugin_Msgs.h "
#include " NppPlugin_MenuCmdID.h "
const int nbChar = 64;
typedef const TCHAR * (__cdecl * PFUNCGETNAME)();
typedef struct _NppData {
HWND _nppHandle;
HWND _scintillaMainHandle;
HWND _scintillaSecondHandle;
} NppData;
typedef void (__cdecl * PFUNCSETINFO)(NppData);
typedef void (__cdecl * PFUNCPLUGINCMD)();
typedef void (__cdecl * PBENOTIFIED)(SCNotification *);
typedef LRESULT (__cdecl * PMESSAGEPROC)(UINT Message, WPARAM wParam, LPARAM lParam);
typedef struct _ShortcutKey {
bool _isCtrl;
bool _isAlt;
bool _isShift;
UCHAR _key;
} ShortcutKey;
typedef struct _FuncItem {
TCHAR _itemName[nbChar];
PFUNCPLUGINCMD _pFunc;
int _cmdID;
bool _init2Check;
ShortcutKey *_pShKey;
} FuncItem;
typedef FuncItem * (__cdecl * PFUNCGETFUNCSARRAY)( int *);
// You should implement (or define an empty function body) those functions which are called by Notepad++ plugin manager
extern " C " __declspec(dllexport) void setInfo(NppData);
extern " C " __declspec(dllexport) const TCHAR * getName();
extern " C " __declspec(dllexport) FuncItem * getFuncsArray( int *);
extern " C " __declspec(dllexport) void beNotified(SCNotification *);
extern " C " __declspec(dllexport) LRESULT messageProc(UINT Message, WPARAM wParam, LPARAM lParam);
extern " C " __declspec(dllexport) BOOL isUnicode();
#endif // PLUGININTERFACE_H
插件接口实现如下:
#include " StdAfx.h "
#include " NppPlugin_StdApi.h "
#include " NppPlugin_XmlEditor.h "
// 插件名称
extern TCHAR* thePluginName;
// 函数表指针
extern FuncItem* theFuncArray;
// 数据指针
extern NppData* theNppData;
// api setInfo
extern " C " __declspec(dllexport)
void setInfo(NppData notpadPlusData)
{
(*theNppData) = notpadPlusData;
}
// api getName
extern " C " __declspec(dllexport)
const TCHAR * getName()
{
return thePluginName;
}
// api getFuncsArray
extern " C " __declspec(dllexport)
FuncItem * getFuncsArray( int *nbF)
{
*nbF = FUNC_COUNT;
return theFuncArray;
}
// api beNotified
extern " C " __declspec(dllexport)
void beNotified(SCNotification *notifyCode)
{
}
// api messageProc
extern " C " __declspec(dllexport)
LRESULT messageProc(UINT nMessage, WPARAM wParam, LPARAM lParam)
{
if (nMessage == WM_MOVE)
{
// ::MessageBox(NULL, "move", "", MB_OK);
}
return TRUE;
}
// api isUnicode
extern " C " __declspec(dllexport)
BOOL isUnicode()
{
return TRUE;
}
其中主要需要实现setInfo、getName、getFuncsArray、isUnicode,如有需要消息反馈可实现messageProc;另外,在插件dll加载时还需要一些初始化操作以及x卸载时的释放操作,所有添加有XmlEditorInit函数和XmlEditorCleanUp函数,该两函数在dll的CWinApp的InitInstance和ExitInstance函数中分别调用即可。
主体功能实现在接口指针结构体数组的实现,一下为功能主体实现接入部分源代码。
头文件:
* NppPlugin_XmlEditor.h
*
* Copyright (c)2012,
*
* 2012-10-10 V1.0 lizhi<msn:ddgooo@hotmail.com> created
*
*/
#pragma once
// 枚举API ID
enum FUNCITEM_ID
{
FUNC_PASTE_SHEET_HEADER = 0,
FUNC_PASTE_SHEET_ATTENTION,
FUNC_PASTE_SHEET_CONTENT,
FUNC_COUNT,
};
// 初始化
void XmlEditorInit(HANDLE hModule);
// 清除
void XmlEditorCleanUp( void);
实现文件:
* NppPlugin_XmlEditor.cpp
*
* Copyright (c)2012,
*
* 2012-10-10 V1.0 lizhi<msn:ddgooo@hotmail.com> created
*
*/
#include "StdAfx.h"
#include "NppPlugin_XmlEditor.h"
#include "XmlEditor_Function.h"
#include "NppPlugin_StdApi.h"
// 插件名称
TCHAR* thePluginName = _T("XML Editor");
// 函数表指针
FuncItem* theFuncArray = NULL;
// 数据指针
NppData* theNppData = NULL;
// 快捷键表
ShortcutKey* theShortcutArray = NULL;
// 设置快捷键
void XmlEditorSetShortcutKey(int nID, bool bCtrl, bool bAlt, bool bShift, UCHAR key)
{
if (nID < FUNC_COUNT)
{
theShortcutArray[nID]._isCtrl = bCtrl;
theShortcutArray[nID]._isAlt = bAlt;
theShortcutArray[nID]._isShift = bShift;
theShortcutArray[nID]._key = key;
}
}
// 设置函数
void XmlEditorSetCommand(int nID, TCHAR *strCmdName, PFUNCPLUGINCMD pFunc, bool bCheck0nInit)
{
if (nID < FUNC_COUNT)
{
lstrcpy(theFuncArray[nID]._itemName, strCmdName);
theFuncArray[nID]._pFunc = pFunc;
theFuncArray[nID]._init2Check = bCheck0nInit;
theFuncArray[nID]._pShKey = theShortcutArray+nID;
}
}
// 添加菜单
void XmlEditorInitCommandMenu(void)
{
XmlEditorSetShortcutKey(FUNC_PASTE_SHEET_HEADER, true, false, false, 103); //7
XmlEditorSetShortcutKey(FUNC_PASTE_SHEET_ATTENTION, true, false, false, 104); //8
XmlEditorSetShortcutKey(FUNC_PASTE_SHEET_CONTENT, true, false, false, 105); //9
XmlEditorSetCommand(FUNC_PASTE_SHEET_HEADER, _T("Paste Sheet Header"), XmlEditorPasteSheetHeader, false);
XmlEditorSetCommand(FUNC_PASTE_SHEET_ATTENTION, _T("Paste Sheet Attention"), XmlEditorPasteSheetAttention, false);
XmlEditorSetCommand(FUNC_PASTE_SHEET_CONTENT, _T("Paste Sheet Content"), XmlEditorPasteSheetContent, false);
}
// 初始化
void XmlEditorInit(HANDLE hModule)
{
theFuncArray = (FuncItem *)malloc(sizeof(FuncItem) * FUNC_COUNT);
memset(theFuncArray, 0, sizeof(FuncItem) * FUNC_COUNT);
theNppData = (NppData *)malloc(sizeof(NppData));
memset(theNppData, 0, sizeof(NppData));
theShortcutArray = (ShortcutKey *)malloc(sizeof(ShortcutKey) * FUNC_COUNT);
memset(theShortcutArray, 0, sizeof(ShortcutKey) * FUNC_COUNT);
XmlEditorInitCommandMenu();
}
// 清除
void XmlEditorCleanUp(void)
{
if (theFuncArray != NULL)
{
free(theFuncArray);
theFuncArray = NULL;
}
if (theShortcutArray != NULL)
{
free(theShortcutArray);
theShortcutArray = NULL;
}
if (theNppData != NULL)
{
free(theNppData);
theNppData = NULL;
}
}
3、插件Demo代码
lizhi0755@sina.com