前言:本站為你精心整理了MFC插件應(yīng)用程序設(shè)計(jì)范文,希望能為你的創(chuàng)作提供參考價(jià)值,我們的客服老師可以幫助你提供個(gè)性化的參考范文,歡迎咨詢。
摘要討論了插件應(yīng)用系統(tǒng)的基礎(chǔ)理論及應(yīng)用優(yōu)勢(shì),據(jù)此設(shè)計(jì)了基本的插件應(yīng)用系統(tǒng)框架模塊并通過(guò)mfc基礎(chǔ)平臺(tái)予以具體實(shí)現(xiàn)。
關(guān)鍵字插件;動(dòng)態(tài)鏈接庫(kù);MFC
1插件體系結(jié)構(gòu)
軟件開發(fā)手段的演化,就在于以最小的代價(jià)得到更健壯且易于擴(kuò)展和維護(hù)的“好”的應(yīng)用系統(tǒng),開發(fā)工具的持續(xù)改進(jìn)和開發(fā)思想的進(jìn)化使得我們有可能實(shí)現(xiàn)上述目標(biāo)。
從面向過(guò)程的開發(fā)至面向?qū)ο蟮木幊?,直至目前面向組件的開發(fā),正是上述思維的展現(xiàn)?;诓寮膽?yīng)用系統(tǒng)從體系結(jié)構(gòu)設(shè)計(jì)出發(fā),著力構(gòu)建低耦合的,靈活可擴(kuò)展的且支持無(wú)編譯熱插拔的應(yīng)用系統(tǒng),通過(guò)分析應(yīng)用需求,提煉功能相似的模塊并設(shè)計(jì)相應(yīng)的模塊間接口,我們就可以將該部分功能分離出來(lái),綜合來(lái)看,基于插件的應(yīng)用系統(tǒng)有以下優(yōu)勢(shì):
(1)實(shí)現(xiàn)真正意義上的軟件組件的“即插即用”。
(2)在二進(jìn)制級(jí)上集成軟件,減少大量的軟件重新編譯與所帶來(lái)的麻煩。
(3)能夠很好地實(shí)現(xiàn)軟件模塊的分工開發(fā),并且能夠大量吸取他人的優(yōu)點(diǎn)。
(4)可以較好地實(shí)現(xiàn)代碼隱藏,保護(hù)知識(shí)產(chǎn)權(quán)。
基于插件的體系結(jié)構(gòu)如圖1所示。
圖1插件應(yīng)用系統(tǒng)體系結(jié)構(gòu)
從圖1可知,一個(gè)完成的基于插件的應(yīng)用系統(tǒng)共分兩部分:插件主控程序(含插件調(diào)度核心模塊)以及插件池(存放所有插件)。主控程序通過(guò)核心模塊提供插件管理功能,主要包括:
(1)注冊(cè)及卸載插件:插件在使用之前必須注冊(cè)或存放于特定的路徑中,主控程序根據(jù)相關(guān)配置參數(shù)對(duì)插件完成初始化工作。
(2)啟用及禁用插件:主控程序可以根據(jù)用戶指令,對(duì)某些已裝載的插件予以啟用或禁用。
(3)顯示插件信息:包括插件描述,開發(fā)者信息,版本和版權(quán)聲明等。
(4)配置插件參數(shù):插件本身的運(yùn)行需要對(duì)某些參數(shù)進(jìn)行定制。
根據(jù)模塊規(guī)劃,插件實(shí)現(xiàn)特定的功能并將接口暴露出來(lái),根據(jù)需要,可能還需要調(diào)用主控程序提供的方法以操作資源或數(shù)據(jù)。
2設(shè)計(jì)思路及MFC實(shí)現(xiàn)
據(jù)上述討論,我們?cè)O(shè)計(jì)一個(gè)基本的插件應(yīng)用系統(tǒng)框架,其中主控程序是基于MFC對(duì)話框的應(yīng)用程序,插件使用動(dòng)態(tài)庫(kù)實(shí)現(xiàn),插件管理部分使用專門的CPluginManager類實(shí)現(xiàn),其實(shí)現(xiàn)的函數(shù)如圖2所示。
圖2插件管理類視圖
就主要函數(shù)說(shuō)明如表1所示。
表1插件管理類提供的函數(shù)
函數(shù)名稱函數(shù)說(shuō)明
Init初始化,搜索所有有效插件
Shutdown釋放資源
GetAll得到所有插件名,用CString對(duì)象返回,名之間用:隔開
Count返回可用插件的個(gè)數(shù)
Run調(diào)用插件提供的函數(shù)接口
Load載入所有插件
UnLoad卸載所有插件
ExtractFilePath提取插件存放路徑
以Load函數(shù)為例,我們使用STL的MAP數(shù)據(jù)結(jié)構(gòu)存放插件句柄和插件的對(duì)應(yīng),代碼如下:
voidCPluginManager::Load()
{
//……相關(guān)變量定義省略
GetModuleFileName(AfxGetApp()->m_hInstance,filepath,MAX_PATH-1);
SetCurrentDirectory(ExtractFilePath(filepath));
CFileFindfinder;
CStringstrWildCard=_T("*.plx");
BOOLbWorking=finder.FindFile(strWildCard);
while(bWorking)
{
bWorking=finder.FindNextFile();
if(finder.IsDots()||finder.IsDirectory())
continue;
HMODULEhm=LoadLibrary(finder.GetFilePath());
if(!hm)
{//……載入失敗處理代碼}
elseif(NULL==GetProcAddress(hm,"PluginMain"))
{//……非可用插件處理代碼}
else_dllMap.insert(make_pair(finder.GetFileName(),hm));
}
插件提供的接口函數(shù)如下(僅作為示例,如需其它接口,可照此添加):
#ifdefPLUG1_EXPORTS
#definePLUG_API__declspec(dllexport)
#else
#definePLUG_API__declspec(dllimport)
#endif
PLUG_APIvoidPluginMain(void)
{
::MessageBox(NULL,"插件1測(cè)試成功!","Plugin1",MB_OK);
}
主控程序使用樹控件展示插件功能,程序初始化時(shí)首先調(diào)用初始化函數(shù)完成控件注冊(cè),然后得到所有控件的名稱并以葉節(jié)點(diǎn)的形式顯示出來(lái),用戶雙擊相應(yīng)的葉節(jié)點(diǎn)時(shí),主控程序調(diào)用插件提供的函數(shù)PluginMain,調(diào)用過(guò)程如下:
voidCTreeCtrlDlg::OnDblClkTree(NMHDR*pNMHDR,LRESULT*pResult)
{
m_hTreeItem=m_wndTree.GetSelectedItem();
CStringplName=
m_wndTree.GetItemText(m_hTreeItem);
g_PluginManager->Run(plName);
*pResult=0;
}
主控程序運(yùn)行時(shí)及雙擊樹形圖葉節(jié)點(diǎn)時(shí)界面,如圖3所示。
圖3主控程序運(yùn)行界面
主控程序所在路徑下建立plugin目錄,并存放三個(gè)插件文件。
3結(jié)束語(yǔ)
開放的組件化體系結(jié)構(gòu)模塊組成清晰,同時(shí)也方便了系統(tǒng)擴(kuò)展和后續(xù)維護(hù),本文從插件應(yīng)用系統(tǒng)的體系結(jié)構(gòu)入手,設(shè)計(jì)了主控模塊與插件池的功能要求,給出了插件管理類實(shí)現(xiàn)的功能,并基于MFC給出了相應(yīng)的具體實(shí)現(xiàn),需要說(shuō)明的是:
(1)插件應(yīng)用系統(tǒng)涉及到主控程序和插件之間的雙向交互,插件也可以利用主控程序提供的接口訪問(wèn)公共資源和數(shù)據(jù),本文對(duì)該部分功能未作實(shí)現(xiàn)。
(2)真正的應(yīng)用系統(tǒng)由于插件眾多,不可避免的涉及到插件之間的協(xié)同和沖突檢測(cè),需要在結(jié)構(gòu)設(shè)計(jì)上解決。
(3)插件的實(shí)現(xiàn)方式較多,可以根據(jù)具體的應(yīng)用需求和系統(tǒng)規(guī)模選用比較合適的一種。
總的來(lái)看,基于組件的插件應(yīng)用系統(tǒng),由于存在諸多優(yōu)勢(shì),必將帶來(lái)更多的應(yīng)用前景和用戶體驗(yàn)。
參考文獻(xiàn)
[1]彭永康,章義來(lái),插件及其接口的研究與應(yīng)用,計(jì)算機(jī)應(yīng)用,2003,6:122~123
[2]于珊珊,軟件插件技術(shù)及其應(yīng)用研究,電腦學(xué)習(xí),2007,8:55~56