我希望您能帮助将一些在Delphi XE8中可用的代码移植到Delphi 10 Seattle。此代码调用Winapi.Windows中的GetPath函数。
新的Win32 API函数签名如下:
function GetPath(DC: HDC; Points: PPointL; Types: PByte; nSize: Integer): Integer; stdcall;
在XE8中,之前的函数有“var Points,Types”,通常被称为“var untyped”参数。
将代码修复以使其与Delphi 10 Seattle一起使用意味着将应用程序代码中的任意类型“统一”为使用在单元本身中声明的确切类型。然而,让我感到困惑的是,有两种类型,PPointL和TPoint,当我让GetPath函数工作时,它所填充的数据填充到一个_WINAPI.WINDOWS中声明的_POINTL记录数组中。
type
_POINTL = record { ptl }
x: Longint;
y: Longint;
end;
{$EXTERNALSYM _POINTL}
PPointL = ^TPointL;
TPointL = _POINTL;
然而,还有另一种类型TPoint,它在System.Types中声明:
TPoint = record
X: FixedInt;
Y: FixedInt;
public
在其他平台上,FixedInt被别名为Longint,无论是32位还是64位的Windows系统,因此,在至少Windows平台上,TPoint和_POINTL是等价的。
如果现有的应用程序组件代码都使用名为TPoint的类型,像这样:
procedure AddPoint(const P:TPoint);
我该如何理解Delphi 10中RTL源代码中的情况?我该如何修复它?应该在单元级别将TPoint重命名为_POINTL吗?
我该如何修复并继续进行?由于此代码是商业组件,我想等待供应商修复此问题,但是了解RTL中的_POINTL和TPoint以及为什么这些结构在定义中会出现重复将有助于其他人将低级Win32代码从Delphi XE8移植到Delphi 10 Seattle。
更新:作为解决方法,我发现我可以重新声明函数GetPath的导入,在我的私有单元实现区域中保持其为var untyped,并继续进行:
{$ifdef D23}
{$POINTERMATH ON}
// Delphi 10 Seattle: function GetPath(DC: HDC; Points: PPointL; Types: PByte; nSize: Integer): Integer; stdcall;
// previously had "var Points,Types" untyped,
const
gdi32 = 'gdi32.dll';
{$EXTERNALSYM GetPath}
function GetPath(DC: HDC; var Points, Types; nSize: Integer): Integer; stdcall; external gdi32 name 'GetPath';
{$endif}
PPoint
而不是PPointL
。 - Rudy VelthuisPOINTL
而不是POINT
,原因我无法理解。但是是的,GetPath
使用POINT
。 - David HeffernanPOINTL
类型不是多余的原因。顺便说一下,POINTL
和RECTL
似乎被用于Metafile APIs中。我不知道为什么它们不能使用普通的POINT
和RECT
结构体。可能是微软内部有竞争的开发组,彼此之间没有沟通。<g> - Rudy Velthuis