DLL问题,搞了一个下午还没有搞定,请大侠帮忙。(200分)

  • 主题发起人 主题发起人 woodstock
  • 开始时间 开始时间
W

woodstock

Unregistered / Unconfirmed
GUEST, unregistred user!
一个程序调用一个DLL,被调用的DLL是一个窗口,
exports
ShowCalendar;

函数声明:

TDLLForm = class(TForm)
calDllCalendar: TCalendar;
end;

function ShowCalendar(AHandle: THandle; ACaption: String; pParent: TWinControl): Longint;
var
DLLForm: TDllForm;
begin
Application.Handle := AHandle; //主程序的Application.Handle赋给DllForm
DLLForm := TDLLForm.Create(Application);
DLLForm.Parent := pParent; // !疑点!
Result := Longint(DLLForm);
DLLForm.Caption := ACaption;
DLLForm.Show;
end;

在程序中调用如下:
ShowCalendar(Application.Handle, Caption, Panel1)

结果:错误!

分析:我的目的是要把DLL窗口 显示在Panel1 上面,即:DLLForm.Parent := pParent
如果在同一个程序中完全可以这么使用的,但是在动态库中,运行错误。

不知道大侠们有什么好的解决办法,谢谢。
 
去掉Caption参数看看。
 
1、你用了string参数,那么在dll的uses的第一个位置应该包含:ShareMem
或者改用PChar传递参数
2、把你的exe中的 ShowCalendar 函数的声明贴出来,我对它也有怀疑
 
所有代码如下:
library CalendarMLLib;
uses
ShareMem,
SysUtils,
Classes,
DLLFrm in 'DLLFrm.pas' {DLLForm};

exports
ShowCalendar,
CloseCalendar;

begin
end.
//-----------------------------
unit MainFfm;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls;

type

TMainForm = class(TForm)
btnShowCalendar: TButton;
btnCloseCalendar: TButton;
Panel1: TPanel;
procedure btnShowCalendarClick(Sender: TObject);
procedure btnCloseCalendarClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FFormRef: TForm;
end;

var
MainForm: TMainForm;

function ShowCalendar(AHandle: THandle; ACaption: String; pParent: TWinControl): Longint; StdCall;
external 'CALENDARMLLIB.DLL';

procedure CloseCalendar(AFormRef: Longint); stdcall;
external 'CALENDARMLLIB.DLL';

implementation

{$R *.DFM}

procedure TMainForm.btnShowCalendarClick(Sender: TObject);
begin
if not Assigned(FFormRef) then
FFormRef := TForm(ShowCalendar(Application.Handle, Caption, Panel1));
end;

procedure TMainForm.btnCloseCalendarClick(Sender: TObject);
begin
if Assigned(FFormRef) then
begin
CloseCalendar(Longint(FFormRef));
FFormRef := nil;
end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
FFormRef := nil; // Initialize the FFormRef field to nil.
end;

end.
//--------------------------------------
unit DLLFrm;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Grids, Calendar;

type

TDLLForm = class(TForm)
calDllCalendar: TCalendar;
end;

{ Declare the export function }
function ShowCalendar(AHandle: THandle; ACaption: String; pParent: TWinControl): Longint; stdCall;
procedure CloseCalendar(AFormRef: Longint); stdcall;


implementation
{$R *.DFM}

function ShowCalendar(AHandle: THandle; ACaption: String; pParent: TWinControl): Longint;
var
DLLForm: TDllForm;
begin
// Copy application handle to DLL's TApplication object
Application.Handle := AHandle;
DLLForm := TDLLForm.Create(Application);
DLLForm.Parent := pParent;
Result := Longint(DLLForm);
DLLForm.Caption := ACaption;
DLLForm.Show;
end;

procedure CloseCalendar(AFormRef: Longint);
begin
if AFormRef > 0 then
TDLLForm(AFormRef).Release;
end;
 
存在问题是:
1、你用了string参数,那么在dll的uses的第一个位置应该包含:ShareMem
或者改用PChar传递参数
2、dll中没有定义函数为stdcall,那么exe中相应的声明也不要加stdcall
或者二者都要加stdcall,或者二者都设置为一样的规范,比如pascal、cdecl、stdcall都可以
但是二者必须一致
 
根据DEBUG的结果,事实上,调用过程没有问题,
function ShowCalendar(AHandle: THandle; ACaption: String; pParent: TWinControl): Longint;
正常进入,但是DllForm就是显示不出来。

至于退出时候出错,那是因为在dll中Application.Handle := Ahandle造成的。
 
找到问题的主要原因了:
DLLForm.Parent := pParent;
这个错误,应该是
DLLForm.ParentWindow := pParent.Hanlde;
别的都没有错。
感谢老虎找出问题所在。
 
多人接受答案了。
 
后退
顶部