How to convert DECLARE_HANDLE and subsequent constants from windef.h to Delphi

The following code is from the Windows 10 Anniversary Update SDK. I need persistent descriptors to use the API in Delphi, because today these headers are not included in 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) 

When I use GetThreadDpiAwarenessContext in various DPI scripts, I found out that the values ​​are like NativeUInts:

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

But I would like to be 100% sure that these values ​​are future. They work in SetThreadDpiAwarenessContext and have the desired effect, but I do not understand how this is achieved. I could not duplicate the header construct in Delphi that gave these results, including for explicitly declaring an integer.

+6
source share
2 answers

For use in SetThreadDpiAwarenessContext you must declare it as

 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); 

but when you get a response from GetThreadDpiAwarenessContext , you need to use GetAwarenessFromDpiAwarenessContext on the received value and compare it with DPI_AWARENESS enum.

You cannot directly compare DPI_AWARENESS_CONTEXT , as it contains several pieces of information, and Microsoft may change it in the future.

+9
source

Delphi does not use files like C / C ++ at all, so it does not matter if the Windows SDK comes with an IDE or not, it will not be used in Delphi projects. Now, if you are worried that Delphi does not provide translations of Pascal C header files, this is another story.

DECLARE_HANDLE() is a C preprocessor macro that declares a new data type alias based on the value of the input parameter and whether the STRICT preprocessor determines the conditional:

 #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 provides a higher level of security for C / C ++ code. Many types of Win32 descriptors are opaque types in user code. Declaring them with DECLARE_HANDLE() allows the compiler to treat them as different data types when STRICT defined, thus preventing erroneous mixing of different types of descriptors (i.e., transmitting HBITMAP where HWND is expected, etc.)). Many developers made this mistake before STRICT was introduced, since all types of descriptors were void* efficiently, preventing any compile-time checks.

This means that DECLARE_HANDLE(DPI_AWARENESS_CONTEXT) will declare DPI_AWARENESS_CONTEXT as follows:

  • when STRICT is determined:

     struct DPI_AWARENESS_CONTEXT__{int unused;}; typedef struct DPI_AWARENESS_CONTEXT__ *DPI_AWARENESS_CONTEXT; 
  • when STRICT not defined:

     typedef void* DPI_AWARENESS_CONTEXT; 

So DPI_AWARENESS_CONTEXT declared as a pointer to a record type or as an untyped pointer , depending on STRICT .

This name resolution cannot be translated into Delphi because it does not support preprocessor macros such as C / C ++. The closest translation would be to declare DPI_AWARENESS_CONTEXT directly:

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

Or just forget about the existence of STRICT in general in Delphi:

 type DPI_AWARENESS_CONTEXT__ = record end; DPI_AWARENESS_CONTEXT = ^DPI_AWARENESS_CONTEXT__; 

In any case, after declaring DPI_AWARENESS_CONTEXT , you can declare its constant values:

 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); 

Update : based on comments, you can use this instead:

 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); 

Note that these constants are used only for input into SetThreadDpiAwarenessContext() , and not for output from GetThreadDpiAwarenessContext() . The latter returns an opaque handle to the private memory structure. You need to use GetAwarenessFromDpiAwarenessContext() to extract the actual DPI_AWARENESS value from this structure.

+6
source

Source: https://habr.com/ru/post/1014170/


All Articles