我正在尝试从包含VCL表单的VCL应用程序加载基于FMX的dll,其中包括FMX表单。
摘自发行说明 - http://docwiki.embarcadero.com/RADStudio/en/Release_Notes_for_XE2_Update_2:
要创建使用GDI +的DLL,您需要从主机应用程序启动GDI +,如下所示:
对于Delphi,将Winapi.GDIPOBJ添加到主窗体单元的interface section uses子句中。
听起来很好,但实际上我现在在退出我的VCL应用程序时遇到访问冲突。我相信这与初始化和释放GDI +有关,但无法找到有关此内容的更多信息。
我已经阅读了这两篇文章:
https://forums.embarcadero.com/thread.jspa?threadID=63425
Delphi XE2: Possible to instantiate a FireMonkey Form in VCL application?
其他人遇到过这个?最终我希望我们的C应用程序加载FMX dll(和GDI +),但是这个过程的一部分涉及让VCL和FireMonkey dll工作。
答案 0 :(得分:2)
这个答案适用于Delphi XE2 Update 2,我不知道Update 3是否发生了变化。
我开始了Embarcadero线程。从主机应用程序启动GDI +对我来说不是一个选择。到目前为止,一切都在DLL方面正常工作而没有错误,但也没有任何东西被释放到外部世界。
如果您能够修改C主机应用程序,您可能会发现MSDN GdiplusStartup() documentation很有用。
====
将此单位添加到您的项目中:
unit InitFmxHack;
interface
procedure InitGDIP; // Call before using FMX.
procedure FreeGDIP; // Call after using FMX.
// NOTE:
// InitGDIP() must be called before instantiating a FireMonkey form.
// FreeGDIP() must be called after all FireMonkey forms are destroyed.
//
// InitGDIP/FreeGDIP can not be called from the initalization or finalization sections,
// or any method called from these sections.
//
implementation
uses
System.SysUtils,
Winapi.GDIPAPI,
Winapi.GDIPOBJ,
FMX.Types;
var
NeedToShutdownGDIPlus: Boolean;
GDIPlusInput: TGDIPlusStartupInput;
gdiplusToken: Cardinal;
TempRgn: GpRegion;
type
TBitmapAccess = class(TBitmap);
procedure InitGDIP;
begin
NeedToShutdownGDIPlus := False;
case GdipCreateRegion(TempRgn) of
Ok: GdipDeleteRegion(TempRgn);
GdiplusNotInitialized:
begin
GDIPlusInput.GdiplusVersion := 1;
GDIPlusInput.DebugEventCallback := nil;
GDIPlusInput.SuppressBackgroundThread := False;
GDIPlusInput.SuppressExternalCodecs := False;
GdiplusStartup(GDIPlusToken, @GDIPlusInput, nil);
NeedToShutdownGDIPlus := True;
end;
end;
end;
procedure FreeGDIP;
begin
// HACK: Need to forcibly release a GDI+ object held in a global variable.
FreeAndNil(TBitmapAccess(GetMeasureBitmap).FCanvas);
// These lines have been copied from Winapi.GDIPOBJ. I'm not 100% sure
// if there needed but it's probably safer to include them as they are part of
// the standard FireMonkey shutdown sequence. Similar code is also found in
// the VGScene library.
if Assigned(GenericSansSerifFontFamily) then FreeAndNil(GenericSansSerifFontFamily);
if Assigned(GenericSerifFontFamily) then FreeAndNil(GenericSerifFontFamily);
if Assigned(GenericMonospaceFontFamily) then FreeAndNil(GenericMonospaceFontFamily);
if Assigned(GenericTypographicStringFormatBuffer) then FreeAndNil(GenericTypographicStringFormatBuffer);
if Assigned(GenericDefaultStringFormatBuffer) then FreeAndNil(GenericDefaultStringFormatBuffer);
// Finalise GDI+ here if needed...
if NeedToShutdownGDIPlus then GdiplusShutdown(GDIPlusToken);
end;
end.
使用:
InitFmxHack.InitGDIP;
// 1. Create form here.
// 2. Use form.
// 3. Destroy form.
InitFmxHack.FreeGDIP;