Win32: Improve window DPI change behavior

When a window transitions between monitors with different scale/dpi
settings:

1. It's automatically resized and repositioned by handling the
   WM_DPICHANGED event (Win8.1)
2. Its non-client area is automatically updated to match the new DPI
   (Win10)
This commit is contained in:
Ioannis Tsakpinis 2017-11-01 16:38:20 +02:00
parent 80d181f12d
commit cd6eb1a6e5
3 changed files with 28 additions and 0 deletions

View File

@ -98,6 +98,8 @@ static GLFWbool loadLibraries(void)
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware) _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware"); GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx) _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");

View File

@ -209,8 +209,10 @@ typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*
// user32.dll function pointer typedefs // user32.dll function pointer typedefs
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void); typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT); typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_ #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_ #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
// dwmapi.dll function pointer typedefs // dwmapi.dll function pointer typedefs
@ -322,6 +324,7 @@ typedef struct _GLFWlibraryWin32
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_SetProcessDPIAware SetProcessDPIAware_; PFN_SetProcessDPIAware SetProcessDPIAware_;
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_; PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
} user32; } user32;

View File

@ -537,6 +537,16 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break; break;
} }
case WM_NCCREATE:
{
// Windows 10: enable automatic non-client area scaling
if (EnableNonClientDpiScaling)
{
EnableNonClientDpiScaling(hWnd);
}
break;
}
} }
return DefWindowProcW(hWnd, uMsg, wParam, lParam); return DefWindowProcW(hWnd, uMsg, wParam, lParam);
@ -988,6 +998,19 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0; return 0;
} }
case WM_DPICHANGED:
{
// Resize and reposition the window to match the new DPI
RECT* const suggestedRect = (RECT*)lParam;
SetWindowPos(hWnd, NULL,
suggestedRect->left,
suggestedRect->top,
suggestedRect->right - suggestedRect->left,
suggestedRect->bottom - suggestedRect->top,
SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
case WM_SETCURSOR: case WM_SETCURSOR:
{ {
if (LOWORD(lParam) == HTCLIENT) if (LOWORD(lParam) == HTCLIENT)