浅述如何为程序提供二次开发功能 - 1 (原创) - wisenowa的专栏 - CSDNBlog

来源:百度文库 编辑:神马文学网 时间:2024/04/30 04:26:49
什么是二次开发?    我自己理解为:用户可以利用提供者提供的接口使用已有系统中的资源、功能为已有系统提供新的功能;而所提供的新功能可以无缝集成到已有系统中,已有系统无需重新编译。
为系统提供二次开发功能,以前觉得是比较神秘的东西,但是自从去年仔细捉摸一番后,发现事实没有那么难,我就把曾经的经历写出来给大家看看.
提到二次开发,我不知道大家首先想的是什么软件,我想到的是AutoCAD,比较熟悉它的VBA二次开发,不过拿起ObjectArx也玩得转.我所说的这套二次开发的思路与ObjectArx比较相像,都是用动态链接库实现;现在跟我一步一步的探索吧,不过还要多动脑筋,免得陷入我的思维定势;那样我的抛砖引玉的想法就泡汤啦,会比较失望:(,Now let's begin.
1.1 动态链接库
动态链接库的简单例子
library mydll;
uses
SysUtils,
Classes,
Dialogs;
procedure test(str: pchar); export; stdcall;
begin
ShowMessage(str);
end;
exports test;
{$R *.res}
begin
end.
上面是一个完整的动态链接库代码,下面是调用方法
type
TDllFunc = procedure(str: pchar); stdcall;
var
DllHandle: THandle;
DllFunc: TDllFunc;
...
DllHandle := LoadLibrary('mydll.dll');
...
DllFunc := GetProcAddress(DllHandle, 'test');
DllFunc('测试我的动态链接库');
...
FreeLibrary(DllHanle);
关于动态链接库就到这,不再赘述了
1.2 动态链接库的统一接口
有了动态链接库,我们的程序可以实现扩充了;但是问题又来了,我们的程序怎么知道动态链接库中的函数名字、参数等?不知道怎么调用?其实解决这个问题有一个很简单地做法---那就是统一函数名称和参数;这样,我们的程序只需要找到动态链接库文件就可以调用它们了;现在我们把编译好的动态链接库放到指定的目录,这样我们的Exe可以到这个目录中遍历所有的.dll文件,从而调用它们提工的功能函数。
下面是我以前的代码中的一部分(加载目中的全部.dll文件,以及得到它们的功能借口)
procedure TDllManager.GetWorkers;
var
SRec: TSearchRec;
retval: Integer;
DllFunc: TDllFunc;
begin
// 在当前目录下的dev2目录中搜索*.dll文件
retval := FindFirst('./dev2/*.dll', faAnyFile, sRec);
try
while retval = 0 do
begin
if (SRec.Attr and faDirectory) = 0 then  // 文件
begin
// 加载动态连接库
try
TmpDllName := SRec.Name;
TmpHandle := LoadLibrary(pchar('./input/' + TmpDllName));   // 加载动态链接库
DllFunc := GetProcAddress(TmpHandle, DLLFuncName);          // 取得函数地址
if assigned(DllFunc) then
DllFunc();        // 调用函数
... ...
except
if TmpHandle <> 0 then
FreeLibrary(TmpHandle);
end;
end;
retval := FindNext(SRec);
end;
finally
FindClose(SRec);
end;
end;
好了,现在程序怎么自动调用动态链接库的方法有了(其实是变通了一下而已)。
1.3 在动态链接库中调用EXE中的函数
现在,我想为主程序添加一个新的菜单,怎么办?把MainMenu作为参数传给动态链接库,对这种做法确实可行,但是又没有考虑过,如果我的二次开发工作是在VC中进行的,怎么办?VC中可没有Delphi的TMainMenu控件。
想想window api中的的窗口回调,我们会不会有启发呢?对,回调函数可以解决上面的问题。
下面用代码简单说明:
type
procedure TCallBack = procedure(menuname: pchar); stdcall;
// 注意这个函数一定不要是类的成员函数
procedure AddMenu(menuname: pchar);
begin
// 添加菜单
... ...
end;
调用动态链接库
type
procedure TDllFunc(CallBacl: TCallBack); stdcall;
... ...
var
DllFunc: TDllFunc;
// 加载dll,取得函数地址
...
DllFunc(TCallBack(AddMenu));
...
动态链接库中这样写
procedure test(CallBacl: TCallBack); stdcall; export;
begin
CallBack('测试菜单');  // 回调函数,实现新增菜单
end;
这样,在动态链接库中调用EXE中函数的功能就实现了,可是如果这样做的话我们会遇到非常大的麻烦,因为我们不得不为系统各种复杂的功能定义很多回调函数和相应的动态连接库接口函数;如果真的这样做了恐怕没有人会去做系统的二次开发,因为那些接口实在太让人头痛了,解决办法将在在下一篇揭晓。
浅述如何为程序提供二次开发功能 - 1 (原创) - wisenowa的专栏 - CSDNBlog 将java程序运行为Windows服务 - dragonbbc的专栏 - CSDNBlog Window Mobile视频会议程序的开发 - enginetanmary的专栏 - CSDNBlog Window Mobile视频会议程序的开发 - enginetanmary的专栏 - CSDNBlog Drupal专业开发指南 第1章 Drupal工作原理(2)对请求提供服务 - g089h515r806的专栏 - CSDNBlog Drupal专业开发指南 第1章 Drupal工作原理(2)对请求提供服务 - g089h515r806的专栏 - CSDNBlog ICE介绍(1) - abetman的专栏 - CSDNBlog 如何迅速成为Java高手 - paulfong的专栏 - CSDNBlog 如何做需求分析 - AJAXBloger的专栏 - CSDNBlog 如何做开源项目——ABC - hoowa的专栏 - CSDNBlog 典型的flex程序的编写步骤 - Booo.Lee 的专栏 - CSDNBlog 一个Dijkstra算法的完整Java程序实现,算法初学者必看! - brokencar的专栏 - CSDNBlog Asp.net程序性能优化的七个方面 - acefly的专栏 - CSDNBlog 使用程序自动调用ANSYS并运行命令流文件 - 王学福的专栏 - CSDNBlog Windows下程序向Linux下移植细节 - wenhm的专栏 - CSDNBlog 学习 c#程序显示所选目录及其子目录内所有文件 - acefly的专栏 - CSDNBlog C armman的专栏 - CSDNBlog [原创]Cygwin完全下载指南(下)-断点续传篇 - Lionwoo的专栏 - CSDNBlog C 如何支持属性 - jsjwql专栏 - CSDNBlog 善用Wink,将电脑操作录屏为flash - sucence的专栏 - CSDNBlog 从网管做到CIO---看如何提升IT人员职业价值。 - 哎呀的专栏 - CSDNBlog Tapestry的介绍 - bfh365的专栏 - CSDNBlog CFileDialog的详解 - bhw1985的专栏 - CSDNBlog Xindice的FAQ - TKDD的专栏 - CSDNBlog