DLL窗体中遇到的问题!!

ba5590484 2004-09-08 08:40:44
我创建了一个DLL窗体,比如form1 ,然后我再在form1 上放一个按钮,来创建一个form2,
然后在form2 中有一个按钮,用来改变form1上的button.caption的值,总是弹出警告:
Project MAINMENU.EXE raised exception class EAccessViolation with message 'Access violation at address 01E62055 in module 'wagedll.dll'.Read of address 00000308'.Process stopped. Use Step or Run to continue
...全文
236 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
reallike 2004-09-08
  • 打赏
  • 举报
回复
而且,如果误解,你根本就没有说清楚你在干什么。怨我误解??
reallike 2004-09-08
  • 打赏
  • 举报
回复
是不是dll的根本无所谓。窗体就是一个个对象,传来传去没有什么困难的。
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
to reallike
谢谢!!
我的问题已经解决了!!

以后还请多指教!!
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
嘻,我看你有点误解我的意思,我不是想改变主窗体中的内容,而是两个窗体都是在DLL中的!
而且用的窗体格式是(formMDIchild)
reallike 2004-09-08
  • 打赏
  • 举报
回复
如果你不想加public成员,感觉不够通用。

Unit2这样写也行。叫主窗体成为Owner。就是了。

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;


type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

function CreateForm(AControledForm: TForm): TForm; stdcall; exports CreateForm;

var
Form2: TForm2;

implementation

{$R *.dfm}

function CreateForm(AControledForm: TForm): TForm;
begin
Result := TForm2.Create(AControledForm);
end;


procedure TForm2.Button1Click(Sender: TObject);
begin
if (Owner is TForm) and (Owner <> nil) then
TForm(Owner).Caption := 'dajfkashdf';
end;

end.
reallike 2004-09-08
  • 打赏
  • 举报
回复
dll' 工程

===
library dll;

uses
ShareMem,
SysUtils,
Classes,
Unit2 in 'Unit2.pas' {Form1};

{$R *.res}

begin
end.

====
dll单元
-=====

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;


type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
ControledForm: TForm;
end;

function CreateForm(AControledForm: TForm): TForm; stdcall; exports CreateForm;

var
Form2: TForm2;

implementation

{$R *.dfm}

function CreateForm(AControledForm: TForm): TForm;
begin
Result := TForm2.Create(nil);
TForm2(Result).ControledForm := AControledForm;
end;


procedure TForm2.Button1Click(Sender: TObject);
begin
if (ControledForm <> nil) then
ControledForm.Caption := 'dajfkashdf';
end;

end.


==============================

主窗体:

============================

program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

===========

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button2: TButton;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

function CreateForm(AControledForm: TForm): TForm; stdcall;

implementation

{$R *.dfm}

function CreateForm; external 'dll.dll' name 'CreateForm';

procedure TForm1.Button2Click(Sender: TObject);
var
vForm: TForm;
begin
vForm := CreateForm(self);
vForm.Show;
end;

end.


困难吗?
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
哦,我一些明白你的意思了!!!
但是我不可以改变调用窗体中的调用代码,
因为我没有!
reallike 2004-09-08
  • 打赏
  • 举报
回复
嗬嗬,这有何难?

form1创建form2对吗?

然后form2控制form1的caption。

对吗?

看好了啊,我给你变魔术,稍等。:〉
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
to reallike 大侠:

既然你知道,你可不可以提供个方法给我解决呢?你提供的那段代码好像没有涉及到两个窗体,你只是创建一个窗体来调用DLL,然后打开一个窗体,并没有实现我的想要的效果!!
我说的两个窗体都是在DLL中的,不是一个用于调用DLL的。。
我对APPLICATION的问题不是很明白!!可不可以说明白一点,我不是很聪明的而已!!
reallike 2004-09-08
  • 打赏
  • 举报
回复
用汇编,或者C写SDK的都了解,写多少窗口函数,消息循环只有一个,

.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax == 0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw

而一个Application就做了这么一个事情,在Inside Vcl中讲解的很清楚,

在Application.Run的时候,就相当于开始执行消息循环了。

而你的dllAppliation,算哪一部分的呢?
reallike 2004-09-08
  • 打赏
  • 举报
回复
唉,一定是Application的问题…… 没话说了。
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
重新贴出我的完整的代码...

library Project2;

uses
SysUtils,
Classes,
forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

exports
loadshowform;

begin
DllApplication:=Application;
DllProc:=@DLLUnloadProc;
end.

//unit1中的代码..

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, StdCtrls,unit2;

