ReactOS  0.4.12-dev-57-g7050ac4
scrollutils.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Clipboard Viewer
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Scrolling related helper functions.
5  * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
6  * Copyright 2015-2018 Hermes Belusca-Maito
7  */
8 
9 #include "precomp.h"
10 
12 {
13  // NOTE: Windows uses an offset of 16 pixels
14  switch (wParam)
15  {
16  case VK_UP:
17  OnScroll(hWnd, SB_VERT, MAKELONG(SB_LINEUP, 0), 5, state);
18  break;
19 
20  case VK_DOWN:
21  OnScroll(hWnd, SB_VERT, MAKELONG(SB_LINEDOWN, 0), 5, state);
22  break;
23 
24  case VK_LEFT:
25  OnScroll(hWnd, SB_HORZ, MAKELONG(SB_LINELEFT, 0), 5, state);
26  break;
27 
28  case VK_RIGHT:
29  OnScroll(hWnd, SB_HORZ, MAKELONG(SB_LINERIGHT, 0), 5, state);
30  break;
31 
32  case VK_PRIOR:
33  OnScroll(hWnd, SB_VERT, MAKELONG(SB_PAGEUP, 0), state->nPageY, state);
34  break;
35 
36  case VK_NEXT:
37  OnScroll(hWnd, SB_VERT, MAKELONG(SB_PAGEDOWN, 0), state->nPageY, state);
38  break;
39 
40  case VK_HOME:
41  {
42  OnScroll(hWnd, SB_HORZ, MAKELONG(SB_LEFT, 0), 0, state);
43  if (GetKeyState(VK_CONTROL) & 0x8000)
44  OnScroll(hWnd, SB_VERT, MAKELONG(SB_TOP, 0), 0, state);
45  break;
46  }
47 
48  case VK_END:
49  {
50  OnScroll(hWnd, SB_HORZ, MAKELONG(SB_RIGHT, 0), 0, state);
51  if (GetKeyState(VK_CONTROL) & 0x8000)
52  OnScroll(hWnd, SB_VERT, MAKELONG(SB_BOTTOM, 0), 0, state);
53  break;
54  }
55 
56  default:
57  break;
58  }
59 }
60 
62 {
63  INT nBar;
64  INT nPage;
65  INT iDelta;
66  UINT uLinesToScroll = state->uLinesToScroll;
67  INT zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
68  WORD sbCode;
69 
70  assert(uMsg == WM_MOUSEWHEEL || uMsg == WM_MOUSEHWHEEL);
71 
72  if (uMsg == WM_MOUSEWHEEL)
73  {
74  nBar = SB_VERT;
75  nPage = state->nPageY;
76 
77  /* Accumulate wheel rotation ticks */
78  zDelta += state->iWheelCarryoverY;
79  state->iWheelCarryoverY = zDelta % WHEEL_DELTA;
80  }
81  else // if (uMsg == WM_MOUSEHWHEEL)
82  {
83  nBar = SB_HORZ;
84  nPage = state->nPageX;
85 
86  /* Accumulate wheel rotation ticks */
87  zDelta += state->iWheelCarryoverX;
88  state->iWheelCarryoverX = zDelta % WHEEL_DELTA;
89  }
90 
91  /*
92  * If the user specified scrolling by pages, do so.
93  * Due to a bug on Windows where, if the window height is
94  * less than the scroll lines delta default value (== 3),
95  * several lines would be skipped when scrolling if we
96  * used the WHEEL_PAGESCROLL value. Instead of this, use
97  * the number of lines per page as the limiting value.
98  * See https://www.strchr.com/corrections_to_raymond_chen_s_wheel_scrolling_code
99  * for more details.
100  */
101  if (uLinesToScroll > nPage) // (uLinesToScroll == WHEEL_PAGESCROLL)
102  uLinesToScroll = nPage;
103  /* If the user specified no wheel scrolling, don't do anything */
104  else if (uLinesToScroll == 0)
105  return;
106 
107  /* Compute the scroll direction and the absolute delta value */
108  if (zDelta > 0)
109  {
110  sbCode = SB_LINEUP;
111  }
112  else
113  {
114  sbCode = SB_LINEDOWN;
115  zDelta = -zDelta;
116  }
117 
118  /* Compute how many lines we should scroll (in absolute value) */
119  iDelta = (INT)uLinesToScroll * zDelta / WHEEL_DELTA;
120 
121  OnScroll(hWnd, nBar, MAKELONG(sbCode, 0), iDelta, state);
122 }
123 
125 {
126  SCROLLINFO si;
127  PINT pCurrent;
128  INT Maximum;
129  INT NewPos;
130  INT OldX, OldY;
131 
132  assert(nBar == SB_HORZ || nBar == SB_VERT);
133 
135  {
136  if (nBar == SB_HORZ)
137  {
139  (WPARAM)hWnd, (LPARAM)wParam);
140  }
141  else // if (nBar == SB_VERT)
142  {
144  (WPARAM)hWnd, (LPARAM)wParam);
145  }
146  return;
147  }
148 
149  if (nBar == SB_HORZ)
150  {
151  pCurrent = &state->CurrentX;
152  Maximum = state->MaxX;
153  }
154  else // if (nBar == SB_VERT)
155  {
156  pCurrent = &state->CurrentY;
157  Maximum = state->MaxY;
158  }
159 
160  ZeroMemory(&si, sizeof(si));
161  si.cbSize = sizeof(si);
163  GetScrollInfo(hWnd, nBar, &si);
164 
165  switch (LOWORD(wParam))
166  {
167  case SB_THUMBPOSITION:
168  case SB_THUMBTRACK:
169  {
170  NewPos = si.nTrackPos;
171  break;
172  }
173 
174  case SB_LINEUP: // SB_LINELEFT:
175  {
176  NewPos = si.nPos - iDelta;
177  break;
178  }
179 
180  case SB_LINEDOWN: // SB_LINERIGHT:
181  {
182  NewPos = si.nPos + iDelta;
183  break;
184  }
185 
186  case SB_PAGEUP: // SB_PAGELEFT:
187  {
188  NewPos = si.nPos - si.nPage;
189  break;
190  }
191 
192  case SB_PAGEDOWN: // SB_PAGERIGHT:
193  {
194  NewPos = si.nPos + si.nPage;
195  break;
196  }
197 
198  case SB_TOP: // SB_LEFT:
199  {
200  NewPos = si.nMin;
201  break;
202  }
203 
204  case SB_BOTTOM: // SB_RIGHT:
205  {
206  NewPos = si.nMax;
207  break;
208  }
209 
210  default:
211  {
212  NewPos = si.nPos;
213  break;
214  }
215  }
216 
217  NewPos = min(max(NewPos, 0), Maximum);
218 
219  if (si.nPos == NewPos)
220  return;
221 
222  OldX = state->CurrentX;
223  OldY = state->CurrentY;
224  *pCurrent = NewPos;
225 
226  ScrollWindowEx(hWnd,
227  OldX - state->CurrentX,
228  OldY - state->CurrentY,
229  NULL,
230  NULL,
231  NULL,
232  NULL,
234  UpdateWindow(hWnd);
235 
236  si.fMask = SIF_POS;
237  si.nPos = NewPos;
238  SetScrollInfo(hWnd, nBar, &si, TRUE);
239 }
240 
242 {
243  UINT uLinesToScroll;
244 
245  if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uLinesToScroll, 0))
246  {
247  /* Default value on Windows */
248  state->uLinesToScroll = 3;
249  }
250  else
251  {
252  state->uLinesToScroll = uLinesToScroll;
253  }
254 }
255 
256 void UpdateWindowScrollState(HWND hWnd, INT nMaxWidth, INT nMaxHeight, LPSCROLLSTATE lpState)
257 {
258  RECT rc;
259  SCROLLINFO si;
260 
261  if (!GetClientRect(hWnd, &rc))
262  SetRectEmpty(&rc);
263 
264  ZeroMemory(&si, sizeof(si));
265  si.cbSize = sizeof(si);
267 
268  lpState->nMaxWidth = nMaxWidth;
269  lpState->MaxX = max(nMaxWidth - rc.right, 0);
270  lpState->CurrentX = min(lpState->CurrentX, lpState->MaxX);
271  lpState->nPageX = rc.right;
272  si.nMin = 0;
273  si.nMax = nMaxWidth;
274  si.nPage = lpState->nPageX;
275  si.nPos = lpState->CurrentX;
276  SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
277 
278  lpState->nMaxHeight = nMaxHeight;
279  lpState->MaxY = max(nMaxHeight - rc.bottom, 0);
280  lpState->CurrentY = min(lpState->CurrentY, lpState->MaxY);
281  lpState->nPageY = rc.bottom;
282  si.nMin = 0;
283  si.nMax = nMaxHeight;
284  si.nPage = lpState->nPageY;
285  si.nPos = lpState->CurrentY;
286  SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
287 }
#define SB_PAGEDOWN
Definition: winuser.h:569
#define WM_HSCROLLCLIPBOARD
Definition: winuser.h:1836
#define SB_PAGEUP
Definition: winuser.h:568
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
#define SIF_RANGE
Definition: winuser.h:1221
#define SB_RIGHT
Definition: winuser.h:576
#define SB_VERT
Definition: winuser.h:553
#define WM_MOUSEWHEEL
Definition: treelist.c:96
#define SB_HORZ
Definition: winuser.h:552
BOOL WINAPI UpdateWindow(_In_ HWND)
HWND hWnd
Definition: settings.c:17
#define SystemParametersInfo
Definition: winuser.h:5724
#define VK_LEFT
Definition: winuser.h:2178
#define assert(x)
Definition: debug.h:53
#define ZeroMemory
Definition: winbase.h:1635
#define VK_DOWN
Definition: winuser.h:2181
#define VK_PRIOR
Definition: winuser.h:2174
LONG right
Definition: windef.h:298
int32_t INT
Definition: typedefs.h:56
#define SIF_PAGE
Definition: winuser.h:1219
#define WM_VSCROLLCLIPBOARD
Definition: winuser.h:1832
WPARAM wParam
Definition: combotst.c:138
#define VK_NEXT
Definition: winuser.h:2175
UINT_PTR WPARAM
Definition: windef.h:207
#define WHEEL_DELTA
Definition: treelist.c:99
CLIPBOARD_GLOBALS Globals
Definition: clipbrd.c:13
#define VK_HOME
Definition: winuser.h:2177
#define VK_UP
Definition: winuser.h:2179
LONG_PTR LPARAM
Definition: windef.h:208
#define CF_OWNERDISPLAY
Definition: constants.h:413
UINT uLinesToScroll
Definition: scrollutils.h:13
#define INT(a)
Definition: assyntax.h:463
#define SW_ERASE
Definition: winuser.h:2534
#define MAKELONG(a, b)
Definition: typedefs.h:248
smooth NULL
Definition: ftsmooth.c:416
void OnScroll(HWND hWnd, INT nBar, WPARAM wParam, INT iDelta, LPSCROLLSTATE state)
Definition: scrollutils.c:124
#define SB_THUMBPOSITION
Definition: winuser.h:572
int WINAPI ScrollWindowEx(_In_ HWND, _In_ int, _In_ int, _In_opt_ LPCRECT, _In_opt_ LPCRECT, _In_opt_ HRGN, _Out_opt_ LPRECT, _In_ UINT)
SHORT WINAPI GetKeyState(_In_ int)
int * PINT
Definition: windef.h:177
#define SB_THUMBTRACK
Definition: winuser.h:573
unsigned int UINT
Definition: ndis.h:50
unsigned short WORD
Definition: ntddk_ex.h:93
LRESULT SendClipboardOwnerMessage(IN BOOL bUnicode, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
Definition: cliputils.c:12
BOOL WINAPI GetScrollInfo(_In_ HWND, _In_ int, _Inout_ LPSCROLLINFO)
void UpdateLinesToScroll(LPSCROLLSTATE state)
Definition: scrollutils.c:241
static int state
Definition: maze.c:121
#define SB_LEFT
Definition: winuser.h:575
BOOL WINAPI SetRectEmpty(_Out_ LPRECT)
#define SB_LINERIGHT
Definition: winuser.h:567
#define SW_INVALIDATE
Definition: winuser.h:2533
void OnMouseScroll(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state)
Definition: scrollutils.c:61
#define SIF_POS
Definition: winuser.h:1220
#define VK_RIGHT
Definition: winuser.h:2180
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define SB_TOP
Definition: winuser.h:578
INT iWheelCarryoverY
Definition: scrollutils.h:15
#define SIF_TRACKPOS
Definition: winuser.h:1223
#define min(a, b)
Definition: monoChain.cc:55
#define SB_LINEDOWN
Definition: winuser.h:565
#define SB_LINEUP
Definition: winuser.h:564
#define SB_BOTTOM
Definition: winuser.h:577
#define VK_CONTROL
Definition: winuser.h:2157
INT iWheelCarryoverX
Definition: scrollutils.h:14
void UpdateWindowScrollState(HWND hWnd, INT nMaxWidth, INT nMaxHeight, LPSCROLLSTATE lpState)
Definition: scrollutils.c:256
#define SIF_DISABLENOSCROLL
Definition: winuser.h:1222
#define SB_LINELEFT
Definition: winuser.h:566
LONG bottom
Definition: windef.h:299
void OnKeyScroll(HWND hWnd, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state)
Definition: scrollutils.c:11
LPARAM lParam
Definition: combotst.c:139
#define LOWORD(l)
Definition: pedump.c:82
int WINAPI SetScrollInfo(_In_ HWND, _In_ int, _In_ LPCSCROLLINFO, _In_ BOOL)
#define VK_END
Definition: winuser.h:2176
UINT uDisplayFormat
Definition: precomp.h:47