VS之插件实现

程序开发中,我们不可能把所有的功能一次全部实现,那么我们就应该留一些接口出来,让其他的功能以插件的形式添加到我们的程序中,这样我们的程序不用做任何更改就可以添加很多新的功能了。我们常用的软件如excel、photoshop等,都有这些功能,那么该如何实现呢?本文通过一个简单的例子实现。

使用工具:VS2008

使用语言:C++

开发步骤:

1.插件应用程序

1.1新建对话框应用程序

1.2新建基类

1.3添加基类纯虚函数

PlugPeople.h

#pragma once

typedef bool (*LPFNREGISTER)(void**);

class CPlugPeople
{
public:
	CPlugPeople(void){};
	~CPlugPeople(void){};
	virtual void Show(void){};
};

1.4加载动态库并显示效果

界面上添加一个列表,用于显示动态库的路径名

	//属性设置
	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);
}

2.插件动态库

2.1新建动态库

2.2添加基类文件

2.3从基类派生自己的类

PlugChild.h

#pragma once
#include "plugpeople.h"

class CPlugChild :
	public CPlugPeople
{
public:
	CPlugChild(void);
	~CPlugChild(void);
	void Show(void);
};

2.4重写虚函数

PlugChild.cpp

#include "StdAfx.h"
#include "PlugChild.h"

CPlugChild::CPlugChild(void)
{
}

CPlugChild::~CPlugChild(void)
{
}

void CPlugChild::Show(void)
{
	AfxMessageBox(_T("小家伙吃了些葡萄..."));
}

2.5添加统一动态库函数接口,传递自己的类

PlugDllChildDemo.cpp

extern "C"
__declspec(dllexport) bool CreateObject(void** pObj)
{
	*pObj = new CPlugChild;
	return true;
}

3.应用程序中调用插件

3.1应用程序运行

3.2选择动态库文件夹

3.3选择完成后效果

3.4点击效果

  

源码下载

时间: 2024-08-24 21:43:38

VS之插件实现的相关文章

使用 Chrome 浏览器插件 Web Scraper 10分钟轻松实现网页数据的爬取

本文标签: WebScraper Chrome浏览器插件 网页数据的爬取 使用Chrome 浏览器插件 Web Scraper 可以轻松实现网页数据的爬取,不写代码,鼠标操作,点哪爬哪,还不用考虑爬虫中的登陆.验证码.异步加载等复杂问题. Web Scraper插件 Web Scraper 官网中的简介: Web Scraper Extension (Free!)Using our extension you can create a plan (sitemap) how a web site

eclipse插件之Findbugs、Checkstyle、PMD安装及使用

一.什么是Findbugs.checkstyle.PMD Findbugs.checkstyle和PMD都可以作为插件插入eclipse,当然也有单独的工具可以实现他们的功能,比如Findbugs Tool就可以不必插入eclipse就可以使用. 三者的功能如下表: 工具 目的 检查项 FindBugs 检查.class 基于Bug Patterns概念,查找javabytecode(.class文件)中的潜在bug 主要检查bytecode中的bug patterns,如NullPoint空指

eclipse安装java ee插件方法步骤

1.本人以前使用的MyEclipse进行Javaweb开发,但是后来由于myeclipse实在太臃肿,经常在运行的过程中不流畅 (可能电脑内存也不是太高吧)   !所以坚决换用eclipse,但是问题来了,下载的eclipse因为是标准版所以也不支持Javaweb开发,所以要来配置一下开发环境,安装Javaee开发插件   ,以下为安装步骤 1.1 在Eclipse中菜单help选项中选择install new software选项 1.2 在work with 栏中输入 http://down

Myeclipse10 安装Aptana插件

安装步骤: 1.下载aptana3.2 Eclipse Plugin插件. 下载地址:http://update1.aptana.org/studio/3.2/024747/index.html 2.在java文件夹下新建文件夹pluginsNew,在里面新建aptana_update_024747文件夹(这个文件夹名根据自己下载的版本自己写),再在里面新建eclipse文件夹,解压出features与plugins文件夹,COPY到 D:\java\pluginsNew\aptana_upda

