在notepad++里面使用qt,首先要做得就是建立qt工程,然后类型是动态链接库,然后将notepad++的模板文件拷贝进去,在里面就可以用用qt书写代码了.编译以后的dll拷贝到notepad++的plugins文件夹内,然后将qt依赖拷贝到notepad++同级目录,就可以正确加载了.
比较麻烦的是怎么把qt窗体塞到notepad++里面.这里我采用的方式是先创建一个它原来支持的窗体,然后根据句柄设置qt窗体的父窗体,从而间接地塞了进去.代码如下:
class MainView : public QWidget
{
Q_OBJECT
public:
MainView(QWidget *parent = 0);
~MainView();
}
这个是我的qt窗体类,它的实现各位就各自发挥了
#ifndef GOTILINE_DLG_H
#define GOTILINE_DLG_H
#include "DockingDlgInterface.h"
#include "resource.h"
#include "QDialog"
#include "mainview.h"
class DemoDlg : public DockingDlgInterface
{
public :
DemoDlg() : DockingDlgInterface(IDD_PLUGINGOLINE_DEMO), dlg(NULL){};
~DemoDlg();
virtual void display(bool toShow = true) const {
DockingDlgInterface::display(toShow);
};
void setParent(HWND parent2set){
_hParent = parent2set;
};
void create(tTbData * data, bool isRTL = false);
MainView* dlg;
protected :
virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
};
#endif //GOTILINE_DLG_H
#include "QtDialogParent.h"
#include "PluginDefinition.h"
extern NppData g_nppData;
#define MINIMUM_WINDOWS_X 350
#define MINIMUM_WINDOWS_Y 200
BOOL CALLBACK DemoDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
switch (wParam)
{
case IDOK:
{
return TRUE;
}
}
return FALSE;
}
case WM_GETMINMAXINFO:
{
((MINMAXINFO *)lParam)->ptMinTrackSize.x = MINIMUM_WINDOWS_X;
((MINMAXINFO *)lParam)->ptMinTrackSize.y = MINIMUM_WINDOWS_Y;
return TRUE;
}
case WM_SIZE:
{
if (dlg)
{
int x = ((int)(short)LOWORD(lParam));
int y = ((int)(short)HIWORD(lParam));
dlg->setGeometry(0, 0, x, y);
}
return TRUE;
}
break;
default:
return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
}
}
void DemoDlg::create(tTbData * data, bool isRTL /*= false*/)
{
DockingDlgInterface::create(data, isRTL);
int arg = 1;
dlg = new MainView;
::SetParent((HWND)dlg->winId(), _hSelf);
dlg->show();
};
DemoDlg::~DemoDlg()
{
if (dlg!=NULL)
{
delete dlg;
}
}
这个是给qt窗体准备的父窗体.
然后在全局变量里面声明一个
DemoDlg g_dlg;
在模块加载的时候进行初始化
void pluginInit(HANDLE hModule)
{
…
g_dlg.init((HINSTANCE)hModule, NULL);
…
}
然后QT的窗体也是全局的
MainView *g_view = NULL;
然后显示窗体的命令这么写
void showDlg()
{
g_dlg.setParent(g_nppData._nppHandle);
tTbData data = { 0 };
if (!g_dlg.isCreated())
{
g_dlg.create(&data);
g_view = g_dlg.dlg;
data.hIconTab =(HICON)::LoadImage((HINSTANCE)g_module, MAKEINTRESOURCE(IDI_ICO), IMAGE_ICON,16, 16, LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT);
data.pszName = TEXT("Lua插件");
data.uMask = DWS_DF_CONT_RIGHT;
data.pszModuleName =TEXT("luatool.dll");
data.dlgID =IDD_PLUGINGOLINE_DEMO;
::SendMessage(g_nppData._nppHandle,NPPM_DMMREGASDCKDLG, 0, (LPARAM)&data);
}
g_dlg.display();
}
这样就可以把qt窗体塞进notepad++里面了,这里需要注意的地方是
virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
这个函数,窗体发生改变的时候会进入这个回调函数,比如窗体大小发生了改变,那么我们判断是WM_SIZE信号,那么我们拿到最新的大小设置给qt窗体就可以了.
然后 获取qt窗体的句柄使用的函数是winId()这个函数,然后强制转换为HWND即可.
最后,也是最重要的是 qt的窗体是依赖于QApplication的,否则无法正常工作,所以需要定义一个全局的
QApplication* app = NULL;
dll加载的时候需要new出一个来,代码如下
QApplication* app = NULL;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD reasonForCall,
LPVOID lpReserved )
{
switch (reasonForCall)
{
case DLL_PROCESS_ATTACH:
{
int arg = 1;
char* argv = new char[1];
argv[0] = '1';
app = new QApplication(arg, &argv);
g_module = hModule;
pluginInit(hModule);
}
break;
case DLL_PROCESS_DETACH:
{
delete g_AutoManager;
commandMenuCleanUp();
pluginCleanUp();
delete app;
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}