CodeBlocks插件開(kāi)發(fā)指南(三)
1. 添加右鍵彈出菜單
我們?cè)谶@里,將會(huì)在插件中加入右鍵彈出菜單功能。也就是如下圖那樣,在文檔區(qū)內(nèi),點(diǎn)擊鼠標(biāo)右鍵時(shí)會(huì)彈出的菜單。我們將在這個(gè)菜單中加入屬于我們插件的菜單項(xiàng)目”testplug”。
加入菜單項(xiàng)目的效果如下圖:
讓我們看看,咱們創(chuàng)建的插件工程中,給我們提供了什么樣的入口代碼了吧。
1. 在函數(shù)BuildModuleMenu中添加菜單項(xiàng)。
在文檔的視圖里才加入菜單項(xiàng)的入口函數(shù)是BuildModuleMenu,它的初始代碼是下面那樣:
1 void testplug::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data)
2 {
3 //Some library module is ready to display a pop-up menu.
4 //Check the parameter \"type\" and see which module it is
5 //and append any items you need in the menu
6 //TIP: for consistency, add a separator as the first item
7 NotImplemented(_T("testplug::BuildModuleMenu()"));
8 }
其實(shí)該函數(shù)就是一個(gè)往日志里打印log而已,里面調(diào)用的函數(shù)NotImplemented也不起到任何作用,可以無(wú)視。
其中函數(shù)參數(shù)的意義如下:
①type 當(dāng)前運(yùn)行的是CodeBlocks的哪個(gè)模塊
②men 編輯器的右鍵彈出菜單的實(shí)例的指針
③data IDE環(huán)境的文件數(shù)列表數(shù)據(jù)的指針
接下來(lái),讓我看看應(yīng)該在這個(gè)函數(shù)里加入什么樣的代碼才能加入我們菜單項(xiàng)目
1 void testplug::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data)
2 {
3 //Some library module is ready to display a pop-up menu.
4 if (!menu || !IsAttached())
5 return;
6 //Check the parameter \"type\" and see which module it is
7 //and append any items you need in the menu
8 if (type == mtEditorManager) {
9 menu->AppendSeparator();
10 menu->Append(idTestPlug, _("TestPlug"), _("hello world"));
11 }
12 //TIP: for consistency, add a separator as the first item
13 NotImplemented(_T("testplug::BuildModuleMenu()"));
14 }
IsAttached函數(shù)的意思是檢查插件是否已經(jīng)被載入到CodeBlocks中,沒(méi)有載入插件的場(chǎng)合返回FALSE.
如果當(dāng)前運(yùn)行的模塊是CodeBlocks的編輯器的話,我們就可以插入我們的菜單項(xiàng)了。插入菜單項(xiàng)的方法非常簡(jiǎn)單,就是利用wxMenu的Append接口就可以了。如上面的代碼中使用了如下的語(yǔ)句:
menu->Append(idTestPlug, _("TestPlug"), _("hello world"));
該接口的原型聲明為:
wxMenu::Append
wxMenuItem* Append(int id, const wxString& item = "", const wxString& helpString = "", wxItemKind kind = wxITEM_NORMAL)
id: 菜單項(xiàng)的ID.
item: 是在右鍵彈出菜單中顯示的字符串
helpString: 是在狀態(tài)條中顯示的字符串
kind: 菜單項(xiàng)的類型
我們?cè)诘诙€(gè)參數(shù)item設(shè)置成字符串TestPlug,helpString隨便傳一個(gè)字符串,第四個(gè)參數(shù)kind不用寫,使用默認(rèn)值即可。
注意,上面代碼中的menu->AppendSeparator()表示在菜單項(xiàng)中加入一個(gè)分割線。AppendSeparator同樣也是wxMenu類的一個(gè)成員。
2. 給菜單項(xiàng)創(chuàng)建資源ID。
里面最重要的一個(gè)參數(shù)非id莫數(shù)了,因?yàn)樵?/span>GUI中,參單項(xiàng)跟畫面上的控件一樣都屬于插件的資源,所以它也應(yīng)該有一個(gè)資源ID,也就是我們這里的參數(shù)id.所以,接下來(lái)我們要給菜單項(xiàng)添加一個(gè)資源標(biāo)示。
const int idTestPlug = wxNewId();
如上所示,使用wxNewId函數(shù)來(lái)創(chuàng)建一個(gè)資源id,并賦值給idTestPlug。
因此,把上述的語(yǔ)句加入到源文件的開(kāi)始處即可. 即把idTestPlug作為一個(gè)全局變量來(lái)使用.
注:wxNewID實(shí)際上是一個(gè)返回static的全局引用計(jì)數(shù)的函數(shù)。在C++中允許在全局變量定義時(shí)執(zhí)行某個(gè)函數(shù),讓函數(shù)的返回值賦值給全局變量。這在C中是不允許的。
3. 在事件管理表中加入事件處理函數(shù)。
接下來(lái),在插件的event table中加入菜單項(xiàng)被單擊后的事件處理函數(shù)。如下:
1 // events handling
2 BEGIN_EVENT_TABLE(testplug, cbPlugin)
3 // add any events you want to handle here
4 EVT_MENU(idTestPlug, testplug::OnTestPlug)
5 END_EVENT_TABLE()
注意,我們這里加入的事件處理函數(shù)的名字是OnTestPlug, 其實(shí)我們就是通過(guò)宏EVT_MENU將idTestPlug和該函數(shù)關(guān)聯(lián)起來(lái)。
4. 聲明事件處理函數(shù)。
在testplug類中要做一下事件處理函數(shù)的聲明,如下:
private:
void OnTestPlug(wxCommandEvent &event);
DECLARE_EVENT_TABLE();
OnTestPlug函數(shù)的參數(shù)event是被傳入的是一個(gè)事件的實(shí)例,它的類名是wxCommandEvent
5. 實(shí)現(xiàn)事件處理函數(shù)。
這里,我們就可以為所欲為了,在OnTestPlug中添加的代碼,在TestPlug菜單項(xiàng)被電擊之后就可以被執(zhí)行了。為了簡(jiǎn)單起見(jiàn),函數(shù)很簡(jiǎn)單,僅僅是彈出一個(gè)消息框而已。
1 void testplug::OnTestPlug(wxCommandEvent &event)
2 {
3 cbMessageBox(_("This is my first Plugin test program"), _("Info"), wxICON_QUESTION);
4 }
數(shù)里面僅僅使用cbMessageBox來(lái)彈出一個(gè)消息。
OK了,如果上述的代碼沒(méi)有敲錯(cuò)任何字符的話,你就可以沒(méi)有任何錯(cuò)誤的編譯通過(guò)了。如果編譯沒(méi)有問(wèn)題,你就按照5-④把你編譯好的插件重新載入到CodeBlocks里了。當(dāng)然在重新載入前,你先得把老版本的插件卸載掉。記住,每次你的插件有什么改動(dòng)的話,你必須都得這么做。
如果上面的步驟都沒(méi)有問(wèn)題,你可以試試在編輯器中點(diǎn)擊鼠標(biāo)右鍵,是不是可以發(fā)現(xiàn)右鍵菜單上多了一個(gè) TestPlug 的菜單項(xiàng)。

