reactos/base/applications/mspaint/scrollbox.cpp
Ștefan Fulea 3d48aa2992 [MSPAINT] Fix scrollbar presence on canvas/view fitting (#878)
* [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).
2018-11-16 23:05:51 +01:00

182 lines
5.8 KiB
C++

/*
* PROJECT: PAINT for ReactOS
* LICENSE: LGPL
* FILE: base/applications/mspaint/scrollbox.cpp
* PURPOSE: Functionality surrounding the scroll box window class
* PROGRAMMERS: Benedikt Freisen
*/
/* 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()
{
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.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.nMin = 0;
si.nMax = sizeImageArea.cx +
(sp_mx[vmode][hmode].bVert == TRUE ? HSCROLL_WIDTH : 0);
si.nPage = sizeScrollBox.cx;
scrollboxWindow.SetScrollInfo(SB_HORZ, &si);
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),
sizeImageArea.cx, sizeImageArea.cy, TRUE);
}
LRESULT CScrollboxWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (m_hWnd == scrollboxWindow.m_hWnd)
{
UpdateScrollbox();
}
return 0;
}
LRESULT CScrollboxWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (m_hWnd == scrollboxWindow.m_hWnd)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
scrollboxWindow.GetScrollInfo(SB_HORZ, &si);
switch (LOWORD(wParam))
{
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
si.nPos = HIWORD(wParam);
break;
case SB_LINELEFT:
si.nPos -= 5;
break;
case SB_LINERIGHT:
si.nPos += 5;
break;
case SB_PAGELEFT:
si.nPos -= si.nPage;
break;
case SB_PAGERIGHT:
si.nPos += si.nPage;
break;
}
scrollboxWindow.SetScrollInfo(SB_HORZ, &si);
scrlClientWindow.MoveWindow(-scrollboxWindow.GetScrollPos(SB_HORZ),
-scrollboxWindow.GetScrollPos(SB_VERT), imageModel.GetWidth() * toolsModel.GetZoom() / 1000 + 6,
imageModel.GetHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
}
return 0;
}
LRESULT CScrollboxWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (m_hWnd == scrollboxWindow.m_hWnd)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
scrollboxWindow.GetScrollInfo(SB_VERT, &si);
switch (LOWORD(wParam))
{
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
si.nPos = HIWORD(wParam);
break;
case SB_LINEUP:
si.nPos -= 5;
break;
case SB_LINEDOWN:
si.nPos += 5;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
}
scrollboxWindow.SetScrollInfo(SB_VERT, &si);
scrlClientWindow.MoveWindow(-scrollboxWindow.GetScrollPos(SB_HORZ),
-scrollboxWindow.GetScrollPos(SB_VERT), imageModel.GetWidth() * toolsModel.GetZoom() / 1000 + 6,
imageModel.GetHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
}
return 0;
}
LRESULT CScrollboxWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
selectionWindow.ShowWindow(SW_HIDE);
pointSP = 0; // resets the point-buffer of the polygon and bezier functions
return 0;
}