//DLL工程代码procedure SyScallForm(Mainform: Tform; FormName: string); stdcall;
begin
if FormName = 'frm_base' then
begin
frm_base := Tfrm_base.Create(Mainform);
frm_base.Show;
end;
end;exports
SyScallForm;end.
//Frm_Main代码
var
Frm_Main: TFrm_Main;
SysMoudle: Thandle;
SyScallForm: procedure(Formu: TForm; FormName: string); stdcall;implementation{$R *.dfm}procedure TFrm_Main.FormCreate(Sender: TObject);
begin
try
SysMoudle := LoadLibrary('.\Sysmdl.dll');
SyScallForm := GetProcAddress(SysMoudle, 'SyScallForm');
except
showmessage('出错啦!');
end;
end;procedure TFrm_Main.b1Click(Sender: TObject);
begin
SyScallForm(Frm_Main, 'frm_base',)
end;
//点击出现no mdi form are active错误
begin
if FormName = 'frm_base' then
begin
frm_base := Tfrm_base.Create(Mainform);
frm_base.Show;
end;
end;exports
SyScallForm;end.
//Frm_Main代码
var
Frm_Main: TFrm_Main;
SysMoudle: Thandle;
SyScallForm: procedure(Formu: TForm; FormName: string); stdcall;implementation{$R *.dfm}procedure TFrm_Main.FormCreate(Sender: TObject);
begin
try
SysMoudle := LoadLibrary('.\Sysmdl.dll');
SyScallForm := GetProcAddress(SysMoudle, 'SyScallForm');
except
showmessage('出错啦!');
end;
end;procedure TFrm_Main.b1Click(Sender: TObject);
begin
SyScallForm(Frm_Main, 'frm_base',)
end;
//点击出现no mdi form are active错误
BTW,参数最好不使用string,使用PChar或者ShortString,否则要包含ShareMem单元
EXE是MDIFORM
加了ShareMem也不行
procedure SyScallForm(AppHandle: HWND; FormName: string); stdcall;
begin
Application.Handle := AppHandle;
if FormName = 'frm_base' then
begin
if frm_base = nil then
frm_base := Tfrm_base.Create(Application);
frm_base.Show;
end;
end;exports
SyScallForm;end.
没有办法,看来你还是菜的,我无话可说了
管它是不是DLL,具体的原理都是一样的
父类窗体设为MDIForm就可以了,组件的内部窗体只要你设为MDIChild按照正常窗体输出方法完全可以达到Show的操作。
具体的接口一般是这样的:
在DLL中定义全局的变量用于置换
var
DllApplication: TApplication;
DllScreen: TScreen;
procedure ShowForm1;
begin
if form1 = nil then
form1 := Tform1.Create(Application);
Form1.Show;
end;procedure ShowFormProc(iFuncId: Integer; hParentAppHandle: HWND;
pScreen: TScreen);Stdcall;
begin
Application.Handle := hParentAppHandle;
Screen := pScreen;
case iFuncId of
1: ShowForm1;//触发事件1 输出TForm对象
2: 触发事件2
....
end;
end;
//DLL入口事件
procedure DllUnLoadProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
begin
Application := DllApplication;
Screen := DllScreen;
end;
end;exports
ShowFormProc name 'ShowFormProc';begin
DllApplication := Application;
DllScreen := Screen;
DllProc := @DLLUnloadProc;
end;DLL只是一个组件,如果把它集成到一个工程里就是一样的,只不过组件化管理易于升级和维护。Delphi输出窗体,必须将DLL的TApplication对象赋值为宿主程序的TApplication对象,为了方便接口的书写,目前一般是将TApplication对象的句柄传到DLL组件内部,否则你的Show出的窗体肯定会报内存错误。这是一个完整的输出窗体的Form的接口实例,不要认为一定要不主窗体对象传进来,如果是非MDI的多文档窗口显示,你需要将相关的宿主对象句柄传进来
比如可以将Dll中的Form Show到一个Panel上、Form上,这样的操作就稍微麻烦一些,不过在论坛里有解决的方案
DLL执行老是有问题,请问你有没有这方面的代码啊?按你在论坛上说的,还错,刚接触希望能帮帮忙
//DLL单元,form1为DLL中的中的窗口,Formstyle为fsMDIChildlibrary bb;uses
forms,
Windows,
Unit1 in 'Unit1.pas' {Form1};
var
DllApplication: TApplication;
DllScreen: TScreen;{$R *.res}procedure ShowForm1;
begin
if form1 = nil then
form1 := Tform1.Create(Application);
form1.Show;
end;procedure ShowFormProc(iFuncId: Integer; hParentAppHandle: HWND; pScreen: TScreen); stdcall;
begin
Application.Handle := hParentAppHandle;
Screen := pScreen;
case iFuncId of
1: ShowForm1; //触发事件1 输出TForm对象
// 2: 触发事件2
// ....
end;
end;//DLL入口事件
procedure DllUnLoadProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
begin
Application := DllApplication;
Screen := DllScreen;
end;
end;exports
ShowFormProc name 'ShowFormProc';begin
DllApplication := Application;
DllScreen := Screen;
DllProc := @DllUnLoadProc;
end.
//EXE单元,执行TFrm_Main.b1Click事件时,出现NO MDICHILD FOUND的错误,怎么解决啊?unit Main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus;type
TFrm_Main = class(TForm)
MainMenu1: TMainMenu;
a1: TMenuItem;
b1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure b1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Frm_Main: TFrm_Main;
SysMoudle: Thandle;
ShowFormProc:procedure(iFuncId: Integer; hParentAppHandle: HWND; pScreen: TScreen);Stdcall;implementation{$R *.dfm}procedure TFrm_Main.FormCreate(Sender: TObject);
begin
try
SysMoudle := LoadLibrary('.\bb.dll');
ShowFormProc := GetProcAddress(SysMoudle, 'ShowFormProc');
except
showmessage('出错啦!');
end;
end;procedure TFrm_Main.b1Click(Sender: TObject);
begin
ShowFormProc(1, Frm_Main.Handle,Screen);end;end.
procedure ShowFormProc(iFuncId: Integer; hParentAppHandle: HWND;...)
改为procedure ShowFormProc(iFuncId: Integer; hParent: TApplcation; ...)
就可以了代码可以稍微改一下
//下面是我做的测试
//Dll组件程序
library DllMoudle;
uses
SysUtils,
Classes,
Windows,
Forms,
f_ModuleSample1 in 'f_ModuleSample1.pas' {Form1};{$R *.res}var
DllApplication: TApplication;
DllScreen: TScreen;procedure ShowFormProc(lBusinId: Integer; pApp: TApplication; pScreen: TScreen);stdcall;
begin
Application := pApp;
Screen := pScreen;
case lBusinId of
1: ShowForm1Proc;
2: ;
else ;
end;
end;//DLLÈë¿Úʼþ
procedure DllUnLoadProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
begin
Application := DllApplication;
Screen := DllScreen;
end;
end;exports
ShowFormProc name 'ShowFormProc';begin
DllApplication := Application;
DllScreen := Screen;
DllProc := @DllUnLoadProc;end.//DLL Form单元
unit f_ModuleSample1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;type
TForm1 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;procedure ShowForm1Proc;implementationprocedure ShowForm1Proc;
begin
if Form1 = nil then
Form1 := TForm1.Create(Application);
Form1.Show;
end;{$R *.dfm}procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
Form1 := nil;
end;end.
//Exe程序
unit f_Exe;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus;type
TShowFormProc = procedure (lBusinId: Integer; pAppHandle: TApplication; pScreen: TScreen);stdcall;
TForm1 = class(TForm)
MainMenu1: TMainMenu;
N1: TMenuItem;
ShowForm11: TMenuItem;
procedure ShowForm11Click(Sender: TObject);
private
{ Private declarations }
FShowFormProc: TShowFormProc;
FDllHandle: Longint;
public
{ Public declarations }
end;var
Form1: TForm1;
implementation{$R *.dfm}procedure TForm1.ShowForm11Click(Sender: TObject);
begin
FDllHandle := LoadLibrary('DllMoudle.dll');
if FDllHandle = 0 then
begin
ShowMessage('组件装载出错!');
Exit;
end;
@FShowFormProc := GetProcAddress(FDllHandle, PChar('ShowFormProc'));
if @FShowFormProc = nil then
begin
ShowMessage('组件事件装载出错!');
Exit;
end;
//响应事件
FShowFormProc(1, Application, Screen);
end;end.