Delphi 10 西雅图更改为 Win32 GetPath 和冗余 TPoint 和 _POINTL 记录类型
Delphi 10 Seattle changes to Win32 GetPath and redundant TPoint and _POINTL record types
我正在尝试将一些在 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 意味着 "unifying" 应用程序代码中的任意类型完全使用单元本身声明的类型。然而,让我感到困惑的是,有两种类型,PPointL 和 TPoint,当我让 GetPath 函数工作时,它填充的数据被填充到一个 _POINTL 记录数组中,因此在 Winapi.Windows:
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
在其他地方,对于 32 位和 64 位 Windows,FixedInt 是 Longint 的别名,因此据我所知,TPoint 和 _POINTL 至少在 Windows 平台上是等效的.
如果现有应用程序组件代码都使用名为 TPoint 的类型,如下所示:
procedure AddPoint(const P:TPoint);
...我对 Delphi 10 中 RTL 源内部的实际情况有何意义?我应该采取什么方法来解决这个问题?在单位级别将 TPoint 别名为 _POINTL?
我该如何解决这个问题并继续?由于这段代码是一个商业组件,我想我会等到供应商修复它,但是,我认为理解 RTL 中的 _POINTL 和 TPoint,以及为什么这些结构在定义中是 redundantly/duplicated,会帮助其他人将低级 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}
除了在 DX Seattle 中对 Winapi.Windows.GetPath
的更改是错误的这一事实之外,对此没什么好说的。我的意思是,从技术上讲它会起作用,但它会将任何使用 GetPath
的代码留在孤立的筒仓中。
这个 TPointL
类型不是新类型,但它是 GetPath
的错误类型。 Win32 API 函数是:
int GetPath(
_In_ HDC hdc,
_Out_ LPPOINT lpPoints,
_Out_ LPBYTE lpTypes,
_In_ int nSize
);
而LPPOINT
是POINT*
,POINT
映射到TPoint
。有一些 Win32 API 函数使用 POINTL
, but the majority use POINT
。当然,Microsoft 在一个就足够的情况下声明了两个相同的类型并没有帮助。
很难看出 Embarcadero 开发人员是如何在新的 GetPath
中想出 POINTL
的,但就这样吧。在我看来,你应该提交一份 QP 报告,并要求将声明从 PPointL
更改为 PPoint
。
同时,一个简单的转换就足够了,因为这两种类型是二进制兼容的。您希望传递 PPoint
,但编译器想要 PPointL
。所以传递 PPointL(...)
其中 ...
是产生 PPoint
.
的表达式
我正在尝试将一些在 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 意味着 "unifying" 应用程序代码中的任意类型完全使用单元本身声明的类型。然而,让我感到困惑的是,有两种类型,PPointL 和 TPoint,当我让 GetPath 函数工作时,它填充的数据被填充到一个 _POINTL 记录数组中,因此在 Winapi.Windows:
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
在其他地方,对于 32 位和 64 位 Windows,FixedInt 是 Longint 的别名,因此据我所知,TPoint 和 _POINTL 至少在 Windows 平台上是等效的.
如果现有应用程序组件代码都使用名为 TPoint 的类型,如下所示:
procedure AddPoint(const P:TPoint);
...我对 Delphi 10 中 RTL 源内部的实际情况有何意义?我应该采取什么方法来解决这个问题?在单位级别将 TPoint 别名为 _POINTL?
我该如何解决这个问题并继续?由于这段代码是一个商业组件,我想我会等到供应商修复它,但是,我认为理解 RTL 中的 _POINTL 和 TPoint,以及为什么这些结构在定义中是 redundantly/duplicated,会帮助其他人将低级 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}
除了在 DX Seattle 中对 Winapi.Windows.GetPath
的更改是错误的这一事实之外,对此没什么好说的。我的意思是,从技术上讲它会起作用,但它会将任何使用 GetPath
的代码留在孤立的筒仓中。
这个 TPointL
类型不是新类型,但它是 GetPath
的错误类型。 Win32 API 函数是:
int GetPath(
_In_ HDC hdc,
_Out_ LPPOINT lpPoints,
_Out_ LPBYTE lpTypes,
_In_ int nSize
);
而LPPOINT
是POINT*
,POINT
映射到TPoint
。有一些 Win32 API 函数使用 POINTL
, but the majority use POINT
。当然,Microsoft 在一个就足够的情况下声明了两个相同的类型并没有帮助。
很难看出 Embarcadero 开发人员是如何在新的 GetPath
中想出 POINTL
的,但就这样吧。在我看来,你应该提交一份 QP 报告,并要求将声明从 PPointL
更改为 PPoint
。
同时,一个简单的转换就足够了,因为这两种类型是二进制兼容的。您希望传递 PPoint
,但编译器想要 PPointL
。所以传递 PPointL(...)
其中 ...
是产生 PPoint
.