引言
目前,不少流行软件都提供有对外挂插件的支持功能,如Winamp、Realplay等等。这些软件通过对插件技术的使用为日后的软件升级和功能扩展提供了相当的便利条件。尤为重要的是,通过使用插件技术,使得对软件的功能扩展将不再完全受限于软件厂商,任何第三方开发商或是程序员个人只要遵循了软件提供的插件接口标准去开发插件就完全可以同主体软件有很好的兼容,从而使用户对应用程序进行个性化功能扩展成为了可能。基于插件技术的以上诸多优势,本文下面将围绕插件的制作、应用程序对插件的支持等具体问题对其展开讨论。
设计思路及插件接口标准
通常支持插件的应用程序多将外挂扩展插件集中放置于某个指定的目录下,程序执行时首先在此目录下搜寻是否有插件存在,如有则为插件将其插入到应用程序,应用程序在终止运行时负责将插件释放。
至于插件以何种形式提供则没有固定的规定,可以是独立的应用程序,也可以是动态链接库或是其他一些文件格式,不管插件具体以何种形式提供,都是以方便使用为目的。本文即以使用较为灵活的动态链接库作为插件的提供形式,动态链接库通过外部导出函数为应用程序提供对插件功能的调用,应用程序在对动态链接库进行动态装载时也比较容易实现。这里与以往对动态链接库的使用有所不同,通常的应用程序事先已经明确知道需要使用哪些动态链接库,动态链接库又提供有哪些函数等信息,而允许使用插件的应用程序在发布时则无法预知在软件发布后第三方开发商将会开发出多少插件、插件都提供有什么功能函数等。因此这就需要在容许插件的应用程序和插件之间建立一种统一的接口标准并通过此接口标准完成对所有后期插件的管理。在此,主程序和插件之间是通过一个标准的DLL导出函数来实现的,主要用于在主体程序内插件对象的创建:
BOOL Plug_CreateObject(void ** pobj) { *pobj = new CPlugA; return *pobj != NULL; } |
class CPlugBase { public: CPlugBase(){}; virtual HICON GetIcon() = 0; virtual void Interface(int k) = 0; virtual void Release() = 0; }; |
typedef struct{ CPlugBase * pObj; HINSTANCE hIns; }PLUG_ST, * LPPLUG_ST; |
…… GetModuleFileName(NULL, filename, MAX_PATH); // 获取应用程序路径 strPath = CString(filename); //设定当前目录下的子目录PLUGINS strPath = strPath.Left(strPath.GetLength() - CString(AfxGetAppName()).GetLength() - 4) + CString("PLUGINS"); CString strFindFile = strPath + "\\*.dll"; // 搜寻子目录PLUGINS下的所有动态链接库 WIN32_FIND_DATA wfd; HANDLE hf = FindFirstFile(strFindFile, &wfd); //寻找第一个 if (hf != INVALID_HANDLE_VALUE) { // 如发现插件就将其插入到本应用程序 CreatePlug(strPath + "\\" + wfd.cFileName); while (FindNextFile(hf, &wfd)) //继续寻找下一个 CreatePlug(strPath + "\\" + wfd.cFileName); FindClose(hf); // 结束搜寻 } |
PLUG_ST stPs; ZeroMemory(&stPs, sizeof(stPs)); stPs.hIns = LoadLibrary(szPlug); PFN_Plug_CreateObject pFunc = (PFN_Plug_CreateObject)GetProcAddress(stPs.hIns, _T("Plug_CreateObject")); if (pFunc((void **)&stPs.pObj)) m_arrPlugObj.Add(stPs); |
int size = m_arrPlugObj.GetSize(); m_ImageList.Create(16, 16, ILC_COLOR32, size + 1, size); for (int i = 0; i < size; i ++) m_ImageList.Add(m_arrPlugObj.pObj->GetIcon()); CToolBarCtrl& ctrlBar = m_wndPlugBar.GetToolBarCtrl(); ctrlBar.SetImageList(&m_ImageList); TBBUTTON btn; for (i = 0; i < size; i ++) { btn.iBitmap = i; btn.idCommand = ID_PLUG_POINTER + i;//command to be sent when button pressed btn.fsState = TBSTATE_ENABLED; //button state--see below btn.fsStyle = TBSTYLE_BUTTON; //button style--see below btn.dwData = 0; //application-defined value btn.iString = NULL; //zero-based index of button label string ctrlBar.AddButtons(1, &btn); } |
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) …… ON_COMMAND_RANGE(ID_PLUG_POINTER, ID_PLUG_POINTER+256, OnPlugHit) END_MESSAGE_MAP() …… void CMainFrame::OnPlugHit(UINT nID) { int id = nID - ID_PLUG_POINTER; if (id >= 0 && id < m_arrPlugObj.GetSize()) { // 调用对应插件的功能函数。 if (m_arrPlugObj[id].pObj) m_arrPlugObj[id].pObj->Interface(id); } } |
for (int i = 0; i < m_arrPlugObj.GetSize(); i++) { if (m_arrPlugObj.pObj) m_arrPlugObj.pObj->Release(); if (m_arrPlugObj.hIns) FreeLibrary(m_arrPlugObj.hIns); } m_arrPlugObj.RemoveAll(); |
LIBRARY "PlugA" DESCRIPTION 'PlugA Windows Dynamic Link Library' EXPORTS Plug_CreateObject @1 |
BOOL WINAPI Plug_CreateObject(void ** pobj) { *pobj = new CPlugA; return *pobj != NULL; } |
Word教程网 | Excel教程网 | Dreamweaver教程网 | Fireworks教程网 | PPT教程网 | FLASH教程网 | PS教程网 |
HTML教程网 | DIV CSS教程网 | FLASH AS教程网 | ACCESS教程网 | SQL SERVER教程网 | C语言教程网 | JAVASCRIPT教程网 |
ASP教程网 | ASP.NET教程网 | CorelDraw教程网 |