(250分求解,分不够还可以加)关于连续两次打开dll中子窗口的mainmenu菜单后报错的问题 (200分)

F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
//如果正确http://www.delphibbs.com/delphibbs/dispq.asp?lid=2148966上的50分也是你的
我在主程序exe中打开dll中子窗口的mainmenu菜单后关闭这个子窗口,然后重复这个操作后关闭主程序就会报错,也就是不能连续调用两次,但只要不用子窗口的mainmenu就不会报错,那位大哥帮我瞧一下呀
另外只要dll中的子窗口不是childform类型的也不会报错
//dll的调用程序如下
unit MainUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Menus, publicUnit, Grids, DB, ADODB,
DBClient, MConnect, SConnect;

type
TfrmMain = class(TForm)
MainMenu1: TMainMenu;
N1: TMenuItem;
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
procedure N1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
procedure WMGetDlgCode(var msgIn: TWMGetDlgCode)
message WM_GETDLGCODE;
public
{ Public declarations }
end;
type
tnet=array[0..3] of pchar;
var
frmMain: TfrmMain;
function ShowDllForm(App: TApplication
ACaption: string
sc: TScreen): Longint;
stdcall
external 'prjDll.dll';
//function openform(App:TApplication;sc:tscreen;netpara:tnet):Longint;
//stdcall;External'../rzbinfo/reportbuild/reportbuild.dll';
//function openForm(App: TApplication;sc: TScreen;netpara:tnet): Longint;
//stdcall;external'../rzbinfo/reportbuild/reportbuild.dll';
implementation

{$R *.dfm}



procedure TfrmMain.N1Click(Sender: TObject);
begin
ShowDllForm(Application, '子窗体', Screen);
end;




procedure TfrmMain.WMGetDlgCode(var msgIn: TWMGetDlgCode);
begin
inherited;
msgIn.Result := msgIn.Result or DLGC_WANTTAB;
end;

procedure TfrmMain.Button1Click(Sender: TObject);
//var
//netp:tnet;
begin
{netp[0]:=pchar(socketconnection1.Address);
netp[1]:=pchar(inttostr(socketconnection1.Port));
netp[2]:=pchar(socketconnection1.ServerName);
netp[3]:=pchar(socketconnection1.ServerGUID);
openForm(Application,Screen,netp);}
end;

procedure TfrmMain.Button2Click(Sender: TObject);
begin
ShowDllForm(Application, '子窗体', Screen);
end;

end.

//dll如下
library prjDLL;


uses
SysUtils,
Classes,
Windows,
Forms,
childUnit in 'childUnit.pas' {frmChild},
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

var
DLLApp: TApplication;
DLLScreen:TScreen;

function ShowDllForm(App:TApplication
ACaption:String
sc:TScreen):Longint;stdcall;
begin
Application := App;
Screen:=sc;

if not Assigned(frmChild) then
frmChild:=TfrmChild.Create(Application);
Result:=Longint(frmChild);
frmChild.Caption := ACaption;
frmChild.Show;
end;

procedure DLLUnloadProc(Reason : Integer);
begin
if Reason = DLL_PROCESS_DETACH then begin
Application := DLLApp;//恢复
Screen:=DLLScreen;
end;
end;


exports
ShowDllForm;

begin
DLLApp := Application
//保存 DLL 中初始的 Application 对象
DLLScreen:=Screen;
DLLProc := @DLLUnloadProc
//保证 DLL 卸载时恢复原来的 Application
end.




//frmchild如下

unit childUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, publicUnit, Grids, DB, ADODB, DBGrids, Menus, StdCtrls;

type
TfrmChild = class(TForm)
ComboBox1: TComboBox;
MainMenu1: TMainMenu;
xxx1: TMenuItem;
xxxx1: TMenuItem;
xxxx2: TMenuItem;
procedure FormClose(Sender: TObject
var Action: TCloseAction);
procedure FormKeyPress(Sender: TObject
var Key: Char);
procedure FormCreate(Sender: TObject);
procedure xxxx2Click(Sender: TObject);
private
procedure WMGetDlgCode(var msgIn: TWMGetDlgCode);
message WM_GETDLGCODE;
public

end;

var
frmChild: TfrmChild;

implementation

uses Unit1;

{$R *.dfm}

procedure TfrmChild.FormClose(Sender: TObject
var Action: TCloseAction);
begin
FreeAndNil(frmChild);
end;

procedure TfrmChild.FormKeyPress(Sender: TObject
var Key: Char);
begin
if Key = #9 then // Char(VK_tab) then
if not (ActiveControl is TDBGrid) then
begin
Key := #0;
Perform(WM_NEXTDLGCTL, 0, 0);
end;
end;

procedure TfrmChild.WMGetDlgCode(var msgIn: TWMGetDlgCode);
begin
inherited;
msgIn.Result := msgIn.Result or DLGC_WANTTAB;
end;

procedure TfrmChild.FormCreate(Sender: TObject);
begin
combobox1.Items.AddStrings(screen.fonts);
Self.KeyPreview := True;
end;

procedure TfrmChild.xxxx2Click(Sender: TObject);
begin
form1:=tform1.create(self);
form1.showmodal;
form1.free;
end;

end.
//form1就是一个空白的tform;
 
K

kirinma

Unregistered / Unconfirmed
GUEST, unregistred user!
是不是因为你创建了子窗体,使用完事之后没有释放?

管杀不管埋,当然就会闹瘟疫了,呵呵不太恰当的比喻,开个玩笑
 
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
当然不是了,只要不加mainmenu就一切正常,加了就不行。难这是delphi的问题
你可以试试主程序中只有一个mdiform窗体和一个mainmenu菜单,然后做一个dll其中包含一个childform,在childform上放一个mainmenu菜单,然后再加一个form1,在childform中mainmenu中调用form1.编译运行后你就发现
如果你在主程序中第二次打开childform上的mainmenu就报错,并且主程序关闭时也报错
如果是在childform上放一个button按钮来代替mainmenu就一切ok
 
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
Z

zhangshunzhong

Unregistered / Unconfirmed
GUEST, unregistred user!
按你的方法做了,没有错误,应该不是mainmenu问题引起的
 
A

angelgekko

Unregistered / Unconfirmed
GUEST, unregistred user!
“管杀不管埋……”
哈哈哈……很有趣的比喻!
没仔细看阁下的程序。

试试这样,
在FormClose事件中:
Action := caFree;
frmChild := nil;
偶一直是这样释放的。(DLL中的From)

我也曾经遇到类似的问题…………你在DLL里把那个“随运行时间包构建”那里勾上看看
 
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
to angelgekko:我已经做过了,问题不在这儿,而在tmainmenu的groupindex上
playicq.com上有人解决了这个问题,所以我已经找到答案了。
 
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
请班主收回此分,我已自己找到答案
 
F

ForestBen

Unregistered / Unconfirmed
GUEST, unregistred user!
太过分了,呜呜,我正想告诉你是不是因为菜单的index冲突,你就已经找到了答案。

不过顺便也告诉你,delphi的dll函数建议不要使用string类型作为参数,改为pchar吧。一方面使用string有的时候会有问题,另外一方面,使用pchar做的dll可以供VC等程序调用。你看呢?
 
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
是呀,我一直就用的pchar
 
顶部