using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { /// Items from the SHCore.dll public static partial class SHCore { private const string Lib_SHCore = "shcore.dll"; /// /// Indicates whether the device is a primary or immersive type of display. /// Note The functions that use these enumeration values are no longer supported as of Windows 8.1. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-display_device_type typedef enum { // DEVICE_PRIMARY, DEVICE_IMMERSIVE } DISPLAY_DEVICE_TYPE; [PInvokeData("shellscalingapi.h", MSDNShortId = "NE:shellscalingapi.__unnamed_enum_0")] public enum DISPLAY_DEVICE_TYPE { /// The device is a primary display device. DEVICE_PRIMARY = 0, /// The device is an immersive display device. DEVICE_IMMERSIVE, } /// Identifies the dots per inch (dpi) setting for a monitor. /// All of these settings are affected by the PROCESS_DPI_AWARENESS of your application // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-monitor_dpi_type typedef enum // MONITOR_DPI_TYPE { MDT_EFFECTIVE_DPI, MDT_ANGULAR_DPI, MDT_RAW_DPI, MDT_DEFAULT } ; [PInvokeData("shellscalingapi.h", MSDNShortId = "NE:shellscalingapi.MONITOR_DPI_TYPE")] public enum MONITOR_DPI_TYPE { /// /// The effective DPI. This value should be used when determining the correct scale factor for scaling UI elements. This /// incorporates the scale factor set by the user for this specific display. /// MDT_EFFECTIVE_DPI = 0, /// /// The angular DPI. This DPI ensures rendering at a compliant angular resolution on the screen. This does not include the scale /// factor set by the user for this specific display. /// MDT_ANGULAR_DPI, /// /// The raw DPI. This value is the linear DPI of the screen as measured on the screen itself. Use this value when you want to /// read the pixel density and not the recommended scaling setting. This does not include the scale factor set by the user for /// this specific display and is not guaranteed to be a supported DPI value. /// MDT_RAW_DPI, /// The default DPI setting for a monitor is MDT_EFFECTIVE_DPI. MDT_DEFAULT = MDT_EFFECTIVE_DPI, } /// /// /// Identifies dots per inch (dpi) awareness values. DPI awareness indicates how much scaling work an application performs for DPI /// versus how much is done by the system. /// /// /// Users have the ability to set the DPI scale factor on their displays independent of each other. Some legacy applications are not /// able to adjust their scaling for multiple DPI settings. In order for users to use these applications without content appearing /// too large or small on displays, Windows can apply DPI virtualization to an application, causing it to be automatically be scaled /// by the system to match the DPI of the current display. The PROCESS_DPI_AWARENESS value indicates what level of scaling /// your application handles on its own and how much is provided by Windows. Keep in mind that applications scaled by the system may /// appear blurry and will read virtualized data about the monitor to maintain compatibility. /// /// /// /// Important /// /// Previous versions of Windows required you to set the DPI awareness for the entire application. Now the DPI awareness is tied to /// individual threads, processes, or windows. This means that the DPI awareness can change while the app is running and that /// multiple windows can have their own independent DPI awareness values. See DPI_AWARENESS for more information about how DPI /// awareness currently works. The recommendations below about setting the DPI awareness in the application manifest are still /// supported, but the current recommendation is to use the DPI_AWARENESS_CONTEXT. /// /// /// The DPI awareness for an application should be set through the application manifest so that it is determined before any actions /// are taken which depend on the DPI of the system. Alternatively, you can set the DPI awareness using SetProcessDpiAwareness, but /// if you do so, you need to make sure to set it before taking any actions dependent on the system DPI. Once you set the DPI /// awareness for a process, it cannot be changed. /// /// Tip /// /// If your app is PROCESS_DPI_UNAWARE, there is no need to set any value in the application manifest. /// PROCESS_DPI_UNAWARE is the default value for apps unless another value is specified. /// /// /// PROCESS_DPI_UNAWARE and PROCESS_SYSTEM_DPI_AWARE apps do not need to respond to WM_DPICHANGED and are not expected /// to handle changes in DPI. The system will automatically scale these types of apps up or down as necessary when the DPI changes. /// PROCESS_PER_MONITOR_DPI_AWARE apps are responsible for recognizing and responding to changes in DPI, signaled by /// WM_DPICHANGED. These will not be scaled by the system. If an app of this type does not resize the window and its content, /// it will appear to grow or shrink by the relative DPI changes as the window is moved from one display to the another with a /// different DPI setting. /// /// Tip /// /// In previous versions of Windows, there was no setting for PROCESS_PER_MONITOR_DPI_AWARE. Apps were either DPI unaware or /// DPI aware. Legacy applications that were classified as DPI aware before Windows 8.1 are considered to have a /// PROCESS_DPI_AWARENESS setting of PROCESS_SYSTEM_DPI_AWARE in current versions of Windows. /// /// /// To understand the importance and impact of the different DPI awareness values, consider a user who has three displays: A, B, and /// C. Display A is set to 100% scaling factor (96 DPI), display B is set to 200% scaling factor (192 DPI), and display C is set to /// 300% scaling factor (288 DPI). The system DPI is set to 200%. /// /// /// An application that is PROCESS_DPI_UNAWARE will always use a scaling factor of 100% (96 DPI). In this scenario, a /// PROCESS_DPI_UNAWARE window is created with a size of 500 by 500. On display A, it will render natively with no scaling. /// On displays B and C, it will be scaled up by the system automatically by a factor of 2 and 3 respectively. This is because a /// PROCESS_DPI_UNAWARE always assumes a DPI of 96, and the system accounts for that. If the app queries for window size, it /// will always get a value of 500 by 500 regardless of what display it is in. If this app were to ask for the DPI of any of the /// three monitors, it will receive 96. /// /// /// Now consider an application that is PROCESS_SYSTEM_DPI_AWARE. Remember that in the sample, the system DPI is 200% or 192 /// DPI. This means that any windows created by this app will render natively on display B. It the window moves to display A, it /// will automatically be scaled down by a factor of 2. This is because a PROCESS_SYSTEM_DPI_AWARE app in this scenario /// assumes that the DPI will always be 192. It queries for the DPI on startup, and then never changes it. The system accommodates /// this by automatically scaling down when moving to display A. Likewise, if the window moves to display C, the system will /// automatically scale up by a factor of 1.5. If the app queries for window size, it will always get the same value, similar to /// PROCESS_DPI_UNAWARE. If it asks for the DPI of any of the three monitors, it will receive 192. /// /// /// Unlike the other awareness values, PROCESS_PER_MONITOR_DPI_AWARE should adapt to the display that it is on. This means /// that it is always rendered natively and is never scaled by the system. The responsibility is on the app to adjust the scale /// factor when receiving the WM_DPICHANGED message. Part of this message includes a suggested rect for the window. This suggestion /// is the current window scaled from the old DPI value to the new DPI value. For example, a window that is 500 by 500 on display A /// and moved to display B will receive a suggested window rect that is 1000 by 1000. If that same window is moved to display C, the /// suggested window rect attached to WM_DPICHANGED will be 1500 by 1500. Furthermore, when this app queries for the window /// size, it will always get the actual native value. Likewise, if it asks for the DPI of any of the three monitors, it will receive /// 96, 192, and 288 respectively. /// /// /// Because of DPI virtualization, if one application queries another with a different awareness level for DPI-dependent /// information, the system will automatically scale values to match the awareness level of the caller. One example of this is if /// you call GetWindowRect and pass in a window created by another application. Using the situation described above, assume that a /// PROCESS_DPI_UNAWARE app created a 500 by 500 window on display C. If you query for the window rect from a different /// application, the size of the rect will vary based upon the DPI awareness of your app. /// /// /// /// PROCESS_DPI_UNAWARE /// /// You will get a 500 by 500 rect because the system will assume a DPI of 96 and automatically scale the actual rect down by a /// factor of 3. /// /// /// /// PROCESS_SYSTEM_DPI_AWARE /// /// You will get a 1000 by 1000 rect because the system will assume a DPI of 192 and automatically scale the actual rect down by a /// factor of 3/2. /// /// /// /// PROCESS_PER_MONITOR_DPI_AWARE /// /// You will get a 1500 by 1500 rect because the system will use the actual DPI of the display and not do any scaling behind the scenes. /// /// /// /// Examples /// This snippet demonstrates how to set a value of PROCESS_SYSTEM_DPI_AWARE in your application manifest. /// /// <dpiAware>true</dpiAware> /// /// This snippet demonstrates how to set a value of PROCESS_PER_MONITOR_DPI_AWARE in your application manifest. /// /// <dpiAware>true/PM</dpiAware> /// /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness typedef enum // PROCESS_DPI_AWARENESS { PROCESS_DPI_UNAWARE, PROCESS_SYSTEM_DPI_AWARE, PROCESS_PER_MONITOR_DPI_AWARE } ; [PInvokeData("shellscalingapi.h", MSDNShortId = "NE:shellscalingapi.PROCESS_DPI_AWARENESS")] public enum PROCESS_DPI_AWARENESS { /// /// DPI unaware. This app does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI). It will /// be automatically scaled by the system on any other DPI setting. /// PROCESS_DPI_UNAWARE = 0, /// /// System DPI aware. This app does not scale for DPI changes. It will query for the DPI once and use that value for the /// lifetime of the app. If the DPI changes, the app will not adjust to the new DPI value. It will be automatically scaled up or /// down by the system when the DPI changes from the system value. /// PROCESS_SYSTEM_DPI_AWARE, /// /// Per monitor DPI aware. This app checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes. /// These applications are not automatically scaled by the system. /// PROCESS_PER_MONITOR_DPI_AWARE, } /// Flags that are used to indicate the scaling change that occurred. // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-scale_change_flags typedef enum { // SCF_VALUE_NONE, SCF_SCALE, SCF_PHYSICAL } SCALE_CHANGE_FLAGS; [PInvokeData("shellscalingapi.h", MSDNShortId = "NE:shellscalingapi.__unnamed_enum_1")] [Flags] public enum SCALE_CHANGE_FLAGS { /// No change. SCF_VALUE_NONE = 0x00, /// The scale factor has changed. SCF_SCALE = 0x01, /// /// The physical dpi of the device has changed. A change in the physical dpi is generally caused either by switching display /// devices or switching display resolutions. /// SCF_PHYSICAL = 0x02, } /// /// /// [Some information relates to pre-released product which may be substantially modified before it's commercially released. /// Microsoft makes no warranties, express or implied, with respect to the information provided here.] /// /// Identifies the type of UI component that is needed in the shell. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-shell_ui_component typedef enum { // SHELL_UI_COMPONENT_TASKBARS, SHELL_UI_COMPONENT_NOTIFICATIONAREA, SHELL_UI_COMPONENT_DESKBAND } SHELL_UI_COMPONENT; [PInvokeData("shellscalingapi.h", MSDNShortId = "NE:shellscalingapi.__unnamed_enum_2")] public enum SHELL_UI_COMPONENT { /// This UI component is a taskbar icon. SHELL_UI_COMPONENT_TASKBARS = 0, /// This UI component is an icon in the notification area. SHELL_UI_COMPONENT_NOTIFICATIONAREA, /// This UI component is a deskband icon. SHELL_UI_COMPONENT_DESKBAND, } /// Queries the dots per inch (dpi) of a display. /// Handle of the monitor being queried. /// The type of DPI being queried. Possible values are from the MONITOR_DPI_TYPE enumeration. /// /// The value of the DPI along the X axis. This value always refers to the horizontal edge, even when the screen is rotated. /// /// /// The value of the DPI along the Y axis. This value always refers to the vertical edge, even when the screen is rotated. /// /// /// This function returns one of the following values. /// /// /// Return code /// Description /// /// /// S_OK /// The function successfully returns the X and Y DPI values for the specified monitor. /// /// /// E_INVALIDARG /// The handle, DPI type, or pointers passed in are not valid. /// /// /// /// /// /// This API is not DPI aware and should not be used if the calling thread is per-monitor DPI aware. For the DPI-aware version of /// this API, see GetDpiForWindow. /// /// /// When you call GetDpiForMonitor, you will receive different DPI values depending on the DPI awareness of the calling /// application. DPI awareness is an application-level property usually defined in the application manifest. For more information /// about DPI awareness values, see PROCESS_DPI_AWARENESS. The following table indicates how the results will differ based on the /// PROCESS_DPI_AWARENESS value of your application. /// /// /// /// PROCESS_DPI_UNAWARE /// 96 because the app is unaware of any other scale factors. /// /// /// PROCESS_SYSTEM_DPI_AWARE /// A value set to the system DPI because the app assumes all applications use the system DPI. /// /// /// PROCESS_PER_MONITOR_DPI_AWARE /// The actual DPI value set by the user for that display. /// /// /// /// The values of *dpiX and *dpiY are identical. You only need to record one of the values to determine the DPI and respond appropriately. /// /// /// When MONITOR_DPI_TYPE is MDT_ANGULAR_DPI or MDT_RAW_DPI, the returned DPI value does not include any changes that /// the user made to the DPI by using the desktop scaling override slider control in Control Panel. /// /// /// For more information about DPI settings in Control Panel, see the Writing DPI-Aware Desktop Applications in Windows 8.1 Preview /// white paper. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiformonitor HRESULT GetDpiForMonitor( // HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.GetDpiForMonitor")] public static extern HRESULT GetDpiForMonitor(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY); /// Retrieves the dots per inch (dpi) occupied by a SHELL_UI_COMPONENT based on the current scale factor and PROCESS_DPI_AWARENESS. /// The type of shell component. /// The DPI required for an icon of this type. // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiforshelluicomponent UINT // GetDpiForShellUIComponent( SHELL_UI_COMPONENT Arg1 ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.GetDpiForShellUIComponent")] public static extern uint GetDpiForShellUIComponent(SHELL_UI_COMPONENT Arg1); /// Retrieves the dots per inch (dpi) awareness of the specified process. /// Handle of the process that is being queried. If this parameter is NULL, the current process is queried. /// The DPI awareness of the specified process. Possible values are from the PROCESS_DPI_AWARENESS enumeration. /// /// This function returns one of the following values. /// /// /// Return code /// Description /// /// /// S_OK /// The function successfully retrieved the DPI awareness of the specified process. /// /// /// E_INVALIDARG /// The handle or pointer passed in is not valid. /// /// /// E_ACCESSDENIED /// The application does not have sufficient privileges. /// /// /// /// /// This function is identical to the following code: /// /// GetAwarenessFromDpiAwarenessContext(GetThreadDpiAwarenessContext()); /// /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getprocessdpiawareness HRESULT // GetProcessDpiAwareness( HANDLE hprocess, PROCESS_DPI_AWARENESS *value ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.GetProcessDpiAwareness")] public static extern HRESULT GetProcessDpiAwareness([In, Optional] HPROCESS hprocess, out PROCESS_DPI_AWARENESS value); /// /// Gets the preferred scale factor for a display device. /// Note This function is not supported as of Windows 8.1. Use GetScaleFactorForMonitor instead. /// /// /// Type: DISPLAY_DEVICE_TYPE /// The value that indicates the type of the display device. /// /// /// Type: DEVICE_SCALE_FACTOR /// A value that indicates the scale factor that should be used with the specified DISPLAY_DEVICE_TYPE. /// /// /// Return code/value /// Description /// /// /// SCALE_100_PERCENT 100 /// Use a scale factor of 1x. /// /// /// SCALE_140_PERCENT 140 /// Use a scale factor of 1.4x. /// /// /// SCALE_180_PERCENT 180 /// Use a scale factor of 1.8x. /// /// /// /// /// The default DEVICE_SCALE_FACTOR is SCALE_100_PERCENT. /// Use the scale factor that is returned to scale point values for fonts and pixel values. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getscalefactorfordevice DEVICE_SCALE_FACTOR // GetScaleFactorForDevice( DISPLAY_DEVICE_TYPE deviceType ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.GetScaleFactorForDevice")] public static extern DEVICE_SCALE_FACTOR GetScaleFactorForDevice(DISPLAY_DEVICE_TYPE deviceType); /// Gets the scale factor of a specific monitor. This function replaces GetScaleFactorForDevice. /// The monitor's handle. /// /// /// When this function returns successfully, this value points to one of the DEVICE_SCALE_FACTOR values that specify the scale /// factor of the specified monitor. /// /// /// If the function call fails, this value points to a valid scale factor so that apps can opt to continue on with incorrectly sized resources. /// /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// Your code needs to handle the WM_WINDOWPOSCHANGED message in addition to the scale change event registered through /// RegisterScaleChangeEvent, because the app window can be moved between monitors. In response to the WM_WINDOWPOSCHANGED /// message, call MonitorFromWindow, followed by GetScaleFactorForMonitor to get the scale factor of the monitor which the /// app window is on. Your code can then react to any dots per inch (dpi) change by reloading assets and changing layout. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getscalefactorformonitor HRESULT // GetScaleFactorForMonitor( HMONITOR hMon, DEVICE_SCALE_FACTOR *pScale ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.GetScaleFactorForMonitor")] public static extern HRESULT GetScaleFactorForMonitor(HMONITOR hMon, out DEVICE_SCALE_FACTOR pScale); /// Registers for an event that is triggered when the scale has possibly changed. This function replaces RegisterScaleChangeNotifications. /// Handle of the event to register for scale change notifications. /// /// When this function returns successfully, this value receives the address of a pointer to a cookie that can be used later to /// unregister for the scale change notifications through UnregisterScaleChangeEvent. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// The event is raised whenever something that can affect scale changes, but just because the scale can be affected doesn't mean /// that it has been. Callers can cache the scale factor to verify that the monitor's scale actually has changed. The event handle /// will be duplicated, so callers can close their handle at any time. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-registerscalechangeevent HRESULT // RegisterScaleChangeEvent( HANDLE hEvent, DWORD_PTR *pdwCookie ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.RegisterScaleChangeEvent")] public static extern HRESULT RegisterScaleChangeEvent(HEVENT hEvent, out IntPtr pdwCookie); /// /// Registers a window to receive callbacks when scaling information changes. /// Note This function is not supported as of Windows 8.1. Use RegisterScaleChangeEvent instead. /// /// /// Type: DISPLAY_DEVICE_TYPE /// The enum value that indicates which display device to receive notifications about. /// /// /// Type: HWND /// The handle of the window that will receive the notifications. /// /// /// Type: UINT /// /// An application-defined message that is passed to the window specified by hwndNotify when scaling information changes. Typically, /// this should be set to WM_APP+x, where x is an integer value. /// /// /// /// Type: DWORD* /// /// Pointer to a value that, when this function returns successfully, receives a registration token. This token is used to revoke /// notifications by calling RevokeScaleChangeNotifications. /// /// /// /// Type: STDAPI /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// This message specified by uMsgNotify is posted to the registered window through PostMessage. The wParam of the message can /// contain a combination of SCALE_CHANGE_FLAGS that describe the change that occurred. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-registerscalechangenotifications HRESULT // RegisterScaleChangeNotifications( DISPLAY_DEVICE_TYPE displayDevice, HWND hwndNotify, UINT uMsgNotify, DWORD *pdwCookie ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.RegisterScaleChangeNotifications")] public static extern HRESULT RegisterScaleChangeNotifications(DISPLAY_DEVICE_TYPE displayDevice, HWND hwndNotify, uint uMsgNotify, out uint pdwCookie); /// /// Revokes the registration of a window, preventing it from receiving callbacks when scaling information changes. /// Note This function is not supported as of Windows 8.1. Use UnregisterScaleChangeEvent instead. /// /// /// Type: DISPLAY_DEVICE_TYPE /// The enum value that indicates which display device to receive notifications about. /// /// /// Type: DWORD /// The registration token returned by a previous call to RegisterScaleChangeNotifications. /// /// /// Type: STDAPI /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-revokescalechangenotifications HRESULT // RevokeScaleChangeNotifications( DISPLAY_DEVICE_TYPE displayDevice, DWORD dwCookie ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.RevokeScaleChangeNotifications")] public static extern HRESULT RevokeScaleChangeNotifications(DISPLAY_DEVICE_TYPE displayDevice, uint dwCookie); /// /// /// It is recommended that you set the process-default DPI awareness via application manifest. See Setting the default DPI awareness /// for a process for more information. Setting the process-default DPI awareness via API call can lead to unexpected application behavior. /// /// /// Sets the process-default DPI awareness level. This is equivalent to calling SetProcessDpiAwarenessContext with the corresponding /// DPI_AWARENESS_CONTEXT value. /// /// /// The DPI awareness value to set. Possible values are from the PROCESS_DPI_AWARENESSenumeration. /// /// This function returns one of the following values. /// /// /// Return code /// Description /// /// /// S_OK /// The DPI awareness for the app was set successfully. /// /// /// E_INVALIDARG /// The value passed in is not valid. /// /// /// E_ACCESSDENIED /// The DPI awareness is already set, either by calling this API previously or through the application (.exe) manifest. /// /// /// /// /// /// It is recommended that you set the process-default DPI awareness via application manifest. See Setting the default DPI awareness /// for a process for more information. Setting the process-default DPI awareness via API call can lead to unexpected application behavior. /// /// /// Previous versions of Windows only had one DPI awareness value for the entire application. For those applications, the /// recommendation was to set the DPI awareness value in the manifest as described in PROCESS_DPI_AWARENESS. Under that /// recommendation, you were not supposed to use SetProcessDpiAwareness to update the DPI awareness. In fact, future calls to /// this API would fail after the DPI awareness was set once. Now that DPI awareness is tied to a thread rather than an application, /// you can use this method to update the DPI awareness. However, consider using SetThreadDpiAwarenessContext instead. /// /// Important /// /// For older applications, it is strongly recommended to not use SetProcessDpiAwareness to set the DPI awareness for your /// application. Instead, you should declare the DPI awareness for your application in the application manifest. See /// PROCESS_DPI_AWARENESS for more information about the DPI awareness values and how to set them in the manifest. /// /// /// You must call this API before you call any APIs that depend on the dpi awareness. This is part of the reason why it is /// recommended to use the application manifest rather than the SetProcessDpiAwareness API. Once API awareness is set for an /// app, any future calls to this API will fail. This is true regardless of whether you set the DPI awareness in the manifest or by /// using this API. /// /// If the DPI awareness level is not set, the default value is PROCESS_DPI_UNAWARE. /// // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness HRESULT // SetProcessDpiAwareness( PROCESS_DPI_AWARENESS value ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.SetProcessDpiAwareness")] public static extern HRESULT SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value); /// Unregisters for the scale change event registered through RegisterScaleChangeEvent. This function replaces RevokeScaleChangeNotifications. /// A pointer to the cookie retrieved in the call to RegisterScaleChangeEvent. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-unregisterscalechangeevent HRESULT // UnregisterScaleChangeEvent( DWORD_PTR dwCookie ); [DllImport(Lib_SHCore, SetLastError = false, ExactSpelling = true)] [PInvokeData("shellscalingapi.h", MSDNShortId = "NF:shellscalingapi.UnregisterScaleChangeEvent")] public static extern HRESULT UnregisterScaleChangeEvent(IntPtr dwCookie); } }