在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;
}
最後結果如下
