Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# Pinvoke for GetWindowDpiAwarenessContext

Tags:

c#

dpi

pinvoke

I am trying to implement GetWindowDpiAwarenessContext in a C# application with no success.

The relevent header files are:

windef.h

DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);

typedef enum DPI_AWARENESS {
    DPI_AWARENESS_INVALID           = -1,
    DPI_AWARENESS_UNAWARE           = 0,
    DPI_AWARENESS_SYSTEM_AWARE      = 1,
    DPI_AWARENESS_PER_MONITOR_AWARE = 2
} DPI_AWARENESS;

#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)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)

WinUser.h

WINUSERAPI
DPI_AWARENESS_CONTEXT
WINAPI
GetWindowDpiAwarenessContext(
    _In_ HWND hwnd);

I am using:

/// <summary>
/// Class for native methods.
/// </summary>
internal static class NativeMethods {

[DllImport("user32.dll")]
internal static extern IntPtr GetWindowDpiAwarenessContext(IntPtr hWnd);

...

            // Dpi awareness context
            IntPtr dpiAwarenessContext = NativeMethods.GetWindowDpiAwarenessContext(process.Handle);
            if (dpiAwarenessContext == (IntPtr)(-1)) {
                sb.AppendLine("  DPI Awareness Context: DPI_AWARENESS_CONTEXT_UNAWARE");
            } else if (dpiAwarenessContext == (IntPtr)(-2)) {
                sb.AppendLine("  DPI Awareness Context: DPI_AWARENESS_CONTEXT_SYSTEM_AWARE");
            } else if (dpiAwarenessContext == (IntPtr)(-3)) {
                sb.AppendLine("  DPI Awareness Context: DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE");
            } else if (dpiAwarenessContext == (IntPtr)(-4)) {
                sb.AppendLine("  DPI Awareness Context: DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2");
            } else {
                sb.AppendLine("  DPI Awareness Context failed: " + dpiAwarenessContext);
            }

It returns one of the following: 0, 18, 34, 24592, 61457, not the expected -1, -2, -3, or -4. In addition, in subsequent calls to the same window, the return value varies. (The windows are in other processes than this application.)

The question is what is the proper way to define and call GetWindowDpiAwarenessContext.

Thanks in advance.

like image 309
Kenneth Evans Avatar asked Jan 03 '23 17:01

Kenneth Evans


1 Answers

I have yet to find exactly what is in a DPI_AWARENESS_CONTEXT. It is implemented as a handle, which will be different for 32-bit and 64-bit systems. Perhaps it points to a structure or perhaps it is a bitmask. If so, the structure is not defined that I can tell.

I do now know you have to use AreDpiAwarenessContextsEqual(context1, context2) to compare two DPI_AWARENESS_CONTEXT's. You can't compare the values. These are the relevant Pinvoke items I am using:

internal enum PROCESS_DPI_AWARENESS {
    PROCESS_DPI_UNAWARE = 0,
    PROCESS_SYSTEM_DPI_AWARE = 1,
    PROCESS_PER_MONITOR_DPI_AWARE = 2
}

internal enum DPI_AWARENESS {
    DPI_AWARENESS_INVALID = -1,
    DPI_AWARENESS_UNAWARE = 0,
    DPI_AWARENESS_SYSTEM_AWARE = 1,
    DPI_AWARENESS_PER_MONITOR_AWARE = 2
}

[DllImport("SHcore.dll")]
internal static extern int GetProcessDpiAwareness(IntPtr hWnd, out PROCESS_DPI_AWARENESS value);

[DllImport("user32.dll")]
internal static extern int GetDpiForWindow(IntPtr hWnd);

[DllImport("user32.dll")]
internal static extern IntPtr GetWindowDpiAwarenessContext(IntPtr hWnd);

[DllImport("user32.dll")]
internal static extern int GetAwarenessFromDpiAwarenessContext(IntPtr dpiContext);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AreDpiAwarenessContextsEqual(IntPtr dpiContextA,
    IntPtr dpiContextB);

You can use these values from WinDef.h to set or compare:

#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)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)

But if you do a Get after a Set with one of these values, don't expect to get one of these values back. Use AreDpiAwarenessContextsEqual.

like image 184
Kenneth Evans Avatar answered Jan 05 '23 18:01

Kenneth Evans