然后你點(diǎn)擊這個(gè)菜單項(xiàng),是不是就彈出下面的對(duì)話框了吧。

如果沒(méi)有出來(lái)的話,你就應(yīng)該反復(fù)的檢查上面的任何一個(gè)步驟,看看是否有什么沒(méi)有照做的地方。
在CodeBlock里添加一個(gè)菜單項(xiàng)還是很簡(jiǎn)單吧。一共就用了不到10行程序就搞定了。接下來(lái),我們將嘗試在CodeBlocks的主菜單里添加一個(gè)同名的菜單項(xiàng)。
2. 主菜單中添加下拉菜單
假設(shè)我們想象下面那樣,在CodeBlocks的Tools主菜單中加入一個(gè)菜單項(xiàng),那該如何做呢?

為了方便起見(jiàn),我們這里加入的菜單項(xiàng)跟上一步的菜單名字是一樣,功能也是一樣的。也就是使用同一個(gè)資源id就行了,就是上一步中的idTestPlug. 如果想設(shè)定不同的名字,不同的功能,你可以重復(fù)上一步中的2~5的步驟就可以了。
關(guān)鍵是要找到,在系統(tǒng)菜單中加入菜單項(xiàng)的入口函數(shù)在哪里。這個(gè)函數(shù)就是testplug類的成員函數(shù)BuildMenu。我們可以看它的初始代碼是什么樣的。
void testplug::BuildMenu(wxMenuBar* menuBar)
{
//The application is offering its menubar for your plugin,
//to add any menu items you want
//Append any items you need in the menu
//NOTE: Be careful in here
The application's menubar is at your disposal.
NotImplemented(_T("testplug::BuildMenu()"));
}
跟BuildModuleMenu函數(shù)一樣,它的初始化函數(shù)基本上也是空的。里面僅僅調(diào)用了一個(gè)無(wú)關(guān)緊要的函數(shù)NotImplemented。大家注意到,這個(gè)函數(shù)的參數(shù)menBar了吧,它是wmMenuBar的實(shí)例的指針,這個(gè)實(shí)例就是系統(tǒng)菜單條(menuBar)的實(shí)例。我們只要利用這個(gè)實(shí)例的接口函數(shù)來(lái)加入我們的菜單項(xiàng)了。
下面,我們看看如何修改這個(gè)函數(shù)。
1 void testplug::BuildMenu(wxMenuBar* menuBar)
2 {
3 //The application is offering its menubar for your plugin,
4 //to add any menu items you want
5 if (!IsAttached())
6 return;
7 //Append any items you need in the menu
8 int pos = menuBar->FindMenu(_("&Tools"));
9 if (pos != wxNOT_FOUND) {
10 m_ToolsMenu = menuBar->GetMenu(pos);
11 m_ToolsMenu->AppendSeparator();
12 m_ToolsMenu->Append(idTestPlug, _("TestPlug\tCtrl-1"));
13 }
14
15 //NOTE: Be careful in here
The application's menubar is at your disposal.
16 NotImplemented(_T("testplug::BuildMenu()"));
17 }
① 首先,跟上一節(jié)一樣,我們?cè)诩尤胛覀兊娜魏蝿?dòng)作之前,都要判斷我們的插件是否已經(jīng)被載入到CodeBlock中了,這時(shí)候使用IsAttached()就可以了。
② 在菜單條menBar中找到Tools主菜單的位置
使用的函數(shù)是FindMenu, 參數(shù)就是菜單的名字,即一個(gè)字符串。該函數(shù)的返回值是該菜單的位置索引,如果查找的菜單不在主菜單中的話,它會(huì)返回wxNOT_FOUND.
③ 根據(jù)這個(gè)位置得到Tools菜單的實(shí)例
使用函數(shù)GetMenu就可以得到菜單的實(shí)例了,該函數(shù)參數(shù)就是菜單的位置索引,也就是上一步FindMenu的返回值。
④ 利用這個(gè)實(shí)例就可以在Tools菜單中加入TestPlug菜單項(xiàng)了。
有了菜單的實(shí)例,就可以跟在右鍵彈出菜單那樣,在里面加入我們自己的菜單項(xiàng)。方法跟1-1是一樣的,這里就不重復(fù)了。
注意:在Apennd函數(shù)的第二個(gè)參數(shù)是菜單項(xiàng)的名字,我們這里是"TestPlug\tCtrl-1"。這個(gè)字符串里有"\tCtrl-1"的字樣,表示激活該菜單項(xiàng)的快捷間是Ctrl-1. 也就是你在IDE中按下Ctrl-1鍵就會(huì)執(zhí)行該菜單項(xiàng)對(duì)應(yīng)消息處理函數(shù),在我們的例子中,則是彈出下面的消息框:
到此為止,在主菜單中添加菜單項(xiàng)的任務(wù)就完成了。如果想要為該菜單項(xiàng)添加自己的消息處理函數(shù),則重復(fù)上一步中的2~5的步驟就可以了。