本贴承接贴:http://expert.csdn.net/Expert/topic/2846/2846596.xml?temp=.5552027。由于大家仅仅给出方案,不能将修改方法调试通过,因此这个问题一直没能解决。希望回复此贴的朋友,在给出方案之前,请先调试一下,如果能通过再回复,问题解决立即结贴。
上贴案例:
程序的目的是通过点击窗体上的按钮调用dll文件,通过dll的过程SetActiveLanguage将按钮的caption变为按钮1,但是当在dll过程SetActiveLanguage()里设置form1.Button1.Caption:='按钮1';时需要将form1.button传递给dll。由于已经uses Unit1 in 'Unit1.pas',//引用Unit1.pas ,所以本以为能够成功,没想到运行时出错,出现Access Violation address 0028332E in moudle 'Project2.dll',Read address 00000324错误,把Form1的成员对象(button1)传递给dll出错。
////////////////////////////
主工程文件
Project1.dprprogram Project1;uses
Forms,
Unit1 in 'Unit1.pas' {Form1};{$R *.res}begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
//////////////////////////////////////////
主单元文件Unit1.pas
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;
//调用project2.dll文件里的过程SetActiveLanguage
procedure SetActiveLanguage(LanguageName:string);export;stdcall;external 'project2.dll';type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
//调用过程
SetActiveLanguage('');
end;end.
//////////////////
编译生成dll文件的工程文件project2.dpr,它引用了Unit1.pas里的按钮对象button1.library Project2;
uses
SysUtils,
Unit1 in 'Unit1.pas',//引用Unit1.pas
Classes;
{$R *.res}procedure SetActiveLanguage(LanguageName:string);export; stdcall;
begin
//处理Unit1.pas里form1类中的按钮对象
form1.Button1.Caption:='按钮1';
end;exports
SetActiveLanguage;
begin
end.
///////////////////////////////////////////////
以下是不用dll实现该功能的方案
不使用dll,而是使用另一个与之无关的单元文件,就可以解决问题。请看如下代码:
Project1.dprprogram Project1;uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};{$R *.res}begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
//////////////////////////////////////////////////
Unit1.pasunit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,unit2;type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
form2.SetActiveLanguage('ddd');
end;end.
///////////////////////////////////////////
Unit2.pasunit Unit2;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;type
TForm2 = class(TForm)
procedure SetActiveLanguage(LanguageName:string);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form2: TForm2;implementation
uses unit1;
{$R *.dfm}
procedure TForm2.SetActiveLanguage(LanguageName:string);
begin
//处理Unit1.pas里form1类中的按钮对象
form1.Button1.Caption:='按钮1';
end;
end.
////////////////////////////////////////////////////////////////
网友提出来的问题和解决方案(但是都不能调试通过)
aiirii(ari-爱的眼睛) ( ) 信誉:181---------------------〉
在兩個程序中, 都加入uses ShareMem;
>>form1.Button1.Caption:='按钮1';
如果你是指主程序的Form1, 那你這種思路是有問題的!
dll與主程序, 是無法這樣簡單共享對象的!
你應該將 主程序的 Button1.handle 傳進來, 然後用sendMessage(handle, ...., BE_Click, nil);
類似這樣的操作, 發送個按鈕點擊消息!!
Shince() ( ) 信誉:100 -----------------〉
SetActiveLanguage 里的Form1在project1.exe运行是是一个未被初始化的对象,所以会出现这个异常。
在兩個程序中, 都加入
uses ShareMem;在Dll和宿主之间共享一个内存块是一个通用的做法,调用DLL里的函数或过程修改共享内存块里的数据,再在宿主里得到修改后的数据。
如果必须使用dll,可考虑传给 Dll 里的SetActiveLanguage 一个地址引用的变量,在里面修改后在Form1里修改Button.Caption.SetActiveLanguage(LanguageName:string;var str: string);
...
str := 'abc';
...
hanlin2004(渴死的鱼) ( ) 信誉:100 --------------------〉
把 string 类型改为 ShortStringxhg0418(新手) ( ) 信誉:100 ---------------------------〉
用回调函数如何!
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
希望回复此贴的朋友先调试通过,然后再给出解决方法,并给出完整代码。
谢谢。
上贴案例:
程序的目的是通过点击窗体上的按钮调用dll文件,通过dll的过程SetActiveLanguage将按钮的caption变为按钮1,但是当在dll过程SetActiveLanguage()里设置form1.Button1.Caption:='按钮1';时需要将form1.button传递给dll。由于已经uses Unit1 in 'Unit1.pas',//引用Unit1.pas ,所以本以为能够成功,没想到运行时出错,出现Access Violation address 0028332E in moudle 'Project2.dll',Read address 00000324错误,把Form1的成员对象(button1)传递给dll出错。
////////////////////////////
主工程文件
Project1.dprprogram Project1;uses
Forms,
Unit1 in 'Unit1.pas' {Form1};{$R *.res}begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
//////////////////////////////////////////
主单元文件Unit1.pas
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;
//调用project2.dll文件里的过程SetActiveLanguage
procedure SetActiveLanguage(LanguageName:string);export;stdcall;external 'project2.dll';type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
//调用过程
SetActiveLanguage('');
end;end.
//////////////////
编译生成dll文件的工程文件project2.dpr,它引用了Unit1.pas里的按钮对象button1.library Project2;
uses
SysUtils,
Unit1 in 'Unit1.pas',//引用Unit1.pas
Classes;
{$R *.res}procedure SetActiveLanguage(LanguageName:string);export; stdcall;
begin
//处理Unit1.pas里form1类中的按钮对象
form1.Button1.Caption:='按钮1';
end;exports
SetActiveLanguage;
begin
end.
///////////////////////////////////////////////
以下是不用dll实现该功能的方案
不使用dll,而是使用另一个与之无关的单元文件,就可以解决问题。请看如下代码:
Project1.dprprogram Project1;uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};{$R *.res}begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
//////////////////////////////////////////////////
Unit1.pasunit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,unit2;type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
form2.SetActiveLanguage('ddd');
end;end.
///////////////////////////////////////////
Unit2.pasunit Unit2;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;type
TForm2 = class(TForm)
procedure SetActiveLanguage(LanguageName:string);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form2: TForm2;implementation
uses unit1;
{$R *.dfm}
procedure TForm2.SetActiveLanguage(LanguageName:string);
begin
//处理Unit1.pas里form1类中的按钮对象
form1.Button1.Caption:='按钮1';
end;
end.
////////////////////////////////////////////////////////////////
网友提出来的问题和解决方案(但是都不能调试通过)
aiirii(ari-爱的眼睛) ( ) 信誉:181---------------------〉
在兩個程序中, 都加入uses ShareMem;
>>form1.Button1.Caption:='按钮1';
如果你是指主程序的Form1, 那你這種思路是有問題的!
dll與主程序, 是無法這樣簡單共享對象的!
你應該將 主程序的 Button1.handle 傳進來, 然後用sendMessage(handle, ...., BE_Click, nil);
類似這樣的操作, 發送個按鈕點擊消息!!
Shince() ( ) 信誉:100 -----------------〉
SetActiveLanguage 里的Form1在project1.exe运行是是一个未被初始化的对象,所以会出现这个异常。
在兩個程序中, 都加入
uses ShareMem;在Dll和宿主之间共享一个内存块是一个通用的做法,调用DLL里的函数或过程修改共享内存块里的数据,再在宿主里得到修改后的数据。
如果必须使用dll,可考虑传给 Dll 里的SetActiveLanguage 一个地址引用的变量,在里面修改后在Form1里修改Button.Caption.SetActiveLanguage(LanguageName:string;var str: string);
...
str := 'abc';
...
hanlin2004(渴死的鱼) ( ) 信誉:100 --------------------〉
把 string 类型改为 ShortStringxhg0418(新手) ( ) 信誉:100 ---------------------------〉
用回调函数如何!
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
希望回复此贴的朋友先调试通过,然后再给出解决方法,并给出完整代码。
谢谢。
發覺, 你思路不對!
代碼錯的很利害!!!dll中 uses unit1;
也有個Form1變量, 但與你主程序的form1, 根本不是一回事!以後就不用說了, 思路錯了, 代碼就不可能對了
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
btnShowModal: TButton;
BtnShow: TButton;
procedure btnShowModalClick(Sender: TObject);
procedure BtnShowClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
//静态引入DLL中的方法
procedure ShowDLLModalForm(aHandle: THandle); stdcall external '..\5-1\DLLShowForm.dll';
procedure ShowDLLForm(aHandle: THandle); stdcall external '..\5-1\DLLShowForm.dll';var
Form1: TForm1;implementation{$R *.dfm}
//调用DLL里输出的ShowDLLModalForm方法,模式显示窗口
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
ShowDLLModalForm(Application.Handle);
end;//调用DLL里输出的ShowDLLForm方法,非模式显示函数
procedure TForm1.BtnShowClick(Sender: TObject);
begin
ShowDLLForm(Application.Handle);
end;end.
library DLLShowForm;uses
SysUtils,
Classes,
DLLFrm in 'DLLFrm.pas' {frmDLL};
{$R *.res}
//输出ShowDLLModalForm,ShowDLLForm接口方法,以便外部程序调用
exports
ShowDLLModalForm, ShowDLLForm;
begin
end.unit DLLFrm;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;type
TfrmDLL = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;{声明要引出的方法}
procedure ShowDLLModalForm(aHandle: THandle); stdcall; //模式显示窗口
procedure ShowDLLForm(aHandle: THandle); stdcall; //非模式显示窗口implementation{$R *.dfm}//模式显示窗口
procedure ShowDLLModalForm(aHandle: THandle);
begin
Application.Handle := aHandle; //传递应用程序句柄
with TfrmDLL.Create(Application) do //创建窗体
begin
try
ShowModal; //模式显示窗体
finally
free;
end;
end;
end;
//非模式显示窗口
procedure ShowDLLForm(aHandle: THandle);
begin
Application.Handle := aHandle; //传递应用程序句柄
with TfrmDLL.Create(application) do //创建窗体
Show; //非模式显示窗体
end;
end.这是一个怎么使用的例子,发给你看看