在DLL中使用FMX表单(FireMonkey/Delphi)

3
我正在尝试在dll中创建一个FMX表单,经过大约17个小时(尝试不同的方法),我成功了,但是在试图卸载dll时出现了异常。我不知道如何使其正常工作,也许有人可以帮助我并指出我做错了什么?
顺便说一句: 由于AA绘图,我不能在我的VCL应用程序中使用FMX表单,我只需要在绘制画布并在VCL应用程序上拥有FMX表单时将其放在我的文本上,我无法在文本上获得清晰度:( 我正在尝试制作某种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.

编辑(修正):

所有答案都很有帮助,但我所做的是,在卸载dll之前关闭了GDI+...那似乎就是问题所在。

新的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移动到接口指令后面的"uses"中,然后它就起作用了...感谢大家的回答!很快就会再见!

你的根本问题是什么? - David Heffernan
另一个类似的问题可能会有所帮助。http://stackoverflow.com/questions/8563938/firemonkey-form-in-a-dll-loaded-from-a-vcl-application/8567919#8567919 - Shannon Matthews
我认为,如果您使用VCL/Win API而不是试图将FMX强制集成到VCL应用程序中,您的生活会变得更加轻松。 - David Heffernan
这篇文章作为一个仅包含链接的回答发布,可能会被删除。https://community.embarcadero.com/blogs/entry/writing-a-firemonkey-dll-for-use-with-a-vcl-application-34 - Stephen Kennedy
1个回答

0

如果在两侧都导入sharemem,这是否有帮助?

您没有使用包,因此双方可能都拥有RTL状态的自己实例,以及VMT表(尽管这只是某些IS和AS情况下的问题)。而内存管理器是RTL状态的 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接