Skip to content

Commit

Permalink
[KBM Editor] Support WM_DPICHANGED event (#11015)
Browse files Browse the repository at this point in the history
* [KBM Editor] Support WM_DPICHANGED event

* [spell checker] add term

* [KBM editor] properly cast new DPI value
  • Loading branch information
enricogior committed Apr 30, 2021
1 parent fa0cfec commit 0c3ce81
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 59 deletions.
1 change: 1 addition & 0 deletions .github/actions/spell-check/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ GDISCALED
generatesqlfromuserquery
GETDISPINFO
GETDLGCODE
GETDPISCALEDSIZE
GETEMPTYMARKUP
GETICON
getline
Expand Down
45 changes: 27 additions & 18 deletions src/common/Display/dpi_aware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,43 @@

namespace DPIAware
{
HRESULT GetScreenDPIForWindow(HWND hwnd, UINT& dpi_x, UINT& dpi_y)
HRESULT GetScreenDPIForMonitor(HMONITOR targetMonitor, UINT& dpi)
{
auto monitor_handle = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
dpi_x = 0;
dpi_y = 0;
if (monitor_handle != nullptr)
if (targetMonitor != nullptr)
{
return GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y);
UINT dummy = 0;
return GetDpiForMonitor(targetMonitor, MDT_EFFECTIVE_DPI, &dpi, &dummy);
}
else
{
dpi = DPIAware::DEFAULT_DPI;
return E_FAIL;
}
}

HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi_x, UINT& dpi_y)
HRESULT GetScreenDPIForWindow(HWND hwnd, UINT& dpi)
{
auto monitor_handle = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
dpi_x = 0;
dpi_y = 0;
if (monitor_handle != nullptr)
{
return GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y);
}
else
auto targetMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
return GetScreenDPIForMonitor(targetMonitor, dpi);
}

HRESULT GetScreenDPIForPoint(POINT point, UINT& dpi)
{
auto targetMonitor = MonitorFromPoint(point, MONITOR_DEFAULTTONEAREST);
return GetScreenDPIForMonitor(targetMonitor, dpi);
}

HRESULT GetScreenDPIForCursor(UINT& dpi)
{
HMONITOR targetMonitor = nullptr;
POINT currentCursorPos{ 0 };

if (GetCursorPos(&currentCursorPos))
{
return E_FAIL;
targetMonitor = MonitorFromPoint(currentCursorPos, MONITOR_DEFAULTTOPRIMARY);
}

return GetScreenDPIForMonitor(targetMonitor, dpi);
}

void Convert(HMONITOR monitor_handle, int& width, int& height)
Expand All @@ -54,7 +63,7 @@ namespace DPIAware
void ConvertByCursorPosition(int& width, int& height)
{
HMONITOR targetMonitor = nullptr;
POINT currentCursorPos{};
POINT currentCursorPos{ 0 };

if (GetCursorPos(&currentCursorPos))
{
Expand Down Expand Up @@ -96,7 +105,7 @@ namespace DPIAware
{
if (AreDpiAwarenessContextsEqual(levels[i], system_returned_value))
{
return static_cast<AwarenessLevel>(i);
return static_cast<DPIAware::AwarenessLevel>(i);
}
}
return AwarenessLevel::UNAWARE;
Expand Down
6 changes: 4 additions & 2 deletions src/common/Display/dpi_aware.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ namespace DPIAware
{
constexpr inline int DEFAULT_DPI = 96;

HRESULT GetScreenDPIForWindow(HWND hwnd, UINT& dpi_x, UINT& dpi_y);
HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi_x, UINT& dpi_y);
HRESULT GetScreenDPIForMonitor(HMONITOR targetMonitor, UINT& dpi);
HRESULT GetScreenDPIForWindow(HWND hwnd, UINT& dpi);
HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi);
HRESULT GetScreenDPIForCursor(UINT& dpi);
void Convert(HMONITOR monitor_handle, int& width, int& height);
void ConvertByCursorPosition(int& width, int& height);
void InverseConvert(HMONITOR monitor_handle, int& width, int& height);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

using namespace winrt::Windows::Foundation;

static UINT g_currentDPI = DPIAware::DEFAULT_DPI;

LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM);

// This Hwnd will be the window handler for the Xaml Island: A child window that contains Xaml.
Expand Down Expand Up @@ -144,6 +146,7 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KeyboardManagerState&
int windowHeight = KeyboardManagerConstants::DefaultEditKeyboardWindowHeight;

DPIAware::ConvertByCursorPosition(windowWidth, windowHeight);
DPIAware::GetScreenDPIForCursor(g_currentDPI);

