線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2276
推到 Plurk!
推到 Facebook!

可以封裝數個Form在一個DLL檔嗎

尚未結案
bill534
一般會員


發表:38
回覆:51
積分:17
註冊:2007-02-22

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-11-20 13:58:47 IP:125.230.xxx.xxx 訂閱
Dear
單一個Form是可行,但數個時build dll没事,一個主程式時就會出錯,試問可以封裝數個Form嗎,若可行方法為何?
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-11-20 15:01:35 IP:59.125.xxx.xxx 訂閱
這樣問,很籠統,難回答
你是如何 call Form 的?
===================引 用 bill534 文 章===================
Dear
單一個Form是可行,但數個時build dll没事,一個主程式時就會出錯,試問可以封裝數個Form嗎,若可行方法為何?
bill534
一般會員


發表:38
回覆:51
積分:17
註冊:2007-02-22

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-11-21 08:18:29 IP:114.41.xxx.xxx 訂閱
library gs1_1;
uses
SysUtils,
Classes,
forms,
Windows,
Controls,
ShareMem,
exports
gs1EmbeddedFormToPanel index 1, initApplication index 2
;

//var
// OldDllAPP: TApplication;

procedure DllEnterPoint(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH:
begin
OldDllAPP := Application;
end;
DLL_PROCESS_DETACH:
begin
Application := OldDllAPP;
end;
end;
end;

begin
//DLLProc := @DLLEnterPoint;
//DllEnterPoint(DLL_PROCESS_ATTACH);
end.

unit gs1_forms1;

interface

uses
SysUtils, Classes, Controls, forms, ExtCtrls,
gs1_p1,
gs1_p101, gs1_p102,
gs1_p201,
gs1_p406, gs1_p407,
gs1_p501, gs1_p502, gs1_p503, gs1_p504, gs1_p506, gs1_p507, gs1_p508, gs1_p509,
gs1_p601;

// Declare the export function of windows of the main DLL
procedure initApplication(AHandle: THandle);StdCall;
function gs1EmbeddedFormToPanel(pform: integer; ppanel: Tpanel): Pointer; Stdcall;

implementation

var
gs1Form1: TForm;
AppHandle: THandle;

procedure initApplication(AHandle: THandle);
begin
AppHandle := AHandle;
end;

function gs1EmbeddedFormToPanel(pform: integer; ppanel: Tpanel): Pointer;
begin
if gs1Form1 <> nil then
gs1Form1.Close;

if pform = 1 then
gs1Form1 := Tfmgs1_p1.Create(application)
else if pform = 101 then
gs1Form1 := Tfmgs1_p101.Create(application)
else if pform = 102 then
gs1Form1 := Tfmgs1_p102.Create(application)
else if pform = 103 then
begin
end
else if pform = 104 then
begin
end
else if pform = 105 then
begin
end
else if pform = 106 then
begin
end
else if pform = 107 then
begin
end
else if pform = 201 then
gs1Form1 := Tfmgs1_p201.Create(application)
else if pform = 406 then
gs1Form1 := Tfmgs1_p406.Create(application)
else if pform = 407 then
gs1Form1 := Tfmgs1_p407.Create(application)
else if pform = 501 then
gs1Form1 := Tfmgs1_p501.Create(application)
else if pform = 502 then
gs1Form1 := Tfmgs1_p502.Create(application)
else if pform = 503 then
gs1Form1 := Tfmgs1_p503.Create(application)
else if pform = 504 then
gs1Form1 := Tfmgs1_p504.Create(application)
else if pform = 506 then
gs1Form1 := Tfmgs1_p506.Create(application)
else if pform = 507 then
gs1Form1 := Tfmgs1_p507.Create(application)
else if pform = 508 then
gs1Form1 := Tfmgs1_p508.Create(application)
else if pform = 509 then
gs1Form1 := Tfmgs1_p509.Create(application)
else if pform = 601 then
gs1Form1 := Tfmgs1_p601.Create(application);

gs1Form1.Parent := ppanel;
gs1Form1.Align := alclient;
gs1Form1.BorderStyle := bsNone;
gs1Form1.Show;
gs1Form1.Visible := true;
result := gs1Form1;
end;

initialization
gs1Form1 := nil;

finalization

end.


syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-11-21 08:57:49 IP:59.125.xxx.xxx 訂閱
建議不要使用 Application 這一類原生全域物件在 DLL 中
DLL 是設計給各種不同編譯結構的程式使用,有其通用性的考量
盡量只使用指標與簡單格式

xxx.Dear
各Form先畫好,在Dll Unit內提供呼叫函數,實作在gs1_forms1(標紅字)
gs1_forms1,
gs1_p601 in 'gs1_p601.pas' {fmgs1_p601},
gs1_p1 in 'gs1_p1.pas' {fmgs1_p1},
gs1_p101 in 'gs1_p101.pas' {fmgs1_p101},
gs1_p102 in 'gs1_p102.pas' {fmgs1_p102},
gs1_p201 in 'gs1_p201.pas' {fmgs1_p201},
gs1_p406 in 'gs1_p406.pas' {fmgs1_p406},
gs1_p407 in 'gs1_p407.pas' {fmgs1_p407},
gs1_p501 in 'gs1_p501.pas' {fmgs1_p501},
gs1_p502 in 'gs1_p502.pas' {fmgs1_p502},
gs1_p503 in 'gs1_p503.pas' {fmgs1_p503},
gs1_p504 in 'gs1_p504.pas' {fmgs1_p504},
gs1_p506 in 'gs1_p506.pas' {fmgs1_p506},
gs1_p507 in 'gs1_p507.pas' {fmgs1_p507},
gs1_p508 in 'gs1_p508.pas' {fmgs1_p508},
gs1_p509 in 'gs1_p509.pas' {fmgs1_p509};

{$R *.res}

// 上述檔案的gs1EmbeddedFormToPanel等,定義在下檔內
gs1Form1.Show;
gs1Form1.Visible := true;
result := gs1Form1;
end;

initialization
gs1Form1 := nil;

finalization

end.


bill534
一般會員


發表:38
回覆:51
積分:17
註冊:2007-02-22

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-11-21 09:14:45 IP:114.41.xxx.xxx 訂閱
Dear
問題是我只開啟主程式,尚未呼叫Dll內的function,就出現無法存取的異常(一直卡著,Run不起來)
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-11-21 11:39:12 IP:118.169.xxx.xxx 未訂閱
其實不是很清楚你這樣的寫法call form 真正的目的在那裡, 按我看來, 
你這樣的做法, 不如直接以 main form 來架構你底下所有的form,
就樣就直接是delphi 最原始的寫作來執行了, 一樣達到你要call form 的方式
也不會造成很多奇怪的問題!
===================引 用 bill534 文 章===================
library gs1_1;
uses
??? SysUtils,
??? Classes,
??? forms,
??? Windows,
??? Controls,
??? ShareMem,
??? exports
??? gs1EmbeddedFormToPanel index 1, initApplication index 2
;

//var
//??? OldDllAPP: TApplication;

procedure DllEnterPoint(Reason: Integer);
begin
??? case Reason of
??? DLL_PROCESS_ATTACH:
??? begin
??? OldDllAPP := Application;
??? end;
??? DLL_PROCESS_DETACH:
??? begin
??? Application := OldDllAPP;
??? end;
??? end;
end;

begin
??? //DLLProc := @DLLEnterPoint;
??? //DllEnterPoint(DLL_PROCESS_ATTACH);
end.

unit gs1_forms1;

interface

uses
??? SysUtils, Classes, Controls, forms, ExtCtrls,
??? gs1_p1,
??? gs1_p101, gs1_p102,
??? gs1_p201,
??? gs1_p406, gs1_p407,
??? gs1_p501, gs1_p502, gs1_p503, gs1_p504, gs1_p506, gs1_p507, gs1_p508, gs1_p509,
??? gs1_p601;

// Declare the export function of windows of the main DLL
procedure initApplication(AHandle: THandle);StdCall;
function gs1EmbeddedFormToPanel(pform: integer; ppanel: Tpanel): Pointer; Stdcall;

implementation

var
??? gs1Form1: TForm;
??? AppHandle: THandle;

procedure initApplication(AHandle: THandle);
begin
??? AppHandle := AHandle;
end;

function gs1EmbeddedFormToPanel(pform: integer; ppanel: Tpanel): Pointer;
begin
??? if gs1Form1 <> nil then
??? gs1Form1.Close;

??? if pform = 1 then
??? gs1Form1 := Tfmgs1_p1.Create(application)
??? else if pform = 101 then
??? gs1Form1 := Tfmgs1_p101.Create(application)
??? else if pform = 102 then
??? gs1Form1 := Tfmgs1_p102.Create(application)
??? else if pform = 103 then
??? begin
??? end
??? else if pform = 104 then
??? begin
??? end
??? else if pform = 105 then
??? begin
??? end
??? else if pform = 106 then
??? begin
??? end
??? else if pform = 107 then
??? begin
??? end
??? else if pform = 201 then
??? gs1Form1 := Tfmgs1_p201.Create(application)
??? else if pform = 406 then
??? gs1Form1 := Tfmgs1_p406.Create(application)
??? else if pform = 407 then
??? gs1Form1 := Tfmgs1_p407.Create(application)
??? else if pform = 501 then
??? gs1Form1 := Tfmgs1_p501.Create(application)
??? else if pform = 502 then
??? gs1Form1 := Tfmgs1_p502.Create(application)
??? else if pform = 503 then
??? gs1Form1 := Tfmgs1_p503.Create(application)
??? else if pform = 504 then
??? gs1Form1 := Tfmgs1_p504.Create(application)
??? else if pform = 506 then
??? gs1Form1 := Tfmgs1_p506.Create(application)
??? else if pform = 507 then
??? gs1Form1 := Tfmgs1_p507.Create(application)
??? else if pform = 508 then
??? gs1Form1 := Tfmgs1_p508.Create(application)
??? else if pform = 509 then
??? gs1Form1 := Tfmgs1_p509.Create(application)
??? else if pform = 601 then
??? gs1Form1 := Tfmgs1_p601.Create(application);

??? gs1Form1.Parent := ppanel;
??? gs1Form1.Align := alclient;
??? gs1Form1.BorderStyle := bsNone;
??? gs1Form1.Show;
??? gs1Form1.Visible := true;
??? result := gs1Form1;
end;

initialization
??? gs1Form1 := nil;

finalization

end.


bill534
一般會員


發表:38
回覆:51
積分:17
註冊:2007-02-22

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-11-21 13:37:58 IP:114.41.xxx.xxx 訂閱
Dear all
我的重點是DLL可以封裝數個以上的FORM嗎?
因為我没用Dll過Form,成功的是一個,數個就會出問題,SO請各位先進幫忙確認我的方法是錯嗎,是對嗎,若錯對的方法有嗎,有招那我繼續下去也才有意義啊!愛你們喔!thk's
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-11-22 00:15:56 IP:118.169.xxx.xxx 未訂閱
這是我一直在使用的方式, 參考看看吧!

建立一個 dll application

[code delphi]
library Pos;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
FastShareMem,
ExceptionLog,
SysUtils,
Classes,
DLLver in '..\..\Dll_UT\DLLver.pas',
U_VarDef in '..\..\Dll_UT\U_VarDef.pas',
U_IBnet in '..\..\Dll_UT\U_IBnet.pas',
U_Net in '..\..\Dll_UT\U_Net.pas',
UT_SYS in '..\..\Dll_UT\UT_SYS.pas' {SysUT},
P_GetDate in '..\..\Dll_UT\P_GetDate.pas' {Form_GetDate},
P_IBSQLorder in '..\..\Dll_UT\P_IBSQLorder.pas' {Form_IBSQLorder},
..... 中間太多了, 略...
P_PosPrint in '..\Delphi5\P_PosPrint.pas' {Form_PosPrint},
P_PosSourceNo in '..\Delphi5\P_PosSourceNo.pas' {Form_SourceNo},
P_PosSeekstg in '..\Delphi5\P_PosSeekstg.pas' {Form_PosSeekstg},
P_AnslyDP001 in '..\Delphi5\P_AnslyDP001.pas' {Form_DP001show},
P_PosEmppass in '..\Delphi5\P_PosEmppass.pas' {Form_Emppass},
P_OverDate in '..\Delphi5\P_OverDate.pas' {Form_OverDate},
P_FingerInput in '..\Delphi5\P_FingerInput.pas' {Form_FingerInput},
P_UserCheck in '..\Delphi5\P_UserCheck.pas' {Form_UserCheck},
P_PosShowTemp in '..\Delphi5\P_PosShowTemp.pas' {Form_PosShowTemp},
D_Pos in 'D_Pos.pas';
exports
DLL_Pos;
begin
end.
[/code]


這是由上支程式去呼叫一支 unit , 有點類似 main form (但不是form), 但裡面也包了數個form

[code delphi]
unit D_Pos;
interface
uses
Windows, SysUtils, Forms, Classes, StdCtrls, ExtCtrls, Controls, Graphics,
ini;
function DLL_Pos(dAlias, diniFile, dLoginAry, dDLLpath,
eVar5: variant): boolean; stdcall;
implementation
uses DLLver, U_VarDef, U_Default, UT_SYS,
DM_PosPhraseDBF, DM_PosDBF, DM_PosLockDBF, DM_IOrwDBF, DM_IOrwsDBF,
DM_PartPosDBF, DM_PartPosLockDBF, DM_PartUpdDBF, DM_LogDBF,
P_DateSet, P_UserIBfunc, P_Pos;
// 收銀機作業
function DLL_Pos(dAlias, diniFile, dLoginAry, dDLLpath,
eVar5: variant): boolean;
var sfile, dfile: string;
Form1: TForm;
Label1: TLabel;
Button1, Button2: TButton;
Panel1: TPanel;
iKey: string;
i: integer;
overtime: integer;
nowtime: integer;
begin
DLLver.nDLLver:= 'V09.01.014';
DLLver.DebugSL:= TStringList.Create;

SysUt:= TSysUt.Create(nil);
SysUt.MsgDialog('系統參數資料庫開啟中...請稍候');
sfile:= ExtractFilePath(trim(readINI('DATA','PATHBASIC'))) 'Basic.gd_';
dfile:= trim(readINI('DATA','PATHBASIC'));
iKey:= 'Continue';
if (U_Default.SRVrecord.DataIP<>'127.0.0.1') and
(U_Default.SRVrecord.DataIP<>'') and
(not U_Default.IBfrom.IO) then
begin
Form1:= TForm.Create(nil);
Form1.Height:= 320;
Form1.Width:= 380;
Form1.Caption:= '系統警告訊息';
Form1.BorderStyle:= bsSingle;
Form1.BorderIcons:= [];
Form1.Position:= poScreenCenter;
Form1.Font.Name:= '細明體';
Form1.Font.Size:= 14;
Panel1:= TPanel.Create(Form1);
Panel1.Parent:= Form1;
Panel1.Height:= 50;
Panel1.Align:= alBottom;
Label1:= TLabel.Create(Form1);
Label1.Parent:= Form1;
Label1.Color:= clBlack;
Label1.Font.Color:= clRed;
Label1.Font.Style:= [fsBold];
Label1.Align:= alClient;
Label1.Alignment:= taLeftJustify;
Label1.Layout:= tlCenter;
Label1.AutoSize:= True;
Label1.Caption:= ' ▁▂▃警告▃▂▁' #13 #13
' 開出的交易資料將無法送回主機';
Button1:= TButton.Create(Form1);
Button1.Parent:= Panel1;
Button1.Font.Size:= 9;
Button1.Caption:= '結束';
Button1.Height:= 40;
Button1.Width:= 80;
Button1.Top:= 5;
Button1.Left:= 10;
Button1.ModalResult:= mrCancel;
Button2:= TButton.Create(Form1);
Button2.Parent:= Panel1;
Button2.Font.Size:= 9;
Button2.Caption:= '繼續';
Button2.Height:= 40;
Button2.Width:= 80;
Button2.Top:= 5;
Button2.Left:= 280;
Button2.ModalResult:= mrOK;
case Form1.ShowModal of
mrOK :iKey:= 'Continue';
mrCancel:iKey:= 'Terminate';
end;
// 記錄異常事件
DM_Log:= TDM_Log.Create(nil);
end;
if iKey<>'Terminate' then begin
SysUt.MsgDialog('收銀資料庫開啟中...請稍候');
DM_PosLock := TDM_PosLock.Create(nil);
DM_PartPos := TDM_PartPos.Create(nil);
DM_PartPosLock:= TDM_PartPosLock.Create(nil);
DM_PartUpd := TDM_PartUpd.Create(nil);
DM_IOrw := TDM_IOrw.Create(nil);
DM_IOrws := TDM_IOrws.Create(nil);
DM_PosPhrase := TDM_PosPhrase.Create(nil);
if DM_Log=nil then DM_Log:= TDM_Log.Create(nil);
if Form_Wait <> nil then FreeandNil(Form_Wait);
SysUt.MsgDialog('權限資料設定中...請稍候');
U_VarDef.fuserid:= U_VarDef.LoginID;
U_VarDef.fmenuid:= '111';
Form_UserIBfunc:= TForm_UserIBfunc.Create(nil);
for i:= 1 to 99 do
U_Default.rightpri[i]:= Form_UserIBFunc.UserFunc(U_VarDef.fmenuid
format('%.2d',[i]));
U_VarDef.fmenuid:= '999';
Form_UserIBfunc.SetDefault;
for i:= 1 to 99 do
U_Default.rightpub[i]:= Form_UserIBFunc.UserFunc(U_VarDef.fmenuid
format('%.2d',[i]));
FreeAndNil(Form_UserIBfunc);
// 指定營業日期
// 如果未被授權(為 True 時), 則不允許修正日期
// 如果隔日未跨指定的時限, 仍歸於本日(須為無權限者有效)
if not U_Default.rightpri[70] then begin
Form_DateSet:= TForm_DateSet.Create(nil);
try
Form_DateSet.ShowModal;
finally
FreeAndNil(Form_DateSet);
end;
end
else begin
overtime:= StrtoIntDef(trim(readINI('POS','OVERTIME')),6);
nowtime := StrtoIntDef(copy(TimetoStr(Time),1,2),0);
if nowtime<=overtime then
U_Default.nowdate:= SysUt.GetCDay(Date-1,U_VarDef.cdatedigit,'DAY')
else
U_Default.nowdate:= SysUt.GetCDay(Date,U_VarDef.cdatedigit,'DAY');
end;
SysUt.MsgDialog('收銀系統載入中...請稍候');
Form_Pos:= TForm_Pos.Create(nil);
Form_Pos.Top := 0;
Form_Pos.Left := 0;
Form_Pos.Height:= 735;
Form_Pos.Width := 1024;
Form_Pos.lblWorkDate.Caption:= SysUt.DayFormat(nowdate,'/',U_VarDef.cdatedigit);
DM_Pos:= TDM_Pos.Create(nil);
if Form_Wait <> nil then FreeandNil(Form_Wait);
try
Form_Pos.ShowModal;
finally
DLLver.DebugSL.Free;
FreeAndNil(SysUt);
if (U_Default.SRVrecord.DataIP<>'127.0.0.1') and
(U_Default.SRVrecord.DataIP<>'') and (not U_Default.IBfrom.IO)
then FreeAndNil(DM_Log);
FreeAndNil(DM_PosLock);
FreeAndNil(DM_PartPos);
FreeAndNil(DM_PartPosLock);
FreeAndNil(DM_PartUpd);
FreeAndNil(DM_IOrw);
FreeAndNil(DM_IOrws);
FreeAndNil(DM_PosPhrase);
if DM_Log<>nil then FreeAndNil(DM_Log);
FreeAndNil(Form_Pos);
FreeAndNil(DM_Pos);
end;
end
else begin
DLLver.DebugSL.Free;
FreeAndNil(SysUt);
if DM_Log<>nil then FreeAndNil(DM_Log);
end;
result:= True;
end;
end.
[/code]


編輯記錄
P.D. 重新編輯於 2009-11-22 00:17:34, 註解 無‧
bill534
一般會員


發表:38
回覆:51
積分:17
註冊:2007-02-22

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-11-23 11:51:21 IP:125.230.xxx.xxx 訂閱
Dear P.D
我的方法,跟你一樣但問題是主程式一RUN就會出錯,DLL的函數都還没呼叫到,好像是一開始的DLL載入就出錯了!
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#10 引用回覆 回覆 發表時間:2009-11-25 08:35:37 IP:59.125.xxx.xxx 訂閱
他用 TForm_DateSet.Create(Create(application); 改掉了嗎?
將你的 code 改好了再貼出來看看
===================引 用 bill534 文 章===================
Dear P.D
我的方法,跟你一樣但問題是主程式一RUN就會出錯,DLL的函數都還没呼叫到,好像是一開始的DLL載入就出錯了!
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#11 引用回覆 回覆 發表時間:2009-12-01 00:50:13 IP:118.169.xxx.xxx 未訂閱
你說一run就出錯, 到底錯誤訊息是啥, 都不見你貼出來, 我何苦在一直猜呢?
而且, 出錯時, 你有實際去測試錯在那一行code嗎? 這些都是你應該要先做的基本功
因為程式並非我在寫, 我沒有辦法得到你所有的問題點, 必須由你來告訴我們, 才有辦法幫你解決!

不管有沒有招, 還是要由你做過所有可能引發錯誤的動作後, po上來告訴我們, 所以並非我們要刁難你, 我在本站已經說了很多, 我們不是猜謎高手, 其次, 我謝絕你的"愛", 冷~~~~

另外, 我發現你的程式有一個地方
ShareMem 要放在第一支, 你放在中間很可能是引發錯誤的問題點!
還有建議使用FastShareMem 取代 ShareMem, 這在xp 或 vista 上有很大的差異, 比較不容易有記憶體的錯誤
上網查一下就可以找到下載點
===================引 用 bill534 文 章===================
Dear all
我的重點是DLL可以封裝數個以上的FORM嗎?
因為我没用Dll過Form,成功的是一個,數個就會出問題,SO請各位先進幫忙確認我的方法是錯嗎,是對嗎,若錯對的方法有嗎,有招那我繼續下去也才有意義啊!愛你們喔!thk's
編輯記錄
P.D. 重新編輯於 2009-12-01 00:55:59, 註解 無‧
P.D. 重新編輯於 2009-12-01 00:58:03, 註解 無‧
P.D. 重新編輯於 2009-12-01 00:59:01, 註解 無‧
系統時間:2024-04-26 5:59:32
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!