的文档GdiplusStartup https://msdn.microsoft.com/en-us/library/windows/desktop/ms534077.aspx函数是这样说的:
不要打电话GdiplusStartup
or GdiplusShutdown
in DllMain
或在任何
被调用的函数DllMain
。如果你想创建一个 DLL
使用 GDI+,您应该使用以下技术之一
初始化GDI+:
- 要求您的客户致电
GdiplusStartup
在他们调用 DLL 中的函数并调用之前GdiplusShutdown
当他们有
完成使用您的 DLL。
- 导出您自己调用的启动函数
GdiplusStartup
和你自己调用的关闭函数GdiplusShutdown
。要求您的客户
在调用您的启动函数之前调用您的其他函数
DLL 并在使用完毕后调用您的关闭函数
你的DLL。
- Call
GdiplusStartup
and GdiplusShutdown
在每个进行 GDI+ 调用的函数中。
通过将此 Delphi GdiPlus 库编译成 DLL,您就违反了此规则GdiplusStartup
and GdiplusShutdown
。这些函数以单元形式调用initialization
and finalization
部分,分别。对于图书馆项目,代码在initialization
and finalization
一个单元的各个部分是从执行的DllMain
.
看来您使用的 GdiPlus 库从来没有打算从库中使用。但作为一般规则,在编写库代码时,您应该了解周围的限制DllMain
并确保您放置的代码initialization
and finalization
部分尊重这一点。我认为这个 GdiPlus 库在这方面失败了。
作为对比,看一下 Delphi RTL 中的代码WinApi.GDIPOBJ
unit:
initialization
if not IsLibrary then
begin
// Initialize StartupInput structure
StartupInput.DebugEventCallback := nil;
StartupInput.SuppressBackgroundThread := False;
StartupInput.SuppressExternalCodecs := False;
StartupInput.GdiplusVersion := 1;
GdiplusStartup(gdiplusToken, @StartupInput, nil);
end;
finalization
if not IsLibrary then
begin
if Assigned(GenericSansSerifFontFamily) then
GenericSansSerifFontFamily.Free;
if Assigned(GenericSerifFontFamily) then
GenericSerifFontFamily.Free;
if Assigned(GenericMonospaceFontFamily) then
GenericMonospaceFontFamily.Free;
if Assigned(GenericTypographicStringFormatBuffer) then
GenericTypographicStringFormatBuffer.free;
if Assigned(GenericDefaultStringFormatBuffer) then
GenericDefaultStringFormatBuffer.Free;
GdiplusShutdown(gdiplusToken);
end;
此代码通过确保它不会调用来遵守规则GdiplusStartup
and GdiplusShutdown
from DllMain
。相反,它把责任留给了任何使用的库的作者WinApi.GDIPOBJ
以确保GdiplusStartup
and GdiplusShutdown
在适当的时间被调用。
如果我是你,我会选择上面列出的三个要点选项之一。第三个选项不太实用,但前两个是不错的选择。如果是我,我会选择第一个选项并修改initialization
and finalization
代码在你的GdiPlus
图书馆看起来更像是在WinApi.GDIPOBJ
.