From 5fe0d5225e7b1594fcba99ae9e4c26392d8772b8 Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Sat, 19 Nov 2016 16:15:10 -0500 Subject: [PATCH] Make the program DPI aware - Set dpi-awareness to true in the manifest (i.e., "system-dpi aware") - Check system dpi and scale and/or position widgets and windows that depend on the system dpi (only components within the status window are affected). Note: Declaring dpi awareness eliminates automatic rescaling of windows that causes blurred text on high dpi monitors. Windows 8.1 and later allow per monitor dpi setting which is not handled here. --- main.c | 42 ++++++++++++++++++++++++++++++++++++++++ main.h | 2 ++ openvpn.c | 26 ++++++++++++++----------- options.h | 1 + res/openvpn-gui.manifest | 6 ++++++ 5 files changed, 66 insertions(+), 11 deletions(-) diff --git a/main.c b/main.c index 2277d02..ce49a31 100644 --- a/main.c +++ b/main.c @@ -302,6 +302,47 @@ ResumeConnections() } } +/* + * Set scale factor of windows in pixels. Scale = 100% for dpi = 96 + */ +static void +dpi_setscale(UINT dpix) +{ + /* scale factor in percentage compared to the reference dpi of 96 */ + if (dpix != 0) + o.dpi_scale = MulDiv(dpix, 100, 96); + else + o.dpi_scale = 100; + PrintDebug(L"DPI scale set to %u", o.dpi_scale); +} + +/* + * Get dpi of the system and set the scale factor. + * The system dpi may be different from the per monitor dpi on + * Win 8.1 later. We set dpi awareness to system-dpi level in the + * manifest, and let Windows automatically re-scale windows + * if/when dpi changes dynamically. + */ +static void +dpi_initialize(void) +{ + UINT dpix = 0; + HDC hdc = GetDC(NULL); + + if (hdc) + { + dpix = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + PrintDebug(L"System DPI: dpix = %u", dpix); + } + else + { + PrintDebug(L"GetDC failed, using default dpi = 96 (error = %lu)", GetLastError()); + dpix = 96; + } + + dpi_setscale(dpix); +} /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -313,6 +354,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM /* Save Window Handle */ o.hWnd = hwnd; + dpi_initialize(); s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); diff --git a/main.h b/main.h index c85b983..27bb18a 100644 --- a/main.h +++ b/main.h @@ -114,4 +114,6 @@ void PrintDebugMsg(TCHAR *msg); DWORD GetDllVersion(LPCTSTR lpszDllName); +#define DPI_SCALE(x) MulDiv(x, o.dpi_scale, 100) + #endif diff --git a/openvpn.c b/openvpn.c index 1e3d213..4b9dde1 100644 --- a/openvpn.c +++ b/openvpn.c @@ -821,6 +821,19 @@ Cleanup (connection_t *c) CloseHandle (c->exit_event); c->exit_event = NULL; } +/* + * Helper to position and scale widgets in status window using current dpi + * Takes status window width and height in screen pixels as input + */ +void +RenderStatusWindow(HWND hwndDlg, UINT w, UINT h) +{ + MoveWindow(GetDlgItem(hwndDlg, ID_EDT_LOG), DPI_SCALE(20), DPI_SCALE(25), w - DPI_SCALE(40), h - DPI_SCALE(70), TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_TXT_STATUS), DPI_SCALE(20), DPI_SCALE(5), w - DPI_SCALE(25), DPI_SCALE(15), TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_DISCONNECT), DPI_SCALE(20), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_RESTART), DPI_SCALE(145), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_HIDE), w - DPI_SCALE(130), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); +} /* * DialogProc for OpenVPN status dialog windows @@ -871,22 +884,13 @@ StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) /* Set size and position of controls */ RECT rect; GetClientRect(hwndDlg, &rect); - MoveWindow(hLogWnd, 20, 25, rect.right - 40, rect.bottom - 70, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_TXT_STATUS), 20, 5, rect.right - 25, 15, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_DISCONNECT), 20, rect.bottom - 30, 110, 23, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_RESTART), 145, rect.bottom - 30, 110, 23, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_HIDE), rect.right - 130, rect.bottom - 30, 110, 23, TRUE); - + RenderStatusWindow(hwndDlg, rect.right, rect.bottom); /* Set focus on the LogWindow so it scrolls automatically */ SetFocus(hLogWnd); return FALSE; case WM_SIZE: - MoveWindow(GetDlgItem(hwndDlg, ID_EDT_LOG), 20, 25, LOWORD(lParam) - 40, HIWORD(lParam) - 70, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_DISCONNECT), 20, HIWORD(lParam) - 30, 110, 23, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_RESTART), 145, HIWORD(lParam) - 30, 110, 23, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_HIDE), LOWORD(lParam) - 130, HIWORD(lParam) - 30, 110, 23, TRUE); - MoveWindow(GetDlgItem(hwndDlg, ID_TXT_STATUS), 20, 5, LOWORD(lParam) - 25, 15, TRUE); + RenderStatusWindow(hwndDlg, LOWORD(lParam), HIWORD(lParam)); InvalidateRect(hwndDlg, NULL, TRUE); return TRUE; diff --git a/options.h b/options.h index ae26e91..34b8150 100644 --- a/options.h +++ b/options.h @@ -173,6 +173,7 @@ typedef struct { HANDLE netcmd_semaphore; version_t version; char ovpn_version[16]; /* OpenVPN version string: 2.3.12, 2.4_alpha2 etc.. */ + unsigned int dpi_scale; } options_t; void InitOptions(options_t *); diff --git a/res/openvpn-gui.manifest b/res/openvpn-gui.manifest index 9371d71..445ab43 100644 --- a/res/openvpn-gui.manifest +++ b/res/openvpn-gui.manifest @@ -26,4 +26,10 @@ + + + true + +