• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >vc/mfc > 各位大侠,如何开发一个能嵌入Add-ins的宿主程序(即让自己的程序支持Add-ins)?

各位大侠,如何开发一个能嵌入Add-ins的宿主程序(即让自己的程序支持Add-ins)?

作者:佚名 字体:[增加 减小] 来源:互联网 时间:2017-06-04

佚名通过本文主要向大家介绍了各位大侠,如何开发一个能嵌入Add-ins的宿主程序(即让自己的程序支持Add-ins)?等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
问题: 各位大侠,如何开发一个能嵌入Add-ins的宿主程序(即让自己的程序支持Add-ins)?
描述:

小弟想开发一个暴露自动化接口的程序,使之支持Add-in机制:我仿照VC++的Add-ins,开发了一个针对自己程序的Add-in,但怎么将此Add-in嵌入到主程序中去呢?如何将嵌入的Add-in工具栏所接受的点击事件和Add-in对象中的命令连接起来,希望知情人多多相助,拜谢!


解决方案1:

在VC中实现应用程序对插件的支持
引言 
  目前,不少流行软件都提供有对外挂插件的支持功能,如Winamp、Realplay等等。这些软件通过对插件技术的使用为日后的软件升级和功能扩展提供了相当的便利条件。尤为重要的是,通过使用插件技术,使得对软件的功能扩展将不再完全受限于软件厂商,任何第三方开发商或是程序员个人只要遵循了软件提供的插件接口标准去开发插件就完全可以同主体软件有很好的兼容,从而使用户对应用程序进行个性化功能扩展成为了可能。基于插件技术的以上诸多优势,本文下面将围绕插件的制作、应用程序对插件的支持等具体问题对其展开讨论。
  设计思路及插件接口标准
  通常支持插件的应用程序多将外挂扩展插件集中放置于某个指定的目录下,程序执行时首先在此目录下搜寻是否有插件存在,如有则为插件将其插入到应用程序,应用程序在终止运行时负责将插件释放。
  至于插件以何种形式提供则没有固定的规定,可以是独立的应用程序,也可以是动态链接库或是其他一些文件格式,不管插件具体以何种形式提供,都是以方便使用为目的。本文即以使用较为灵活的动态链接库作为插件的提供形式,动态链接库通过外部导出函数为应用程序提供对插件功能的调用,应用程序在对动态链接库进行动态装载时也比较容易实现。这里与以往对动态链接库的使用有所不同,通常的应用程序事先已经明确知道需要使用哪些动态链接库,动态链接库又提供有哪些函数等信息,而允许使用插件的应用程序在发布时则无法预知在软件发布后第三方开发商将会开发出多少插件、插件都提供有什么功能函数等。因此这就需要在容许插件的应用程序和插件之间建立一种统一的接口标准并通过此接口标准完成对所有后期插件的管理。在此,主程序和插件之间是通过一个标准的DLL导出函数来实现的,主要用于在主体程序内插件对象的创建:
BOOL Plug_CreateObject(void ** pobj)
{
*pobj = new CPlugA;
return *pobj != NULL;
}  
  其中类CPlugA是在动态链接库中由基类CPlugBase派生出来的,提供有插件的大部分主要功能,如插件图标的获取、插件提供的功能接口函数以及插件的释放等。基类CPlugBase的结构如下:
class CPlugBase 
{
public:
CPlugBase(){};
virtual HICON GetIcon() = 0;
virtual void Interface(int k) = 0;
virtual void Release() = 0;
}; 
  考虑到主体程序无法预知待插入的插件数目,为管理插件对象方便, 通过模板类CArray完成对各个插件对象的存储与管理,此模板类所管理的数组为PLUG_ST结构对象。PLUG_ST结构记录了插件类提供的的CPlugBase型指针和作为插件载体的动态链接库的实例句柄,其具体定义如下:
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); // 结束搜寻
} 
  其中,CreatePlug()函数负责将插件装载到应用程序,其参数指定了待装载的插件的绝对路径。在实现时,首先通过LoadLibrary()函数将插件模块装载到内存,并将获取到的实例句柄保存到PLUG_ST结构的hIns中,最后将此结构对象添加到CArray模板类对象m_arrPlugObj中,主要实现代码如下:
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); 
  同用户交互部分,则采取这样的处理:将所有插件的图标从插件动态链接库中提取出来,并放置于图象列表,最后在浮动工具条上创建对应的按钮并将插件图标绘制其上。同样也是出于对后期插件的不可预知性,在工具条上创建按钮的资源ID从ID_PLUG_POINTER开始,依次累加。具体实现可参考如下代码:
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);
} 
  对于各个插件按钮的命令响应也不能以通常的ON_COMMAND宏执行命令映射,而要以ON_COMMAND_RANGE宏实现对一个ID范围的命令映射:
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(); 
  至此,只要应用程序在PLUGINS子目录下发现了插件动态链接库的存在,就会将其装载到程序并通过工具条按钮完成用户同新添加插件的交互。如要从程序去掉某个插

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 请各位大侠推荐学习OCX的网站和书籍
  • quickpatch!!各位大侠看过来!!!
  • 急!请教一个在WORD文档中搜寻关键字的方法,有代码的扔一段过来,谢谢各位大侠
  • 各位大侠给点建议
  • 各位大侠,我想做一个支持flv的FLASH播放器,请问要怎么下手,VC控件可以用吗(MFC),
  • 如何在对话框中使用MSChart?恳请各位大侠指点!!!
  • 各位大侠帮帮我,怎么用VC开发插件式系统?
  • 本人编了个单文档下基于MSCOMM32串口通信程序,但是始终存在bug,请各位大侠指教
  • 创建OCX控件失败,请各位大侠帮帮忙了!
  • 各位大侠,请问如何实现word或Excel中的鼠标悬停取词?

相关文章

  • 2017-06-05 请教一个简单的问题C语言中宽字符的格式转换,
  • 2017-06-05 NOTIFYICONDATA与线程的问题
  • 2017-06-04 难题征解:COM中事件槽事件重载时Variant类型的获取问题
  • 2017-06-04 ATL做的ActiveX控件全屏后如何获得输入焦点
  • 2017-06-04 请问:在word中修改柱状图数据
  • 2017-06-04 VC编程,借用automation技术读写EXCEL文件数据/在VC程序中创建新EXCEL文件……(答出者给450分)
  • 2017-06-04 这些输出什么意思?怎么解决?
  • 2017-06-05 请问Debug时出现“DamageAfterNormalBlock#616065at0x005CB050”的错误是什么原因?
  • 2017-06-05 新站开张送100
  • 2017-06-05 两线程不同步共享数据问题?

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 向专家请教,怎样在打开某文件时,自动执行进程。
    • VisualC++60到VS2010中出现的ASSERTIsWindowpTemp->m_hWnd错误
    • 在线程中生成一个CView派生类的实例,为什么不能响应鼠标?
    • 如何制作一个安装包,能在安装的过程中将一个exe文件安装成系统服务
    • 求助,有什么控件可以实现类似效果,有图
    • ActiveX控件中的全局变量问题
    • 不能将参数1从“ATL::CTime__w64”转换为“ATL::CTime&”
    • 关于bho及控制ie行为的问题,
    • 如何用com创建文件,最好有源码?
    • 400分高手指点:如何把所有对话框转到view中显示,如同诺盾界面?

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有