当前位置:  开发笔记 > 开发工具 > 正文

如何将DECLARE_HANDLE和后续的consts从windef.h转换为Delphi

如何解决《如何将DECLARE_HANDLE和后续的consts从windef.h转换为Delphi》经验,为你挑选了2个好方法。

以下代码来自Windows 10 Anniversary Update SDK.我需要常量句柄才能在Delphi中使用API​​,因为截至今天,Delphi中不包含这些头文件.

  DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);

  #define DPI_AWARENESS_CONTEXT_UNAWARE           ((DPI_AWARENESS_CONTEXT)-1)
  #define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE      ((DPI_AWARENESS_CONTEXT)-2)
  #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)

当我在各种DPI场景中使用GetThreadDpiAwarenessContext时,我已经了解了NativeUInts的值是什么:

  DPI_AWARENESS_CONTEXT_UNAWARE = 16;  
  DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 17;
  DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = 18;

但我想100%肯定这些价值观是面向未来的.它们在SetThreadDpiAwarenessContext调用中工作并具有所需的效果,但我不清楚这些值是如何得出的.除了显式整数声明之外,我无法在Delphi中复制生成这些结果的头部构造.



1> EugeneK..:

要在SetThreadDpiAwarenessContext中使用, 您应该将其声明为

type
  DPI_AWARENESS_CONTEXT = type THandle;
const
  DPI_AWARENESS_CONTEXT_UNAWARE          = DPI_AWARENESS_CONTEXT(-1);
  DPI_AWARENESS_CONTEXT_SYSTEM_AWARE     = DPI_AWARENESS_CONTEXT(-2);
  DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE= DPI_AWARENESS_CONTEXT(-3);

但是当您从GetThreadDpiAwarenessContext获得响应时,您需要对收到的值使用GetAwarenessFromDpiAwarenessContext并将其与DPI_AWARENESS枚举进行比较 .

您不能直接比较,DPI_AWARENESS_CONTEXT因为它包含多条信息,Microsoft可能会在将来更改它.



2> Remy Lebeau..:

Delphi根本不使用C/C++包含文件,因此如果Windows SDK随IDE一起提供并不重要,它将不会在Delphi项目中使用.现在,如果您担心Delphi不提供C头文件的Pascal翻译,那就是另一个故事.

DECLARE_HANDLE()是一个C预处理器宏,它根据输入参数的值声明一个新的数据类型别名,以及是否STRICT定义了预处理器条件:

#ifdef STRICT
typedef void *HANDLE;
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
#endif
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif

STRICT为C/C++代码提供更多类型安全性.许多Win32句柄类型在用户代码中是不透明的类型.声明使用它们DECLARE_HANDLE()允许将它们视为当不同数据类型进行编译器STRICT被定义,从而防止不同句柄类型被错误地混合在一起(即,传递一个HBITMAP其中一个HWND预计,等等).许多开发人员在STRICT引入之前就犯了这种错误,因为所有句柄类型都是有效的void*,因此阻止了任何编译时验证.

这意味着DECLARE_HANDLE(DPI_AWARENESS_CONTEXT)将声明DPI_AWARENESS_CONTEXT如下:

    什么时候STRICT定义:

    struct DPI_AWARENESS_CONTEXT__{int unused;};
    typedef struct DPI_AWARENESS_CONTEXT__ *DPI_AWARENESS_CONTEXT;
    

    什么时候STRICT没有定义:

    typedef void* DPI_AWARENESS_CONTEXT;
    

因此,DPI_AWARENESS_CONTEXT声明为指向记录类型指针无类型指针,具体取决于STRICT.

这种名称解析不能转换为Delphi,因为它不支持像C/C++这样的预处理器宏.最接近的翻译是DPI_AWARENESS_CONTEXT直接声明:

type
  {$IFDEF STRICT}
  DPI_AWARENESS_CONTEXT__ = record
  end; 
  DPI_AWARENESS_CONTEXT = ^DPI_AWARENESS_CONTEXT__;
  {$ELSE}
  DPI_AWARENESS_CONTEXT = Pointer;
  {$ENDIF}

或者STRICT在Delphi 中完全忘记存在:

type
  DPI_AWARENESS_CONTEXT__ = record
  end; 
  DPI_AWARENESS_CONTEXT = ^DPI_AWARENESS_CONTEXT__;

无论哪种方式,一旦DPI_AWARENESS_CONTEXT声明,您就可以声明其常量值:

const
  DPI_AWARENESS_CONTEXT_UNAWARE = DPI_AWARENESS_CONTEXT(-1);
  DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = DPI_AWARENESS_CONTEXT(-2);
  DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = DPI_AWARENESS_CONTEXT(-3);

更新:根据评论,你可以改为使用它:

type
  DPI_AWARENESS_CONTEXT = type THandle;

const
  DPI_AWARENESS_CONTEXT_UNAWARE = DPI_AWARENESS_CONTEXT(-1);  
  DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = DPI_AWARENESS_CONTEXT(-2);
  DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = DPI_AWARENESS_CONTEXT(-3);

请注意,这些常量仅用于输入SetThreadDpiAwarenessContext(),而不用于输出GetThreadDpiAwarenessContext().后者将私有内存结构的不透明句柄返回.您需要使用从该结构中GetAwarenessFromDpiAwarenessContext()检索实际DPI_AWARENESS值.


GetThreadDpiAwarenessContext返回的值并不意味着匹配SetThreadDpiAwarenessContext的已定义的consts.这是令我困惑的一部分.
推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有