[MSPAINT] Fix scrollbar presence on canvas/view fitting (#878)
authorȘtefan Fulea <reactos-contributor@programmer.net>
Fri, 16 Nov 2018 22:05:51 +0000 (00:05 +0200)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Fri, 16 Nov 2018 22:05:51 +0000 (23:05 +0100)
* [MSPAINT] Fix scrollbar presence on canvas/view fitting

This is a small fix for a scrollbar related edge case functionality exhibited in mspaint (and in a lesser degree also elsewhere in instances of) scrollbar controlled content. As known, the scrollbars presence is given by the size ratio between the accommodating outer frame and the scroll-controlled contents inside it, and it works for the most part. There is, however, a case where the presence of both toolbars is kept even when the contents would fit the frame (if not for the scrollbars themselves that increase the size of the contents' area). Please take the current commit as a demo fix and a provisional correction for mspaint (as I think that the proper fix should reside in common controls).

* [MSPAINT] Fix a small mistake and improve readability in UpdateScrollbox()

Although with no visible impact on testing, I've used a wrong constant related to vertical scrollbox width in one instance (SM_CXHSCROLL instead of SM_CXVSCROLL), and this fixes it. Also, prefer using constants, to improve a bit readability and performance (by avoiding repeated function calls).

base/applications/mspaint/scrollbox.cpp

index b0ef737..351c59c 100644 (file)
@@ -9,31 +9,89 @@
 /* INCLUDES *********************************************************/
 
 #include "precomp.h"
+#include <atltypes.h>
+
+/*
+ * Scrollbar functional modes:
+ * 0  view < canvas
+ * 1  view < canvas + scroll width
+ * 2  view >= canvas + scroll width
+ *
+ * Matrix of scrollbar presence (VERTICAL,HORIZONTAL) given by
+ * vertical & horizontal scrollbar modes (view:canvas ratio):
+ *
+ *           horizontal mode
+ *             |      0      |      1      |      2
+ * vertical ---+-------------+-------------+------------
+ *   mode    0 |  TRUE,TRUE  |  TRUE,TRUE  |  TRUE,FALSE
+ *          ---+-------------+-------------+------------
+ *           1 |  TRUE,TRUE  | FALSE,FALSE | FALSE,FALSE
+ *          ---+-------------+-------------+------------
+ *           2 | FALSE,TRUE  | FALSE,FALSE | FALSE,FALSE
+ */
+
+struct ScrollbarPresence
+{
+    BOOL bVert;
+    BOOL bHoriz;
+};
+
+CONST ScrollbarPresence sp_mx[3][3] =
+{
+    { {  TRUE,TRUE  }, {  TRUE,TRUE  }, {  TRUE,FALSE } },
+    { {  TRUE,TRUE  }, { FALSE,FALSE }, { FALSE,FALSE } },
+    { { FALSE,TRUE  }, { FALSE,FALSE }, { FALSE,FALSE } }
+};
+
+CONST INT HSCROLL_WIDTH = ::GetSystemMetrics(SM_CYHSCROLL);
+CONST INT VSCROLL_WIDTH = ::GetSystemMetrics(SM_CXVSCROLL);
+
 
 /* FUNCTIONS ********************************************************/
 
 void
 UpdateScrollbox()
 {
-    RECT clientRectScrollbox;
-    RECT clientRectImageArea;
+    CONST INT EXTRASIZE = 5; /* 3 px of selection markers + 2 px of border */
+
+    CRect tempRect;
+    CSize sizeImageArea;
+    CSize sizeScrollBox;
+    INT vmode, hmode;
     SCROLLINFO si;
-    scrollboxWindow.GetClientRect(&clientRectScrollbox);
-    imageArea.GetClientRect(&clientRectImageArea);
+
+    scrollboxWindow.GetWindowRect(&tempRect);
+    sizeScrollBox = CSize(tempRect.Width(), tempRect.Height());
+
+    imageArea.GetClientRect(&tempRect);
+    sizeImageArea = CSize(tempRect.Width(), tempRect.Height());
+    sizeImageArea += CSize(EXTRASIZE * 2, EXTRASIZE * 2);
+
+    /* show/hide the scrollbars */
+    vmode = (sizeScrollBox.cy < sizeImageArea.cy ? 0 :
+                (sizeScrollBox.cy < sizeImageArea.cy + HSCROLL_WIDTH ? 1 : 2));
+    hmode = (sizeScrollBox.cx < sizeImageArea.cx ? 0 :
+                (sizeScrollBox.cx < sizeImageArea.cx + VSCROLL_WIDTH ? 1 : 2));
+    scrollboxWindow.ShowScrollBar(SB_VERT, sp_mx[vmode][hmode].bVert);
+    scrollboxWindow.ShowScrollBar(SB_HORZ, sp_mx[vmode][hmode].bHoriz);
+
     si.cbSize = sizeof(SCROLLINFO);
     si.fMask  = SIF_PAGE | SIF_RANGE;
-    si.nMax   = clientRectImageArea.right + 6 - 1;
     si.nMin   = 0;
-    si.nPage  = clientRectScrollbox.right;
+
+    si.nMax   = sizeImageArea.cx +
+                    (sp_mx[vmode][hmode].bVert == TRUE ? HSCROLL_WIDTH : 0);
+    si.nPage  = sizeScrollBox.cx;
     scrollboxWindow.SetScrollInfo(SB_HORZ, &si);
-    scrollboxWindow.GetClientRect(&clientRectScrollbox);
-    si.nMax   = clientRectImageArea.bottom + 6 - 1;
-    si.nPage  = clientRectScrollbox.bottom;
+
+    si.nMax   = sizeImageArea.cy +
+                    (sp_mx[vmode][hmode].bHoriz == TRUE ? VSCROLL_WIDTH : 0);
+    si.nPage  = sizeScrollBox.cy;
     scrollboxWindow.SetScrollInfo(SB_VERT, &si);
-    scrlClientWindow.MoveWindow(
-        -scrollboxWindow.GetScrollPos(SB_HORZ), -scrollboxWindow.GetScrollPos(SB_VERT),
-        max(clientRectImageArea.right + 6, clientRectScrollbox.right),
-        max(clientRectImageArea.bottom + 6, clientRectScrollbox.bottom), TRUE);
+
+    scrlClientWindow.MoveWindow(-scrollboxWindow.GetScrollPos(SB_HORZ),
+                                -scrollboxWindow.GetScrollPos(SB_VERT),
+                                sizeImageArea.cx, sizeImageArea.cy, TRUE);
 }
 
 LRESULT CScrollboxWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)