type
TForm1 = class(TForm)
Button1: TButton;
procedure createfund();
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
MyParentForm:Tform;
MyParentApplication:TApplication;
end;

var
Form1: TForm1;
DllApplication:TApplication;

procedure loadshowform(parentApplication:TApplication;Parentform:Tform);export;StdCall;
procedure DLLUnloadProc(Reason:Integer);register;

implementation

{$R *.dfm}

//引出函数
procedure loadshowform(parentApplication:TApplication;Parentform:Tform);export;StdCall;
var
dllform:TForm1;
//DllProc:Pointer;
begin
Application:=parentApplication;
dllform:=TForm1.create(parentform);
dllform.MyParentform:=ParentForm;
dllform.MyParentApplication:=parentApplication;
dllform.createfund();
dllform.show;
end;

// DLLUnloadProc ***************************************************************
procedure DLLUnloadProc(Reason:Integer);register;
begin
if Reason=DLL_PROCESS_DETACH then
Application:=DllApplication;
end;

// TOperationLogForm.createfund ***************************************** 初始化
procedure Tform1.createfund();
begin
//处理该页面生成后的处理(显示处理)
{adoconnection1.ConnectionString:=pub_var.pub_connect;
adoconnection1.Close;}
end;


////////////////////////////////////////////////////////////////////////////////

procedure TForm1.Button1Click(Sender: TObject);
var
form2:Tform2;
begin
form2:=Tform2.Create(self);
form2.Show;
end;

end.

//unit2中的代码

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
form1.Button1.Caption:='dfdfd';
end;

end.
reallike 2004-09-08
  • 打赏
  • 举报
回复
唉…… 一个程序只允许一个Application维持消息循环分发消息队列,

这是一个delphi的基本原则,请看inside vcl。

你调用dll,就把原来的applicaton修改掉了,

我不知道有什么后果……

如果你坚持,我没话可说。

sigh......
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
dllApplication:TApplication

我已经在上面定义的一个全局的!
这个根本不是一个原因来的!
reallike 2004-09-08
  • 打赏
  • 举报
回复
另外:不可能存在你所谓的dllApplication,

TApplication只可能有一个对象实例,你新建就是一个大的设计失败。
reallike 2004-09-08
  • 打赏
  • 举报
回复
唉…… 我说一个。不按你的办法。其他随便你。

dll代码:

==================

library dll;

uses
ShareMem,
SysUtils,
Classes,
Unit2 in 'Unit2.pas' {Form1};

{$R *.res}

begin
end.

========

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

function CreateForm: TForm;stdcall; exports CreateForm;

type
TForm2 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;



var
Form2: TForm2;

implementation

{$R *.dfm}

function CreateForm: Tform;
begin
result := TForm2.Create(nil);
end;

end.


=====

form1

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TCreateForm = function: TForm;

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);
var
vCreate: TCreateForm;
hLib: THandle;
Form1: TForm;
begin
hLib := LoadLibrary('dll.dll');
if (hLib = 0) then Exit;

@vCreate := GetProcAddress(hLib, 'CreateBplForm');
if (@vCreate = nil) then Exit;

Form1 := vCreate;
Form1.Show;
end;

end.
ba5590484 2004-09-08
  • 打赏
  • 举报
回复
form1中。。
//引出函数
procedure test(parentApplication:TApplication;Parentform:Tform);export;StdCall;
var
dllform:Tform;
begin
Application:=parentApplication;
dllform:=Tform.create(parentform);
dllform.MyParentform:=ParentForm;
dllform.MyParentApplication:=parentApplication;
//dllform.createfund();
dllform.show;
end;

// DLLUnloadProc ***************************************************************
procedure DLLUnloadProc(Reason:Integer);register;
begin
if Reason=DLL_PROCESS_DETACH then
Application:=DllApplication;
end;

procedure Tform1.Button1Click(Sender: TObject);
begin
if form2=nil then
begin
application.create(Tform2,form2);
end;
form2.show;
end;

form2中,,,

procedure Tform2.Button1Click(Sender: TObject);
begin
form1.button.caption:='dfdfd';
end;

就是这样了!是否我在form2的创建时,漏了什么呢?

aiirii 2004-09-08
  • 打赏
  • 举报
回复
你的要求是可以的,出錯,說明代碼有問題, 貼出來
minjunw 2004-09-08
  • 打赏
  • 举报
回复
或者在调用DLL时,将Application传入到DLL,用TForm.Create(Application)的方式创建应该就可以
shitianj 2004-09-08
  • 打赏
  • 举报
回复
楼上的能说具体点儿吗?
加载更多回复(1)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