源代码如下:
library CalendarLib;{CalendarLib.dll}
uses
ShareMem,
SysUtils,
Classes,
DLLFrm in 'DLLFrm.pas' {DLLForm};
exports
ShowCalendar;
begin
end.unit DLLFrm;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Grids, Calendar;
type
TDLLForm = class(TForm)
calDllCalendar: TCalendar;
procedure calDllCalendarDblClick(Sender: TObject);
end;
{ Declare the export function }
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime; StdCall;
implementation
{$R *.DFM}
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
var
DLLForm: TDllForm;
begin
// Copy application handle to DLL's TApplication object
Application.Handle := AHandle;
DLLForm := TDLLForm.Create(Application);
try
DLLForm.Caption := ACaption;
DLLForm.ShowModal;
Result := DLLForm.calDLLCalendar.CalendarDate; // Pass the date back in Result
finally
DLLForm.Free;
end;
end;procedure TDLLForm.calDllCalendarDblClick(Sender: TObject);
begin
Close;
end;end.{
Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira
}unit MainFfm;//调用DLL的程序interfaceuses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;type
{ First, define a procedural data type, this should reflect the
procedure that is exported from the DLL. }
TShowCalendar = function (AHandle: THandle; ACaption: String): TDateTime; StdCall; { Create a new exception class to reflect a failed DLL load }
EDLLLoadError = class(Exception); TMainForm = class(TForm)
lblDate: TLabel;
btnGetCalendar: TButton;
procedure btnGetCalendarClick(Sender: TObject);
end;var
MainForm: TMainForm;implementation{$R *.DFM}procedure TMainForm.btnGetCalendarClick(Sender: TObject);
var
LibHandle : THandle;
ShowCalendar: TShowCalendar;
begin { Attempt to load the DLL }
LibHandle := LoadLibrary('CALENDARLIB.DLL');
try
{ If the load failed, LibHandle will be zero.
If this occurs, raise an exception. }
if LibHandle = 0 then
raise EDLLLoadError.Create('Unable to Load DLL');
{ If the code makes it here, the DLL loaded successfully, now obtain
the link to the DLL's exported function so that it can be called. }
@ShowCalendar := GetProcAddress(LibHandle, 'ShowCalendar');
{ If the function is imported successfully, then set lblDate.Caption to reflect
the returned date from the function. Otherwise, show the return raise
an exception. }
if not (@ShowCalendar = nil) then
lblDate.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
else
RaiseLastWin32Error;
finally
FreeLibrary(LibHandle); // Unload the DLL.
//注:运行此句会出错,将此句注释掉后就正常了。
//我用的是Delphi6。
end;
end;end.
library CalendarLib;{CalendarLib.dll}
uses
ShareMem,
SysUtils,
Classes,
DLLFrm in 'DLLFrm.pas' {DLLForm};
exports
ShowCalendar;
begin
end.unit DLLFrm;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Grids, Calendar;
type
TDLLForm = class(TForm)
calDllCalendar: TCalendar;
procedure calDllCalendarDblClick(Sender: TObject);
end;
{ Declare the export function }
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime; StdCall;
implementation
{$R *.DFM}
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
var
DLLForm: TDllForm;
begin
// Copy application handle to DLL's TApplication object
Application.Handle := AHandle;
DLLForm := TDLLForm.Create(Application);
try
DLLForm.Caption := ACaption;
DLLForm.ShowModal;
Result := DLLForm.calDLLCalendar.CalendarDate; // Pass the date back in Result
finally
DLLForm.Free;
end;
end;procedure TDLLForm.calDllCalendarDblClick(Sender: TObject);
begin
Close;
end;end.{
Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira
}unit MainFfm;//调用DLL的程序interfaceuses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;type
{ First, define a procedural data type, this should reflect the
procedure that is exported from the DLL. }
TShowCalendar = function (AHandle: THandle; ACaption: String): TDateTime; StdCall; { Create a new exception class to reflect a failed DLL load }
EDLLLoadError = class(Exception); TMainForm = class(TForm)
lblDate: TLabel;
btnGetCalendar: TButton;
procedure btnGetCalendarClick(Sender: TObject);
end;var
MainForm: TMainForm;implementation{$R *.DFM}procedure TMainForm.btnGetCalendarClick(Sender: TObject);
var
LibHandle : THandle;
ShowCalendar: TShowCalendar;
begin { Attempt to load the DLL }
LibHandle := LoadLibrary('CALENDARLIB.DLL');
try
{ If the load failed, LibHandle will be zero.
If this occurs, raise an exception. }
if LibHandle = 0 then
raise EDLLLoadError.Create('Unable to Load DLL');
{ If the code makes it here, the DLL loaded successfully, now obtain
the link to the DLL's exported function so that it can be called. }
@ShowCalendar := GetProcAddress(LibHandle, 'ShowCalendar');
{ If the function is imported successfully, then set lblDate.Caption to reflect
the returned date from the function. Otherwise, show the return raise
an exception. }
if not (@ShowCalendar = nil) then
lblDate.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
else
RaiseLastWin32Error;
finally
FreeLibrary(LibHandle); // Unload the DLL.
//注:运行此句会出错,将此句注释掉后就正常了。
//我用的是Delphi6。
end;
end;end.
注释后仍然报错。
在TDLLForm的CLose事件中要让DLLForm的实例Free掉。
procedure TForm_Main.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
DLLForm.Free;这条语句会Free掉窗体的。而且用你的方法仍然报错。
to sywind(来如风):
因为运行到那句会报错,所以我把那一句注掉了,结果就不报错了,但我不明白是为什么。
var
DLLForm: TDllForm;
begin
// Copy application handle to DLL's TApplication object
Application.Handle := AHandle;
DLLForm := TDLLForm.Create(Application);
try
DLLForm.Caption := ACaption;
DLLForm.ShowModal;
Result := DLLForm.calDLLCalendar.CalendarDate; // Pass the date back in Result
finally
DLLForm.Free;
application.Handle:= 0; //在DllForm这里加上这一句。
end;
end;
警告:如果DLL中的导出函数或过程以字符串或动态数组作为参数或返回值,那么ShareMem必须是DLL和项目的uses子句中的第一单元。这应用于应用程序和DLL的一切字符串的传递,甚至隐含在记录和类中的字符串。ShareMem是共享的内存管理器Borlandmm.dll的接口单元,Borlandmm.dll必须与DLL一起发布。要避免使用Borlandmm.dll,就得用PChar或者ShortString来传递字符串信息。我打开调用DLL的项目代码,居然没有引用SharMem单元,添加进去后就OK了。
D5, D6都试过。FreeLibrary(LibHandle);
是把打开的库Free掉,你可以Trace到这一句,看看LibHandle是不是变了?
DLLForm := TDLLForm.Create(Application);
改为
DLLForm := TDLLForm.Create(nil);
好像就可以了。