// Window Creation
HWND _hWndEditKeyboardWindow = CreateWindow(
Expand Down Expand Up @@ -385,47 +388,62 @@ void CreateEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
TerminateProcess(GetCurrentProcess(), 0);
}

inline std::wstring getMessage(UINT messageCode)
{
switch (messageCode)
{
case WM_SIZE:
return L"WM_SIZE";
case WM_NCDESTROY:
return L"WM_NCDESTROY";
default:
return L"";
}
}

LRESULT CALLBACK EditKeyboardWindowProc(HWND hWnd, UINT messageCode, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
auto message = getMessage(messageCode);
if (message != L"")
{
Logger::trace(L"EditKeyboardWindowProc() messageCode={}", getMessage(messageCode));
}

switch (messageCode)
{
// Resize the XAML window whenever the parent window is painted or resized
case WM_PAINT:
case WM_SIZE:
{
GetClientRect(hWnd, &rcClient);
SetWindowPos(hWndXamlIslandEditKeyboardWindow, 0, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, SWP_SHOWWINDOW);
RECT rect = { 0 };
GetClientRect(hWnd, &rect);
SetWindowPos(hWndXamlIslandEditKeyboardWindow, 0, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
}
break;
// To avoid UI elements overlapping on making the window smaller enforce a minimum window size
case WM_GETMINMAXINFO:
{
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
LPMINMAXINFO mmi = (LPMINMAXINFO)lParam;
int minWidth = KeyboardManagerConstants::MinimumEditKeyboardWindowWidth;
int minHeight = KeyboardManagerConstants::MinimumEditKeyboardWindowHeight;
DPIAware::Convert(MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL), minWidth, minHeight);
lpMMI->ptMinTrackSize.x = minWidth;
lpMMI->ptMinTrackSize.y = minHeight;
mmi->ptMinTrackSize.x = minWidth;
mmi->ptMinTrackSize.y = minHeight;
}
break;
case WM_GETDPISCALEDSIZE:
{
UINT newDPI = static_cast<UINT>(wParam);
SIZE* size = reinterpret_cast<SIZE*>(lParam);
Logger::trace(L"WM_GETDPISCALEDSIZE: DPI {} size X {} Y {}", newDPI, size->cx, size->cy);

float scalingFactor = static_cast<float>(newDPI) / g_currentDPI;
Logger::trace(L"WM_GETDPISCALEDSIZE: scaling factor {}", scalingFactor);

size->cx = static_cast<LONG>(size->cx * scalingFactor);
size->cy = static_cast<LONG>(size->cy * scalingFactor);

return 1;
}
break;
case WM_DPICHANGED:
{
UINT newDPI = static_cast<UINT>(LOWORD(wParam));
g_currentDPI = newDPI;

RECT* rect = reinterpret_cast<RECT*>(lParam);
SetWindowPos(
hWnd,
nullptr,
rect->left,
rect->top,
rect->right - rect->left,
rect->bottom - rect->top,
SWP_NOZORDER | SWP_NOACTIVATE
);

Logger::trace(L"WM_DPICHANGED: new dpi {} rect {} {} ", newDPI, rect->right - rect->left, rect->bottom - rect->top);
}
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

using namespace winrt::Windows::Foundation;

static UINT g_currentDPI = DPIAware::DEFAULT_DPI;

LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);

// This Hwnd will be the window handler for the Xaml Island: A child window that contains Xaml.
Expand Down Expand Up @@ -96,6 +98,7 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KeyboardManagerState&
int windowWidth = KeyboardManagerConstants::DefaultEditShortcutsWindowWidth;
int windowHeight = KeyboardManagerConstants::DefaultEditShortcutsWindowHeight;
DPIAware::ConvertByCursorPosition(windowWidth, windowHeight);
DPIAware::GetScreenDPIForCursor(g_currentDPI);

// Window Creation
HWND _hWndEditShortcutsWindow = CreateWindow(
Expand Down Expand Up @@ -360,26 +363,60 @@ void CreateEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa

LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
switch (messageCode)
{
// Resize the XAML window whenever the parent window is painted or resized
case WM_PAINT:
case WM_SIZE:
{
GetClientRect(hWnd, &rcClient);
SetWindowPos(hWndXamlIslandEditShortcutsWindow, 0, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, SWP_SHOWWINDOW);
RECT rect = { 0 };
GetClientRect(hWnd, &rect);
SetWindowPos(hWndXamlIslandEditShortcutsWindow, 0, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
}
break;
// To avoid UI elements overlapping on making the window smaller enforce a minimum window size
case WM_GETMINMAXINFO:
{
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
LPMINMAXINFO mmi = (LPMINMAXINFO)lParam;
int minWidth = KeyboardManagerConstants::MinimumEditShortcutsWindowWidth;
int minHeight = KeyboardManagerConstants::MinimumEditShortcutsWindowHeight;
DPIAware::Convert(MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL), minWidth, minHeight);
lpMMI->ptMinTrackSize.x = minWidth;
lpMMI->ptMinTrackSize.y = minHeight;
mmi->ptMinTrackSize.x = minWidth;
mmi->ptMinTrackSize.y = minHeight;
}
break;
case WM_GETDPISCALEDSIZE:
{
UINT newDPI = static_cast<UINT>(wParam);
SIZE* size = reinterpret_cast<SIZE*>(lParam);
Logger::trace(L"WM_GETDPISCALEDSIZE: DPI {} size X {} Y {}", newDPI, size->cx, size->cy);

float scalingFactor = static_cast<float>(newDPI) / g_currentDPI;
Logger::trace(L"WM_GETDPISCALEDSIZE: scaling factor {}", scalingFactor);

size->cx = static_cast<LONG>(size->cx * scalingFactor);
size->cy = static_cast<LONG>(size->cy * scalingFactor);

return 1;
}
break;
case WM_DPICHANGED:
{
UINT newDPI = static_cast<UINT>(LOWORD(wParam));
g_currentDPI = newDPI;

RECT* rect = reinterpret_cast<RECT*>(lParam);
SetWindowPos(
hWnd,
nullptr,
rect->left,
rect->top,
rect->right - rect->left,
rect->bottom - rect->top,
SWP_NOZORDER | SWP_NOACTIVATE
);

Logger::trace(L"WM_DPICHANGED: new dpi {} rect {} {} ", newDPI, rect->right - rect->left, rect->bottom - rect->top);
}
break;
default:
Expand Down
17 changes: 13 additions & 4 deletions src/modules/keyboardmanager/common/KeyboardManagerConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,22 @@ namespace KeyboardManagerConstants
// Default window sizes
inline const int DefaultEditKeyboardWindowWidth = 800;
inline const int DefaultEditKeyboardWindowHeight = 600;
inline const int MinimumEditKeyboardWindowWidth = 500;
inline const int MinimumEditKeyboardWindowHeight = 450;

// Increasing the min size can cause issues when moving the window between
// monitors with different DPI scaling factor
inline const int MinimumEditKeyboardWindowWidth = 200;
inline const int MinimumEditKeyboardWindowHeight = 200;

inline const int EditKeyboardTableMinWidth = 700;

inline const int DefaultEditShortcutsWindowWidth = 1050;
inline const int DefaultEditShortcutsWindowHeight = 600;
inline const int MinimumEditShortcutsWindowWidth = 500;
inline const int MinimumEditShortcutsWindowHeight = 500;

// Increasing the min size can cause issues when moving the window between
// monitors with different DPI scaling factor
inline const int MinimumEditShortcutsWindowWidth = 200;
inline const int MinimumEditShortcutsWindowHeight = 200;

inline const int EditShortcutsTableMinWidth = 1000;

// Key Remap table constants
Expand Down
7 changes: 3 additions & 4 deletions src/modules/powerrename/ui/PowerRenameUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,7 @@ void CPowerRenameUI::_OnInitDlg()
m_initialWidth = RECT_WIDTH(rc);
m_initialHeight = RECT_HEIGHT(rc);

UINT dummy = 0;
DPIAware::GetScreenDPIForWindow(m_hwnd, m_initialDPI, dummy);
DPIAware::GetScreenDPIForWindow(m_hwnd, m_initialDPI);

for (UINT u = 0; u < ARRAYSIZE(g_repositionMap); u++)
{
Expand Down Expand Up @@ -887,8 +886,8 @@ void CPowerRenameUI::_MoveControl(_In_ DWORD id, _In_ DWORD repositionFlags)
int width = rcWindow.right - rcWindow.left;
int height = rcWindow.bottom - rcWindow.top;

UINT currentDPI = 0, dummy;
DPIAware::GetScreenDPIForWindow(m_hwnd, currentDPI, dummy);
UINT currentDPI = 0;
DPIAware::GetScreenDPIForWindow(m_hwnd, currentDPI);
float scale = (float)currentDPI / m_initialDPI;

switch (id)
Expand Down

0 comments on commit 0c3ce81

Please sign in to comment.