2012-01-01 80 views
3

我試圖在一個dll中做一個FMX窗體,大約17小時之後(嘗試diffrent approches)我得到它的工作,除了我得到一個異常,試圖卸載dll。我不知道如何使它工作,也許有人可以幫助我,並指出我做錯了什麼?FMX窗體中的一個DLL(firemonkey /德爾福)

附註: 我無法在我的VCL應用程序中使用FMX表單,因爲AA繪圖中,我只需要在我的文本上繪製畫布時使用它,而在VCL應用程序上使用FMX表單時,我沒有文字:(IM說的ClearType試圖使某種OSD的/ HUD

項目顯示我的問題:

EXE unit1.pas

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

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

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

uses 
    unitLoadDLL, Winapi.GDIPOBJ; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    showme(); 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
    closeme(); 
end; 

end. 

個EXE unitLoadDll.pas

unit unitLoadDLL; 

interface 

uses Windows, Dialogs; 

type 
    TShowme = procedure(); 
    TCloseme = procedure(); 

var 
    showme : TShowme = nil; 
    closeme : TCloseme = nil; 
    DllHandle : THandle; 

implementation 

initialization 

    if DllHandle = 0 then begin 
    DllHandle := LoadLibrary('C:\Users\Ja\Desktop\dupa\dll\Win32\Debug\Project1.dll'); 
    if DllHandle > 0 then begin 
     @showme := GetProcAddress(DllHandle,'showme'); 
     @closeme := GetProcAddress(DllHandle,'closeme'); 
    end 
    else begin 
     MessageDlg('Select Image functionality is not available', mtInformation, [mbOK], 0); 
    end; 
    end; 

finalization 
    if DLLHandle <> 0 then 
    FreeLibrary(DLLHandle); 
end. 

DLL project1.dpr

library Project1; 


uses 
    FMX.Forms, 
    System.SysUtils, 
    System.Classes, 
    Unit1 in 'Unit1.pas' {Form1}; 

{$R *.res} 

procedure showme(); stdcall export; 
begin 
    TForm1.showme; 
end; 

procedure closeme(); stdcall export; 
begin 
    TForm1.closeme; 
end; 

exports 
    showme, closeme; 

begin 
end. 

DLL unit1.pas

unit Unit1; 

interface 

uses 
    System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 
    FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs; 

type 
    TForm1 = class(TForm) 
    Label1: TLabel; 
    private 
    { Private declarations } 
    public 
    class procedure showme(); 
    class procedure closeme(); 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.fmx} 

class procedure TForm1.showme(); 
begin 
    Form1 := TForm1.Create(Application); 
    Form1.Show; 
end; 

class procedure TForm1.closeme(); 
begin 
    Form1.Free; 
end; 

end. 

EDIT(FIX):

所有的答案潔具有用,但我所做的是,GDI +在dll卸載之前已經關閉......看起來是問題所在。

新unitLoadDll.pas

unit unitLoadDLL; 

interface 

uses Windows, Dialogs; 

type 
    TShowme = procedure(); 
    TCloseme = procedure(); 

var 
    showme : TShowme = nil; 
    closeme : TCloseme = nil; 
    DllHandle : THandle; 

    function LoadLib : Boolean; 
    procedure UnloadLib; 

implementation 

function LoadLib : Boolean; 
begin 
    if DllHandle = 0 then begin 
    DllHandle := LoadLibrary('C:\Users\Ja\Desktop\dupa\dll\Win32\Debug\Project1.dll'); 
    if DllHandle > 0 then begin 
     @showme := GetProcAddress(DllHandle,'showme'); 
     @closeme := GetProcAddress(DllHandle,'closeme'); 
    end 
    else begin 
     MessageDlg('Select Image functionality is not available', mtInformation, [mbOK], 0); 
    end; 
    end; 
    Result := DllHandle <> 0; 
end; 

procedure UnloadLib; 
begin 
    if DLLHandle <> 0 then begin 
    FreeLibrary(DLLHandle); 
    DllHandle := 0; 
    end; 
end; 

initialization 
    LoadLib; 

finalization 
    UnloadLib; 
end. 

新unit1.pas

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Winapi.GDIPOBJ; 

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

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

uses 
    unitLoadDLL; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    showme(); 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
    closeme(); 
end; 

end. 

在unit1.pas我感動Winapi.GDIPOBJ爲 「使用」 剛剛接口指令後,和它的工作...

謝謝大家的答案!再見!很快......

+0

你的底層問題是什麼? – 2012-01-01 23:47:55

+0

當然,我修好了。 – Knobik 2012-01-02 00:11:47

+0

另一個類似的問題可能有所幫助。 http://stackoverflow.com/questions/8563938/firemonkey-form-in-a-dll-loaded-from-a-vcl-application/8567919#8567919 – Shannon 2012-01-02 01:53:27

回答

4

Embarcadero公司的Stephen球產生了this article demonstraitng怎麼做的正是你想要做什麼

+0

是的,我檢查出來了,表單和free'ing不是問題,我想在關閉應用程序時卸載dll。它顯示了我的問題中指出的一個例外。仍然使用他的unitLoadDLL.pas不起作用:( – Knobik 2012-01-02 00:13:45

0

它是否幫助,如果你導入兩側sharemem?

你沒有使用包,所以雙方可能都有自己的實例所有RTL狀態,以及VMT表(儘管這只是某些IS和AS情況下的問題)。內存管理器是RTL狀態:-)