diff --git a/Externals/crystaledit/Sample/ChildFrm.cpp b/Externals/crystaledit/Sample/ChildFrm.cpp index 93a9600c23f..9dbc2cc372d 100755 --- a/Externals/crystaledit/Sample/ChildFrm.cpp +++ b/Externals/crystaledit/Sample/ChildFrm.cpp @@ -5,6 +5,7 @@ #include "Sample.h" #include "ChildFrm.h" +#include "MainFrm.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -15,10 +16,11 @@ static char THIS_FILE[] = __FILE__; ///////////////////////////////////////////////////////////////////////////// // CChildFrame -IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) +IMPLEMENT_DYNCREATE(CChildFrame, DpiAware::CDpiAwareWnd) -BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) +BEGIN_MESSAGE_MAP(CChildFrame, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CChildFrame) + ON_WM_SIZE() // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG_MAP @@ -41,8 +43,25 @@ BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs - - return CMDIChildWnd::PreCreateWindow(cs); + CMainFrame* pMainFrame = static_cast(AfxGetMainWnd()); + MDITileLayout::LayoutManager& layoutManager = pMainFrame->GetLayoutManager(); + if (!layoutManager.GetTileLayoutEnabled()) + return __super::PreCreateWindow(cs); + __super::PreCreateWindow(cs); + cs.style &= ~WS_CAPTION; + CRect rcMain; + ::GetWindowRect(pMainFrame->m_hWndMDIClient, rcMain); + CRect rc = layoutManager.GetDefaultOpenPaneRect(); + rc.left -= rcMain.left; + rc.top -= rcMain.top; + rc.right -= rcMain.left; + rc.bottom -= rcMain.top; + AdjustWindowRectEx(rc, cs.style, false, cs.dwExStyle); + cs.x = rc.left; + cs.y = rc.top; + cs.cx = rc.Width(); + cs.cy = rc.Height(); + return true; } ///////////////////////////////////////////////////////////////////////////// @@ -51,12 +70,12 @@ BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) #ifdef _DEBUG void CChildFrame::AssertValid() const { - CMDIChildWnd::AssertValid(); + __super::AssertValid(); } void CChildFrame::Dump(CDumpContext& dc) const { - CMDIChildWnd::Dump(dc); + __super::Dump(dc); } #endif //_DEBUG @@ -66,5 +85,28 @@ void CChildFrame::Dump(CDumpContext& dc) const BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { + static_cast(AfxGetMainWnd())->GetLayoutManager().NotifyChildOpened(this); return m_wndSplitter.Create(this, 2, 2, CSize(30, 30), pContext); } + +BOOL CChildFrame::DestroyWindow() +{ + static_cast(AfxGetMainWnd())->GetLayoutManager().NotifyChildClosed(this); + return __super::DestroyWindow(); +} + +void CChildFrame::OnSize(UINT nType, int cx, int cy) +{ + __super::OnSize(nType, cx, cy); + if (nType == SIZE_MAXIMIZED && IsDifferentDpiFromSystemDpi()) + { + // This is a workaround of the problem that the maximized MDI child window is in the wrong position when the DPI changes + // I don't think MDI-related processing inside Windows fully supports per-monitor dpi awareness + CRect rc; + GetParent()->GetClientRect(rc); + AdjustWindowRectEx(&rc, GetStyle(), FALSE, GetExStyle()); + SetWindowPos(nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE); + } + static_cast(AfxGetMainWnd())->GetLayoutManager().NotifyChildResized(this); +} + diff --git a/Externals/crystaledit/Sample/ChildFrm.h b/Externals/crystaledit/Sample/ChildFrm.h index 0c578b39dd0..1a65a7a2756 100755 --- a/Externals/crystaledit/Sample/ChildFrm.h +++ b/Externals/crystaledit/Sample/ChildFrm.h @@ -4,7 +4,9 @@ #pragma once -class CChildFrame : public CMDIChildWnd +#include "utils/DpiAware.h" + +class CChildFrame : public DpiAware::CDpiAwareWnd { DECLARE_DYNCREATE(CChildFrame) public: @@ -24,6 +26,7 @@ class CChildFrame : public CMDIChildWnd virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); + virtual BOOL DestroyWindow(); //}}AFX_VIRTUAL // Implementation @@ -40,6 +43,7 @@ class CChildFrame : public CMDIChildWnd // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG + afx_msg void OnSize(UINT nType, int cx, int cy); DECLARE_MESSAGE_MAP() }; diff --git a/Externals/crystaledit/Sample/MainFrm.cpp b/Externals/crystaledit/Sample/MainFrm.cpp index 612a018733d..af04970d3ff 100755 --- a/Externals/crystaledit/Sample/MainFrm.cpp +++ b/Externals/crystaledit/Sample/MainFrm.cpp @@ -17,13 +17,22 @@ static char THIS_FILE[] = __FILE__; ///////////////////////////////////////////////////////////////////////////// // CMainFrame -IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) +IMPLEMENT_DYNAMIC(CMainFrame, DpiAware::CDpiAwareWnd) -BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) +BEGIN_MESSAGE_MAP(CMainFrame, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code ! ON_WM_CREATE() + ON_WM_SIZE() + ON_COMMAND_EX(ID_WINDOW_ARRANGE, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_CASCADE, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_TILE_HORZ, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_TILE_VERT, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_SPLIT_VERTICALLY, OnWindowSplit) + ON_COMMAND_EX(ID_WINDOW_SPLIT_HORIZONTALLY, OnWindowSplit) + ON_COMMAND(ID_WINDOW_COMBINE, OnWindowCombine) + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) //}}AFX_MSG_MAP END_MESSAGE_MAP() @@ -44,7 +53,7 @@ static UINT indicators[] = ///////////////////////////////////////////////////////////////////////////// // CMainFrame construction/destruction -CMainFrame::CMainFrame() +CMainFrame::CMainFrame() : m_layoutManager(this) { // TODO: add member initialization code here @@ -56,7 +65,7 @@ CMainFrame::~CMainFrame() int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { - if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) + if (__super::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.Create(this) || @@ -92,7 +101,7 @@ BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs - return CMDIFrameWnd::PreCreateWindow(cs); + return __super::PreCreateWindow(cs); } BOOL CMainFrame::LoadToolBar() @@ -100,8 +109,8 @@ BOOL CMainFrame::LoadToolBar() const int ICON_COUNT = 17; m_wndToolBar.LoadToolBar(IDR_MAINFRAME); CToolBarCtrl& toolbarCtrl = m_wndToolBar.GetToolBarCtrl(); - const int cx = MulDiv(16, GetSystemMetrics(SM_CXSMICON), 16); - const int cy = MulDiv(15, GetSystemMetrics(SM_CYSMICON), 16); + const int cx = MulDiv(16, m_dpi, USER_DEFAULT_SCREEN_DPI); + const int cy = MulDiv(15, m_dpi, USER_DEFAULT_SCREEN_DPI); m_imgListToolBar.Detach(); m_imgListToolBar.Create(cx, cy, ILC_COLOR32, ICON_COUNT, 0); CBitmap bm; @@ -119,15 +128,66 @@ BOOL CMainFrame::LoadToolBar() #ifdef _DEBUG void CMainFrame::AssertValid() const { - CMDIFrameWnd::AssertValid(); + __super::AssertValid(); } void CMainFrame::Dump(CDumpContext& dc) const { - CMDIFrameWnd::Dump(dc); + __super::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMainFrame message handlers + +BOOL CMainFrame::OnMDIWindowCmd(UINT nID) +{ + switch (nID) + { + case ID_WINDOW_TILE_HORZ: + case ID_WINDOW_TILE_VERT: + { + bool bHorizontal = (nID == ID_WINDOW_TILE_HORZ); + m_layoutManager.SetTileLayoutEnabled(true); + m_layoutManager.Tile(bHorizontal); + break; + } + case ID_WINDOW_CASCADE: + m_layoutManager.SetTileLayoutEnabled(false); + __super::OnMDIWindowCmd(nID); + break; + } + return 0; +} + +BOOL CMainFrame::OnWindowSplit(UINT nID) +{ + m_layoutManager.SplitActivePane(nID == ID_WINDOW_SPLIT_HORIZONTALLY, 0.5); + return 0; +} + +void CMainFrame::OnWindowCombine() +{ + m_layoutManager.CombineActivePane(); +} + +void CMainFrame::OnSize(UINT nType, int cx, int cy) +{ + __super::OnSize(nType, cx, cy); + m_layoutManager.NotifyMainResized(); +} + +LRESULT CMainFrame::OnDpiChanged(WPARAM wParam, LPARAM lParam) +{ + __super::OnDpiChanged(wParam, lParam); + DpiAware::UpdateAfxDataSysMetrics(GetDpi()); + LoadToolBar(); + const RECT* pRect = reinterpret_cast(lParam); + SetWindowPos(nullptr, pRect->left, pRect->top, + pRect->right - pRect->left, + pRect->bottom - pRect->top, SWP_NOZORDER | SWP_NOACTIVATE); + Default(); + return 0; +} + diff --git a/Externals/crystaledit/Sample/MainFrm.h b/Externals/crystaledit/Sample/MainFrm.h index 7c39d1637de..a926ba7610a 100755 --- a/Externals/crystaledit/Sample/MainFrm.h +++ b/Externals/crystaledit/Sample/MainFrm.h @@ -4,7 +4,10 @@ #pragma once -class CMainFrame : public CMDIFrameWnd +#include "utils/DpiAware.h" +#include "utils/MDITileLayout.h" + +class CMainFrame : public DpiAware::CDpiAwareWnd { DECLARE_DYNAMIC(CMainFrame) public: @@ -30,11 +33,14 @@ class CMainFrame : public CMDIFrameWnd virtual void Dump(CDumpContext& dc) const; #endif BOOL LoadToolBar(); + MDITileLayout::LayoutManager& GetLayoutManager() { return m_layoutManager; }; protected: // control bar embedded members CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; CImageList m_imgListToolBar; + CSplitterWnd m_wndSplitter; + MDITileLayout::LayoutManager m_layoutManager; // Generated message map functions protected: @@ -42,7 +48,12 @@ class CMainFrame : public CMDIFrameWnd afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code! + afx_msg BOOL OnMDIWindowCmd(UINT nID); + afx_msg BOOL OnWindowSplit(UINT nID); + afx_msg void OnWindowCombine(); + afx_msg void OnSize(UINT nType, int cx, int cy); //}}AFX_MSG + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() }; diff --git a/Externals/crystaledit/Sample/Sample.rc b/Externals/crystaledit/Sample/Sample.rc index 7e7118f6feb..4eb90ce7026 100755 --- a/Externals/crystaledit/Sample/Sample.rc +++ b/Externals/crystaledit/Sample/Sample.rc @@ -200,8 +200,12 @@ BEGIN BEGIN MENUITEM "&New Window", ID_WINDOW_NEW MENUITEM "&Cascade", ID_WINDOW_CASCADE - MENUITEM "&Tile", ID_WINDOW_TILE_HORZ + MENUITEM "Tile &Vertically", ID_WINDOW_TILE_VERT + MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + MENUITEM "Split V&ertically", ID_WINDOW_SPLIT_VERTICALLY + MENUITEM "Split H&orizontally", ID_WINDOW_SPLIT_HORIZONTALLY + MENUITEM "Com&bine", ID_WINDOW_COMBINE END POPUP "&Help" BEGIN diff --git a/Externals/crystaledit/Sample/SampleStatic.manifest b/Externals/crystaledit/Sample/SampleStatic.manifest new file mode 100644 index 00000000000..466356eb27c --- /dev/null +++ b/Externals/crystaledit/Sample/SampleStatic.manifest @@ -0,0 +1,10 @@ + + + + + True + PerMonitorV2 + + + + diff --git a/Externals/crystaledit/Sample/SampleStatic.vcxproj b/Externals/crystaledit/Sample/SampleStatic.vcxproj index 3ff2e1691e4..37e917e53e2 100644 --- a/Externals/crystaledit/Sample/SampleStatic.vcxproj +++ b/Externals/crystaledit/Sample/SampleStatic.vcxproj @@ -237,6 +237,12 @@ true + + SampleStatic.manifest + + + + @@ -279,6 +285,12 @@ true + + SampleStatic.manifest + + + + @@ -321,6 +333,12 @@ true + + SampleStatic.manifest + + + + @@ -363,6 +381,12 @@ true + + SampleStatic.manifest + + + + @@ -408,6 +432,12 @@ true + + SampleStatic.manifest + + + + @@ -453,6 +483,12 @@ true + + SampleStatic.manifest + + + + @@ -498,6 +534,12 @@ true + + SampleStatic.manifest + + + + @@ -543,6 +585,12 @@ true + + SampleStatic.manifest + + + + diff --git a/Externals/crystaledit/Sample/SampleView.cpp b/Externals/crystaledit/Sample/SampleView.cpp index 20b897a44b1..189705bc46d 100755 --- a/Externals/crystaledit/Sample/SampleView.cpp +++ b/Externals/crystaledit/Sample/SampleView.cpp @@ -93,7 +93,9 @@ void CSampleView::OnInitialUpdate() { CCrystalEditViewEx::OnInitialUpdate(); - SetFont(GetDocument()->m_lf); + LOGFONT lf{ GetDocument()->m_lf }; + lf.lfHeight = MulDiv(lf.lfHeight, m_dpi, 96); + SetFont(lf); SetColorContext(GetDocument()->m_pSyntaxColors); SetMarkersContext(GetDocument()->m_pMarkers); if (GetDocument()->m_xTextBuffer.GetTableEditing()) diff --git a/Externals/crystaledit/Sample/resource.h b/Externals/crystaledit/Sample/resource.h index 41b7efe8411..7c9c213e514 100755 --- a/Externals/crystaledit/Sample/resource.h +++ b/Externals/crystaledit/Sample/resource.h @@ -54,6 +54,9 @@ #define ID_VIEW_SELECT_FONT 32801 #define ID_VIEW_LINENUMBERS 32802 #define ID_FILE_CONVERT_TO_HTML 32803 +#define ID_WINDOW_SPLIT_VERTICALLY 32804 +#define ID_WINDOW_SPLIT_HORIZONTALLY 32805 +#define ID_WINDOW_COMBINE 32806 #define ID_EDIT_INDICATOR_COL 37900 #define ID_READ_ONLY 37901 #define ID_INDICATOR_ENCODING 37905 @@ -65,7 +68,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 135 -#define _APS_NEXT_COMMAND_VALUE 32802 +#define _APS_NEXT_COMMAND_VALUE 32804 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/Externals/crystaledit/editlib/ccrystaltextview.cpp b/Externals/crystaledit/editlib/ccrystaltextview.cpp index 94009c33838..8aabc7bc538 100644 --- a/Externals/crystaledit/editlib/ccrystaltextview.cpp +++ b/Externals/crystaledit/editlib/ccrystaltextview.cpp @@ -165,7 +165,7 @@ IMPLEMENT_DYNCREATE (CCrystalTextView, CView) HINSTANCE CCrystalTextView::s_hResourceInst = nullptr; CCrystalTextView::RENDERING_MODE CCrystalTextView::s_nRenderingModeDefault = RENDERING_MODE::GDI; -BEGIN_MESSAGE_MAP (CCrystalTextView, CView) +BEGIN_MESSAGE_MAP (CCrystalTextView, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CCrystalTextView) ON_WM_DESTROY () ON_WM_ERASEBKGND () @@ -222,9 +222,9 @@ ON_COMMAND (ID_EDIT_TEXT_END, OnTextEnd) ON_COMMAND (ID_EDIT_EXT_TEXT_END, OnExtTextEnd) // Standard printing commands ON_COMMAND (ID_FILE_PAGE_SETUP, OnFilePageSetup) -ON_COMMAND (ID_FILE_PRINT, CView::OnFilePrint) -ON_COMMAND (ID_FILE_PRINT_DIRECT, CView::OnFilePrint) -ON_COMMAND (ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) +ON_COMMAND (ID_FILE_PRINT, __super::OnFilePrint) +ON_COMMAND (ID_FILE_PRINT_DIRECT, __super::OnFilePrint) +ON_COMMAND (ID_FILE_PRINT_PREVIEW, __super::OnFilePrintPreview) // Status ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_CRLF, OnUpdateIndicatorCRLF) ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_POSITION, OnUpdateIndicatorPosition) @@ -263,6 +263,7 @@ ON_COMMAND (ID_FORCE_REDRAW, OnForceRedraw) ON_UPDATE_COMMAND_UI(ID_EDIT_FIND_INCREMENTAL_BACKWARD, OnUpdateEditFindIncrementalBackward) //END SW ON_COMMAND (ID_EDIT_TOGGLE_COLUMNSELECTION, OnToggleColumnSelection) + ON_MESSAGE (WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) END_MESSAGE_MAP () #define EXPAND_PRIMITIVE(impl, func) \ @@ -519,7 +520,7 @@ PreCreateWindow (CREATESTRUCT & cs) //END SW } cs.lpszClass = AfxRegisterWndClass (CS_DBLCLKS); - return CView::PreCreateWindow (cs); + return __super::PreCreateWindow (cs); } @@ -3380,7 +3381,7 @@ GoToLine (int nLine, bool bRelative) void CCrystalTextView:: OnInitialUpdate () { - CView::OnInitialUpdate (); + __super::OnInitialUpdate (); std::basic_string sDoc = GetDocument ()->GetPathName (), sExt = GetExt (sDoc); if (!sExt.empty ()) SetTextType (sExt.c_str ()); @@ -3424,7 +3425,7 @@ OnInitialUpdate () void CCrystalTextView:: OnPrepareDC (CDC * pDC, CPrintInfo * pInfo /*= nullptr*/) { - CView::OnPrepareDC (pDC, pInfo); + __super::OnPrepareDC (pDC, pInfo); if (pInfo != nullptr) { @@ -3956,7 +3957,7 @@ OnDestroy () DetachFromBuffer (); m_hAccel = nullptr; - CView::OnDestroy (); + __super::OnDestroy (); if (m_pCacheBitmap != nullptr) { @@ -3975,7 +3976,7 @@ OnEraseBkgnd (CDC * pdc) void CCrystalTextView:: OnSize (UINT nType, int cx, int cy) { - CView::OnSize (nType, cx, cy); + __super::OnSize (nType, cx, cy); //BEGIN SW // get char position of top left visible character with old cached word wrap @@ -4102,7 +4103,7 @@ RecalcVertScrollBar (bool bPositionOnly /*= false*/, bool bRedraw /*= true */) void CCrystalTextView:: OnVScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar) { - CView::OnVScroll (nSBCode, nPos, pScrollBar); + __super::OnVScroll (nSBCode, nPos, pScrollBar); // Note we cannot use nPos because of its 16-bit nature SCROLLINFO si{ sizeof(si) }; @@ -4219,7 +4220,7 @@ void CCrystalTextView:: OnHScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar) { // Default handler not needed - //CView::OnHScroll (nSBCode, nPos, pScrollBar); + //__super::OnHScroll (nSBCode, nPos, pScrollBar); // Again, we cannot use nPos because it's 16-bit SCROLLINFO si { sizeof(si) }; @@ -4320,7 +4321,7 @@ OnSetCursor (CWnd * pWnd, UINT nHitTest, UINT message) } return true; } - return CView::OnSetCursor (pWnd, nHitTest, message); + return __super::OnSetCursor (pWnd, nHitTest, message); } int CCrystalTextView:: @@ -4764,7 +4765,7 @@ AdjustTextPoint (CPoint & point) void CCrystalTextView:: OnSetFocus (CWnd * pOldWnd) { - CView::OnSetFocus (pOldWnd); + __super::OnSetFocus (pOldWnd); m_bFocused = true; if (m_ptSelStart != m_ptSelEnd) @@ -4963,7 +4964,7 @@ EnsureVisible (CEPoint pt) void CCrystalTextView:: OnKillFocus (CWnd * pNewWnd) { - CView::OnKillFocus (pNewWnd); + __super::OnKillFocus (pNewWnd); m_bFocused = false; UpdateCaret (); @@ -4980,7 +4981,7 @@ OnKillFocus (CWnd * pNewWnd) void CCrystalTextView:: OnSysColorChange () { - CView::OnSysColorChange (); + __super::OnSysColorChange (); Invalidate (); } @@ -5188,7 +5189,7 @@ OnCreate (LPCREATESTRUCT lpCreateStruct) m_lfBaseFont.lfQuality = DEFAULT_QUALITY; m_lfBaseFont.lfPitchAndFamily = DEFAULT_PITCH; - if (CView::OnCreate (lpCreateStruct) == -1) + if (__super::OnCreate (lpCreateStruct) == -1) return -1; ASSERT (m_hAccel == nullptr); @@ -5231,7 +5232,7 @@ PreTranslateMessage (MSG * pMsg) OnLButtonTrippleClk(static_cast(pMsg->wParam), { GET_X_LPARAM(pMsg->lParam), GET_Y_LPARAM(pMsg->lParam) }); return true; } - return CView::PreTranslateMessage (pMsg); + return __super::PreTranslateMessage (pMsg); } void CCrystalTextView:: @@ -6268,7 +6269,7 @@ OnMouseWheel (UINT nFlags, short zDelta, CPoint pt) UpdateSiblingScrollPos(false); UpdateCaret (); - return CView::OnMouseWheel (nFlags, zDelta, pt); + return __super::OnMouseWheel (nFlags, zDelta, pt); } void CCrystalTextView:: @@ -6288,7 +6289,7 @@ OnMouseHWheel (UINT nFlags, short zDelta, CPoint pt) UpdateCaret (); UpdateSiblingScrollPos (true); - CView::OnMouseHWheel (nFlags, zDelta, pt); + __super::OnMouseHWheel (nFlags, zDelta, pt); } void CCrystalTextView:: @@ -6672,6 +6673,19 @@ OnToggleColumnSelection () Invalidate (); } +LRESULT CCrystalTextView:: +OnDpiChangedBeforeParent (WPARAM wParam, LPARAM lParam) +{ + const int oldDpi = m_dpi; + __super::OnDpiChangedBeforeParent(wParam, lParam); + if (m_dpi != oldDpi) + { + m_lfBaseFont.lfHeight = MulDiv(m_lfBaseFont.lfHeight, m_dpi, oldDpi); + SetFont (m_lfBaseFont); + } + return 0; +} + void CCrystalTextView::SetRenderingMode(RENDERING_MODE nRenderingMode) { #ifdef _WIN64 @@ -6728,7 +6742,7 @@ BOOL CCrystalTextView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDL { // just look for commands if( nCode != CN_COMMAND || pExtra != nullptr ) - return CView::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); + return __super::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); // handle code: // each command that is not related to incremental search @@ -6736,17 +6750,17 @@ BOOL CCrystalTextView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDL if( nID == ID_EDIT_FIND_INCREMENTAL_FORWARD || nID == ID_EDIT_FIND_INCREMENTAL_BACKWARD || nID == ID_EDIT_DELETE_BACK ) - return CView::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); + return __super::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); if( nID >= ID_EDIT_FIRST && nID <= ID_EDIT_LAST ) m_bIncrementalSearchForward = m_bIncrementalSearchBackward = false; - return CView::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); + return __super::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); } void CCrystalTextView::OnChar( wchar_t nChar, UINT nRepCnt, UINT nFlags ) { - CView::OnChar( nChar, nRepCnt, nFlags ); + __super::OnChar( nChar, nRepCnt, nFlags ); // we only have to handle character-input, if we are in incremental search mode if( !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward ) diff --git a/Externals/crystaledit/editlib/ccrystaltextview.h b/Externals/crystaledit/editlib/ccrystaltextview.h index 2f01fd717bc..2eec3693098 100644 --- a/Externals/crystaledit/editlib/ccrystaltextview.h +++ b/Externals/crystaledit/editlib/ccrystaltextview.h @@ -40,6 +40,7 @@ #include "renderers/ccrystalrenderer.h" #include "utils/cregexp.h" #include "utils/icu.hpp" +#include "utils/DpiAware.h" #include //////////////////////////////////////////////////////////////////////////// @@ -77,7 +78,7 @@ enum : updateview_flags_t * not implement text editing. There are classes inherited from this * class which implement text editing. */ -class EDITPADC_CLASS CCrystalTextView : public CView +class EDITPADC_CLASS CCrystalTextView : public DpiAware::CDpiAwareWnd { DECLARE_DYNCREATE (CCrystalTextView) @@ -520,7 +521,7 @@ protected : int GetMarginIconSize() const { - return MulDiv(CCrystalRenderer::MARGIN_ICON_SIZE, GetSystemMetrics(SM_CXSMICON), 16); + return MulDiv(CCrystalRenderer::MARGIN_ICON_SIZE, m_dpi, USER_DEFAULT_SCREEN_DPI); } #ifdef _UNICODE @@ -942,6 +943,7 @@ protected : //END SW afx_msg void OnToggleColumnSelection (); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP () }; diff --git a/Externals/crystaledit/editlib/dialogs/memcombo.cpp b/Externals/crystaledit/editlib/dialogs/memcombo.cpp index 4fb18d4fb06..fcada9410b3 100644 --- a/Externals/crystaledit/editlib/dialogs/memcombo.cpp +++ b/Externals/crystaledit/editlib/dialogs/memcombo.cpp @@ -68,9 +68,14 @@ void SetComboBoxWidth(CComboBox &Control, const tchar_t* lpszText = nullptr) if(!cnt) return; + + HMONITOR monitor = MonitorFromWindow(Control.m_hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO info{ sizeof MONITORINFO }; + GetMonitorInfo(monitor, &info); + CClientDC dc(&Control); CFont *oldFont; - int width = 0, nMax = ::GetSystemMetrics(SM_CXSCREEN) - 48; + int width = 0, nMax = info.rcMonitor.right - 48; CRect rc; CSize size; diff --git a/Externals/crystaledit/editlib/editlib.vcxitems b/Externals/crystaledit/editlib/editlib.vcxitems index 711dd5e7a14..d1470c66120 100644 --- a/Externals/crystaledit/editlib/editlib.vcxitems +++ b/Externals/crystaledit/editlib/editlib.vcxitems @@ -48,12 +48,14 @@ + pch.h $(IntDir)$(TargetName)2.pch + pch.h $(IntDir)$(TargetName)2.pch @@ -92,9 +94,12 @@ + + + diff --git a/Externals/crystaledit/editlib/editlib.vcxitems.filters b/Externals/crystaledit/editlib/editlib.vcxitems.filters index 8c1dd183b4b..feceb3792a1 100644 --- a/Externals/crystaledit/editlib/editlib.vcxitems.filters +++ b/Externals/crystaledit/editlib/editlib.vcxitems.filters @@ -100,6 +100,12 @@ Utils + + Utils + + + Utils + @@ -202,5 +208,14 @@ Utils + + Utils + + + Utils + + + Utils + \ No newline at end of file diff --git a/Externals/crystaledit/editlib/utils/DpiAware.cpp b/Externals/crystaledit/editlib/utils/DpiAware.cpp new file mode 100644 index 00000000000..08a7f4acafd --- /dev/null +++ b/Externals/crystaledit/editlib/utils/DpiAware.cpp @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BSL-1.0 +// Copyright (c) 2020 Takashi Sawanaka +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "StdAfx.h" +#include "DpiAware.h" +#include +#include <../src/mfc/afximpl.h> + +namespace DpiAware +{ + GetDpiForWindowType GetDpiForWindow = nullptr; + SystemParametersInfoForDpiType SystemParametersInfoForDpi = nullptr; + GetSystemMetricsForDpiType GetSystemMetricsForDpi = nullptr; + OpenThemeDataForDpiType OpenThemeDataForDpi = nullptr; + AdjustWindowRectExForDpiType AdjustWindowRectExForDpi = nullptr; + LoadIconWithScaleDownType LoadIconWithScaleDown = nullptr; + + int DPIOnInit = 0; + + bool DpiAwareSupport = []() + { + DPIOnInit = MulDiv(USER_DEFAULT_SCREEN_DPI, ::GetSystemMetrics(SM_CXSMICON), 16); + HMODULE hLibraryUser32 = GetModuleHandleW(L"user32.dll"); + if (hLibraryUser32) + { + AdjustWindowRectExForDpi = reinterpret_cast(GetProcAddress(hLibraryUser32, "AdjustWindowRectExForDpi")); + GetDpiForWindow = reinterpret_cast(GetProcAddress(hLibraryUser32, "GetDpiForWindow")); + SystemParametersInfoForDpi = reinterpret_cast(GetProcAddress(hLibraryUser32, "SystemParametersInfoForDpi")); + GetSystemMetricsForDpi = reinterpret_cast(GetProcAddress(hLibraryUser32, "GetSystemMetricsForDpi")); + } + HMODULE hLibraryComctl32 = GetModuleHandleW(L"comctl32.dll"); + if (hLibraryComctl32) + { + LoadIconWithScaleDown = reinterpret_cast(GetProcAddress(hLibraryComctl32, "LoadIconWithScaleDown")); + } + HMODULE hLibraryUxTheme = GetModuleHandleW(L"uxtheme.dll"); + if (hLibraryUxTheme) + { + OpenThemeDataForDpi = reinterpret_cast(GetProcAddress(hLibraryUxTheme, "OpenThemeDataForDpi")); + } + if (!AdjustWindowRectExForDpi) + AdjustWindowRectExForDpi = [](LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi) -> BOOL + { return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); }; + if (!GetDpiForWindow) + GetDpiForWindow = [](HWND hwnd) -> UINT { return CClientDC(CWnd::FromHandle(hwnd)).GetDeviceCaps(LOGPIXELSX); }; + if (!SystemParametersInfoForDpi) + SystemParametersInfoForDpi = [](UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi) -> BOOL { return SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); }; + if (!GetSystemMetricsForDpi) + GetSystemMetricsForDpi = [](int nIndex, UINT dpi) -> int { return GetSystemMetrics(nIndex); }; + if (!LoadIconWithScaleDown) + LoadIconWithScaleDown = [](HINSTANCE hinst, PCWSTR pszName, int cx, int cy, HICON *phico) -> HRESULT + { *phico = LoadIconW(hinst, pszName); return *phico != nullptr ? S_OK : E_FAIL; }; + if (!OpenThemeDataForDpi) + { + OpenThemeDataForDpi = [](HWND hwnd, LPCWSTR pszClassList, UINT dpi) -> HTHEME { return OpenThemeData(hwnd, pszClassList); }; + return false; + } + return true; + }(); + + void GetPointLogFont(LOGFONT& logFont, float point, const TCHAR* lfFaceName, int dpi) + { + LOGFONT lfv{}; + lfv.lfHeight = static_cast(-point * dpi / 72.0f); + lfv.lfCharSet = DEFAULT_CHARSET; + _tcscpy_s(lfv.lfFaceName, lfFaceName); + logFont = lfv; + } + + bool GetNonClientLogFont(LOGFONT& logFont, size_t memberOffset, int dpi) + { + DpiAware::NONCLIENTMETRICS6 ncm{}; + ncm.cbSize = sizeof(NONCLIENTMETRICS); + if (DpiAware::DpiAwareSupport) + ncm.cbSize = sizeof DpiAware::NONCLIENTMETRICS6; + if (!SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, static_cast(&ncm), 0, dpi)) + return false; + memcpy(&logFont, (char*)&ncm + memberOffset, sizeof(LOGFONT)); + return true; + } + + void UpdateAfxDataSysMetrics(int dpi) + { + afxData.cxIcon = GetSystemMetricsForDpi(SM_CXICON, dpi); + afxData.cyIcon = GetSystemMetricsForDpi(SM_CYICON, dpi); + afxData.cxVScroll = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi) + AFX_CX_BORDER; + afxData.cyHScroll = GetSystemMetricsForDpi(SM_CYHSCROLL, dpi) + AFX_CY_BORDER; + afxData.cxPixelsPerInch = dpi; + afxData.cyPixelsPerInch = dpi; + } + + void TreeView_UpdateIndent(HWND hwnd, int olddpi, int newdpi) + { + int indent = TreeView_GetIndent(hwnd); + TreeView_SetIndent(hwnd, MulDiv(indent, newdpi, olddpi)); + } + + void ListView_UpdateColumnWidths(HWND hwnd, int olddpi, int newdpi) + { + HWND hwndHeader = ListView_GetHeader(hwnd); + const int nColumns = Header_GetItemCount(hwndHeader); + for (int i = 0; i < nColumns; ++i) + { + const int nColumnWidth = MulDiv(ListView_GetColumnWidth(hwnd, i), newdpi, olddpi); + ListView_SetColumnWidth(hwnd, i, nColumnWidth); + } + } + + void Dialog_UpdateControlInnerWidths(HWND hwnd, int olddpi, int newdpi) + { + struct Dpis { int olddpi, newdpi; HWND hwndParent; } dpis{ olddpi, newdpi, hwnd }; + auto enumfunc = [](HWND hwnd, LPARAM lParam) -> BOOL + { + const Dpis *pdpis = (const Dpis *)lParam; + TCHAR name[256]; + GetClassName(hwnd, name, sizeof(name) / sizeof(TCHAR)); + if (_tcsicmp(name, _T("SysListView32")) == 0 && pdpis->hwndParent == GetParent(hwnd)) + ListView_UpdateColumnWidths(hwnd, pdpis->olddpi, pdpis->newdpi); + else if (_tcsicmp(name, _T("SysTreeView32")) == 0 && pdpis->hwndParent == GetParent(hwnd)) + TreeView_UpdateIndent(hwnd, pdpis->olddpi, pdpis->newdpi); + return TRUE; + }; + EnumChildWindows(hwnd, enumfunc, (LPARAM)&dpis); + } + + CSize Dialog_GetSizeFromTemplate(const TCHAR *pTemplateID, const TCHAR *pszFaceName, int nFontSize) + { + CDialogTemplate tmpl; + CSize size; + tmpl.Load(pTemplateID); + tmpl.SetFont(pszFaceName, nFontSize); + tmpl.GetSizeInPixels(&size); + return size; + } + + CSize Dialog_CalcUpdatedSize(const TCHAR *pszFontFace, int nFontSize, const CSize& oldsize, int olddpi, int newdpi) + { + UINT cxSysChar[2], cySysChar[2]; + LOGFONT lf[2] = {}; + CClientDC dc(nullptr); + lf[0].lfHeight = -MulDiv(nFontSize, olddpi, 72); + lf[0].lfWeight = FW_NORMAL; + lf[0].lfCharSet = DEFAULT_CHARSET; + _tcscpy_s(lf[0].lfFaceName, pszFontFace); + lf[1] = lf[0]; + lf[1].lfHeight = -MulDiv(nFontSize, newdpi, 72); + + for (int i = 0; i < 2; ++i) + { + CFont font; + font.CreateFontIndirect(&lf[i]); + HFONT hFontOld = (HFONT)SelectObject(dc, font); + TEXTMETRIC tm; + dc.GetTextMetrics(&tm); + cySysChar[i] = tm.tmHeight + tm.tmExternalLeading; + SIZE size; + GetTextExtentPoint32(dc, _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &size); + cxSysChar[i] = (size.cx + 26) / 52; + dc.SelectObject(hFontOld); + } + + int newcx = MulDiv(oldsize.cx, cxSysChar[1], cxSysChar[0]); + int newcy = MulDiv(oldsize.cy, cySysChar[1], cySysChar[0]); + return { newcx, newcy }; + } + + HIMAGELIST LoadShellImageList(int dpi) + { + SHFILEINFO sfi{}; + if (dpi == DpiAware::DPIOnInit) + { + return (HIMAGELIST)SHGetFileInfo(_T(""), 0, + &sfi, sizeof(sfi), SHGFI_SMALLICON | SHGFI_SYSICONINDEX); + } + else + { + int cxsmicon = ::GetSystemMetrics(SM_CXSMICON); + int iconsize = MulDiv(16, dpi, USER_DEFAULT_SCREEN_DPI); + int size = SHIL_EXTRALARGE; + if (iconsize < cxsmicon * 2) + size = SHIL_SMALL; + else if (iconsize < cxsmicon * 3) + size = SHIL_LARGE; + IImageList *pImageList = nullptr; + if (FAILED(SHGetImageList(size, IID_IImageList, (void**)&pImageList))) + return nullptr; + CComQIPtr pImageList2(pImageList); + if (pImageList2) + pImageList2->Resize(iconsize, iconsize); + return IImageListToHIMAGELIST(pImageList); + } + } +} + diff --git a/Externals/crystaledit/editlib/utils/DpiAware.h b/Externals/crystaledit/editlib/utils/DpiAware.h new file mode 100644 index 00000000000..a46d9763e8b --- /dev/null +++ b/Externals/crystaledit/editlib/utils/DpiAware.h @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: BSL-1.0 +// Copyright (c) 2020 Takashi Sawanaka +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include +#include "mfc_templ_defines.h" + +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif +#ifndef WM_DPICHANGED_BEFOREPARENT +#define WM_DPICHANGED_BEFOREPARENT 0x02E2 +#define WM_DPICHANGED_AFTERPARENT 0x02E3 +#endif +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 +#endif + +namespace DpiAware +{ +#if(WINVER >= 0x0600) + struct NONCLIENTMETRICS6 : public NONCLIENTMETRICS { }; +#else + struct NONCLIENTMETRICS6 : public NONCLIENTMETRICS { int iPaddedBorderWidth; }; +#endif + + using AdjustWindowRectExForDpiType = BOOL(__stdcall*)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi); + using GetDpiForWindowType = UINT(__stdcall*)(HWND hwnd); + using SystemParametersInfoForDpiType = BOOL(__stdcall*)(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi); + using GetSystemMetricsForDpiType = int(__stdcall*)(int nIndex, UINT dpi); + using OpenThemeDataForDpiType = HTHEME(__stdcall*)(HWND hwnd, LPCWSTR pszClassList, UINT dpi); + using LoadIconWithScaleDownType = HRESULT(__stdcall*)(HINSTANCE hinst, PCWSTR pszName, int cx, int cy, HICON* phico); + + extern bool DpiAwareSupport; + extern int DPIOnInit; + + extern AdjustWindowRectExForDpiType AdjustWindowRectExForDpi; + extern GetDpiForWindowType GetDpiForWindow; + extern SystemParametersInfoForDpiType SystemParametersInfoForDpi; + extern GetSystemMetricsForDpiType GetSystemMetricsForDpi; + extern OpenThemeDataForDpiType OpenThemeDataForDpi; + extern LoadIconWithScaleDownType LoadIconWithScaleDown; + + void GetPointLogFont(LOGFONT& logFont, float point, const TCHAR* lfFaceName, int dpi); + bool GetNonClientLogFont(LOGFONT& logFont, size_t memberOffset, int dpi); + void UpdateAfxDataSysMetrics(int dpi); + void ListView_UpdateColumnWidths(HWND hwnd, int olddpi, int newdpi); + void Dialog_UpdateControlInnerWidths(HWND hwnd, int olddpi, int newdpi); + CSize Dialog_CalcUpdatedSize(const TCHAR* pszFontFace, int nFontSize, const CSize& oldsize, int olddpi, int newdpi); + CSize Dialog_GetSizeFromTemplate(const TCHAR* pTemplateID, const TCHAR* pszFaceName, int nFontSize); + HIMAGELIST LoadShellImageList(int dpi); + template + T MulDivRect(const T* p, int nNumerator, int nDenominator) + { + T rc; + rc.left = MulDiv(p->left, nNumerator, nDenominator); + rc.top = MulDiv(p->top, nNumerator, nDenominator); + rc.right = MulDiv(p->right, nNumerator, nDenominator); + rc.bottom = MulDiv(p->bottom, nNumerator, nDenominator); + return rc; + } + + template + class CDpiAwareWnd : public Base + { + public: + using this_type = CDpiAwareWnd; + using base_type = Base; + using Base::Base; + + int GetDpi() const { return m_dpi; } + + int PointToPixel(int point) const { return MulDiv(point, m_dpi, 72); } + template + int PointToPixel(T point) const { return static_cast((point * m_dpi) / 72); } + void UpdateDpi() + { + m_dpi = GetDpiForWindow(m_hWnd); + } + int GetSystemMetrics(int nIndex) { return GetSystemMetricsForDpi(nIndex, m_dpi); } + BOOL AdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle) + { + return DpiAware::AdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, m_dpi); + } + + virtual void CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType = CWnd::adjustBorder) + { + DWORD dwExStyle = GetWindowLong(m_hWnd, GWL_EXSTYLE); + if (nAdjustType == 0) + dwExStyle &= ~WS_EX_CLIENTEDGE; + DWORD dwStyle = (DWORD)GetWindowLong(m_hWnd, GWL_STYLE); + DpiAware::AdjustWindowRectExForDpi(lpClientRect, dwStyle, FALSE, dwExStyle, m_dpi); + } + + bool IsDifferentDpiFromSystemDpi() const + { + return DPIOnInit != m_dpi; + } + + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct) + { + UpdateDpi(); + return __super::OnCreate(lpCreateStruct); + } + + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam) + { + int olddpi = m_dpi; + UpdateDpi(); + return 0; + } + + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) + { + UpdateDpi(); + return 0; + } + + int m_dpi = DPIOnInit; + + BEGIN_MESSAGE_MAP_INLINE(this_type, base_type) + ON_WM_CREATE() + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) + END_MESSAGE_MAP_INLINE() + }; + + template + class CDpiAwareDialog : public CDpiAwareWnd + { + public: + using this_type = CDpiAwareDialog; + using base_type = CDpiAwareWnd; + using CDpiAwareWnd::CDpiAwareWnd; + + CRect m_rcInit; + + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct) + { + GetClientRect(m_rcInit); + return __super::OnCreate(lpCreateStruct); + } + + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam) + { + int olddpi = m_dpi; + bool bDynamicLayoutEnabled = IsDynamicLayoutEnabled(); + CSize sizeMin; + if (bDynamicLayoutEnabled) + { +// sizeMin = GetDynamicLayout()->GetMinSize(); +// CRect rc = m_rcInit; +// AdjustWindowRectEx(&rc, GetStyle(), false, GetExStyle()); +// SetWindowPos(nullptr, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER); +// GetDynamicLayout()->Adjust(); + EnableDynamicLayout(FALSE); + } + UpdateDpi(); + Default(); + if (bDynamicLayoutEnabled) + { + /* + CFont *pFont = GetFont(); + LOGFONT lfFont; + pFont->GetLogFont(&lfFont); + CSize size = Dialog_GetSizeFromTemplate(m_lpszTemplateName, lfFont.lfFaceName, MulDiv(abs(lfFont.lfHeight), 72, m_dpi)); + SetWindowPos(nullptr, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOZORDER); + LoadDynamicLayoutResource(m_lpszTemplateName); + */ + } + return 0; + } + + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) + { + return OnDpiChanged(wParam, lParam); + } + + BEGIN_MESSAGE_MAP_INLINE(this_type, base_type) + ON_WM_CREATE() + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) + END_MESSAGE_MAP_INLINE() + }; +} + diff --git a/Externals/crystaledit/editlib/utils/MDITileLayout.cpp b/Externals/crystaledit/editlib/utils/MDITileLayout.cpp new file mode 100644 index 00000000000..95bb4d19803 --- /dev/null +++ b/Externals/crystaledit/editlib/utils/MDITileLayout.cpp @@ -0,0 +1,452 @@ +// SPDX-License-Identifier: BSL-1.0 +// Copyright (c) 2020 Takashi Sawanaka +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "StdAfx.h" +#include "MDITileLayout.h" +#include "DpiAware.h" + +namespace MDITileLayout +{ + bool Pane::Split(bool bHorizontal, double ratio) + { + if (IsSplitted()) + return false; + m_pSplittedLayout.reset(new SplittedLayout(this, bHorizontal, ratio, m_wndList)); + m_wndList.clear(); + return true; + } + + bool Pane::Combine() + { + if (IsSplitted()) + { + if (m_pSplittedLayout->m_pPaneFirst->IsSplitted()) + m_pSplittedLayout->m_pPaneFirst->Combine(); + if (m_pSplittedLayout->m_pPaneSecond->IsSplitted()) + m_pSplittedLayout->m_pPaneSecond->Combine(); + for (auto& pWnd : m_pSplittedLayout->m_pPaneFirst->m_wndList) + m_wndList.push_back(pWnd); + for (auto& pWnd : m_pSplittedLayout->m_pPaneSecond->m_wndList) + m_wndList.push_back(pWnd); + m_pSplittedLayout.reset(); + return true; + } + if (m_pParentSplittedLayout == nullptr) + return false; + return m_pParentSplittedLayout->m_pParentPane->Combine(); + } + + void Pane::Tile(bool bHorizontal) + { + if (IsSplitted()) + Combine(); + size_t nCount = m_wndList.size(); + if (nCount <= 1) + return; + Split(bHorizontal, 1.0 / nCount); + for (size_t i = 1; i < nCount; ++i) + m_pSplittedLayout->m_pPaneFirst->MoveWindow(m_pSplittedLayout->m_pPaneSecond.get(), m_pSplittedLayout->m_pPaneFirst->m_wndList[1]); + m_pSplittedLayout->m_pPaneSecond->Tile(bHorizontal); + } + + CRect Pane::GetRect(const CRect& rcMainWnd) const + { + double left = 0, top = 0, width = 1.0, height = 1.0; + for (auto *pPane = this; + pPane->m_pParentSplittedLayout != nullptr; + pPane = pPane->m_pParentSplittedLayout->m_pParentPane) + { + SplittedLayout* pParentSplittedLayout = pPane->m_pParentSplittedLayout; + if (pParentSplittedLayout->m_pPaneFirst.get() == pPane) + { + if (pParentSplittedLayout->m_bHorizontal) + { + top *= pParentSplittedLayout->m_firstPaneSizeRatio; + height *= pParentSplittedLayout->m_firstPaneSizeRatio; + } + else + { + left *= pParentSplittedLayout->m_firstPaneSizeRatio; + width *= pParentSplittedLayout->m_firstPaneSizeRatio; + } + } + else + { + if (pParentSplittedLayout->m_bHorizontal) + { + top = pParentSplittedLayout->m_firstPaneSizeRatio + top * (1.0 - pParentSplittedLayout->m_firstPaneSizeRatio); + height *= (1.0 - pParentSplittedLayout->m_firstPaneSizeRatio); + } + else + { + left = pParentSplittedLayout->m_firstPaneSizeRatio + left * (1.0 - pParentSplittedLayout->m_firstPaneSizeRatio); + width *= (1.0 - pParentSplittedLayout->m_firstPaneSizeRatio); + } + } + + } + return CRect( + static_cast(rcMainWnd.left + rcMainWnd.Width() * left), + static_cast(rcMainWnd.top + rcMainWnd.Height() * top), + static_cast(rcMainWnd.left + rcMainWnd.Width() * (left + width)), + static_cast(rcMainWnd.top + rcMainWnd.Height() * (top + height))); + } + + void Pane::SetDefaultOpenPane() + { + for (auto *pPane = this; + pPane->m_pParentSplittedLayout != nullptr; + pPane = pPane->m_pParentSplittedLayout->m_pParentPane) + { + SplittedLayout* pParentSplittedLayout = pPane->m_pParentSplittedLayout; + pParentSplittedLayout->m_bDefaultOpenPaneIsFirst = (pParentSplittedLayout->m_pPaneFirst.get() == pPane); + } + } + + Pane* Pane::GetDefaultOpenPane() const + { + if (!IsSplitted()) + return const_cast(this); + if (m_pSplittedLayout->m_bDefaultOpenPaneIsFirst) + return m_pSplittedLayout->m_pPaneFirst->GetDefaultOpenPane(); + return m_pSplittedLayout->m_pPaneSecond->GetDefaultOpenPane(); + } + + bool Pane::AddWindow(CWnd* pWnd) + { + if (IsSplitted()) + return false; + m_wndList.push_back(pWnd); + return true; + } + + bool Pane::RemoveWindow(CWnd* pWnd) + { + auto it = std::remove(m_wndList.begin(), m_wndList.end(), pWnd); + if (it == m_wndList.end()) + return false; + m_wndList.erase(it); + return true; + } + + bool Pane::MoveWindow(Pane* pDstPane, CWnd* pWnd) + { + if (!RemoveWindow(pWnd)) + return false; + return pDstPane->AddWindow(pWnd); + } + + Pane* Pane::FindPaneByWindow(CWnd* pWnd) const + { + if (!IsSplitted()) + { + auto it = std::find(m_wndList.begin(), m_wndList.end(), pWnd); + if (it != m_wndList.end()) + return const_cast(this); + return nullptr; + } + if (Pane *pPane = m_pSplittedLayout->m_pPaneFirst->FindPaneByWindow(pWnd)) + return pPane; + return m_pSplittedLayout->m_pPaneSecond->FindPaneByWindow(pWnd); + } + + void Pane::UpdateSizeRatio(const CRect& rcMainWnd, const CRect& rcChildWnd) + { + if (m_pParentSplittedLayout == nullptr) + return; + const int None = 0, Left = 1, Top = 2, Right = 4, Bottom = 8; + int changedBorders = None; + CRect rcChildWndOld = GetRect(rcMainWnd); + if (rcChildWndOld.left != rcChildWnd.left) + changedBorders |= Left; + if (rcChildWndOld.top != rcChildWnd.top) + changedBorders |= Top; + if (rcChildWndOld.right != rcChildWnd.right) + changedBorders |= Right; + if (rcChildWndOld.bottom != rcChildWnd.bottom) + changedBorders |= Bottom; + if (changedBorders & Left) + { + for (auto* pPane = this; + pPane->m_pParentSplittedLayout != nullptr; + pPane = pPane->m_pParentSplittedLayout->m_pParentPane) + { + if (!pPane->m_pParentSplittedLayout->m_bHorizontal && pPane->m_pParentSplittedLayout->m_pPaneSecond.get() == pPane) + { + CRect rcParentWnd = pPane->m_pParentSplittedLayout->m_pParentPane->GetRect(rcMainWnd); + if (rcChildWnd.Width() <= 0 || rcChildWnd.Width() >= rcParentWnd.Width()) + { + pPane->m_pParentSplittedLayout->m_pParentPane->Combine(); + return; + } + pPane->m_pParentSplittedLayout->m_firstPaneSizeRatio = static_cast(rcChildWnd.left - rcParentWnd.left) / rcParentWnd.Width(); + break; + } + } + } + if (changedBorders & Top) + { + for (auto* pPane = this; + pPane->m_pParentSplittedLayout != nullptr; + pPane = pPane->m_pParentSplittedLayout->m_pParentPane) + { + if (pPane->m_pParentSplittedLayout->m_bHorizontal && pPane->m_pParentSplittedLayout->m_pPaneSecond.get() == pPane) + { + CRect rcParentWnd = pPane->m_pParentSplittedLayout->m_pParentPane->GetRect(rcMainWnd); + if (rcChildWnd.Height() <= 0 || rcChildWnd.Height() >= rcParentWnd.Height()) + { + pPane->m_pParentSplittedLayout->m_pParentPane->Combine(); + return; + } + pPane->m_pParentSplittedLayout->m_firstPaneSizeRatio = static_cast(rcChildWnd.top - rcParentWnd.top) / rcParentWnd.Height(); + break; + } + } + } + if (changedBorders & Right) + { + for (auto* pPane = this; + pPane->m_pParentSplittedLayout != nullptr; + pPane = pPane->m_pParentSplittedLayout->m_pParentPane) + { + if (!pPane->m_pParentSplittedLayout->m_bHorizontal && pPane->m_pParentSplittedLayout->m_pPaneFirst.get() == pPane) + { + CRect rcParentWnd = pPane->m_pParentSplittedLayout->m_pParentPane->GetRect(rcMainWnd); + if (rcChildWnd.Width() <= 0 || rcChildWnd.Width() >= rcParentWnd.Width()) + { + pPane->m_pParentSplittedLayout->m_pParentPane->Combine(); + return; + } + pPane->m_pParentSplittedLayout->m_firstPaneSizeRatio = static_cast(rcChildWnd.right - rcParentWnd.left) / rcParentWnd.Width(); + break; + } + } + } + if (changedBorders & Bottom) + { + for (auto* pPane = this; + pPane->m_pParentSplittedLayout != nullptr; + pPane = pPane->m_pParentSplittedLayout->m_pParentPane) + { + if (pPane->m_pParentSplittedLayout->m_bHorizontal && pPane->m_pParentSplittedLayout->m_pPaneFirst.get() == pPane) + { + CRect rcParentWnd = pPane->m_pParentSplittedLayout->m_pParentPane->GetRect(rcMainWnd); + if (rcChildWnd.Height() <= 0 || rcChildWnd.Height() >= rcParentWnd.Height()) + { + pPane->m_pParentSplittedLayout->m_pParentPane->Combine(); + return; + } + pPane->m_pParentSplittedLayout->m_firstPaneSizeRatio = static_cast(rcChildWnd.bottom - rcParentWnd.top) / rcParentWnd.Height(); + break; + } + } + } + } + + SplittedLayout::SplittedLayout(Pane* pParentPane, bool bHorizontal, double ratio, std::vector& wndList) + : m_pParentPane(pParentPane) + , m_bHorizontal(bHorizontal) + , m_firstPaneSizeRatio(ratio) + , m_pPaneFirst(new Pane(this)) + , m_pPaneSecond(new Pane(this)) + { + m_pPaneFirst->m_wndList = wndList; + m_pPaneSecond->SetDefaultOpenPane(); + } + + void LayoutManager::SetTileLayoutEnabled(bool bEnabled) + { + if (m_bEnabled == bEnabled) + return; + + m_bEnabled = bEnabled; + + HWND hWndMDIActive = m_pMDIFrameWnd->MDIGetActive()->GetSafeHwnd(); + if (hWndMDIActive == nullptr) + return; + + m_pMDIFrameWnd->MDICascade(); + + for (CWnd* pWnd = m_pMDIFrameWnd->MDIGetActive()->GetParent()->GetTopWindow(); pWnd; pWnd = pWnd->GetNextWindow()) + { + DWORD dwStyle = pWnd->GetStyle(); + if (m_bEnabled) + { + SetWindowLong(pWnd->m_hWnd, GWL_STYLE, dwStyle & ~(WS_CAPTION)); + } + else + { + SetWindowLong(pWnd->m_hWnd, GWL_STYLE, dwStyle | WS_CAPTION); + pWnd->ShowWindow(SW_HIDE); + pWnd->ShowWindow(SW_SHOW); + } + } + + UpdateChildWindows(); + } + + void LayoutManager::Tile(bool bHorizontal) + { + m_pPane->Tile(bHorizontal); + UpdateChildWindows(); + } + + bool LayoutManager::SplitActivePane(bool bHorizontal, double ratio) + { + bool result = false; + if (Pane* pPane = GetActivePane()) + result = pPane->Split(bHorizontal, ratio); + if (result) + UpdateChildWindows(); + return result; + } + + bool LayoutManager::CombineActivePane() + { + bool result = false; + if (Pane* pPane = GetActivePane()) + result = pPane->Combine(); + if (result) + UpdateChildWindows(); + return result; + } + + void LayoutManager::SetActivePaneAsDefaultOpenPane() + { + if (Pane* pPane = GetActivePane()) + pPane->SetDefaultOpenPane(); + } + + CRect LayoutManager::GetDefaultOpenPaneRect() const + { + CRect rc = GetMainRect(); + if (Pane* pPane = m_pPane->GetDefaultOpenPane()) + return pPane->GetRect(rc); + return rc; + } + + void LayoutManager::NotifyMainResized() + { + UpdateChildWindows(); + } + + void LayoutManager::NotifyChildOpened(CWnd* pChildWnd) + { + if (Pane* pPane = m_pPane->GetDefaultOpenPane()) + pPane->AddWindow(pChildWnd); + } + + void LayoutManager::NotifyChildClosed(CWnd* pChildWnd) + { + if (Pane* pPane = m_pPane->FindPaneByWindow(pChildWnd)) + { + pPane->RemoveWindow(pChildWnd); + if (pPane->GetWindowCount() == 0) + { + pPane->Combine(); + UpdateChildWindows(); + } + } + } + + void LayoutManager::NotifyChildResized(CWnd* pChildWnd) + { + if (m_bInResizing) + return; + Pane* pPane = m_pPane->FindPaneByWindow(pChildWnd); + if (pPane == nullptr) + return; + CRect rcMain = GetMainRect(); + CRect rcChild = GetChildRect(pChildWnd, rcMain); + pPane->UpdateSizeRatio(rcMain, rcChild); + + UpdateChildWindows(); + } + + Pane* LayoutManager::FindPaneByPosition(CPoint& pt) const + { + CRect rc = GetMainRect(); + for (CWnd* pWnd = m_pMDIFrameWnd->MDIGetActive()->GetParent()->GetTopWindow(); pWnd; pWnd = pWnd->GetNextWindow()) + { + if (Pane* pPane = m_pPane->FindPaneByWindow(pWnd)) + { + CRect rcChild = pPane->GetRect(rc); + if (rcChild.left <= pt.x && pt.x < rcChild.right && + rcChild.top <= pt.y && pt.y < rcChild.bottom) + return pPane; + } + } + return nullptr; + } + + Pane* LayoutManager::GetActivePane() const + { + if (CWnd* pWnd = m_pMDIFrameWnd->MDIGetActive()) + return m_pPane->FindPaneByWindow(pWnd); + return nullptr; + } + + CRect LayoutManager::AdjustChildRect(const CRect& rcMain, const CRect& rc, DWORD dwStyle, DWORD dwExStyle, int dpi) const + { + CRect rcChild = rc; + CRect rcChildOrg = rcChild; + DpiAware::AdjustWindowRectExForDpi(rcChild, dwStyle, false, dwExStyle, dpi); + if (rcChildOrg.right < rcMain.right) + rcChild.right = rcChildOrg.right; + if (rcChildOrg.bottom < rcMain.bottom) + rcChild.bottom = rcChildOrg.bottom; + return rcChild; + } + + void LayoutManager::UpdateChildWindows() + { + if (!m_bEnabled || m_pMDIFrameWnd->MDIGetActive()->GetSafeHwnd() == nullptr) + return; + m_bInResizing = true; + CRect rc = GetMainRect(); + CWnd* pWndMDIClient = CWnd::FromHandle(m_pMDIFrameWnd->m_hWndMDIClient); + const int dpi = DpiAware::GetDpiForWindow(m_pMDIFrameWnd->m_hWndMDIClient); + CRect rcMainMargin; + DpiAware::AdjustWindowRectExForDpi(rcMainMargin, pWndMDIClient->GetStyle(), false, pWndMDIClient->GetExStyle(), dpi); + HDWP hdwp = BeginDeferWindowPos(8); + for (CWnd* pWnd = m_pMDIFrameWnd->MDIGetActive()->GetParent()->GetTopWindow(); pWnd; pWnd = pWnd->GetNextWindow()) + { + if (Pane* pPane = m_pPane->FindPaneByWindow(pWnd)) + { + CRect rcChild = AdjustChildRect(rc, pPane->GetRect(rc), pWnd->GetStyle(), pWnd->GetExStyle(), dpi); + DeferWindowPos(hdwp, pWnd->m_hWnd, nullptr, + rcChild.left - rc.left + rcMainMargin.left, + rcChild.top - rc.top + rcMainMargin.top, + rcChild.Width(), rcChild.Height(), SWP_NOZORDER); + } + } + EndDeferWindowPos(hdwp); + m_bInResizing = false; + } + + CRect LayoutManager::GetMainRect() const + { + CRect rc; + CWnd *pWnd = CWnd::FromHandle(m_pMDIFrameWnd->m_hWndMDIClient); + pWnd->GetWindowRect(rc); + return rc; + } + + CRect LayoutManager::GetChildRect(CWnd* pChildWnd, const CRect& rcMain) const + { + const int dpi = DpiAware::GetDpiForWindow(pChildWnd->m_hWnd); + CRect rc, rcOuter; + pChildWnd->GetWindowRect(rc); + DpiAware::AdjustWindowRectExForDpi(rcOuter, pChildWnd->GetStyle(), false, pChildWnd->GetExStyle(), dpi); + CRect rcChild { rc.left - rcOuter.left, rc.top - rcOuter.top, rc.right - rcOuter.right, rc.bottom - rcOuter.bottom}; + if (rc.right < rcMain.right) + rcChild.right = rc.right; + if (rc.bottom < rcMain.bottom) + rcChild.bottom = rc.bottom; + return rcChild; + } +} diff --git a/Externals/crystaledit/editlib/utils/MDITileLayout.h b/Externals/crystaledit/editlib/utils/MDITileLayout.h new file mode 100644 index 00000000000..de2a276c084 --- /dev/null +++ b/Externals/crystaledit/editlib/utils/MDITileLayout.h @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSL-1.0 +// Copyright (c) 2020 Takashi Sawanaka +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include +#include + +namespace MDITileLayout +{ + class SplittedLayout; + + class Pane + { + friend SplittedLayout; + public: + Pane(SplittedLayout* pParentSplittedLayout) : m_pParentSplittedLayout(pParentSplittedLayout) {} + bool Split(bool bHorizontal, double ratio); + bool Combine(); + void Tile(bool bHorizontal); + CRect GetRect(const CRect& rcMainWnd) const; + bool IsSplitted() const { return m_pSplittedLayout != nullptr; } + void SetDefaultOpenPane(); + Pane* GetDefaultOpenPane() const; + bool AddWindow(CWnd* pWnd); + bool RemoveWindow(CWnd* pWnd); + size_t GetWindowCount() const { return m_wndList.size(); } + bool MoveWindow(Pane *pDstPane, CWnd* pWnd); + Pane* FindPaneByWindow(CWnd* pWnd) const; + void UpdateSizeRatio(const CRect& rcMainWnd, const CRect& rcChildWnd); + + protected: + std::vector m_wndList; + std::unique_ptr m_pSplittedLayout; + SplittedLayout* m_pParentSplittedLayout; + }; + + class SplittedLayout + { + friend Pane; + public: + SplittedLayout(Pane* pParentPane, bool bHorizontal, double ratio, std::vector& wndList); + + protected: + Pane* m_pParentPane = nullptr; + std::unique_ptr m_pPaneFirst; + std::unique_ptr m_pPaneSecond; + bool m_bDefaultOpenPaneIsFirst = false; + bool m_bHorizontal = false; + double m_firstPaneSizeRatio = 0.5; + }; + + class LayoutManager + { + public: + LayoutManager(CMDIFrameWnd* pMDIFrameWnd) : m_pMDIFrameWnd(pMDIFrameWnd), m_pPane(new Pane(nullptr)) {} + void SetTileLayoutEnabled(bool bEnabled); + bool GetTileLayoutEnabled() const { return m_bEnabled; }; + void Tile(bool bHorizontal); + bool SplitActivePane(bool bHorizontal, double ratio); + bool CombineActivePane(); + void SetActivePaneAsDefaultOpenPane(); + CRect GetDefaultOpenPaneRect() const; + void NotifyMainResized(); + void NotifyChildOpened(CWnd* pChlidWnd); + void NotifyChildClosed(CWnd* pChlidWnd); + void NotifyChildResized(CWnd* pChlidWnd); + CRect AdjustChildRect(const CRect& rcMain, const CRect& rc, DWORD dwStyle, DWORD dwExStyle, int dpi) const; + + protected: + Pane* FindPaneByPosition(CPoint& pt) const; + Pane* GetActivePane() const; + void UpdateChildWindows(); + CRect GetMainRect() const; + CRect GetChildRect(CWnd* pChildWnd, const CRect& rcMain) const; + + bool m_bInResizing = false; + bool m_bEnabled = false; + std::unique_ptr m_pPane; + CMDIFrameWnd* m_pMDIFrameWnd = nullptr; + }; +} diff --git a/Externals/crystaledit/editlib/utils/mfc_templ_defines.h b/Externals/crystaledit/editlib/utils/mfc_templ_defines.h new file mode 100644 index 00000000000..3f7c1fa311f --- /dev/null +++ b/Externals/crystaledit/editlib/utils/mfc_templ_defines.h @@ -0,0 +1,150 @@ +// Usage is granted as specified in the following "Boost Software License - Version 1.0", but usage and / or distribution and / or selling as a or as part of a commercial Fortran to C / C++ translation - tool and / or translation - service is prohibited. +// +// +// Boost Software License - Version 1.0 - August 17th, 2003 +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license(the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third - parties to whom the Software is furnished to +// do so, all subject to the following : +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine - executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON - INFRINGEMENT.IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +/*============================================================================= +Copyright (c) 2019 Tobias Loew + +Distributed under the Boost Software License, Version 1.0. (See above or at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + + +#pragma once + +/////////////////////////////////////////////////////////////////////////////// +// +// mfc_templ_defines.h +// +// inline versions of MFC's message-map macros that work within template-class +// (but also work in non-template classes) +// usage: +// +// template<...> +// class derived : public base { +// +// public: +// using this_type = derived; +// using base_type = base; +// +// ... +// +// BEGIN_MESSAGE_MAP_INLINE(this_type, base_type) +// ON_WM_... +// END_MESSAGE_MAP_INLINE() +// }; +// +// // no DECLARE_MESSAGE_MAP... or IMPLEMENT_MESSAGE_MAP... needed! +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// definition for MESSAGE_MAP: + +// the original, non-template version +/********************************************** + +#define BEGIN_MESSAGE_MAP(theClass, baseClass) \ + PTM_WARNING_DISABLE \ + const AFX_MSGMAP* theClass::GetMessageMap() const \ + { return GetThisMessageMap(); } \ + const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \ + { \ + typedef theClass ThisClass; \ + typedef baseClass TheBaseClass; \ + static const AFX_MSGMAP_ENTRY _messageEntries[] = \ + { + +#define END_MESSAGE_MAP() \ + {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ + }; \ + static const AFX_MSGMAP messageMap = \ + { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \ + return &messageMap; \ + } \ + PTM_WARNING_RESTORE + +*************************************************/ + +#ifndef POINTER_CAST_WARNING_DISABLE + +#define POINTER_CAST_WARNING_DISABLE \ + __pragma(warning( push )) \ + __pragma(warning( disable : 4407 )) +#define POINTER_CAST_WARNING_RESTORE \ + __pragma(warning( pop )) + +#endif + + +#ifndef PTM_WARNING_DISABLE + +#define PTM_WARNING_DISABLE \ + __pragma(warning( push )) \ + __pragma(warning( disable : 4867 )) +#define PTM_WARNING_RESTORE \ + __pragma(warning( pop )) + +#endif + + +#define STATIC_ASSERT_CCMDTARGET_IS_FIRST_BASE(theClass) \ + static_assert(offsetof(theClass, CCmdTarget::m_dwRef) == offsetof(CCmdTarget, m_dwRef), "") + + +// class inline version +#define BEGIN_MESSAGE_MAP_INLINE(theClass, baseClass) \ + protected: \ + PTM_WARNING_DISABLE \ + POINTER_CAST_WARNING_DISABLE \ + virtual const AFX_MSGMAP* GetMessageMap() const \ + { return GetThisMessageMap(); } \ + static const AFX_MSGMAP* PASCAL GetThisMessageMap() \ + { \ + static_assert(offsetof(theClass, CCmdTarget::m_dwRef) == offsetof(CCmdTarget, m_dwRef), "");\ + typedef theClass ThisClass; \ + typedef baseClass TheBaseClass; \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4640)) /* message maps can only be called by single threaded message pump */ \ + static const AFX_MSGMAP_ENTRY _messageEntries[] = \ + { + + + +#define END_MESSAGE_MAP_INLINE() \ + {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ + }; \ + static const AFX_MSGMAP messageMap = \ + { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \ + return &messageMap; \ + } \ + POINTER_CAST_WARNING_RESTORE \ + PTM_WARNING_RESTORE + + +#define BEGIN_MESSAGE_MAP_INLINE_THIS_BASE() BEGIN_MESSAGE_MAP_INLINE(this_type, base_type) + + + diff --git a/Src/AboutDlg.cpp b/Src/AboutDlg.cpp index fc3fb169eb3..955ec5e5c18 100644 --- a/Src/AboutDlg.cpp +++ b/Src/AboutDlg.cpp @@ -59,8 +59,11 @@ class CAboutDlg::Impl : public CTrDialog afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx_msg void OnBnClickedWWW(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam); private: + void RecreateResources(); + CAboutDlg *const m_p; ATL::CImage m_image; CFont m_font; @@ -74,18 +77,13 @@ BEGIN_MESSAGE_MAP(CAboutDlg::Impl, CTrDialog) ON_WM_ERASEBKGND() ON_WM_CTLCOLOR() ON_NOTIFY(NM_CLICK, IDC_WWW, OnBnClickedWWW) + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) END_MESSAGE_MAP() CAboutDlg::Impl::Impl(CAboutDlg *p, CWnd* pParent /*= nullptr*/) : CTrDialog(CAboutDlg::Impl::IDD) , m_p(p) { - m_font.CreatePointFont(10 * 10, _T("Tahoma")); - LOGFONT lf = { 0 }; - lf.lfHeight = 14 * 10; - lf.lfWeight = FW_BOLD; - _tcscpy_s(lf.lfFaceName, _T("Courier New")); - m_font_gnu_ascii.CreatePointFontIndirect(&lf); } void CAboutDlg::Impl::DoDataExchange(CDataExchange* pDX) @@ -109,8 +107,8 @@ BOOL CAboutDlg::Impl::OnInitDialog() // FIXME: LoadImageFromResource() seems to fail when running on Wine 5.0. } - GetDlgItem(IDC_VERSION)->SetFont(&m_font); - GetDlgItem(IDC_GNU_ASCII)->SetFont(&m_font_gnu_ascii); + RecreateResources(); + ::SetDlgItemTextA(m_hWnd, IDC_GNU_ASCII, gnu_ascii); String link; @@ -168,6 +166,37 @@ void CAboutDlg::Impl::OnBnClickedWWW(NMHDR *pNMHDR, LRESULT *pResult) m_p->m_onclick_url.notify(m_p, tmp); } +LRESULT CAboutDlg::Impl::OnDpiChanged(WPARAM wParam, LPARAM lParam) +{ + CTrDialog::OnDpiChanged(wParam, lParam); + RecreateResources(); + Invalidate(); + return 0; +} + +void CAboutDlg::Impl::RecreateResources() +{ + if (!GetDlgItem(IDC_VERSION)) + return; + + const int dpi = GetDpi(); + + LOGFONT lfv{}; + DpiAware::GetPointLogFont(lfv, 10, _T("Tahoma"), dpi); + lfv.lfWeight = FW_NORMAL; + m_font.DeleteObject(); + m_font.CreateFontIndirect(&lfv); + + LOGFONT lf{}; + DpiAware::GetPointLogFont(lf, 14, _T("Courier New"), dpi); + lf.lfWeight = FW_BOLD; + m_font_gnu_ascii.DeleteObject(); + m_font_gnu_ascii.CreateFontIndirect(&lf); + + GetDlgItem(IDC_VERSION)->SetFont(&m_font); + GetDlgItem(IDC_GNU_ASCII)->SetFont(&m_font_gnu_ascii); +} + CAboutDlg::CAboutDlg() : m_pimpl(new CAboutDlg::Impl(this)) {} CAboutDlg::~CAboutDlg() = default; int CAboutDlg::DoModal() { return static_cast(m_pimpl->DoModal()); } diff --git a/Src/Common/BCMenu.cpp b/Src/Common/BCMenu.cpp index 7c5aaa5402c..6035431b54f 100644 --- a/Src/Common/BCMenu.cpp +++ b/Src/Common/BCMenu.cpp @@ -25,6 +25,7 @@ #include "stdafx.h" // Standard windows header file #include "BCMenu.h" // BCMenu class declaration +#include "utils/DpiAware.h" #include //SK: makes A2W and other spiffy AFX macros work #pragma comment(lib, "uxtheme.lib") @@ -168,34 +169,7 @@ BCMenu::BCMenu() m_bitmapBackgroundFlag=false; m_loadmenu=false; if (m_hTheme==nullptr && IsThemeActive()) - { - m_hTheme = OpenThemeData(nullptr, _T("MENU")); - if (m_hTheme != nullptr) - { - const int dpi = CClientDC(CWnd::GetDesktopWindow()).GetDeviceCaps(LOGPIXELSX); - auto resizeMargins = [dpi](MARGINS& margins) - { - margins.cxLeftWidth = MulDiv(margins.cxLeftWidth, dpi, 96); - margins.cxRightWidth = MulDiv(margins.cxRightWidth, dpi, 96); - margins.cyTopHeight = MulDiv(margins.cyTopHeight, dpi, 96); - margins.cyBottomHeight = MulDiv(margins.cyBottomHeight, dpi, 96); - }; - MARGINS marginCheckBg, marginArrow; - GetThemePartSize(m_hTheme, nullptr, MENU_POPUPCHECK, 0, nullptr, TS_TRUE, &m_sizeCheck); - GetThemeMargins(m_hTheme, nullptr, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, nullptr, &m_marginCheck); - GetThemePartSize(m_hTheme, nullptr, MENU_POPUPSEPARATOR, 0, nullptr, TS_TRUE, &m_sizeSeparator); - GetThemeMargins(m_hTheme, nullptr, MENU_POPUPSEPARATOR, 0, TMT_SIZINGMARGINS, nullptr, &m_marginSeparator); - GetThemeMargins(m_hTheme, nullptr, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, nullptr, &marginCheckBg); - GetThemeMargins(m_hTheme, nullptr, MENU_POPUPSUBMENU, 0, TMT_CONTENTMARGINS, nullptr, &marginArrow); - GetThemeInt(m_hTheme, MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &m_textBorder); - for (auto* pmargins : { &m_marginCheck, &m_marginSeparator, &marginCheckBg, &marginArrow }) - resizeMargins(*pmargins); - m_textBorder = MulDiv(m_textBorder, dpi, 96); - m_checkBgWidth = m_marginCheck.cxLeftWidth + m_sizeCheck.cx + m_marginCheck.cxRightWidth; - m_gutterWidth = marginCheckBg.cxLeftWidth + m_checkBgWidth + marginCheckBg.cxRightWidth; - m_arrowWidth = marginArrow.cxRightWidth; - } - } + ReopenTheme(DpiAware::GetDpiForWindow(AfxGetMainWnd()->m_hWnd)); } @@ -224,6 +198,39 @@ void BCMenuData::SetWideString(const wchar_t *szWideString) m_szMenuText=nullptr;//set to nullptr so we need not bother about dangling non-nullptr Ptrs } +bool BCMenu::ReopenTheme(int dpi) +{ + if (!IsThemeActive()) + return false; + if (m_hTheme != nullptr) + CloseThemeData(m_hTheme); + m_hTheme = DpiAware::OpenThemeDataForDpi(nullptr, _T("MENU"), dpi); + if (m_hTheme == nullptr) + return false; + auto resizeMargins = [dpi](MARGINS& margins) + { + margins.cxLeftWidth = MulDiv(margins.cxLeftWidth, dpi, 96); + margins.cxRightWidth = MulDiv(margins.cxRightWidth, dpi, 96); + margins.cyTopHeight = MulDiv(margins.cyTopHeight, dpi, 96); + margins.cyBottomHeight = MulDiv(margins.cyBottomHeight, dpi, 96); + }; + MARGINS marginCheckBg, marginArrow; + GetThemePartSize(m_hTheme, nullptr, MENU_POPUPCHECK, 0, nullptr, TS_TRUE, &m_sizeCheck); + GetThemeMargins(m_hTheme, nullptr, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, nullptr, &m_marginCheck); + GetThemePartSize(m_hTheme, nullptr, MENU_POPUPSEPARATOR, 0, nullptr, TS_TRUE, &m_sizeSeparator); + GetThemeMargins(m_hTheme, nullptr, MENU_POPUPSEPARATOR, 0, TMT_SIZINGMARGINS, nullptr, &m_marginSeparator); + GetThemeMargins(m_hTheme, nullptr, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, nullptr, &marginCheckBg); + GetThemeMargins(m_hTheme, nullptr, MENU_POPUPSUBMENU, 0, TMT_CONTENTMARGINS, nullptr, &marginArrow); + GetThemeInt(m_hTheme, MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &m_textBorder); + for (auto* pmargins : { &m_marginCheck, &m_marginSeparator, &marginCheckBg, &marginArrow }) + resizeMargins(*pmargins); + m_textBorder = MulDiv(m_textBorder, dpi, 96); + m_checkBgWidth = m_marginCheck.cxLeftWidth + m_sizeCheck.cx + m_marginCheck.cxRightWidth; + m_gutterWidth = marginCheckBg.cxLeftWidth + m_checkBgWidth + marginCheckBg.cxRightWidth; + m_arrowWidth = marginArrow.cxRightWidth; + return true; +} + bool BCMenu::IsMenu(HMENU submenu) { INT_PTR m; @@ -551,8 +558,9 @@ void BCMenu::DrawItem_Theme(LPDRAWITEMSTRUCT lpDIS) INT_PTR xoffset = mdata->global_offset; CString strText = mdata->GetString(); - int cxSMIcon = GetSystemMetrics(SM_CXSMICON); - int cySMIcon = GetSystemMetrics(SM_CYSMICON); + const int dpi = DpiAware::GetDpiForWindow(AfxGetMainWnd()->m_hWnd); + const int cxSMIcon = DpiAware::GetSystemMetricsForDpi(SM_CXSMICON, dpi); + const int cySMIcon = DpiAware::GetSystemMetricsForDpi(SM_CYSMICON, dpi); if(xoffset >= 0){ CImage bitmapstandard; @@ -719,10 +727,10 @@ void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS ) } else{ CFont fontMenu; - NONCLIENTMETRICS nm = { sizeof NONCLIENTMETRICS }; - VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, - nm.cbSize,&nm,0)); - fontMenu.CreateFontIndirect (&nm.lfMenuFont); + LOGFONT lfMenuFont{}; + const int dpi = DpiAware::GetDpiForWindow(AfxGetMainWnd()->m_hWnd); + DpiAware::GetNonClientLogFont(lfMenuFont, offsetof(NONCLIENTMETRICS, lfMenuFont), dpi); + fontMenu.CreateFontIndirect (&lfMenuFont); // Obtain the width of the text: CClientDC dc(AfxGetMainWnd() ? AfxGetMainWnd() : CWnd::GetDesktopWindow()); // Get device context @@ -748,11 +756,16 @@ void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS ) lpMIS->itemHeight = temp>m_iconY+BCMENU_PAD ? temp : m_iconY+BCMENU_PAD; if (m_hTheme == nullptr) { - lpMIS->itemWidth = m_iconX + BCMENU_PAD + 8 + t.cx; + lpMIS->itemWidth = MulDiv(m_iconX + BCMENU_PAD + 8, dpi, USER_DEFAULT_SCREEN_DPI) + t.cx; } else { lpMIS->itemWidth = m_gutterWidth+m_textBorder+t.cx+m_arrowWidth; + /* + int temp = DpiAware::GetSystemMetricsForDpi(SM_CYMENU, dpi); + int temp2 = MulDiv(m_iconY + BCMENU_PAD, dpi, USER_DEFAULT_SCREEN_DPI); + lpMIS->itemHeight = temp>temp2 ? temp : temp2; + */ unsigned menuHeight = static_cast( m_sizeCheck.cy + m_marginCheck.cyTopHeight + m_marginCheck.cyBottomHeight); if (menuHeight > lpMIS->itemHeight) diff --git a/Src/Common/BCMenu.h b/Src/Common/BCMenu.h index 3c9cb83587f..26ea4130d33 100644 --- a/Src/Common/BCMenu.h +++ b/Src/Common/BCMenu.h @@ -103,6 +103,7 @@ class BCMenu : public CMenu virtual void MeasureItem( LPMEASUREITEMSTRUCT ); // Measure an item // Static functions used for handling menu's in the mainframe + static bool ReopenTheme(int dpi); static void UpdateMenu(CMenu *pmenu); static bool IsMenu(CMenu *submenu) { diff --git a/Src/Common/CMoveConstraint.cpp b/Src/Common/CMoveConstraint.cpp index 6f078cbc611..3131cea706e 100644 --- a/Src/Common/CMoveConstraint.cpp +++ b/Src/Common/CMoveConstraint.cpp @@ -17,6 +17,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include "StdAfx.h" #include "CMoveConstraint.h" +#include "utils/DpiAware.h" #include // MFC template collection classes #include // needed for CFormView @@ -39,8 +40,9 @@ static RECT getGripRect(HWND hwnd) { RECT rc; GetClientRect(hwnd, &rc); - rc.left = rc.right - GetSystemMetrics(SM_CXVSCROLL); - rc.top = rc.bottom - GetSystemMetrics(SM_CYHSCROLL); + const int dpi = DpiAware::GetDpiForWindow(hwnd); + rc.left = rc.right - DpiAware::GetSystemMetricsForDpi(SM_CXVSCROLL, dpi); + rc.top = rc.bottom - DpiAware::GetSystemMetricsForDpi(SM_CYHSCROLL, dpi); return rc; } @@ -89,6 +91,7 @@ CMoveConstraint::InitializeCurrentSize(HWND hwndDlg) if (!IsWindow(hwndDlg)) return false; m_hwndDlg = hwndDlg; + m_dpi = DpiAware::GetDpiForWindow(hwndDlg); GrabCurrentDimensionsAsOriginal(hwndDlg); return true; @@ -101,6 +104,11 @@ CMoveConstraint::GrabCurrentDimensionsAsOriginal(HWND hwndDlg) GetClientRect(hwndDlg, m_rectDlgOriginal); CRect rect; GetWindowRect(hwndDlg, &rect); + LOGFONT lf; + CFont* pFont = CWnd::FromHandle(hwndDlg)->GetFont(); + pFont->GetLogFont(&lf); + m_fontFace = lf.lfFaceName; + m_fontSize = MulDiv(abs(lf.lfHeight), 72, m_dpi); // (min/max code) // remember original width & heighth in case a disallow function called @@ -132,6 +140,7 @@ CMoveConstraint::InitializeOriginalSize(HWND hwndDlg) { ASSERT(hwndDlg != nullptr && m_hwndDlg == nullptr); m_hwndDlg = hwndDlg; + m_dpi = DpiAware::GetDpiForWindow(hwndDlg); return m_nOrigX != 0; // if 0, we didn't get WM_SIZE so we don't know the original size } @@ -246,6 +255,7 @@ CMoveConstraint::ClearMostData() m_nMaxX=0; m_nMaxY=0; m_nDelayed=0; + m_dpi=0; // this specifically does NOT touch m_bSubclassed, as a subclass may still be in use m_pFormView=nullptr; m_nOrigScrollX=0; @@ -657,6 +667,41 @@ CMoveConstraint::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, L } else if (msg==WM_NOTIFY && TTN_NEEDTEXT==((NMHDR*)lParam)->code) { if (OnTtnNeedText((TOOLTIPTEXT*)lParam, plresult)) return true; + } else if (WM_DPICHANGED == msg) { + const int olddpi = m_dpi; + m_dpi = HIWORD(wParam); + const int oldnonclientsx = m_nOrigX - m_rectDlgOriginal.Width(); + const int oldnonclientsy = m_nOrigY - m_rectDlgOriginal.Height(); + CRect rc, rcClient; + GetWindowRect(m_hwndDlg, &rc); + GetClientRect(m_hwndDlg, &rcClient); + const int newnonclientsx = rc.Width() - rcClient.Width(); + const int newnonclientsy = rc.Height() - rcClient.Height(); + const RECT* pRect = reinterpret_cast(lParam); + CSize sizeOld = { m_rectDlgOriginal.right, m_rectDlgOriginal.bottom }; + CSize sizeNew = DpiAware::Dialog_CalcUpdatedSize(m_fontFace.c_str(), m_fontSize, sizeOld, olddpi, m_dpi); + m_rectDlgOriginal.right = sizeNew.cx; + m_rectDlgOriginal.bottom = sizeNew.cx; + for (auto& pval : { &m_nMaxX, &m_nMinX, &m_nOrigX }) + { + if (*pval) + *pval = MulDiv(*pval - oldnonclientsx, sizeNew.cx, sizeOld.cx) + newnonclientsx; + } + for (auto& pval : { &m_nMaxY, &m_nMinY, &m_nOrigY }) + { + if (*pval) + *pval = MulDiv(*pval - oldnonclientsy, sizeNew.cy, sizeOld.cy) + newnonclientsy; + } + ConstraintList & constraintList = m_ConstraintList; + for (auto& constraint : constraintList) + { + for (auto& pval : + { &constraint.m_rectChildOriginal.left, &constraint.m_rectChildOriginal.right }) + *pval = MulDiv(*pval, sizeNew.cx, sizeOld.cx); + for (auto& pval : + { &constraint.m_rectChildOriginal.top, &constraint.m_rectChildOriginal.bottom }) + *pval = MulDiv(*pval, sizeNew.cy, sizeOld.cy); + } } return false; diff --git a/Src/Common/CMoveConstraint.h b/Src/Common/CMoveConstraint.h index 1d2b4369b9a..e08719ce1fc 100644 --- a/Src/Common/CMoveConstraint.h +++ b/Src/Common/CMoveConstraint.h @@ -213,6 +213,8 @@ class CMoveConstraint private: HWND m_hwndDlg; // parent of controls - could be FormView or PropertyPage or whatever as well CRect m_rectDlgOriginal; + String m_fontFace; + double m_fontSize; int m_nOrigX; int m_nOrigY; EGRIP m_nGrip; @@ -222,6 +224,7 @@ class CMoveConstraint int m_nMaxX; int m_nMaxY; int m_nDelayed; // CWnds without HWND + int m_dpi; bool m_bSubclassed; WNDPROC m_oldWndProc; // formview stuff diff --git a/Src/Common/LanguageSelect.cpp b/Src/Common/LanguageSelect.cpp index a4c47ab2d61..788dc08d74c 100644 --- a/Src/Common/LanguageSelect.cpp +++ b/Src/Common/LanguageSelect.cpp @@ -751,7 +751,12 @@ void CLanguageSelect::SetIndicators(CStatusBar &sb, const UINT *rgid, int n) con sb.SetIndicators(0, n); else n = sb.m_nCount; - int cx = ::GetSystemMetrics(SM_CXSCREEN) / 4; // default to 1/4 the screen width + + HMONITOR monitor = MonitorFromWindow(sb.m_hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO info{ sizeof MONITORINFO }; + GetMonitorInfo(monitor, &info); + + int cx = (info.rcMonitor.right - info.rcMonitor.left) / 4; // default to 1/4 the screen width UINT style = SBPS_STRETCH | SBPS_NOBORDERS; // first pane is stretchy for (int i = 0 ; i < n ; ++i) { diff --git a/Src/Common/MDITabBar.cpp b/Src/Common/MDITabBar.cpp index 4275d409817..a8443329cad 100644 --- a/Src/Common/MDITabBar.cpp +++ b/Src/Common/MDITabBar.cpp @@ -30,14 +30,10 @@ BEGIN_MESSAGE_MAP(CMDITabBar, CControlBar) ON_WM_MOUSELEAVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) //}}AFX_MSG_MAP END_MESSAGE_MAP() -static int determineIconSize() -{ - return GetSystemMetrics(SM_CXSMICON); -} - /** * @brief Create tab bar. * @param pParentWnd [in] main frame window pointer @@ -50,12 +46,7 @@ BOOL CMDITabBar::Create(CMDIFrameWnd* pMainFrame) if (!CWnd::Create(WC_TABCONTROL, nullptr, WS_CHILD | WS_VISIBLE | TCS_OWNERDRAWFIXED, CRect(0, 0, 0, 0), pMainFrame, AFX_IDW_CONTROLBAR_FIRST+30)) return FALSE; - TabCtrl_SetPadding(m_hWnd, determineIconSize(), 4); - - NONCLIENTMETRICS ncm = { sizeof NONCLIENTMETRICS }; - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof NONCLIENTMETRICS, &ncm, 0); - m_font.CreateFontIndirect(&ncm.lfMenuFont); - SetFont(&m_font); + OnDpiChangedBeforeParent(0, 0); m_tooltips.Create(m_pMainFrame, TTS_NOPREFIX); m_tooltips.AddTool(this, _T("")); @@ -346,6 +337,22 @@ void CMDITabBar::UpdateTabs() m_nTooltipTabItemIndex = -1; } +LRESULT CMDITabBar::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + __super::OnDpiChangedBeforeParent(wParam, lParam); + + m_cxSMIcon = GetSystemMetrics(SM_CXSMICON); + + TabCtrl_SetPadding(m_hWnd, m_cxSMIcon, 4); + + LOGFONT lfMenuFont{}; + DpiAware::GetNonClientLogFont(lfMenuFont, offsetof(NONCLIENTMETRICS, lfMenuFont), m_dpi); + m_font.DeleteObject(); + m_font.CreateFontIndirect(&lfMenuFont); + SetFont(&m_font); + return 0; +} + /** * @brief Called when middle mouse button is pressed. * This function closes the tab when the middle mouse button is pressed. @@ -396,7 +403,7 @@ void CMDITabBar::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) rc.top += 3; SetTextColor(lpDraw->hDC, GetSysColor(COLOR_BTNTEXT)); } - CSize iconsize(determineIconSize(), determineIconSize()); + CSize iconsize(m_cxSMIcon, m_cxSMIcon); rc.left += iconsize.cx; SetBkMode(lpDraw->hDC, TRANSPARENT); HWND hwndFrame = reinterpret_cast(item.lParam); @@ -507,7 +514,7 @@ void CMDITabBar::OnLButtonUp(UINT nFlags, CPoint point) CRect CMDITabBar::GetCloseButtonRect(int nItem) const { CRect rc; - CSize size(determineIconSize(), determineIconSize()); + CSize size(m_cxSMIcon, m_cxSMIcon); GetItemRect(nItem, &rc); rc.left = rc.right - size.cx - 4; rc.right = rc.left + size.cx; diff --git a/Src/Common/MDITabBar.h b/Src/Common/MDITabBar.h index a0fead897c5..61906ba116c 100644 --- a/Src/Common/MDITabBar.h +++ b/Src/Common/MDITabBar.h @@ -6,10 +6,12 @@ */ #pragma once +#include "utils/DpiAware.h" + /** * @brief Class for Tab bar. */ -class CMDITabBar : public CControlBar +class CMDITabBar : public DpiAware::CDpiAwareWnd { DECLARE_DYNAMIC(CMDITabBar) @@ -26,9 +28,10 @@ class CMDITabBar : public CControlBar CFont m_font; CToolTipCtrl m_tooltips; /**< Tooltip for the tab */ int m_nTooltipTabItemIndex; /**< Index of the tab displaying tooltip */ + int m_cxSMIcon; public: - CMDITabBar() : m_bInSelchange(false), m_pMainFrame(nullptr), m_bMouseTracking(false), m_bCloseButtonDown(false), m_bAutoMaxWidth(true), m_nDraggingTabItemIndex(-1), m_nTooltipTabItemIndex(-1){} + CMDITabBar() : m_bInSelchange(false), m_pMainFrame(nullptr), m_bMouseTracking(false), m_bCloseButtonDown(false), m_bAutoMaxWidth(true), m_nDraggingTabItemIndex(-1), m_nTooltipTabItemIndex(-1), m_cxSMIcon(0) {} virtual ~CMDITabBar() {} BOOL Create(CMDIFrameWnd* pParentWnd); void UpdateTabs(); @@ -71,10 +74,12 @@ class CMDITabBar : public CControlBar afx_msg void OnMouseLeave(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM, LPARAM); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: + int determineIconSize() const; CRect GetCloseButtonRect(int nItem) const; int GetItemIndexFromPoint(CPoint pt) const; void SwapTabs(int nIndexA, int nIndexB); diff --git a/Src/Common/MessageBoxDialog.cpp b/Src/Common/MessageBoxDialog.cpp index 34a7a2882b3..d0c35c7f539 100644 --- a/Src/Common/MessageBoxDialog.cpp +++ b/Src/Common/MessageBoxDialog.cpp @@ -85,7 +85,7 @@ IMPLEMENT_DYNAMIC(CMessageBoxDialog, CDialog) */ CMessageBoxDialog::CMessageBoxDialog ( CWnd* pParent, CString strMessage, CString strTitle, UINT nStyle, UINT nHelp, const CString& strRegistryKey ) - : CDialog ( CMessageBoxDialog::IDD, pParent ) + : DpiAware::CDpiAwareWnd ( CMessageBoxDialog::IDD, pParent ) , m_strMessage(strMessage) , m_strTitle(strTitle.IsEmpty() ? AfxGetAppName() : strTitle) , m_nStyle(nStyle) @@ -108,23 +108,8 @@ IMPLEMENT_DYNAMIC(CMessageBoxDialog, CDialog) m_aButtons.clear(); - NONCLIENTMETRICS ncm = { sizeof NONCLIENTMETRICS }; - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof NONCLIENTMETRICS, &ncm, 0); - m_font.CreateFontIndirect(&ncm.lfMessageFont); - - LOGFONT lf = { 0 }; - HTHEME hTheme = OpenThemeData(nullptr, _T("TEXTSTYLE")); - if (hTheme != nullptr && SUCCEEDED(GetThemeFont(hTheme, nullptr, TEXT_MAININSTRUCTION, 0, TMT_FONT, &lf))) - { - m_fontMainInstruction.CreateFontIndirect(&lf); - GetThemeColor(hTheme, TEXT_MAININSTRUCTION, 0, TMT_TEXTCOLOR, &m_clrMainInstructionFont); - CloseThemeData(hTheme); - } - else - { - m_fontMainInstruction.CreateFontIndirect(&ncm.lfMessageFont); - m_clrMainInstructionFont = GetSysColor(COLOR_WINDOWTEXT); - } + const int dpi = DpiAware::GetDpiForWindow((pParent ? pParent : AfxGetMainWnd())->m_hWnd); + UpdateResources(dpi); } /* @@ -820,6 +805,22 @@ HBRUSH CMessageBoxDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) return __super::OnCtlColor(pDC, pWnd, nCtlColor); } +LRESULT CMessageBoxDialog::OnDpiChanged(WPARAM wParam, LPARAM lParam) +{ + __super::OnDpiChanged(wParam, lParam); + UpdateResources(m_dpi); + Default(); + if (!GetDlgItem(IDCHECKBOX)) + return 0; + for (vector::iterator iter = m_aButtons.begin(); iter != m_aButtons.end(); ++iter) + GetDlgItem(iter->nID)->SetFont(&m_font); + GetDlgItem(IDCHECKBOX)->SetFont(&m_font); + m_stcMessage.SetFont(&m_fontMainInstruction); + Invalidate(); + m_sDialogUnit = {}; + return 0; +} + ////////////////////////////////////////////////////////////////////////////// // Other dialog handling methods. @@ -854,10 +855,11 @@ BOOL CMessageBoxDialog::OnWndMsg ( UINT message, WPARAM wParam, LPARAM lParam, return __super::OnWndMsg(message, wParam, lParam, pResult); } -BEGIN_MESSAGE_MAP(CMessageBoxDialog, CDialog) +BEGIN_MESSAGE_MAP(CMessageBoxDialog, DpiAware::CDpiAwareWnd) ON_WM_TIMER() ON_WM_ERASEBKGND() ON_WM_CTLCOLOR() + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) END_MESSAGE_MAP() ////////////////////////////////////////////////////////////////////////////// @@ -1183,38 +1185,45 @@ void CMessageBoxDialog::ParseStyle ( ) if ( ( m_nStyle & MB_ICONMASK ) && ( m_hIcon == nullptr ) ) { // Switch the icon. + LPTSTR icon = nullptr; switch ( m_nStyle & MB_ICONMASK ) { case MB_ICONEXCLAMATION: // Load the icon with the exclamation mark. - m_hIcon = AfxGetApp()->LoadStandardIcon(IDI_EXCLAMATION); + icon = IDI_EXCLAMATION; break; case MB_ICONHAND: // Load the icon with the error symbol. - m_hIcon = AfxGetApp()->LoadStandardIcon(IDI_HAND); + icon = IDI_HAND; break; case MB_ICONQUESTION: // Load the icon with the question mark. - m_hIcon = AfxGetApp()->LoadStandardIcon(IDI_QUESTION); + icon = IDI_QUESTION; break; case MB_ICONASTERISK: // Load the icon with the information symbol. - m_hIcon = AfxGetApp()->LoadStandardIcon(IDI_ASTERISK); + icon = IDI_ASTERISK; break; } + if (icon) + { + const int cx = GetSystemMetrics(SM_CXICON); + const int cy = GetSystemMetrics(SM_CYICON); + DpiAware::LoadIconWithScaleDown(nullptr, icon, cx, cy, &m_hIcon); + } } } @@ -1277,8 +1286,12 @@ void CMessageBoxDialog::CreateMessageControl ( ) // Select the new font and store the old one. CFont* pOldFont = dcDisplay.SelectObject(&m_fontMainInstruction); + HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO info{ sizeof MONITORINFO }; + GetMonitorInfo(monitor, &info); + // Define the maximum width of the message. - int nMaxWidth = ( GetSystemMetrics(SM_CXSCREEN) / 2 ) + 100; + int nMaxWidth = ( info.rcMonitor.right / 2 ) + 100; // Check whether an icon is displayed. if ( m_hIcon != nullptr ) @@ -1604,3 +1617,26 @@ void CMessageBoxDialog::DefineLayout ( ) // Center the window. CenterWindow(); } + +void CMessageBoxDialog::UpdateResources(int dpi) +{ + LOGFONT lfMessageFont; + DpiAware::GetNonClientLogFont(lfMessageFont, offsetof(NONCLIENTMETRICS, lfMessageFont), dpi); + m_font.DeleteObject(); + m_font.CreateFontIndirect(&lfMessageFont); + + m_fontMainInstruction.DeleteObject(); + LOGFONT lf = { 0 }; + HTHEME hTheme = DpiAware::OpenThemeDataForDpi(nullptr, _T("TEXTSTYLE"), dpi); + if (hTheme != nullptr && SUCCEEDED(GetThemeFont(hTheme, nullptr, TEXT_MAININSTRUCTION, 0, TMT_FONT, &lf))) + { + m_fontMainInstruction.CreateFontIndirect(&lf); + GetThemeColor(hTheme, TEXT_MAININSTRUCTION, 0, TMT_TEXTCOLOR, &m_clrMainInstructionFont); + CloseThemeData(hTheme); + } + else + { + m_fontMainInstruction.CreateFontIndirect(&lfMessageFont); + m_clrMainInstructionFont = GetSysColor(COLOR_WINDOWTEXT); + } +} diff --git a/Src/Common/MessageBoxDialog.h b/Src/Common/MessageBoxDialog.h index d98a1278c7d..8f387c636cc 100644 --- a/Src/Common/MessageBoxDialog.h +++ b/Src/Common/MessageBoxDialog.h @@ -32,6 +32,7 @@ #include "resource.h" #include "UnicodeString.h" +#include "utils/DpiAware.h" #include ////////////////////////////////////////////////////////////////////////////// @@ -85,7 +86,7 @@ ////////////////////////////////////////////////////////////////////////////// // Class definition. -class CMessageBoxDialog : public CDialog +class CMessageBoxDialog : public DpiAware::CDpiAwareWnd { DECLARE_DYNAMIC(CMessageBoxDialog) @@ -188,6 +189,7 @@ class CMessageBoxDialog : public CDialog afx_msg void OnTimer ( UINT_PTR nIDEvent ); afx_msg BOOL OnEraseBkgnd( CDC* pDC ); afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor ); + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam); protected: @@ -289,4 +291,6 @@ class CMessageBoxDialog : public CDialog // Method for defining the layout of the dialog. void DefineLayout ( ); + void UpdateResources (int dpi); + }; diff --git a/Src/Common/PreferencesDlg.cpp b/Src/Common/PreferencesDlg.cpp index b75c4e63ef9..68c0f548af7 100644 --- a/Src/Common/PreferencesDlg.cpp +++ b/Src/Common/PreferencesDlg.cpp @@ -91,7 +91,7 @@ END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPreferencesDlg message handlers -BOOL CPreferencesDlg::OnInitDialog() +BOOL CPreferencesDlg::OnInitDialog() { CTrDialog::OnInitDialog(); @@ -161,7 +161,8 @@ void CPreferencesDlg::OnSize(UINT nType, int cx, int cy) CRect rPPHost; pPPHostWnd->GetWindowRect(rPPHost); ScreenToClient(rPPHost); - m_pphost.MoveWindow(&rPPHost); + if (m_pphost.m_hWnd) + m_pphost.MoveWindow(&rPPHost); } } diff --git a/Src/Common/SuperComboBox.cpp b/Src/Common/SuperComboBox.cpp index 8ce33f06b18..6dd88d7095e 100644 --- a/Src/Common/SuperComboBox.cpp +++ b/Src/Common/SuperComboBox.cpp @@ -23,7 +23,7 @@ T &placement_cast(void *p) ///////////////////////////////////////////////////////////////////////////// // CSuperComboBox -HIMAGELIST CSuperComboBox::m_himlSystem = nullptr; +std::map CSuperComboBox::m_himlSystemMap; CSuperComboBox::CSuperComboBox() : m_pDropHandler(nullptr) @@ -66,6 +66,7 @@ BEGIN_MESSAGE_MAP(CSuperComboBox, CComboBoxEx) ON_WM_DESTROY() ON_WM_DRAWITEM() ON_NOTIFY_REFLECT(CBEN_GETDISPINFO, OnGetDispInfo) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) //}}AFX_MSG_MAP END_MESSAGE_MAP() @@ -74,6 +75,7 @@ END_MESSAGE_MAP() void CSuperComboBox::PreSubclassWindow() { + UpdateDpi(); __super::PreSubclassWindow(); m_pDropHandler = new DropHandler(std::bind(&CSuperComboBox::OnDropFiles, this, std::placeholders::_1)); RegisterDragDrop(m_hWnd, m_pDropHandler); @@ -199,16 +201,18 @@ int CSuperComboBox::FindString(int nStartAfter, LPCTSTR lpszString) const */ bool CSuperComboBox::AttachSystemImageList() { + HIMAGELIST hImageList = nullptr; ASSERT(m_bComboBoxEx); - if (m_himlSystem==nullptr) + if (m_himlSystemMap.find(m_dpi) == m_himlSystemMap.end()) { - SHFILEINFO sfi = {0}; - m_himlSystem = (HIMAGELIST)SHGetFileInfo(_T(""), 0, - &sfi, sizeof(sfi), SHGFI_SMALLICON | SHGFI_SYSICONINDEX); - if (m_himlSystem==nullptr) + hImageList = DpiAware::LoadShellImageList(m_dpi); + if (hImageList == nullptr) return false; + m_himlSystemMap.emplace(m_dpi, hImageList); } - SetImageList(CImageList::FromHandle(m_himlSystem)); + else + hImageList = m_himlSystemMap[m_dpi]; + SetImageList(CImageList::FromHandle(hImageList)); m_bHasImageList = true; return true; } @@ -573,7 +577,7 @@ void CSuperComboBox::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) if (!pEdit->GetModify() || GetFocus() != pEdit) GetWindowText(sText); int iIcon = GetFileTypeIconIndex(pvText); - ImageList_DrawEx(m_himlSystem, iIcon, lpDrawItemStruct->hDC, + ImageList_DrawEx(m_himlSystemMap[m_dpi], iIcon, lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top, 0, 0, GetSysColor(COLOR_WINDOW), CLR_NONE, ILD_NORMAL); return; @@ -598,3 +602,20 @@ void CSuperComboBox::OnGetDispInfo(NMHDR *pNotifyStruct, LRESULT *pResult) } *pResult = 0; } + +LRESULT CSuperComboBox::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + __super::OnDpiChangedBeforeParent(wParam, lParam); + if (m_bHasImageList) + { + if (m_himlSystemMap.find(m_dpi) == m_himlSystemMap.end()) + { + HIMAGELIST hImageList = DpiAware::LoadShellImageList(m_dpi); + if (!hImageList) + return 0; + m_himlSystemMap.emplace(m_dpi, hImageList); + } + SetImageList(CImageList::FromHandle(m_himlSystemMap[m_dpi])); + } + return 0; +} diff --git a/Src/Common/SuperComboBox.h b/Src/Common/SuperComboBox.h index ddec4f3ff0c..15c48f5f51e 100644 --- a/Src/Common/SuperComboBox.h +++ b/Src/Common/SuperComboBox.h @@ -5,13 +5,14 @@ #include #include "UnicodeString.h" +#include "utils/DpiAware.h" class DropHandler; ///////////////////////////////////////////////////////////////////////////// // CSuperComboBox window -class CSuperComboBox : public CComboBoxEx +class CSuperComboBox : public DpiAware::CDpiAwareWnd { // Construction public: @@ -31,7 +32,7 @@ class CSuperComboBox : public CComboBoxEx bool m_bCanBeEmpty; bool m_bMustUninitOLE; - static HIMAGELIST m_himlSystem; + static std::map m_himlSystemMap; DropHandler *m_pDropHandler; @@ -85,6 +86,7 @@ class CSuperComboBox : public CComboBoxEx afx_msg void OnGetDispInfo(NMHDR *pNotifyStruct, LRESULT *pResult); afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); afx_msg void OnDestroy(); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Src/Common/scbarcf.cpp b/Src/Common/scbarcf.cpp index 0f157838131..a8f8d89d1b5 100644 --- a/Src/Common/scbarcf.cpp +++ b/Src/Common/scbarcf.cpp @@ -94,22 +94,20 @@ void CSizingControlBarCF::NcPaintGripper(CDC* pDC, const CRect& rcClient) // compute the caption rectangle bool bHorz = IsHorzDocked(); CRect rcGrip = rcClient; - const int lpx = pDC->GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](double point) { return static_cast(point * lpx / 72); }; - CRect rcBtn(m_biHide.ptOrg, CSize(pointToPixel(m_biHide.dblBoxSize), pointToPixel(m_biHide.dblBoxSize))); + CRect rcBtn(m_biHide.ptOrg, CSize(PointToPixel(m_biHide.dblBoxSize), PointToPixel(m_biHide.dblBoxSize))); if (bHorz) { // right side gripper - rcGrip.left -= pointToPixel(m_dblGripper + 0.75); - rcGrip.right = rcGrip.left + pointToPixel(8.25); - rcGrip.top = rcBtn.bottom + pointToPixel(2.25); + rcGrip.left -= PointToPixel(m_dblGripper + 0.75); + rcGrip.right = rcGrip.left + PointToPixel(8.25); + rcGrip.top = rcBtn.bottom + PointToPixel(2.25); } else { // gripper at top - rcGrip.top -= pointToPixel(m_dblGripper + 0.75); - rcGrip.bottom = rcGrip.top + pointToPixel(8.25); - rcGrip.right = rcBtn.left - pointToPixel(2.25); + rcGrip.top -= PointToPixel(m_dblGripper + 0.75); + rcGrip.bottom = rcGrip.top + PointToPixel(8.25); + rcGrip.right = rcBtn.left - PointToPixel(2.25); } - rcGrip.InflateRect(bHorz ? pointToPixel(0.75) : 0, bHorz ? 0 : pointToPixel(0.75)); + rcGrip.InflateRect(bHorz ? PointToPixel(0.75) : 0, bHorz ? 0 : PointToPixel(0.75)); // draw the caption background //CBrush br; @@ -173,7 +171,8 @@ void CSizingControlBarCF::NcPaintGripper(CDC* pDC, const CRect& rcClient) // draw the caption text - first select a font CFont font; LOGFONT lf; - bool bFont = !!font.CreatePointFont(85/*8.5 points*/, m_sFontFace); + DpiAware::GetPointLogFont(lf, 8.5, m_sFontFace, GetDpi()); + bool bFont = !!font.CreateFontIndirect(&lf); if (bFont) { // get the text color @@ -198,8 +197,8 @@ void CSizingControlBarCF::NcPaintGripper(CDC* pDC, const CRect& rcClient) GetWindowText(sTitle); CPoint ptOrg = bHorz ? - CPoint(rcGrip.left - pointToPixel(0.75), rcGrip.bottom - pointToPixel(2.25)) : - CPoint(rcGrip.left + pointToPixel(2.25), rcGrip.top - pointToPixel(0.75)); + CPoint(rcGrip.left - PointToPixel(0.75), rcGrip.bottom - PointToPixel(2.25)) : + CPoint(rcGrip.left + PointToPixel(2.25), rcGrip.top - PointToPixel(0.75)); pDC->ExtTextOut(ptOrg.x, ptOrg.y, ETO_CLIPPED, rcGrip, sTitle, nullptr); diff --git a/Src/Common/scbarcf.h b/Src/Common/scbarcf.h index 587699bac38..167738df8ac 100644 --- a/Src/Common/scbarcf.h +++ b/Src/Common/scbarcf.h @@ -32,6 +32,8 @@ ///////////////////////////////////////////////////////////////////////// // CSizingControlBarCF +#include "utils/DpiAware.h" + #ifndef baseCSizingControlBarCF #define baseCSizingControlBarCF CSizingControlBarG #endif diff --git a/Src/Common/scbarg.cpp b/Src/Common/scbarg.cpp index 0713431d169..f851fa80c9e 100644 --- a/Src/Common/scbarg.cpp +++ b/Src/Common/scbarg.cpp @@ -85,20 +85,17 @@ void CSizingControlBarG::NcCalcClient(LPRECT pRc, UINT nDockBarID) bool bHorz = (nDockBarID == AFX_IDW_DOCKBAR_TOP) || (nDockBarID == AFX_IDW_DOCKBAR_BOTTOM); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](double point) { return static_cast(point * lpx / 72); }; - if (bHorz) - rc.DeflateRect(pointToPixel(m_dblGripper), 0, 0, 0); + rc.DeflateRect(PointToPixel(m_dblGripper), 0, 0, 0); else - rc.DeflateRect(0, pointToPixel(m_dblGripper), 0, 0); + rc.DeflateRect(0, PointToPixel(m_dblGripper), 0, 0); // set position for the "x" (hide bar) button CPoint ptOrgBtn; if (bHorz) - ptOrgBtn = CPoint(rc.left - pointToPixel(9.75), rc.top); + ptOrgBtn = CPoint(rc.left - PointToPixel(9.75), rc.top); else - ptOrgBtn = CPoint(rc.right - pointToPixel(9.0), rc.top - pointToPixel(9.75)); + ptOrgBtn = CPoint(rc.right - PointToPixel(9.0), rc.top - PointToPixel(9.75)); m_biHide.Move(ptOrgBtn - rcBar.TopLeft()); @@ -112,30 +109,29 @@ void CSizingControlBarG::NcPaintGripper(CDC* pDC, const CRect& rcClient) // paints a simple "two raised lines" gripper // override this if you want a more sophisticated gripper - const int lpx = pDC->GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](double point) { return static_cast(point * lpx / 72); }; + auto PointToPixel = [dpi = GetDpi()](double point) { return static_cast(point * dpi / 72); }; CRect gripper = rcClient; - CRect rcbtn(m_biHide.ptOrg, CSize(pointToPixel(m_biHide.dblBoxSize), pointToPixel(m_biHide.dblBoxSize))); + CRect rcbtn(m_biHide.ptOrg, CSize(PointToPixel(m_biHide.dblBoxSize), PointToPixel(m_biHide.dblBoxSize))); bool bHorz = IsHorzDocked(); gripper.DeflateRect(1, 1); if (bHorz) { // gripper at left - gripper.left -= pointToPixel(m_dblGripper); - gripper.right = gripper.left + pointToPixel(2.25); - gripper.top = rcbtn.bottom + pointToPixel(2.25); + gripper.left -= PointToPixel(m_dblGripper); + gripper.right = gripper.left + PointToPixel(2.25); + gripper.top = rcbtn.bottom + PointToPixel(2.25); } else { // gripper at top - gripper.top -= pointToPixel(m_dblGripper); - gripper.bottom = gripper.top + pointToPixel(2.25); - gripper.right = rcbtn.left - pointToPixel(2.25); + gripper.top -= PointToPixel(m_dblGripper); + gripper.bottom = gripper.top + PointToPixel(2.25); + gripper.right = rcbtn.left - PointToPixel(2.25); } pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT), ::GetSysColor(COLOR_BTNSHADOW)); - gripper.OffsetRect(bHorz ? pointToPixel(2.25) : 0, bHorz ? 0 : pointToPixel(2.25)); + gripper.OffsetRect(bHorz ? PointToPixel(2.25) : 0, bHorz ? 0 : PointToPixel(2.25)); pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT), ::GetSysColor(COLOR_BTNSHADOW)); @@ -152,9 +148,8 @@ LRESULT CSizingControlBarG::OnNcHitTest(CPoint point) if (nRet != HTCLIENT) return nRet; - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](double point) { return static_cast(point * lpx / 72); }; - CRect rc(m_biHide.ptOrg, CSize(pointToPixel(m_biHide.dblBoxSize), pointToPixel(m_biHide.dblBoxSize))); + auto PointToPixel = [dpi = GetDpi()](double point) { return static_cast(point * dpi / 72); }; + CRect rc(m_biHide.ptOrg, CSize(PointToPixel(m_biHide.dblBoxSize), PointToPixel(m_biHide.dblBoxSize))); rc.OffsetRect(rcBar.TopLeft()); if (rc.PtInRect(point)) return HTCLOSE; @@ -205,9 +200,9 @@ CSCBButton::CSCBButton() void CSCBButton::Paint(CDC* pDC) { - const int lpx = pDC->GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](double point) { return static_cast(point * lpx / 72); }; - CRect rc(ptOrg, CSize(pointToPixel(dblBoxSize), pointToPixel(dblBoxSize))); + const int dpi = DpiAware::GetDpiForWindow(AfxGetMainWnd()->m_hWnd); + auto PointToPixel = [dpi](double point) { return static_cast(point * dpi / 72); }; + CRect rc(ptOrg, CSize(PointToPixel(dblBoxSize), PointToPixel(dblBoxSize))); if (bPushed) pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNSHADOW), @@ -221,10 +216,12 @@ void CSCBButton::Paint(CDC* pDC) pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); int nPrevBkMode = pDC->SetBkMode(TRANSPARENT); CFont font; - font.CreatePointFont(60/*6 points*/, _T("Marlett")); + LOGFONT lf; + DpiAware::GetPointLogFont(lf, 6, _T("Marlett"), dpi); + font.CreateFontIndirect(&lf); CFont* oldfont = pDC->SelectObject(&font); - pDC->TextOut(ptOrg.x + pointToPixel(1.5), ptOrg.y + pointToPixel(1.5), CString(_T("r"))); // x-like + pDC->TextOut(ptOrg.x + PointToPixel(1.5), ptOrg.y + PointToPixel(1.5), CString(_T("r"))); // x-like pDC->SelectObject(oldfont); pDC->SetBkMode(nPrevBkMode); diff --git a/Src/Common/sizecbar.cpp b/Src/Common/sizecbar.cpp index e620311cce7..06ebd7f9257 100644 --- a/Src/Common/sizecbar.cpp +++ b/Src/Common/sizecbar.cpp @@ -75,7 +75,7 @@ CSizingControlBar::~CSizingControlBar() { } -BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar) +BEGIN_MESSAGE_MAP(CSizingControlBar, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CSizingControlBar) ON_WM_CREATE() ON_WM_PAINT() @@ -96,6 +96,7 @@ BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar) ON_WM_SIZE() //}}AFX_MSG_MAP ON_MESSAGE(WM_SETTEXT, OnSetText) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) END_MESSAGE_MAP() BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, @@ -1097,7 +1098,7 @@ void CSizingControlBar::LoadState(LPCTSTR lpszProfileName) // found this bar - offset origin and save settings pInfo->m_pointPos.x++; pInfo->m_pointPos.y += - ::GetSystemMetrics(SM_CYSMCAPTION) + 1; + GetSystemMetrics(SM_CYSMCAPTION) + 1; pInfo->SaveState(lpszProfileName, i); } } @@ -1176,6 +1177,23 @@ void CSizingControlBar::GlobalSaveState(CFrameWnd* pFrame, } } +LRESULT CSizingControlBar::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + int olddpi = m_dpi; + + __super::OnDpiChangedBeforeParent(wParam, lParam); + + for (auto& size : { &m_szHorz, &m_szVert, &m_szFloat }) + { + size->cx = MulDiv(size->cx, m_dpi, olddpi); + size->cy = MulDiv(size->cy, m_dpi, olddpi); + } + + m_pDockSite->DelayRecalcLayout(); + + return 0; +} + #ifdef _SCB_REPLACE_MINIFRAME #ifndef _SCB_MINIFRAME_CAPTION ///////////////////////////////////////////////////////////////////////////// diff --git a/Src/Common/sizecbar.h b/Src/Common/sizecbar.h index 917f648b2dd..9b9eddbb2a2 100644 --- a/Src/Common/sizecbar.h +++ b/Src/Common/sizecbar.h @@ -29,6 +29,7 @@ #include // for CDockContext #include // for CTypedPtrArray +#include "utils/DpiAware.h" #if defined(_SCB_MINIFRAME_CAPTION) && !defined(_SCB_REPLACE_MINIFRAME) #error "_SCB_MINIFRAME_CAPTION requires _SCB_REPLACE_MINIFRAME" @@ -63,7 +64,7 @@ class CSCBDockBar : public CDockBar class CSizingControlBar; typedef CTypedPtrArray CSCBArray; -class CSizingControlBar : public baseCSizingControlBar +class CSizingControlBar : public DpiAware::CDpiAwareWnd { DECLARE_DYNAMIC(CSizingControlBar); @@ -169,6 +170,7 @@ class CSizingControlBar : public baseCSizingControlBar afx_msg void OnSize(UINT nType, int cx, int cy); //}}AFX_MSG afx_msg LRESULT OnSetText(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() diff --git a/Src/CompareStatisticsDlg.cpp b/Src/CompareStatisticsDlg.cpp index 1671c5c1b6b..64d3d8c868c 100644 --- a/Src/CompareStatisticsDlg.cpp +++ b/Src/CompareStatisticsDlg.cpp @@ -43,7 +43,7 @@ BOOL CompareStatisticsDlg::OnInitDialog() CTrDialog::OnInitDialog(); int totalFiles = 0; int totalFolders = 0; - const int iconCX = []() { + const int iconCX = [this]() { const int cx = GetSystemMetrics(SM_CXSMICON); if (cx < 24) return 16; diff --git a/Src/DirColsDlg.cpp b/Src/DirColsDlg.cpp index 382fd9b9515..f0a308c1eba 100644 --- a/Src/DirColsDlg.cpp +++ b/Src/DirColsDlg.cpp @@ -58,13 +58,10 @@ END_MESSAGE_MAP() */ void CDirColsDlg::InitList() { - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; - // Show selection across entire row. // Also enable infotips. m_listColumns.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); - m_listColumns.InsertColumn(0, _T(""), LVCFMT_LEFT, pointToPixel(148)); + m_listColumns.InsertColumn(0, _T(""), LVCFMT_LEFT, PointToPixel(148)); } /** diff --git a/Src/DirFrame.cpp b/Src/DirFrame.cpp index b656af05fae..0145d78c8bb 100644 --- a/Src/DirFrame.cpp +++ b/Src/DirFrame.cpp @@ -111,14 +111,12 @@ int CDirFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) } String sText = _("RO"); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; m_wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH | SBPS_NOBORDERS, 0); - m_wndStatusBar.SetPaneInfo(PANE_COMPMETHOD, ID_STATUS_FILTER, 0, pointToPixel(COMPMETHOD_PANEL_WIDTH)); - m_wndStatusBar.SetPaneInfo(PANE_FILTER, ID_STATUS_FILTER, 0, pointToPixel(FILTER_PANEL_WIDTH)); - m_wndStatusBar.SetPaneInfo(PANE_LEFT_RO, ID_STATUS_LEFTDIR_RO, 0, pointToPixel(RO_PANEL_WIDTH)); - m_wndStatusBar.SetPaneInfo(PANE_MIDDLE_RO, ID_STATUS_MIDDLEDIR_RO, 0, pointToPixel(RO_PANEL_WIDTH)); - m_wndStatusBar.SetPaneInfo(PANE_RIGHT_RO, ID_STATUS_RIGHTDIR_RO, 0, pointToPixel(RO_PANEL_WIDTH)); + m_wndStatusBar.SetPaneInfo(PANE_COMPMETHOD, ID_STATUS_FILTER, 0, PointToPixel(COMPMETHOD_PANEL_WIDTH)); + m_wndStatusBar.SetPaneInfo(PANE_FILTER, ID_STATUS_FILTER, 0, PointToPixel(FILTER_PANEL_WIDTH)); + m_wndStatusBar.SetPaneInfo(PANE_LEFT_RO, ID_STATUS_LEFTDIR_RO, 0, PointToPixel(RO_PANEL_WIDTH)); + m_wndStatusBar.SetPaneInfo(PANE_MIDDLE_RO, ID_STATUS_MIDDLEDIR_RO, 0, PointToPixel(RO_PANEL_WIDTH)); + m_wndStatusBar.SetPaneInfo(PANE_RIGHT_RO, ID_STATUS_RIGHTDIR_RO, 0, PointToPixel(RO_PANEL_WIDTH)); m_wndStatusBar.SetPaneText(PANE_LEFT_RO, sText.c_str(), TRUE); m_wndStatusBar.SetPaneText(PANE_MIDDLE_RO, sText.c_str(), TRUE); m_wndStatusBar.SetPaneText(PANE_RIGHT_RO, sText.c_str(), TRUE); diff --git a/Src/DirView.cpp b/Src/DirView.cpp index ae70654e0dd..321c570fda9 100644 --- a/Src/DirView.cpp +++ b/Src/DirView.cpp @@ -117,7 +117,7 @@ CDirView::~CDirView() { } -BEGIN_MESSAGE_MAP(CDirView, CListView) +BEGIN_MESSAGE_MAP(CDirView, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CDirView) ON_WM_CONTEXTMENU() ON_WM_LBUTTONDBLCLK() @@ -379,6 +379,7 @@ BEGIN_MESSAGE_MAP(CDirView, CListView) ON_UPDATE_COMMAND_UI(ID_STATUS_RIGHTDIR_RO, OnUpdateStatusRightRO) ON_UPDATE_COMMAND_UI(ID_STATUS_MIDDLEDIR_RO, OnUpdateStatusMiddleRO) ON_UPDATE_COMMAND_UI(ID_STATUS_LEFTDIR_RO, OnUpdateStatusLeftRO) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) //}}AFX_MSG_MAP END_MESSAGE_MAP() @@ -399,7 +400,7 @@ CDirDoc* CDirView::GetDocument() // non-debug version is inline void CDirView::OnInitialUpdate() { - const int iconCX = []() { + const int iconCX = [this]() { const int cx = GetSystemMetrics(SM_CXSMICON); if (cx < 24) return 16; @@ -2596,6 +2597,14 @@ bool CDirView::OnHeaderEndDrag(LPNMHEADER hdr, LRESULT* pResult) return true; } +LRESULT CDirView::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + int olddpi = m_dpi; + __super::OnDpiChangedBeforeParent(wParam, lParam); + DpiAware::ListView_UpdateColumnWidths(m_hWnd, olddpi, m_dpi); + return 0; +} + /** * @brief Remove any windows reordering of columns */ diff --git a/Src/DirView.h b/Src/DirView.h index 19755baa74f..31e92d9707e 100644 --- a/Src/DirView.h +++ b/Src/DirView.h @@ -22,6 +22,7 @@ #include "DirActions.h" #include "IListCtrlImpl.h" #include "FileOpenFlags.h" +#include "utils/DpiAware.h" class FileActionScript; @@ -62,7 +63,7 @@ constexpr int DefColumnWidth = 111; * CDiffContext items are linked by storing POSITION of CDiffContext item * as CDirView listitem key. */ -class CDirView : public CListView +class CDirView : public DpiAware::CDpiAwareWnd { friend struct FileCmpReport; friend DirItemEnumerator; @@ -410,6 +411,7 @@ class CDirView : public CListView bool OnHeaderEndDrag(LPNMHEADER hdr, LRESULT* pResult); void HideItems(const std::vector& ItemsToHide); bool IsItemToHide(const String& currentItem, const std::vector& ItemsToHide) const; + LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam); private: void Open(CDirDoc *pDoc, const PathContext& paths, fileopenflags_t dwFlags[3], FileTextEncoding encoding[3], PackingInfo * infoUnpacker = nullptr); @@ -437,7 +439,7 @@ class CDirView : public CListView void CollapseSubdir(int sel); void ExpandSubdir(int sel, bool bRecursive = false); void GetColors(int nRow, int nCol, COLORREF& clrBk, COLORREF& clrText) const; - int GetDefColumnWidth() const { return MulDiv(DefColumnWidth, CClientDC(const_cast(this)).GetDeviceCaps(LOGPIXELSX), 72); }; + int GetDefColumnWidth() const { return PointToPixel(DefColumnWidth); }; public: DirItemIterator Begin() const { return DirItemIterator(m_pIList.get()); } diff --git a/Src/EditorFilepathBar.cpp b/Src/EditorFilepathBar.cpp index ab8b51e5e0d..f3c5aa9ac78 100644 --- a/Src/EditorFilepathBar.cpp +++ b/Src/EditorFilepathBar.cpp @@ -18,11 +18,12 @@ #endif -BEGIN_MESSAGE_MAP(CEditorFilePathBar, CDialogBar) +BEGIN_MESSAGE_MAP(CEditorFilePathBar, DpiAware::CDpiAwareWnd) ON_NOTIFY_EX (TTN_NEEDTEXT, 0, OnToolTipNotify) ON_CONTROL_RANGE (EN_SETFOCUS, IDC_STATIC_TITLE_PANE0, IDC_STATIC_TITLE_PANE2, OnSetFocusEdit) ON_CONTROL_RANGE (EN_USER_CAPTION_CHANGED, IDC_STATIC_TITLE_PANE0, IDC_STATIC_TITLE_PANE2, OnChangeEdit) ON_CONTROL_RANGE (EN_USER_FILE_SELECTED, IDC_STATIC_TITLE_PANE0, IDC_STATIC_TITLE_PANE2, OnSelectEdit) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) END_MESSAGE_MAP() @@ -53,14 +54,14 @@ BOOL CEditorFilePathBar::Create(CWnd* pParentWnd) CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY, AFX_IDW_CONTROLBAR_FIRST+29)) return FALSE; - NONCLIENTMETRICS ncm = { sizeof NONCLIENTMETRICS }; - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof NONCLIENTMETRICS, &ncm, 0)) - m_font.CreateFontIndirect(&ncm.lfStatusFont); + LOGFONT lfStatusFont; + if (DpiAware::GetNonClientLogFont(lfStatusFont, offsetof(NONCLIENTMETRICS, lfStatusFont), GetDpi())) + m_font.CreateFontIndirect(&lfStatusFont); // subclass the two custom edit boxes const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; - int cx = -pointToPixel(ncm.lfStatusFont.lfHeight); + int cx = -pointToPixel(lfStatusFont.lfHeight); int m = pointToPixel(3); for (int pane = 0; pane < static_cast(std::size(m_Edit)); pane++) { @@ -204,6 +205,22 @@ void CEditorFilePathBar::OnSelectEdit(UINT id) (pane, m_Edit[pane].GetSelectedPath()); } +LRESULT CEditorFilePathBar::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + __super::OnDpiChangedBeforeParent(wParam, lParam); + + LOGFONT lfStatusFont; + if (DpiAware::GetNonClientLogFont(lfStatusFont, offsetof(NONCLIENTMETRICS, lfStatusFont), GetDpi())) + { + m_font.DeleteObject(); + m_font.CreateFontIndirect(&lfStatusFont); + } + + for (int pane = 0; pane < static_cast(std::size(m_Edit)); pane++) + m_Edit[pane].SetFont(&m_font); + return 0; +} + /** * @brief Get the path for one side * diff --git a/Src/EditorFilepathBar.h b/Src/EditorFilepathBar.h index 6691d400137..bc177169f64 100644 --- a/Src/EditorFilepathBar.h +++ b/Src/EditorFilepathBar.h @@ -12,6 +12,7 @@ #pragma once #include "FilepathEdit.h" +#include "utils/DpiAware.h" #include /** @@ -38,7 +39,7 @@ class IHeaderBar * The bar looks like a statusBar (font, height). The control * displays a tip for each path (as a tooltip). */ -class CEditorFilePathBar : public CDialogBar, public IHeaderBar +class CEditorFilePathBar : public DpiAware::CDpiAwareWnd, public IHeaderBar { public : CEditorFilePathBar(); @@ -69,6 +70,7 @@ public : afx_msg void OnSetFocusEdit(UINT id); afx_msg void OnChangeEdit(UINT id); afx_msg void OnSelectEdit(UINT id); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM, LPARAM); //}}AFX_MSG DECLARE_MESSAGE_MAP(); diff --git a/Src/FileFiltersDlg.cpp b/Src/FileFiltersDlg.cpp index 192c57f6aee..d25c8845d82 100644 --- a/Src/FileFiltersDlg.cpp +++ b/Src/FileFiltersDlg.cpp @@ -111,15 +111,12 @@ void FileFiltersDlg::InitList() // Also enable infotips. m_listFilters.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; - String title = _("Name"); - m_listFilters.InsertColumn(0, title.c_str(), LVCFMT_LEFT, pointToPixel(112)); + m_listFilters.InsertColumn(0, title.c_str(), LVCFMT_LEFT, PointToPixel(112)); title = _("Description"); - m_listFilters.InsertColumn(1, title.c_str(), LVCFMT_LEFT, pointToPixel(262)); + m_listFilters.InsertColumn(1, title.c_str(), LVCFMT_LEFT, PointToPixel(262)); title = _("Location"); - m_listFilters.InsertColumn(2, title.c_str(), LVCFMT_LEFT, pointToPixel(262)); + m_listFilters.InsertColumn(2, title.c_str(), LVCFMT_LEFT, PointToPixel(262)); title = _(""); m_listFilters.InsertItem(1, title.c_str()); diff --git a/Src/HexMergeFrm.cpp b/Src/HexMergeFrm.cpp index 24a2f3dd69b..a85278f98d8 100644 --- a/Src/HexMergeFrm.cpp +++ b/Src/HexMergeFrm.cpp @@ -79,13 +79,11 @@ CHexMergeFrame::~CHexMergeFrame() */ void CHexMergeFrame::CreateHexWndStatusBar(CStatusBar &wndStatusBar, CWnd *pwndPane) { - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; wndStatusBar.Create(pwndPane, WS_CHILD|WS_VISIBLE); wndStatusBar.SetIndicators(0, 3); wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH, 0); - wndStatusBar.SetPaneInfo(1, 0, 0, pointToPixel(60)); - wndStatusBar.SetPaneInfo(2, 0, 0, pointToPixel(60)); + wndStatusBar.SetPaneInfo(1, 0, 0, PointToPixel(60)); + wndStatusBar.SetPaneInfo(2, 0, 0, PointToPixel(60)); wndStatusBar.SetParent(this); wndStatusBar.SetWindowPos(&wndBottom, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } diff --git a/Src/LineFiltersDlg.cpp b/Src/LineFiltersDlg.cpp index fc1ab56d448..e8078db315d 100644 --- a/Src/LineFiltersDlg.cpp +++ b/Src/LineFiltersDlg.cpp @@ -88,11 +88,8 @@ void LineFiltersDlg::InitList() // Also enable infotips. m_filtersList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; - String title = _("Regular expression"); - m_filtersList.InsertColumn(1, title.c_str(), LVCFMT_LEFT, pointToPixel(570)); + m_filtersList.InsertColumn(1, title.c_str(), LVCFMT_LEFT, PointToPixel(570)); size_t count = m_pList->GetCount(); for (size_t i = 0; i < count; i++) diff --git a/Src/MainFrm.cpp b/Src/MainFrm.cpp index dc9e2d3609e..921b7a45b4f 100644 --- a/Src/MainFrm.cpp +++ b/Src/MainFrm.cpp @@ -207,7 +207,7 @@ const CMainFrame::MENUITEM_ICON CMainFrame::m_MenuIcons[] = { IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) -BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) +BEGIN_MESSAGE_MAP(CMainFrame, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_MENUCHAR() ON_WM_MEASUREITEM() @@ -220,6 +220,7 @@ BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) ON_MESSAGE(WM_COPYDATA, OnCopyData) ON_MESSAGE(WM_USER+1, OnUser1) ON_WM_ACTIVATEAPP() + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) // [File] menu ON_COMMAND(ID_FILE_NEW, (OnFileNew<2, ID_MERGE_COMPARE_TEXT>)) ON_COMMAND(ID_FILE_NEW_TABLE, (OnFileNew<2, ID_MERGE_COMPARE_TABLE>)) @@ -270,6 +271,10 @@ BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) // [Window] menu ON_COMMAND(ID_WINDOW_CLOSEALL, OnWindowCloseAll) ON_UPDATE_COMMAND_UI(ID_WINDOW_CLOSEALL, OnUpdateWindowCloseAll) + ON_COMMAND_EX(ID_WINDOW_ARRANGE, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_CASCADE, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_TILE_HORZ, OnMDIWindowCmd) + ON_COMMAND_EX(ID_WINDOW_TILE_VERT, OnMDIWindowCmd) // [Help] menu ON_COMMAND(ID_HELP_CONTENTS, OnHelpContents) ON_COMMAND(ID_HELP_GNULICENSE, OnHelpGnulicense) @@ -359,7 +364,9 @@ CMainFrame::CMainFrame() , m_lfDiff(Options::Font::Load(GetOptionsMgr(), OPT_FONT_FILECMP)) , m_lfDir(Options::Font::Load(GetOptionsMgr(), OPT_FONT_DIRCMP)) , m_pDirWatcher(new DirWatcher()) +, m_layoutManager(this) { + m_layoutManager.SetTileLayoutEnabled(true); } CMainFrame::~CMainFrame() @@ -401,6 +408,7 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) return -1; m_wndMDIClient.SubclassWindow(m_hWndMDIClient); + m_wndMDIClient.UpdateDpi(); if (!CreateToolbar()) { @@ -426,12 +434,10 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) theApp.SetIndicators(m_wndStatusBar, StatusbarIndicators, static_cast(std::size(StatusbarIndicators))); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; m_wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH | SBPS_NOBORDERS, 0); - m_wndStatusBar.SetPaneInfo(1, ID_STATUS_PLUGIN, 0, pointToPixel(225)); - m_wndStatusBar.SetPaneInfo(2, ID_STATUS_MERGINGMODE, 0, pointToPixel(75)); - m_wndStatusBar.SetPaneInfo(3, ID_STATUS_DIFFNUM, 0, pointToPixel(112)); + m_wndStatusBar.SetPaneInfo(1, ID_STATUS_PLUGIN, 0, PointToPixel(225)); + m_wndStatusBar.SetPaneInfo(2, ID_STATUS_MERGINGMODE, 0, PointToPixel(75)); + m_wndStatusBar.SetPaneInfo(3, ID_STATUS_DIFFNUM, 0, PointToPixel(112)); if (!GetOptionsMgr()->GetBool(OPT_SHOW_STATUSBAR)) __super::ShowControlBar(&m_wndStatusBar, false, 0); @@ -1634,10 +1640,10 @@ void CMainFrame::ActivateFrame(int nCmdShow) CRect dsk_rc,rc(wp.rcNormalPosition); - dsk_rc.left = ::GetSystemMetrics(SM_XVIRTUALSCREEN); - dsk_rc.top = ::GetSystemMetrics(SM_YVIRTUALSCREEN); - dsk_rc.right = dsk_rc.left + ::GetSystemMetrics(SM_CXVIRTUALSCREEN); - dsk_rc.bottom = dsk_rc.top + ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + dsk_rc.left = GetSystemMetrics(SM_XVIRTUALSCREEN); + dsk_rc.top = GetSystemMetrics(SM_YVIRTUALSCREEN); + dsk_rc.right = dsk_rc.left + GetSystemMetrics(SM_CXVIRTUALSCREEN); + dsk_rc.bottom = dsk_rc.top + GetSystemMetrics(SM_CYVIRTUALSCREEN); if (rc.Width() != 0 && rc.Height() != 0) { // Ensure top-left corner is on visible area, @@ -3502,6 +3508,31 @@ void CMainFrame::OnAccelQuit() SendMessage(WM_CLOSE); } +LRESULT CMainFrame::OnDpiChanged(WPARAM wParam, LPARAM lParam) +{ + int olddpi = m_dpi; + + __super::OnDpiChanged(wParam, lParam); + + DpiAware::UpdateAfxDataSysMetrics(m_dpi); + BCMenu::ReopenTheme(m_dpi); + + m_lfDiff.lfHeight = MulDiv(m_lfDiff.lfHeight, m_dpi, olddpi); + m_lfDir.lfHeight = MulDiv(m_lfDir.lfHeight, m_dpi, olddpi); + + UpdateFont(FRAME_FILE); + UpdateFont(FRAME_FOLDER); + + LoadToolbarImages(); + + const RECT* pRect = reinterpret_cast(lParam); + SetWindowPos(nullptr, pRect->left, pRect->top, + pRect->right - pRect->left, + pRect->bottom - pRect->top, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; +} + LRESULT CMainFrame::OnChildFrameAdded(WPARAM wParam, LPARAM lParam) { for (int i = 0; i < m_arrChild.GetSize(); ++i) @@ -3563,3 +3594,24 @@ LRESULT CMainFrame::OnChildFrameActivated(WPARAM wParam, LPARAM lParam) return 1; } + +BOOL CMainFrame::OnMDIWindowCmd(UINT nID) +{ + switch (nID) + { + case ID_WINDOW_TILE_HORZ: + case ID_WINDOW_TILE_VERT: + { + bool bHorizontal = (nID == ID_WINDOW_TILE_HORZ); + m_layoutManager.SetTileLayoutEnabled(true); + m_layoutManager.Tile(bHorizontal); + break; + } + case ID_WINDOW_CASCADE: + m_layoutManager.SetTileLayoutEnabled(false); + __super::OnMDIWindowCmd(nID); + break; + } + return 0; +} + diff --git a/Src/MainFrm.h b/Src/MainFrm.h index 081c2e4f17b..5958951d81b 100644 --- a/Src/MainFrm.h +++ b/Src/MainFrm.h @@ -19,6 +19,8 @@ #include "OptionsDef.h" #include "OptionsMgr.h" #include "FileOpenFlags.h" +#include "utils/DpiAware.h" +#include "utils/MDITileLayout.h" class BCMenu; class CDirView; @@ -56,7 +58,7 @@ CMainFrame * GetMainFrame(); // access to the singleton main frame object /** * @brief Frame class containing save-routines etc */ -class CMainFrame : public CMDIFrameWnd +class CMainFrame : public DpiAware::CDpiAwareWnd { friend CLanguageSelect; DECLARE_DYNAMIC(CMainFrame) @@ -223,6 +225,7 @@ class CMainFrame : public CMDIFrameWnd void UnwatchDocuments(IMergeDoc* pMergeDoc); CToolBar* GetToolbar() { return &m_wndToolBar; } static void WaitAndDoMessageLoop(bool& completed, int ms); + MDITileLayout::LayoutManager& GetLayoutManager() { return m_layoutManager; }; // Overrides virtual void GetMessageString(UINT nID, CString& rMessage) const; @@ -233,6 +236,7 @@ class CMainFrame : public CMDIFrameWnd virtual BOOL PreTranslateMessage(MSG* pMsg); virtual void OnUpdateFrameTitle(BOOL bAddToTitle); virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL // Implementation methods @@ -251,9 +255,10 @@ class CMainFrame : public CMDIFrameWnd CToolBar m_wndToolBar; CMDITabBar m_wndTabBar; CTypedPtrArray m_arrChild; + MDITileLayout::LayoutManager m_layoutManager; // Tweak MDI client window behavior - class CMDIClient : public CWnd + class CMDIClient : public DpiAware::CDpiAwareWnd { static UINT_PTR const m_nRedrawTimer = 1612; virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) @@ -281,6 +286,13 @@ class CMainFrame : public CMDIFrameWnd RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE); } break; + case WM_SIZE: + if (AfxGetMainWnd()) + GetMainFrame()->GetLayoutManager().NotifyMainResized(); + break; + case WM_DPICHANGED_BEFOREPARENT: + UpdateDpi(); + break; } return CWnd::WindowProc(message, wParam, lParam); } @@ -333,6 +345,7 @@ class CMainFrame : public CMDIFrameWnd DropHandler *m_pDropHandler; std::unique_ptr m_pDirWatcher; + // Generated message map functions protected: //{{AFX_MSG(CMainFrame) @@ -413,6 +426,8 @@ class CMainFrame : public CMDIFrameWnd afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnDestroy(); afx_msg void OnAccelQuit(); + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnMDIWindowCmd(UINT nID); afx_msg LRESULT OnChildFrameAdded(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnChildFrameRemoved(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnChildFrameActivate(WPARAM wParam, LPARAM lParam); diff --git a/Src/Merge.cpp b/Src/Merge.cpp index c92a96680bb..f7be9141433 100644 --- a/Src/Merge.cpp +++ b/Src/Merge.cpp @@ -351,17 +351,6 @@ BOOL CMergeApp::InitInstance() FileTransform::AutoUnpacking = GetOptionsMgr()->GetBool(OPT_PLUGINS_UNPACKER_MODE); FileTransform::AutoPrediffing = GetOptionsMgr()->GetBool(OPT_PLUGINS_PREDIFFER_MODE); - NONCLIENTMETRICS ncm = { sizeof NONCLIENTMETRICS }; - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof NONCLIENTMETRICS, &ncm, 0)) - { - const int lfHeight = -MulDiv(9, CClientDC(CWnd::GetDesktopWindow()).GetDeviceCaps(LOGPIXELSY), 72); - if (abs(ncm.lfMenuFont.lfHeight) > abs(lfHeight)) - ncm.lfMenuFont.lfHeight = lfHeight; - if (wcscmp(ncm.lfMenuFont.lfFaceName, L"Meiryo") == 0 || wcscmp(ncm.lfMenuFont.lfFaceName, L"\U000030e1\U000030a4\U000030ea\U000030aa"/* "Meiryo" in Japanese */) == 0) - wcscpy_s(ncm.lfMenuFont.lfFaceName, L"Meiryo UI"); - m_fontGUI.CreateFontIndirect(&ncm.lfMenuFont); - } - if (m_pSyntaxColors != nullptr) Options::SyntaxColors::Init(GetOptionsMgr(), m_pSyntaxColors.get()); @@ -1575,13 +1564,38 @@ void CMergeApp::TranslateMenu(HMENU h) const */ void CMergeApp::TranslateDialog(HWND h) const { - CWnd *pWnd = CWnd::FromHandle(h); - pWnd->SetFont(const_cast(&m_fontGUI)); - pWnd->SendMessageToDescendants(WM_SETFONT, (WPARAM)m_fontGUI.m_hObject, MAKELPARAM(FALSE, 0), TRUE); - + const int dpi = DpiAware::GetDpiForWindow(h); + ChangeDialogFont(h, dpi); m_pLangDlg->TranslateDialog(h); } +void CMergeApp::ChangeDialogFont(HWND hwnd, int dpi) const +{ + CWnd *pWnd = CWnd::FromHandle(hwnd); + CFont* pFont = GetGUIFont(dpi); + pWnd->SetFont(pFont); + pWnd->SendMessageToDescendants(WM_SETFONT, (WPARAM)pFont->m_hObject, MAKELPARAM(FALSE, 0), TRUE); +} + +CFont* CMergeApp::GetGUIFont(int dpi) const +{ + auto adjustFont = [](auto& ncm, int dpi) + { + }; + if (m_mapFontGUI.find(dpi) == m_mapFontGUI.end()) + { + LOGFONT lfMenuFont; + DpiAware::GetNonClientLogFont(lfMenuFont, offsetof(NONCLIENTMETRICS, lfMenuFont), dpi); + const int lfHeight = -MulDiv(9, dpi, 72); + if (abs(lfMenuFont.lfHeight) > abs(lfHeight)) + lfMenuFont.lfHeight = lfHeight; + if (wcscmp(lfMenuFont.lfFaceName, L"Meiryo") == 0 || wcscmp(lfMenuFont.lfFaceName, L"\U000030e1\U000030a4\U000030ea\U000030aa"/* "Meiryo" in Japanese */) == 0) + wcscpy_s(lfMenuFont.lfFaceName, L"Meiryo UI"); + m_mapFontGUI[dpi].CreateFontIndirect(&lfMenuFont); + } + return &m_mapFontGUI[dpi]; +} + /** * @brief Load string and translate to current WinMerge GUI language */ diff --git a/Src/Merge.h b/Src/Merge.h index e2fdb9aab5f..7f4535e50e3 100644 --- a/Src/Merge.h +++ b/Src/Merge.h @@ -75,6 +75,7 @@ class CMergeApp : public CWinApp void SetIndicators(CStatusBar &, const UINT *, int) const; void TranslateMenu(HMENU) const; void TranslateDialog(HWND) const; + void ChangeDialogFont(HWND hwnd, int dpi) const; String LoadString(UINT) const; bool TranslateString(const std::string&, String&) const; bool TranslateString(const std::wstring&, String&) const; @@ -167,6 +168,8 @@ class CMergeApp : public CWinApp void AddZombieThread(CWinThread* pThread); bool WaitZombieThreads(); + + CFont *GetGUIFont(int dpi) const; //{{AFX_MSG(CMergeApp) afx_msg BOOL OnOpenRecentFile(UINT nID); @@ -186,7 +189,7 @@ class CMergeApp : public CWinApp LONG m_nActiveOperations; /**< Active operations count. */ bool m_bMergingMode; /**< Merging or Edit mode */ bool m_bEnableExitCode; - CFont m_fontGUI; + mutable std::map m_mapFontGUI; ATL::CImage m_imageForInitializingGdiplus; std::list> m_idleFuncs; std::list m_threads; diff --git a/Src/Merge.vcxproj b/Src/Merge.vcxproj index 5c8dce8cb9a..c384befc2f3 100644 --- a/Src/Merge.vcxproj +++ b/Src/Merge.vcxproj @@ -1428,11 +1428,16 @@ pch.h $(IntDir)$(TargetName)2.pch + + + + + true diff --git a/Src/Merge.vcxproj.filters b/Src/Merge.vcxproj.filters index a750db5afb2..83ceebe7e5f 100644 --- a/Src/Merge.vcxproj.filters +++ b/Src/Merge.vcxproj.filters @@ -727,6 +727,15 @@ MFCGui\MDIChild\FolderCompare\Source Files + + EditLib\Utils + + + EditLib\Utils + + + EditLib\Utils + @@ -1347,6 +1356,18 @@ MFCGui\PropertyPages\Header Files + + EditLib\Utils + + + EditLib\Utils + + + EditLib\Utils + + + EditLib\Utils + Header Files @@ -1842,6 +1863,7 @@ + Source Files diff --git a/Src/MergeAppLib.h b/Src/MergeAppLib.h index 895e58161f4..56ce5e5c3cd 100644 --- a/Src/MergeAppLib.h +++ b/Src/MergeAppLib.h @@ -3,12 +3,12 @@ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ - /* File created by MIDL compiler version 7.00.0555 */ -/* at Tue May 07 08:06:27 2024 + /* File created by MIDL compiler version 8.01.0628 */ +/* at Tue Jan 19 12:14:07 2038 */ /* Compiler settings for MergeAppLib.idl: - Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 - protocol : dce , ms_ext, c_ext, robust + Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0628 + protocol : all , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) @@ -16,12 +16,11 @@ */ /* @@MIDL_FILE_HEADING( ) */ -#pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#define __REQUIRED_RPCNDR_H_VERSION__ 500 #endif #include "rpc.h" @@ -29,7 +28,7 @@ #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ +#endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" @@ -43,17 +42,27 @@ #pragma once #endif +#ifndef DECLSPEC_XFGVIRT +#if defined(_CONTROL_FLOW_GUARD_XFG) +#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func)) +#else +#define DECLSPEC_XFGVIRT(base, func) +#endif +#endif + /* Forward Declarations */ #ifndef __IMergeApp_FWD_DEFINED__ #define __IMergeApp_FWD_DEFINED__ typedef interface IMergeApp IMergeApp; + #endif /* __IMergeApp_FWD_DEFINED__ */ #ifndef __IMergeApp_FWD_DEFINED__ #define __IMergeApp_FWD_DEFINED__ typedef interface IMergeApp IMergeApp; + #endif /* __IMergeApp_FWD_DEFINED__ */ @@ -111,34 +120,41 @@ EXTERN_C const IID IID_IMergeApp; }; + #else /* C style interface */ typedef struct IMergeAppVtbl { BEGIN_INTERFACE + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IMergeApp * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ - __RPC__deref_out void **ppvObject); + _COM_Outptr_ void **ppvObject); + DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( IMergeApp * This); + DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( IMergeApp * This); + DECLSPEC_XFGVIRT(IDispatch, GetTypeInfoCount) HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( IMergeApp * This, /* [out] */ UINT *pctinfo); + DECLSPEC_XFGVIRT(IDispatch, GetTypeInfo) HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( IMergeApp * This, /* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo **ppTInfo); + DECLSPEC_XFGVIRT(IDispatch, GetIDsOfNames) HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( IMergeApp * This, /* [in] */ REFIID riid, @@ -147,33 +163,46 @@ EXTERN_C const IID IID_IMergeApp; /* [in] */ LCID lcid, /* [size_is][out] */ DISPID *rgDispId); + DECLSPEC_XFGVIRT(IDispatch, Invoke) /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( IMergeApp * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); + /* [annotation][in] */ + _In_ DISPID dispIdMember, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][in] */ + _In_ LCID lcid, + /* [annotation][in] */ + _In_ WORD wFlags, + /* [annotation][out][in] */ + _In_ DISPPARAMS *pDispParams, + /* [annotation][out] */ + _Out_opt_ VARIANT *pVarResult, + /* [annotation][out] */ + _Out_opt_ EXCEPINFO *pExcepInfo, + /* [annotation][out] */ + _Out_opt_ UINT *puArgErr); + DECLSPEC_XFGVIRT(IMergeApp, Translate) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Translate )( IMergeApp * This, /* [in] */ BSTR text, /* [retval][out] */ BSTR *pRet); + DECLSPEC_XFGVIRT(IMergeApp, GetOption) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GetOption )( IMergeApp * This, /* [in] */ BSTR name, /* [in] */ VARIANT varDefault, /* [retval][out] */ VARIANT *pRet); + DECLSPEC_XFGVIRT(IMergeApp, SaveOption) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *SaveOption )( IMergeApp * This, /* [in] */ BSTR name, /* [in] */ VARIANT varValue); + DECLSPEC_XFGVIRT(IMergeApp, MsgBox) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *MsgBox )( IMergeApp * This, /* [in] */ BSTR prompt, @@ -181,6 +210,7 @@ EXTERN_C const IID IID_IMergeApp; /* [optional][in] */ VARIANT varTitle, /* [retval][out] */ int *pRet); + DECLSPEC_XFGVIRT(IMergeApp, InputBox) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *InputBox )( IMergeApp * This, /* [in] */ BSTR prompt, @@ -188,6 +218,7 @@ EXTERN_C const IID IID_IMergeApp; /* [optional][in] */ VARIANT varDefault, /* [retval][out] */ BSTR *pRet); + DECLSPEC_XFGVIRT(IMergeApp, LogError) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *LogError )( IMergeApp * This, /* [in] */ BSTR text); @@ -281,6 +312,16 @@ unsigned char * __RPC_USER VARIANT_UserMarshal( unsigned long *, unsigned char unsigned char * __RPC_USER VARIANT_UserUnmarshal(unsigned long *, unsigned char *, VARIANT * ); void __RPC_USER VARIANT_UserFree( unsigned long *, VARIANT * ); +unsigned long __RPC_USER BSTR_UserSize64( unsigned long *, unsigned long , BSTR * ); +unsigned char * __RPC_USER BSTR_UserMarshal64( unsigned long *, unsigned char *, BSTR * ); +unsigned char * __RPC_USER BSTR_UserUnmarshal64(unsigned long *, unsigned char *, BSTR * ); +void __RPC_USER BSTR_UserFree64( unsigned long *, BSTR * ); + +unsigned long __RPC_USER VARIANT_UserSize64( unsigned long *, unsigned long , VARIANT * ); +unsigned char * __RPC_USER VARIANT_UserMarshal64( unsigned long *, unsigned char *, VARIANT * ); +unsigned char * __RPC_USER VARIANT_UserUnmarshal64(unsigned long *, unsigned char *, VARIANT * ); +void __RPC_USER VARIANT_UserFree64( unsigned long *, VARIANT * ); + /* end of Additional Prototypes */ #ifdef __cplusplus diff --git a/Src/MergeDoc.cpp b/Src/MergeDoc.cpp index 89557f8b8e7..6dbda023dec 100644 --- a/Src/MergeDoc.cpp +++ b/Src/MergeDoc.cpp @@ -3155,10 +3155,8 @@ bool CMergeDoc::GenerateReport(const String& sFileName) const { // calculate HTML font size LOGFONT lf; - CDC dc; - dc.CreateDC(_T("DISPLAY"), nullptr, nullptr, nullptr); m_pView[0][0]->GetFont(lf); - int nFontSize = -MulDiv (lf.lfHeight, 72, dc.GetDeviceCaps (LOGPIXELSY)); + int nFontSize = -MulDiv (lf.lfHeight, 72, m_pView[0][0]->m_dpi); // create HTML report UniStdioFile file; diff --git a/Src/MergeEditView.cpp b/Src/MergeEditView.cpp index bf5e9907fa4..c6e979210cb 100644 --- a/Src/MergeEditView.cpp +++ b/Src/MergeEditView.cpp @@ -4250,7 +4250,7 @@ void CMergeEditView::ZoomText(short amount) LOGFONT lf = { 0 }; GetFont(lf); - const int nLogPixelsY = CClientDC(this).GetDeviceCaps(LOGPIXELSY); + const int nLogPixelsY = m_dpi; int nPointSize = -MulDiv(lf.lfHeight, 72, nLogPixelsY); int nOrgPointSize = GetOptionsMgr()->GetInt(OPT_FONT_FILECMP + OPT_FONT_POINTSIZE); diff --git a/Src/MergeFrameCommon.cpp b/Src/MergeFrameCommon.cpp index 7d1f5790036..74a27a311d6 100644 --- a/Src/MergeFrameCommon.cpp +++ b/Src/MergeFrameCommon.cpp @@ -11,15 +11,19 @@ #include "paths.h" #include "Merge.h" #include "FileTransform.h" +#include "MainFrm.h" +#include "utils/DpiAware.h" #include <../src/mfc/afximpl.h> IMPLEMENT_DYNCREATE(CMergeFrameCommon, CMDIChildWnd) -BEGIN_MESSAGE_MAP(CMergeFrameCommon, CMDIChildWnd) +BEGIN_MESSAGE_MAP(CMergeFrameCommon, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(CMergeFrameCommon) ON_WM_GETMINMAXINFO() + ON_WM_SIZE() ON_WM_DESTROY() ON_WM_MDIACTIVATE() +// ON_MESSAGE(WM_GETICON, OnGetIcon) //}}AFX_MSG_MAP END_MESSAGE_MAP() @@ -31,11 +35,37 @@ CMergeFrameCommon::CMergeFrameCommon(int nIdenticalIcon, int nDifferentIcon) , m_nLastSplitPos{0} { ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEADDED, 0, reinterpret_cast(this)); + GetMainFrame()->GetLayoutManager().NotifyChildOpened(this); } CMergeFrameCommon::~CMergeFrameCommon() { ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEREMOVED, 0, reinterpret_cast(this)); + GetMainFrame()->GetLayoutManager().NotifyChildClosed(this); +} + +BOOL CMergeFrameCommon::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + MDITileLayout::LayoutManager& layoutManager = GetMainFrame()->GetLayoutManager(); + if (!layoutManager.GetTileLayoutEnabled()) + return __super::PreCreateWindow(cs); + __super::PreCreateWindow(cs); + cs.style &= ~WS_CAPTION; + CRect rcMain; + ::GetWindowRect(GetMainFrame()->m_hWndMDIClient, rcMain); + CRect rc = layoutManager.GetDefaultOpenPaneRect(); + rc = layoutManager.AdjustChildRect(rcMain, rc, cs.style, WS_EX_WINDOWEDGE | WS_EX_MDICHILD, GetMainFrame()->GetDpi()); + rc.right -= rcMain.left; + rc.bottom -= rcMain.top; + rc.left -= rcMain.left; + rc.top -= rcMain.top; + cs.x = rc.left; + cs.y = rc.top; + cs.cx = rc.Width(); + cs.cy = rc.Height(); + return true; } void CMergeFrameCommon::ActivateFrame(int nCmdShow) @@ -374,6 +404,21 @@ void CMergeFrameCommon::OnGetMinMaxInfo(MINMAXINFO* lpMMI) lpMMI->ptMaxTrackSize.y = max(lpMMI->ptMaxTrackSize.y, lpMMI->ptMaxSize.y); } +void CMergeFrameCommon::OnSize(UINT nType, int cx, int cy) +{ + __super::OnSize(nType, cx, cy); + if (nType == SIZE_MAXIMIZED && IsDifferentDpiFromSystemDpi()) + { + // This is a workaround of the problem that the maximized MDI child window is in the wrong position when the DPI changes + // I don't think MDI-related processing inside Windows fully supports per-monitor dpi awareness + CRect rc; + GetParent()->GetClientRect(rc); + AdjustWindowRectEx(&rc, GetStyle(), FALSE, GetExStyle()); + SetWindowPos(nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE); + } + GetMainFrame()->GetLayoutManager().NotifyChildResized(this); +} + void CMergeFrameCommon::OnDestroy() { // https://stackoverflow.com/questions/35553955/getting-rid-of-3d-look-of-mdi-frame-window diff --git a/Src/MergeFrameCommon.h b/Src/MergeFrameCommon.h index 9ec9ff21179..3bed217329b 100644 --- a/Src/MergeFrameCommon.h +++ b/Src/MergeFrameCommon.h @@ -8,11 +8,12 @@ #include "UnicodeString.h" #include "PathContext.h" +#include "utils/DpiAware.h" class PrediffingInfo; class PackingInfo; -class CMergeFrameCommon: public CMDIChildWnd +class CMergeFrameCommon: public DpiAware::CDpiAwareWnd { DECLARE_DYNCREATE(CMergeFrameCommon) public: @@ -28,6 +29,7 @@ class CMergeFrameCommon: public CMDIChildWnd void SaveWindowState(); void SetSharedMenu(HMENU hMenu) { m_hMenuShared = hMenu; } void RemoveBarBorder(); + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL IsTabbedMDIChild() { return TRUE; // https://stackoverflow.com/questions/35553955/getting-rid-of-3d-look-of-mdi-frame-window @@ -46,6 +48,7 @@ class CMergeFrameCommon: public CMDIChildWnd protected: //{{AFX_MSG(CMergeFrameCommon) afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); + afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDestroy(); afx_msg void OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd); //}}AFX_MSG diff --git a/Src/MergeStatusBar.cpp b/Src/MergeStatusBar.cpp index 2aa3fe34936..b713b5ec912 100644 --- a/Src/MergeStatusBar.cpp +++ b/Src/MergeStatusBar.cpp @@ -68,8 +68,9 @@ static UINT indicatorsBottom[] = ID_SEPARATOR, }; -BEGIN_MESSAGE_MAP(CMergeStatusBar, CStatusBar) +BEGIN_MESSAGE_MAP(CMergeStatusBar, DpiAware::CDpiAwareWnd) ON_WM_SETCURSOR() + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) END_MESSAGE_MAP() /** @@ -169,17 +170,15 @@ void CMergeStatusBar::Resize(int widths[]) // Set bottom statusbar panel widths // Kimmo - I don't know why 4 seems to be right for me int borderWidth = 4; // GetSystemMetrics(SM_CXEDGE); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; for (int pane = 0; pane < m_nPanes; pane++) { - int fixedPaneWidth = pointToPixel(RO_PANEL_WIDTH + ENCODING_PANEL_WIDTH + EOL_PANEL_WIDTH) + + int fixedPaneWidth = PointToPixel(RO_PANEL_WIDTH + ENCODING_PANEL_WIDTH + EOL_PANEL_WIDTH) + (3 * borderWidth); int paneWidth = widths[pane] - fixedPaneWidth; - int encodingWidth = pointToPixel(ENCODING_PANEL_WIDTH) - borderWidth; - int roWidth = pointToPixel(RO_PANEL_WIDTH) - borderWidth; - int eolWidth = pointToPixel(EOL_PANEL_WIDTH) - borderWidth; + int encodingWidth = PointToPixel(ENCODING_PANEL_WIDTH) - borderWidth; + int roWidth = PointToPixel(RO_PANEL_WIDTH) - borderWidth; + int eolWidth = PointToPixel(EOL_PANEL_WIDTH) - borderWidth; if (paneWidth < 0) { paneWidth = 0; @@ -332,3 +331,18 @@ BOOL CMergeStatusBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) return TRUE; } +LRESULT CMergeStatusBar::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + __super::OnDpiChangedBeforeParent(wParam, lParam); + + if (m_font.m_hObject == GetFont()->m_hObject) + m_font.DeleteObject(); + + LOGFONT lfStatusFont; + if (DpiAware::GetNonClientLogFont(lfStatusFont, offsetof(NONCLIENTMETRICS, lfStatusFont), GetDpi())) + m_font.CreateFontIndirect(&lfStatusFont); + + SetFont(&m_font); + return 0; +} + diff --git a/Src/MergeStatusBar.h b/Src/MergeStatusBar.h index 664a212a386..54efb62b4fe 100644 --- a/Src/MergeStatusBar.h +++ b/Src/MergeStatusBar.h @@ -14,8 +14,9 @@ #include "MergeEditStatus.h" #include "OptionsDiffColors.h" #include "UnicodeString.h" +#include "utils/DpiAware.h" -class CMergeStatusBar : public CStatusBar +class CMergeStatusBar : public DpiAware::CDpiAwareWnd { public : CMergeStatusBar(); @@ -29,7 +30,11 @@ public : void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); protected: + + //{{AFX_MSG(CEditorFilePathBar) afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM, LPARAM); + //}}AFX_MSG DECLARE_MESSAGE_MAP(); private: @@ -71,4 +76,5 @@ public : }; friend class MergeStatus; // MergeStatus accesses status bar MergeStatus m_status[3]; + CFont m_font; }; diff --git a/Src/OpenFrm.cpp b/Src/OpenFrm.cpp index f3a3da3555f..c269beb7b41 100644 --- a/Src/OpenFrm.cpp +++ b/Src/OpenFrm.cpp @@ -5,6 +5,7 @@ #include "OptionsDef.h" #include "OptionsMgr.h" #include "MergeFrameCommon.h" +#include "MainFrm.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -74,7 +75,8 @@ LRESULT COpenFrame::OnNcHitTest(CPoint point) void COpenFrame::OnWindowPosChanging(WINDOWPOS* lpwndpos) { // Retain frame sizes during tile operations (tolerate overlapping) - if ((lpwndpos->flags & (SWP_NOSIZE | SWP_NOOWNERZORDER)) == 0 && !IsZoomed()) + if ((lpwndpos->flags & (SWP_NOSIZE | SWP_NOOWNERZORDER)) == 0 && + !(IsZoomed() || GetMainFrame()->GetLayoutManager().GetTileLayoutEnabled())) { if (CScrollView *const pView = static_cast(GetActiveView())) { @@ -90,9 +92,9 @@ void COpenFrame::OnWindowPosChanging(WINDOWPOS* lpwndpos) void COpenFrame::ActivateFrame(int nCmdShow) { __super::ActivateFrame(nCmdShow); - if (CView *const pView = GetActiveView()) + if (!GetMainFrame()->GetLayoutManager().GetTileLayoutEnabled()) { - if (!IsZoomed()) + if (CView* const pView = GetActiveView(); pView && !IsZoomed()) { WINDOWPLACEMENT wp = { sizeof wp }; GetWindowPlacement(&wp); diff --git a/Src/OpenView.cpp b/Src/OpenView.cpp index 6ff8ae525fb..324df11da08 100644 --- a/Src/OpenView.cpp +++ b/Src/OpenView.cpp @@ -54,7 +54,7 @@ const int RETRY_MAX = 3; IMPLEMENT_DYNCREATE(COpenView, CFormView) -BEGIN_MESSAGE_MAP(COpenView, CFormView) +BEGIN_MESSAGE_MAP(COpenView, DpiAware::CDpiAwareWnd) //{{AFX_MSG_MAP(COpenView) ON_CONTROL_RANGE(BN_CLICKED, IDC_PATH0_BUTTON, IDC_PATH2_BUTTON, OnPathButton) ON_BN_CLICKED(IDC_SWAP01_BUTTON, (OnSwapButton)) @@ -107,6 +107,7 @@ BEGIN_MESSAGE_MAP(COpenView, CFormView) ON_COMMAND_RANGE(ID_UNPACKERS_FIRST, ID_UNPACKERS_LAST, OnCompare) ON_COMMAND_RANGE(ID_OPEN_WITH_UNPACKER, ID_OPEN_WITH_UNPACKER, OnCompare) ON_MESSAGE(WM_USER + 1, OnUpdateStatus) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) ON_WM_PAINT() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() @@ -120,7 +121,7 @@ END_MESSAGE_MAP() // COpenView construction/destruction COpenView::COpenView() - : CFormView(COpenView::IDD) + : DpiAware::CDpiAwareWnd(COpenView::IDD) , m_pUpdateButtonStatusThread(nullptr) , m_bRecurse(false) , m_pDropHandler(nullptr) @@ -458,7 +459,7 @@ void COpenView::OnWindowPosChanging(WINDOWPOS* lpwndpos) if ((lpwndpos->flags & (SWP_NOMOVE | SWP_NOSIZE)) == 0) { CFrameWnd *const pFrameWnd = GetParentFrame(); - if (pFrameWnd == GetTopLevelFrame()->GetActiveFrame()) + if (pFrameWnd == GetTopLevelFrame()->GetActiveFrame() || GetMainFrame()->GetLayoutManager().GetTileLayoutEnabled()) { CRect rc; pFrameWnd->GetClientRect(&rc); @@ -472,7 +473,7 @@ void COpenView::OnWindowPosChanging(WINDOWPOS* lpwndpos) if (lpwndpos->y < 0) lpwndpos->y = 0; } - else if (pFrameWnd->IsZoomed()) + else if (pFrameWnd->IsZoomed() || GetMainFrame()->GetLayoutManager().GetTileLayoutEnabled()) { lpwndpos->cx = m_totalLog.cx; lpwndpos->y = (rc.bottom - lpwndpos->cy) / 2; @@ -499,9 +500,9 @@ void COpenView::OnWindowPosChanged(WINDOWPOS* lpwndpos) if (pFrameWnd == GetTopLevelFrame()->GetActiveFrame()) { m_constraint.Persist(true, false); - if (!pFrameWnd->IsZoomed()) + if (!GetMainFrame()->GetLayoutManager().GetTileLayoutEnabled()) { - WINDOWPLACEMENT wp = { sizeof wp }; + WINDOWPLACEMENT wp { sizeof wp }; pFrameWnd->GetWindowPlacement(&wp); CRect rc; GetWindowRect(&rc); @@ -525,7 +526,7 @@ void COpenView::OnDestroy() LRESULT COpenView::OnNcHitTest(CPoint point) { - if (GetParentFrame()->IsZoomed()) + if (GetParentFrame()->IsZoomed() || GetMainFrame()->GetLayoutManager().GetTileLayoutEnabled()) { CRect rc; GetWindowRect(&rc); @@ -1444,6 +1445,21 @@ LRESULT COpenView::OnUpdateStatus(WPARAM wParam, LPARAM lParam) return 0; } +LRESULT COpenView::OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) +{ + const int olddpi = m_dpi; + CRect rc; + GetWindowRect(&rc); + __super::OnDpiChangedBeforeParent(wParam, lParam); + rc.left = MulDiv(rc.left, m_dpi, olddpi); + rc.right = MulDiv(rc.right, m_dpi, olddpi); + rc.top = MulDiv(rc.top, m_dpi, olddpi); + rc.bottom = MulDiv(rc.bottom, m_dpi, olddpi); + DefWindowProc(WM_DPICHANGED, (WPARAM)m_dpi, (LPARAM)&rc); + SetWindowPos(nullptr, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER); + return 0; +} + /** * @brief Sets the path status text. * The open dialog shows a status text of selected paths. This function diff --git a/Src/OpenView.h b/Src/OpenView.h index d0f1a15444c..61fdab592b2 100644 --- a/Src/OpenView.h +++ b/Src/OpenView.h @@ -34,7 +34,7 @@ class DropHandler; * The dialog shows also a status of the selected paths (found/not found), * if enabled in the options (enabled by default). */ -class COpenView : public CFormView, public DlgUtils +class COpenView : public DpiAware::CDpiAwareWnd, public DlgUtils { protected: // create from serialization only COpenView(); @@ -158,6 +158,7 @@ virtual BOOL PreCreateWindow(CREATESTRUCT& cs); afx_msg void OnHelp(); afx_msg void OnDropFiles(const std::vector& files); afx_msg LRESULT OnUpdateStatus(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam); afx_msg void OnPaint(); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); diff --git a/Src/PluginsListDlg.cpp b/Src/PluginsListDlg.cpp index 206be2b482c..f0177aa9403 100644 --- a/Src/PluginsListDlg.cpp +++ b/Src/PluginsListDlg.cpp @@ -96,15 +96,12 @@ void PluginsListDlg::InitList() // Also enable infotips. m_list.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); - const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX); - auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); }; - String title = _("Name"); - m_list.InsertColumn(0, title.c_str(), LVCFMT_LEFT, pointToPixel(150)); + m_list.InsertColumn(0, title.c_str(), LVCFMT_LEFT, PointToPixel(150)); title = _("Type"); - m_list.InsertColumn(1, title.c_str(), LVCFMT_LEFT, pointToPixel(150)); + m_list.InsertColumn(1, title.c_str(), LVCFMT_LEFT, PointToPixel(75)); title = _("Description"); - m_list.InsertColumn(2, title.c_str(), LVCFMT_LEFT, pointToPixel(300)); + m_list.InsertColumn(2, title.c_str(), LVCFMT_LEFT, PointToPixel(225)); } /** diff --git a/Src/TrDialogs.cpp b/Src/TrDialogs.cpp index 3604e5f4069..c7474134786 100644 --- a/Src/TrDialogs.cpp +++ b/Src/TrDialogs.cpp @@ -6,6 +6,24 @@ IMPLEMENT_DYNAMIC(CTrDialog, CDialog) IMPLEMENT_DYNAMIC(CTrPropertyPage, CPropertyPage) IMPLEMENT_DYNAMIC(CTrDialogBar, CDialogBar) +BEGIN_MESSAGE_MAP(CTrDialog, DpiAware::CDpiAwareDialog) + ON_MESSAGE(WM_DPICHANGED, OnDpiChanged) +END_MESSAGE_MAP() + +BEGIN_MESSAGE_MAP(CTrPropertyPage, DpiAware::CDpiAwareDialog) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) +END_MESSAGE_MAP() + +BEGIN_MESSAGE_MAP(CTrDialogBar, DpiAware::CDpiAwareDialog) + ON_MESSAGE(WM_DPICHANGED_BEFOREPARENT, OnDpiChangedBeforeParent) +END_MESSAGE_MAP() + +void DpiChangedImplHelper(HWND hwnd, int olddpi, int newdpi) +{ + theApp.ChangeDialogFont(hwnd, newdpi); + DpiAware::Dialog_UpdateControlInnerWidths(hwnd, olddpi, newdpi); +} + void StaticDlgUtils::WildcardRemoveDuplicatePatterns(String& patterns) { size_t i = 0, j = 0, k = 0; diff --git a/Src/TrDialogs.h b/Src/TrDialogs.h index 6e4a1e98bd8..98ddc66cbba 100644 --- a/Src/TrDialogs.h +++ b/Src/TrDialogs.h @@ -1,6 +1,7 @@ #pragma once #include "DDXHelper.h" +#include "utils/DpiAware.h" #undef GetDlgItemText #undef SetDlgItemText @@ -94,25 +95,50 @@ class DlgUtils : public StaticDlgUtils } }; -class CTrDialog : public CDialog, public DlgUtils +void DpiChangedImplHelper(HWND hwnd, int olddpi, int newdpi); + +class CTrDialog + : public DpiAware::CDpiAwareDialog + , public DlgUtils { DECLARE_DYNAMIC(CTrDialog) public: - using CDialog::CDialog; + using DpiAware::CDpiAwareDialog::CDpiAwareDialog; virtual BOOL OnInitDialog(); + + DECLARE_MESSAGE_MAP() + afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam) + { + int olddpi = m_dpi; + LRESULT result = __super::OnDpiChanged(wParam, lParam); + DpiChangedImplHelper(m_hWnd, olddpi, m_dpi); + return result; + } }; -class CTrPropertyPage : public CPropertyPage, public DlgUtils +class CTrPropertyPage + : public DpiAware::CDpiAwareDialog + , public DlgUtils { DECLARE_DYNAMIC(CTrPropertyPage) public: - using CPropertyPage::CPropertyPage; + using DpiAware::CDpiAwareDialog::CDpiAwareDialog; virtual BOOL OnInitDialog(); + + DECLARE_MESSAGE_MAP() + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) { + int olddpi = m_dpi; + LRESULT result = __super::OnDpiChangedBeforeParent(wParam, lParam); + DpiChangedImplHelper(m_hWnd, olddpi, m_dpi); + return result; + } }; -class CTrDialogBar : public CDialogBar, public DlgUtils +class CTrDialogBar + : public DpiAware::CDpiAwareDialog + , public DlgUtils { DECLARE_DYNAMIC(CTrDialogBar) public: @@ -120,4 +146,13 @@ class CTrDialogBar : public CDialogBar, public DlgUtils UINT nStyle, UINT nID); virtual BOOL Create(CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID); + + DECLARE_MESSAGE_MAP() + afx_msg LRESULT OnDpiChangedBeforeParent(WPARAM wParam, LPARAM lParam) + { + int olddpi = m_dpi; + LRESULT result = __super::OnDpiChangedBeforeParent(wParam, lParam); + DpiChangedImplHelper(m_hWnd, olddpi, m_dpi); + return result; + } }; diff --git a/Src/WinMergeU.manifest b/Src/WinMergeU.manifest new file mode 100644 index 00000000000..466356eb27c --- /dev/null +++ b/Src/WinMergeU.manifest @@ -0,0 +1,10 @@ + + + + + True + PerMonitorV2 + + + + diff --git a/Src/WindowsManagerDialog.cpp b/Src/WindowsManagerDialog.cpp index 9932fdd72d6..0c8a704b631 100644 --- a/Src/WindowsManagerDialog.cpp +++ b/Src/WindowsManagerDialog.cpp @@ -141,7 +141,7 @@ void CWindowsManagerDialog::AdjustSize() const int nImgWidth = rect.right - rect.left; const int nSpaceWidth = m_List.GetStringWidth(_T(" ")); - const int nLeftMargin = ::GetSystemMetrics(SM_CXFRAME) * 2 + nSpaceWidth * 4; + const int nLeftMargin = GetSystemMetrics(SM_CXFRAME) * 2 + nSpaceWidth * 4; int nMaxWidth = -1; diff --git a/Src/res/WinMerge.exe.manifest b/Src/res/WinMerge.exe.manifest index fa20920c2b5..d7da91e137f 100755 --- a/Src/res/WinMerge.exe.manifest +++ b/Src/res/WinMerge.exe.manifest @@ -1,5 +1,5 @@ - + WinMerge Application + + + true + PerMonitorV2 + + + diff --git a/Testing/FolderCompare/FolderCompare.vcxproj b/Testing/FolderCompare/FolderCompare.vcxproj index 6db85e855a8..d42ff599c81 100644 --- a/Testing/FolderCompare/FolderCompare.vcxproj +++ b/Testing/FolderCompare/FolderCompare.vcxproj @@ -802,6 +802,7 @@ + diff --git a/Testing/FolderCompare/FolderCompare.vcxproj.filters b/Testing/FolderCompare/FolderCompare.vcxproj.filters index 3b1e4bee0fe..ba0435eb98a 100644 --- a/Testing/FolderCompare/FolderCompare.vcxproj.filters +++ b/Testing/FolderCompare/FolderCompare.vcxproj.filters @@ -344,5 +344,8 @@ Header Files + + Header Files + \ No newline at end of file