8

我正在尝试将一些在 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 函数工作时,它填充的数据被填充到一个 _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,因此至少在 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}
4

1 回答 1

9

Winapi.Windows.GetPath除了DX Seattle 的更改是错误的这一事实之外,对此没什么可说的。我的意思是,从技术上讲,它会起作用,但它会留下任何GetPath在孤立的孤岛中使用的代码。

这种TPointL类型不是新的,但它是错误的类型GetPath。Win32 API 函数为:

int GetPath(
  _In_  HDC     hdc,
  _Out_ LPPOINT lpPoints,
  _Out_ LPBYTE  lpTypes,
  _In_  int     nSize
);

并且LPPOINTPOINT*并且POINT映射到TPoint。有一些 Win32 API 函数使用POINTL,但大多数使用POINT。当然,微软在一个足够的情况下声明了两个相同的类型并没有帮助。

很难看出 Embarcadero 开发人员是如何POINTL在新的GetPath. 在我看来,您应该提交一份 QP 报告并要求将声明从 更改PPointLPPoint

同时,一个简单的转换就足够了,因为这两种类型是二进制兼容的。您希望传递 a PPoint,但编译器想要PPointL. 所以通过PPointL(...)where...是产生 a 的表达式PPoint

于 2015-09-01T14:38:40.037 回答