MDI+DLL的问题说过很多很多了!
就我就发过好多帖子了!
可是一直有问题没有完全解决!首先说一下我的“机制”:
library testDlls002;uses
SysUtils,
Classes,
Windows,
Forms,
Unt_Child1 in 'Unt_Child1.pas' {FrmChild001};{$R *.RES}var
DLLApp: TApplication;
DLLScr: TScreen;procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
DLLScr := Screen;
DLLApp := Application;
end;
DLL_PROCESS_DETACH:
begin
Screen := DllScr;
Application := DllApp;
end;
end;
end;//// 运行DLL主窗口 //////////////////////////////////////
procedure RunApp(AApplication: TApplication; AScreen: TScreen); stdcall;
begin
Screen := AScreen;
Application := AApplication;
FrmChild001 := TFrmChild001.Create(Application);
end;//////////////////////////////////////////////////////////////////////
exports
RunApp;//////////////////////////////////////////////////////////////
begin
DLLProc := @DLLEntryPoint; //Assign the address of DLLEntryPoint to DLLProc
DLLEntryPoint(DLL_PROCESS_ATTACH); //Indicate that the DLL is attaching to the process
end.传递了Application何Screen
就我就发过好多帖子了!
可是一直有问题没有完全解决!首先说一下我的“机制”:
library testDlls002;uses
SysUtils,
Classes,
Windows,
Forms,
Unt_Child1 in 'Unt_Child1.pas' {FrmChild001};{$R *.RES}var
DLLApp: TApplication;
DLLScr: TScreen;procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
DLLScr := Screen;
DLLApp := Application;
end;
DLL_PROCESS_DETACH:
begin
Screen := DllScr;
Application := DllApp;
end;
end;
end;//// 运行DLL主窗口 //////////////////////////////////////
procedure RunApp(AApplication: TApplication; AScreen: TScreen); stdcall;
begin
Screen := AScreen;
Application := AApplication;
FrmChild001 := TFrmChild001.Create(Application);
end;//////////////////////////////////////////////////////////////////////
exports
RunApp;//////////////////////////////////////////////////////////////
begin
DLLProc := @DLLEntryPoint; //Assign the address of DLLEntryPoint to DLLProc
DLLEntryPoint(DLL_PROCESS_ATTACH); //Indicate that the DLL is attaching to the process
end.传递了Application何Screen
解决方案 »
- DELPHI中进行IP地址查询的问题,字符串转双精度
- delphi执行查询语句时的进度条怎么做
- 求救:activeForm释放问题?
- 做过连锁配送的朋友,请帮我看看方案,如何解决异地数据交互?嫌分不够单独给!
- ***请教怎样用SPCOMM 给串口设备发送 ‘00MZ’+CHR(13)+CHR(10) ,具体代码怎么实现?
- 一个空件得到焦点的事件是什么,tks
- 如何通过程序,把*.doc文档转换成*.htm文件 急!!! 在线
- 怎样让TWebBrowser向需要接收表单元素的页面发表单数据?(怎样Post)?
- 这段C语言代码怎样改写成Delphi代码啊
- 如何把字符串中的每一个字符转化成为ascii码?
- sql语句求救!!!!!!!!!!!!!!!!!!!! 急!!!!!!!!!!!!!!
- 请问哪位有1stClass Professional for delphi 7的密码?
可是用得多了,用的复杂了就出现问题了!
如:
调用DLL中的MDIChild时,在MDIChild中无法使用Tab键、设置的快捷键无效、ShowHint出现“can not assign tfont to tfont”错误以及没有Application.MainForm.ActiveMDIChild
等等一系列的问题!当然有“解决”办法,就是在所有模块(包括主程序和DLLMDI)都要在Build的选项中,Package的Runtime Packages中勾选Build with runtime packages!
这样就没问题了!可是为什么呢?!我现在不想这么做——也不能这么做!
怎么找出问题根源——改进构架?!欢迎讨论!
unit MainUnit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ToolWin, ComCtrls, Menus;type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
Start: TMenuItem;
procedure StartClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; T_ProvaChild = procedure (ParentApplication: TApplication; ParentForm: TForm); stdcall;var
MainForm: TMainForm;implementation{$R *.DFM}procedure TMainForm.StartClick(Sender: TObject);
var
DllHandle: THandle;
ProcAddr: FarProc;
ProvaChild: T_ProvaChild;
begin
DllHandle := LoadLibrary('ProjectDll');
ProcAddr := GetProcAddress(DllHandle, 'ProvaChild');
if ProcAddr <> nil then
begin
ProvaChild := ProcAddr;
ProvaChild(Application,Self);
end;
end;end.
子窗体dll
library ProjectDll;
uses
Windows,
Messages,
SysUtils,
Classes,
Graphics,
Controls,
Forms,
Dialogs,
UnitDll in 'UnitDll.pas' {Form1};procedure ProvaChild(ParentApplication: TApplication; ParentForm: TForm); export; stdcall;
var
Form1: TForm1;
DllProc: Pointer; { Called whenever DLL entry point is called }begin
Application:=ParentApplication; Form1:=TForm1.Create(ParentForm);
Form1.MyParentForm:=ParentForm;
Form1.MyParentApplication:=ParentApplication;
// windows.SetParent(Form1.Handle,ParentForm.Handle);
// Form1.FormStyle:=fsMDIChild;
Form1.Show;
end;procedure DLLUnloadProc(Reason: Integer); register;
begin
if Reason = DLL_PROCESS_DETACH then Application:=DllApplication;
end;exports
ProvaChild;begin
DllApplication:=Application;
DLLProc := @DLLUnloadProc;
end.
unit UnitDll;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;type
TForm1 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
MyParentForm: TForm;
MyParentApplication: TApplication;
end;var
DllApplication: TApplication;implementation{$R *.DFM}procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
// Application:=DllApplication;
end;end.
我也遇到这样的问题!Font的事还好说,在Graphic.pas有一段代码:
procedure TFont.Assign(Source: TPersistent);
begin
if Source is TFont then
begin
Lock;
try
TFont(Source).Lock;
try
FontManager.AssignResource(Self, TFont(Source).FResource);
Color := TFont(Source).Color;
if PixelsPerInch <> TFont(Source).PixelsPerInch then
Size := TFont(Source).Size;
finally
TFont(Source).Unlock;
end;
finally
Unlock;
end;
Exit;
end;
//inherited Assign(Source); //我把这里注释了!
end;理由:TFont.Assign(Source: TPersistent);中的Source肯定应该是TFont才能Assign!
所以
if Source is TFont then
begin
......
Exit;
end;
干吗还要inherited Assign(Source); 呢?
:)
我就注释了!这样就没有TFont的那个错误了!嘻嘻~
其他的...
唉~我也不会!
学习!
就是工程的选项的Search Path中要加上$(DELPHI)\Source\Vcl
解决Font的方法看来挺多的!
vivian_y(玮玮) 的方法只能解决font!
theone_jxm()的方法好像也只是这样!?:(
我觉得问题主要是出在 Application.MainForm.ActiveMDIChild 上!
可是在往下就没思路了!
各位...
:(
procedure RunApp(AApplication: TApplication; AScreen: TScreen;
AHintWindowClass: THintWindowClass); stdcall;
如果传递的参数再多加一个AHintWindowClass: THintWindowClass,ShowHint的问题也可以解决了!而且不用修改Option选项和VCL单元从这里是不是可以说明,问题出在对Form对象的传递上?!
因为,在Forms.pas这个单元中可以看到
{ Global objects }var
Application: TApplication;
Screen: TScreen;
Ctl3DBtnWndProc: Pointer = nil; { obsolete }
Ctl3DDlgFramePaint: function(Window: HWnd; Msg, wParam, lParam: Longint): Longint stdcall = nil; { obsolete }
Ctl3DCtlColorEx: function(Window: HWnd; Msg, wParam, lParam: Longint): Longint stdcall = nil; { obsolete }
HintWindowClass: THintWindowClass = THintWindow;
......
有这么多Global objects,
而在传递Application时,可以构建MDIDll的结构
在传递Screen后,可以增加Screen的Form都数量,从而增加了MDIChildCount!
在传递HintWindowClass后,又解决了ShowHint的问题!那再往下是不是就可以逐步解决问题呢?!
可是
Ctl3DBtnWndProc: Pointer = nil; { obsolete }
Ctl3DDlgFramePaint: function(Window: HWnd; Msg, wParam, lParam: Longint): Longint stdcall = nil; { obsolete }
Ctl3DCtlColorEx: function(Window: HWnd; Msg, wParam, lParam: Longint): Longint stdcall = nil; { obsolete }
这是什么呢?看上去好像不对路!?
怎么搞?就像 vivian_y(玮玮) 说的 “觉得问题主要是出在Application.MainForm.ActiveMDIChild上”,可是在单元Forms.pas中GetActiveMDIChild是这样子的:
function TCustomForm.GetActiveMDIChild: TForm;
begin
Result := nil;
if (FormStyle = fsMDIForm) and (FClientHandle <> 0) then
Result := TForm(FindControl(SendMessage(FClientHandle, WM_MDIGETACTIVE, 0,
0)));
end;
总不能又去修改VCL源代码吧?!——这不是“正路”
怎么再多传递些信息或者其他方法来解决问题呢?!
{$DEFINE VENDORLL}uses
ShareMem,
SysUtils,
windows,
dialogs,
forms,
Classes,
controls,
vendorInt in 'vendorInt.pas',
rollpagebuttonsfrm in '..\pubmodule\rollpagebuttonsfrm.pas' {frmRollPageButtons: TFrame},
postmoneyfrm in 'postmoneyfrm.pas' {frmpostmoney},
vendorfrm in 'vendorfrm.pas' {frmvendor},
VledgeQueryfrm in 'VledgeQueryfrm.pas' {frmVLedgeQuery},
SysfuncInt in '..\sysfuncDLL\SysfuncInt.pas',
sysobj in '..\sysobject\sysobj.pas',
VendorListRep in 'VendorListRep.pas' {repVendorList: TQuickRep},
vlstatrep in 'vlstatrep.pas' {repVLStat: TQuickRep},
vlstatfrm in 'vlstatfrm.pas' {frmVLStat},
VendorAdjustfrm in 'VendorAdjustfrm.pas' {frmVendorAdjust},
registInt in '..\regist\registInt.pas',
vendorlistfrm in 'vendorlistfrm.pas' {frmVendorList},
vendorlistsignrep in 'vendorlistsignrep.pas' {repVendorListSign: TQuickRep};{$R *.RES}
var
OApplication:TApplication;function ShowVendor(PApplication:TApplication;PForm:TForm):longint;stdcall;
var
oForm:TfrmVendor;
begin
//will to do...
Application:=PApplication;
oForm:=TfrmVendor.Create(application);
oForm.ParentApplication:=PApplication;
oForm.ParentForm:=PForm;
result:=longint(oForm);
oForm.Show;
end;
function ShowVendorMoneyManage(PApplication:TApplication;PForm:TForm):longint;stdcall;
var
oForm:TfrmPostMoney;
begin
//will to do...
Application:=PApplication;
oForm:=TfrmPostMoney.Create(application);
oForm.ParentApplication:=PApplication;
oForm.ParentForm:=PForm;
result:=longint(oForm);
oForm.Show;
end;function ShowVendorLedgeQuery(PApplication:TApplication;PForm:TForm):longint;stdcall;
var
oForm:TfrmVLedgeQuery;
begin
//will to do...
Application:=PApplication;
oForm:=TfrmVLedgeQuery.Create(application);
oForm.ParentApplication:=PApplication;
oForm.ParentForm:=PForm;
result:=longint(oForm);
oForm.Show;
end;function ShowVendorLedgeStat(PApplication:TApplication;PForm:TForm):longint;stdcall;
var
oForm:TfrmVLStat;
begin
//will to do...
Application:=PApplication;
oForm:=TfrmVLStat.Create(application);
oForm.ParentApplication:=PApplication;
oForm.ParentForm:=PForm;
result:=longint(oForm);
oForm.Show;
end;
function ShowVendorList(PApplication:TApplication;PForm:TForm):longint;stdcall;
var
oForm:TfrmVendorList;
begin
//will to do...
Application:=PApplication;
oForm:=TfrmVendorList.Create(application);
oForm.ParentApplication:=PApplication;
oForm.ParentForm:=PForm;
result:=longint(oForm);
oForm.Show;
end;function ShowVendorAdjust(PApplication:TApplication;PForm:TForm):longint;stdcall;
var
oForm:TfrmVendorAdjust;
begin
//will to do...
Application:=PApplication;
oForm:=TfrmVendorAdjust.Create(application);
oForm.ParentApplication:=PApplication;
oForm.ParentForm:=PForm;
result:=longint(oForm);
oForm.Show;
end;procedure DLLEntryPoint(dwReason:DWord);
begin
case dwReason of
DLL_PROCESS_ATTACH:begin
OApplication:=Application;
// HInstance:=Maininstance;
end;
DLL_PROCESS_DETACH:Application:=OApplication;
DLL_THREAD_ATTACH:;
DLL_THREAD_DETACH:;
end;
end;exports
ShowVendor,
ShowVendorMoneyManage,
ShowVendorLedgeQuery,
ShowVendorLedgeStat,
ShowVendorAdjust,
ShowVendorList
;
begin
DllProc:=@DllEntryPoint;
DllEntryPoint(DLL_PROCESS_ATTACH);end.
可是,为什么DLL中的MDI就和普通的MDI用起来不一样呢?!:(为什么我现在在“揪”这个问题呢?!是因为我们现在的项目要用到这种“机制”,而且子窗体会有很多!如果不解决这些,重复的工作量太大!:(
begin
Action:=caFree;
Form1 := nil; //你的程序里面最好加上,
end;
字体的原因是有些VCL控件你不能从外面传入,否则会有问题,而tab健我现在还没有找到答案
begin
Action:=caFree;
Form1 := nil; //这句加上
end;字体的原因是有些VCL控件不能传入dll,TAb健的问题我也没有找到答案