以下代码来自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中复制生成这些结果的头部构造.
要在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可能会在将来更改它.
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
值.