程序开发中,我们不可能把所有的功能一次全部实现,那么我们就应该留一些接口出来,让其他的功能以插件的形式添加到我们的程序中,这样我们的程序不用做任何更改就可以添加很多新的功能了。我们常用的软件如excel、photoshop等,都有这些功能,那么该如何实现呢?本文通过一个简单的例子实现。
使用工具:VS2008
使用语言:C++
开发步骤:
#pragma once
typedef bool (*LPFNREGISTER)(void**);
class CPlugPeople
{
public:
CPlugPeople(void){};
~CPlugPeople(void){};
virtual void Show(void){};
};
//属性设置
m_list.ModifyStyle(LVS_TYPEMASK,LVS_REPORT & LVS_TYPEMASK | LVS_SINGLESEL);//important for show
DWORD dwStyle = m_list.GetExtendedStyle();
m_list.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_list.InsertColumn(0,_T("PathName"),LVCFMT_LEFT,480,0);添加一个按钮,用于选择文件夹,并枚举选中文件夹,将动态库路径名显示到列表中void CPlugAppDemoDlg::OnBnClickedBtnLoad()
{
// TODO: 在此添加控件通知处理程序代码
char szDir[MAX_PATH];
BROWSEINFO bi;
ITEMIDLIST *pidl;
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = (LPWSTR)szDir;
bi.lpszTitle = _T("请选择目录 ");//strDlgTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
pidl = SHBrowseForFolder(&bi);
if(pidl == NULL)
return ;
if(!SHGetPathFromIDList(pidl, (LPWSTR)szDir))
return ;
CString sTargetFullPath = _T("");
sTargetFullPath.Format(_T("%s"),szDir);
if(sTargetFullPath.IsEmpty())
{
return;
}
m_list.DeleteAllItems();
int index = 0;
CString strPath = sTargetFullPath;
CString strFullName = _T("");
WIN32_FIND_DATA FindFileData;
BOOL bFinishFind = FALSE;
ZeroMemory(&FindFileData, sizeof(WIN32_FIND_DATA));
strPath += _T("\\*.*");
HANDLE hFindFile = FindFirstFile(strPath, &FindFileData);
if (hFindFile == INVALID_HANDLE_VALUE) //枚举失败
{
return ;
}
while(hFindFile != INVALID_HANDLE_VALUE && GetLastError() !=ERROR_NO_MORE_FILES)
{
if ((_tcscmp( FindFileData.cFileName , _T("."))) ==0 ||
(_tcscmp(FindFileData.cFileName , _T("..")) == 0))
{
FindNextFile(hFindFile , &FindFileData);
continue;
}
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //递归枚举文件夹里面的
{
FindNextFile(hFindFile , &FindFileData);
SetLastError(0);
continue;
}
strFullName = sTargetFullPath + _T("\\") + FindFileData.cFileName;
CString strType = strFullName.Right(4);
strType.MakeLower();
if(_T(".dll") == strType)
{
m_list.InsertItem(index,strFullName);
index++;
}
FindNextFile(hFindFile , &FindFileData);
}
}点击了列表中哪个动态库则显示对应动态库信息void CPlugAppDemoDlg::OnNMClickListDll(NMHDR *pNMHDR, LRESULT *pResult)
{
//LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nItem = pNMListView->iItem;
if(-1 == nItem)
{
return ;
}
else
{
RunDLL(m_list.GetItemText(nItem,0));
}
*pResult = 0;
}
void CPlugAppDemoDlg::RunDLL(CString strPathName)
{
CPlugPeople* pPlug = NULL;
HINSTANCE hIn = NULL;
hIn = LoadLibrary(strPathName);
if(hIn != INVALID_HANDLE_VALUE)
{}
else
{
MessageBox(_T("Load DLL error"));
return;
}
LPFNREGISTER lpfnRegister = NULL;
char p[256] = {0};
CString str = _T("CreateObject");
int cnt = str.GetLength();
for(int i=0; i<cnt; i++)
{
p[i] = str.GetAt(i);
}
lpfnRegister = (LPFNREGISTER)GetProcAddress(hIn,p);
bool result = false;
if(lpfnRegister)
{
result = (*lpfnRegister)((void**)&pPlug);
}
else
{
FreeLibrary(hIn);
return;
}
if(result)
{}
else
{
MessageBox(_T("Create Object error"));
FreeLibrary(hIn);
return;
}
pPlug->Show();
delete pPlug;
pPlug = NULL;
FreeLibrary(hIn);
}
#pragma once
#include "plugpeople.h"
class CPlugChild :
public CPlugPeople
{
public:
CPlugChild(void);
~CPlugChild(void);
void Show(void);
};
#include "StdAfx.h"
#include "PlugChild.h"
CPlugChild::CPlugChild(void)
{
}
CPlugChild::~CPlugChild(void)
{
}
void CPlugChild::Show(void)
{
AfxMessageBox(_T("小家伙吃了些葡萄..."));
}PlugDllChildDemo.cpp
extern "C"
__declspec(dllexport) bool CreateObject(void** pObj)
{
*pObj = new CPlugChild;
return true;
}3.2选择动态库文件夹
3.3选择完成后效果
3.4点击效果
原文地址:http://blog.csdn.net/bingdianlanxin/article/details/42341023