From c9865a2efc8c970f4cbd8d084aac0d0a164d68b7 Mon Sep 17 00:00:00 2001 From: Quantum Date: Tue, 15 Oct 2019 19:15:13 -0400 Subject: [PATCH] Add high DPI support --- Makefile | 2 +- highdpi.manifest | 16 ++++++ include/MainWindow.hpp | 4 ++ keyboard.rc | 1 - src/MainWindow.cpp | 109 +++++++++++++++++++++++++++-------------- 5 files changed, 94 insertions(+), 38 deletions(-) create mode 100644 highdpi.manifest diff --git a/Makefile b/Makefile index 9a926a9..8312456 100644 --- a/Makefile +++ b/Makefile @@ -63,4 +63,4 @@ $(OUTDIR)\keyboard.res: keyboard.rc $(CXX) $(CXXFLAGS) /Fo$(OUTDIR)\ /Fd$(OUTDIR)\ $< $(DISTDIR)\Keyboard.exe: $(FILES) - $(LD) /out:$@ $(LDFLAGS) $** $(LIBS) + $(LD) /out:$@ $(LDFLAGS) $** $(LIBS) /manifest:embed /manifestinput:highdpi.manifest /manifestinput:commctrl6.manifest diff --git a/highdpi.manifest b/highdpi.manifest new file mode 100644 index 0000000..407dd08 --- /dev/null +++ b/highdpi.manifest @@ -0,0 +1,16 @@ + + + + + + + + + + + True/PM + permonitorv2,permonitor + + + \ No newline at end of file diff --git a/include/MainWindow.hpp b/include/MainWindow.hpp index 9833e28..53ab00c 100644 --- a/include/MainWindow.hpp +++ b/include/MainWindow.hpp @@ -74,6 +74,9 @@ protected: void UpdateNoteDisplay(); virtual HICON GetIcon(); + void UpdateScale(); + int scale(int unscaled) { return static_cast(m_scale * unscaled); } + int active[128]; bool capsDown; bool useBeep; @@ -108,6 +111,7 @@ protected: MIDI_FILE *m_midifile; DWORD lastTime; bool saving; + double m_scale; LRESULT CALLBACK LowLevelKeyboardHook(HHOOK hHook, int nCode, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); diff --git a/keyboard.rc b/keyboard.rc index 8beff46..06cf7a2 100644 --- a/keyboard.rc +++ b/keyboard.rc @@ -2,7 +2,6 @@ #include RID_ICON ICON keyboard.ico -1 24 commctrl6.manifest STRINGTABLE LANGUAGE 0x09, 0x01 // en-US BEGIN diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index c182987..b8622dc 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #define LEFT(x, y, cx, cy) x, y, cx, cy #define RIGHT(x, y, cx, cy) (x - cx), y, cx, cy @@ -142,13 +143,39 @@ BOOL MainWindow::WinRegisterClass(WNDCLASS *pwc) return Window::WinRegisterClass(pwc); } +typedef HRESULT (WINAPI *FN_GETDPIFORMONITOR)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); + +void MainWindow::UpdateScale() +{ + HMONITOR hMonitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST); + HMODULE hShCore; + + m_scale = 1; + + hShCore = LoadLibrary(L"ShCore.dll"); + if (hShCore) { + FN_GETDPIFORMONITOR GetDpiForMonitor = + (FN_GETDPIFORMONITOR) GetProcAddress(hShCore, "GetDpiForMonitor"); + if (GetDpiForMonitor) { + UINT dpiX, dpiY; + GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + m_scale = dpiX / 96.0; + } + } +} + LRESULT MainWindow::OnCreate() { + UpdateScale(); + + RECT client = {0, 0, scale(622), scale(431)}; + AdjustWindowRect(&client, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, FALSE); + SetWindowPos(m_hwnd, NULL, 0, 0, client.right - client.left, + client.bottom - client.top, SWP_NOMOVE | SWP_NOZORDER); + NONCLIENTMETRICS ncmMetrics = { sizeof(NONCLIENTMETRICS) }; - RECT client; SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncmMetrics, 0); - GetClientRect(m_hwnd, &client); hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont); @@ -530,7 +557,8 @@ void MainWindow::PaintContent(PAINTSTRUCT *pps) SetBkColor(pps->hdc, GetSysColor(COLOR_3DFACE)); SetDCPenColor(pps->hdc, GetSysColor(COLOR_3DHILIGHT)); - RoundRect(pps->hdc, 12, client.bottom - 52, client.right - 12, client.bottom - 12, 5, 5); + RoundRect(pps->hdc, scale(12), client.bottom - scale(52), client.right - scale(12), + client.bottom - scale(12), scale(5), scale(5)); SelectPen(pps->hdc, hOldPen); SelectBrush(pps->hdc, hOldBrush); @@ -706,41 +734,52 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_NCDESTROY: PostQuitMessage(0); break; + case WM_DPICHANGED: { + LPRECT lpBox = (LPRECT) lParam; + m_scale = LOWORD(wParam) / 96.0; + SetWindowPos(m_hwnd, NULL, lpBox->left, lpBox->top, lpBox->right - lpBox->left, + lpBox->bottom - lpBox->top, SWP_NOZORDER | SWP_NOACTIVATE); + RedrawWindow(m_hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + break; + } case WM_SIZE: { RECT client; HDWP hdwp; + if (!piano) return 0; GetClientRect(m_hwnd, &client); -#define REPOS(hwnd, k) hdwp = DeferWindowPos(hdwp, hwnd, 0, k, SWP_NOACTIVATE|SWP_NOZORDER) - hdwp = BeginDeferWindowPos(14); - REPOS(piano->GetHWND(), LEFT(12, 12, client.right - 24, client.bottom - 262)); - REPOS(m_instruLabel, BOTTOM(12, client.bottom - 217, 70, 25)); - REPOS(m_instruSelect, BOTTOM(82, client.bottom - 217, client.right - 94, 25)); - REPOS(m_forceLabel, BOTTOM(12, client.bottom - 187, 70, 25)); - REPOS(m_forceBar, BOTTOM(82, client.bottom - 187, client.right - 94, 25)); - REPOS(m_volumeLabel, BOTTOM(12, client.bottom - 157, 70, 25)); - REPOS(m_volumeBar, BOTTOM(82, client.bottom - 157, client.right - 94, 25)); - REPOS(m_deviceLabel, BOTTOM(12, client.bottom - 127, 70, 25)); - REPOS(m_deviceSelect, BOTTOM(82, client.bottom - 127, client.right - 94, 25)); - REPOS(m_pipeAboveRadio, BOTTOM(12, client.bottom - 97, 150, 25)); - REPOS(m_pipeLeftRadio, BOTTOM(162, client.bottom - 97, 150, 25)); - REPOS(m_adjustLabel, BOTTOM(12, client.bottom - 67, 70, 25)); - REPOS(m_semitoneSelect, BOTTOM(82, client.bottom - 67, 50, 20)); - REPOS(m_semitoneUpDown, BOTTOM(132, client.bottom - 67, 18, 20)); - REPOS(m_semitoneLabel, BOTTOM(155, client.bottom - 67, 60, 20)); - REPOS(m_octaveSelect, BOTTOM(220, client.bottom - 67, 50, 20)); - REPOS(m_octaveUpDown, BOTTOM(270, client.bottom - 67, 18, 20)); - REPOS(m_octaveLabel, BOTTOM(293, client.bottom - 67, 50, 20)); - REPOS(m_keyLabel, BOTTOM(345, client.bottom - 67, 45, 20)); - REPOS(m_keySelect, BOTTOM(390, client.bottom - 67, 65, 22)); - REPOS(m_saveCheck, BOTTOM(22, client.bottom - 42, 50, 20)); - REPOS(m_saveLabel, BOTTOM(27, client.bottom - 19, 30, 20)); - REPOS(m_saveFile, BOTTOM(62, client.bottom - 17, client.right - 334, 25)); - REPOS(m_saveBrowse, BOTTOMRIGHT(client.right - 187, client.bottom - 17, 80, 25)); - REPOS(m_reopen, BOTTOMRIGHT(client.right - 102, client.bottom - 17, 80, 25)); - REPOS(m_closeFile, BOTTOMRIGHT(client.right - 17, client.bottom - 17, 80, 25)); - REPOS(m_beepCheck, BOTTOMRIGHT(client.right - 17, client.bottom - 42, 60, 20)); +#define s(x) scale(x) +#define REPOS(hwnd, k) hdwp = DeferWindowPos(hdwp, hwnd, 0, k, SWP_NOACTIVATE | SWP_NOZORDER) + hdwp = BeginDeferWindowPos(27); + REPOS(piano->GetHWND(), LEFT(s(12), s(12), client.right - s(24), client.bottom - s(262))); + REPOS(m_instruLabel, BOTTOM(s(12), client.bottom - s(217), s(70), s(25))); + REPOS(m_instruSelect, BOTTOM(s(82), client.bottom - s(217), client.right - s(94), s(25))); + REPOS(m_forceLabel, BOTTOM(s(12), client.bottom - s(187), s(70), s(25))); + REPOS(m_forceBar, BOTTOM(s(82), client.bottom - s(187), client.right - s(94), s(25))); + REPOS(m_volumeLabel, BOTTOM(s(12), client.bottom - s(157), s(70), s(25))); + REPOS(m_volumeBar, BOTTOM(s(82), client.bottom - s(157), client.right - s(94), s(25))); + REPOS(m_deviceLabel, BOTTOM(s(12), client.bottom - s(127), s(70), s(25))); + REPOS(m_deviceSelect, BOTTOM(s(82), client.bottom - s(127), client.right - s(94), s(25))); + REPOS(m_pipeAboveRadio, BOTTOM(s(12), client.bottom - s(97), s(150), s(25))); + REPOS(m_pipeLeftRadio, BOTTOM(s(162), client.bottom - s(97), s(150), s(25))); + REPOS(m_adjustLabel, BOTTOM(s(12), client.bottom - s(67), s(70), s(25))); + REPOS(m_semitoneSelect, BOTTOM(s(82), client.bottom - s(67), s(50), s(20))); + REPOS(m_semitoneUpDown, BOTTOM(s(132), client.bottom - s(67), s(18), s(20))); + REPOS(m_semitoneLabel, BOTTOM(s(155), client.bottom - s(67), s(60), s(20))); + REPOS(m_octaveSelect, BOTTOM(s(220), client.bottom - s(67), s(50), s(20))); + REPOS(m_octaveUpDown, BOTTOM(s(270), client.bottom - s(67), s(18), s(20))); + REPOS(m_octaveLabel, BOTTOM(s(293), client.bottom - s(67), s(50), s(20))); + REPOS(m_keyLabel, BOTTOM(s(345), client.bottom - s(67), s(45), s(20))); + REPOS(m_keySelect, BOTTOM(s(390), client.bottom - s(67), s(65), s(22))); + REPOS(m_saveCheck, BOTTOM(s(22), client.bottom - s(42), s(50), s(20))); + REPOS(m_saveLabel, BOTTOM(s(27), client.bottom - s(19), s(30), s(20))); + REPOS(m_saveFile, BOTTOM(s(62), client.bottom - s(17), client.right - s(334), s(25))); + REPOS(m_saveBrowse, BOTTOMRIGHT(client.right - s(187), client.bottom - s(17), s(80), s(25))); + REPOS(m_reopen, BOTTOMRIGHT(client.right - s(102), client.bottom - s(17), s(80), s(25))); + REPOS(m_closeFile, BOTTOMRIGHT(client.right - s(17), client.bottom - s(17), s(80), s(25))); + REPOS(m_beepCheck, BOTTOMRIGHT(client.right - s(17), client.bottom - s(42), s(60), s(20))); EndDeferWindowPos(hdwp); #undef REPOS +#undef s return 0; } case WM_COMMAND: @@ -941,13 +980,11 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) MainWindow *MainWindow::Create(LPCTSTR szTitle) { MainWindow *self = new MainWindow(); - RECT client = {0, 0, 622, 431}; - AdjustWindowRect(&client, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, FALSE); if (self && self->WinCreateWindow(0, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, client.right - client.left, - client.bottom - client.top, NULL, NULL)) { + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL)) { return self; } delete self;