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; |
另外,在程序界面上,每向应用程序添加一个新的插件,都应当在主程序的界面上增添与之相关联的按钮或菜单等,以便用户可以通过位于主程序界面上的按钮或菜单实现对插件内部功能函数的调用。本文在此是通过向工具条增添按钮的方式来达到此目的的,按钮上的图标由插件提供,应用程序通过插件类的GetIcon()函数获取到图标句柄,并将其绘制在工具条按钮上。
为普通应用程序扩展插件支持功能
插件支持功能并非Winamp、RealPlay等大牌软件所独有,任何普通应用程序经过程序编码均可将其扩展为支持插件的应用程序。通常将这部分扩展代码在主框架类中完成,根据前面所述思路,首先从应用程序所在目录下搜寻子目录PLUGINS下是否存在以动态链接库形式提供的插件,如果在此目录下没有找到动态链接库那么就说明当前还没有插件,因此程序也就不需要做进一步处理,如果找到插件,就一一将其插入到应用程序。搜寻插件的部分代码如下:
…… 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[i].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[i].pObj) m_arrPlugObj[i].pObj->Release(); if (m_arrPlugObj[i].hIns) FreeLibrary(m_arrPlugObj[i].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; } |