这是一款借助chrome 插件的微信机器人

1.chrome kit微信机器人简介(github:https://github.com/LinuxForYQH/chrome_kit) 借助chrome 插件 js注入来实现消息的发送 chrome devtool api的调用来监听https请求 打开微信登录界面,在扫码登录前必须先打开toolbar(F12 或者 鼠标右键检查),如上所说因为借助了chrome devtool api所以需要打开toolbar才能执行相关dev域的js. 2.相关开发原理介绍 https://develo

使用插件bootstrap-table实现表格记录的查询、分页、排序等处理

在业务系统开发中,对表格记录的查询.分页.排序等处理是非常常见的,在Web开发中,可以采用很多功能强大的插件来满足要求,且能极大的提高开发效率,本随笔介绍这个bootstrap-table是一款非常有名的开源表格插件,在很多项目中广泛的应用.Bootstrap-table插件提供了非常丰富的属性设置,可以实现查询.分页.排序.复选框.设置显示列.Card view视图.主从表显示.合并列.国际化处理等处理功能,而且该插件同时也提供了一些不错的扩展功能,如移动行.移动列位置等一些特殊的功能,插件可

页面滚动图片等元素动态加载插件jquery.scrollLoading.js

如果一个网页很长,那么该页面的加载时间也会相应的较长.而这里给大家介绍的这个jQuery插件scrollLoading的作用则是,对页面元素进行动态加载,通俗的说就是滚到哪就加载到哪,屏幕以下看不见的就不用加载了.这样还可以在一定程度上节省服务器资源.该插件作者的网页将该插件的功能和使用方法描述的非常详细,这里把最一般最普遍的使用情况给大家展现一下. 插件作者:http://www.zhangxinxu.com/ 首先我们需要加载jQuery库和本插件js文件. (jquery.scrollLo

怎样将「插件化」接入到项目之中?

本期移动开发精英社群讨论的主题是「插件化」,上网查了一下,发现一篇 CSDN 博主写的文章<Android 使用动态载入框架DL进行插件化开发>.此处引用原作者的话: 随着应用的不断迭代,应用的体积不断增大,项目越来越臃肿,冗余添加.项目新功能的加入,无法确定与用户匹配性,发生严重异常往往牵一发而动全身,仅仅能紧急公布补丁版本号,强制用户进行更新.结果频繁的更新.反而easy减少用户使用黏性,或者是公司业务的不断发展,同系的应用越来越多,传统方式须要通过用户量最大的主项目进行引导下载并安装.

Android插件实例——360 DroidPlugin具体解释

在中国找到钱不难,但你的一个点子不意味着是一个创业.你谈一个再好的想法,比方我今天谈一个创意说,新浪为什么不收购GOOGLE呢?这个创意非常好.新浪一收购GOOGLE.是不是新浪就变成老大了?你从哪儿弄来钱?怎么去整合GOOGLE呢: 之前写过有关于Android 插件方向的文章,解析了一下Android的插件原理与执行方式.非常多小伙伴都问我.为什么不把我制作的插件放到Github上,让大家共享一下. 我仅仅能说.大哥啊,这个插件是我在公司研发的时候制作的,商业机密.不能开源啊. 刚好.近期逛

jQuery插件ImgAreaSelect 实例讲解一(头像上传预览和裁剪功能)

上一节随笔中,我们已经知道了关于jQuery插件ImgAreaSelect基本的知识:那么现在看一下实例: 首先,要知道我们应该实现什么功能? (1)图片能够实现上传预览功能 (2)拖拽裁剪图片,使其能够显示裁剪后的区域 (3)显示要裁剪区域的坐标 其次,该如何引用该插件呢? 那就具体看一下吧! 第一步:先将样式和文件包引入(根据你自己的位置引入) <!--引入imgareaselect的css样式--> <link rel="stylesheet" type=&qu