113 lines
2.5 KiB
C
113 lines
2.5 KiB
C
// 29 november 2014
|
|
|
|
static void vscrollto(struct table *t, intptr_t newpos)
|
|
{
|
|
SCROLLINFO si;
|
|
RECT scrollArea;
|
|
|
|
if (newpos < 0)
|
|
newpos = 0;
|
|
if (newpos > (t->count - t->pagesize))
|
|
newpos = (t->count - t->pagesize);
|
|
|
|
scrollArea = realClientRect(t);
|
|
|
|
// negative because ScrollWindowEx() is "backwards"
|
|
if (ScrollWindowEx(t->hwnd, 0, (-(newpos - t->firstVisible)) * rowHeight(t),
|
|
&scrollArea, &scrollArea, NULL, NULL,
|
|
SW_ERASE | SW_INVALIDATE) == ERROR)
|
|
abort();
|
|
t->firstVisible = newpos;
|
|
|
|
ZeroMemory(&si, sizeof (SCROLLINFO));
|
|
si.cbSize = sizeof (SCROLLINFO);
|
|
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
|
|
si.nPage = t->pagesize;
|
|
si.nMin = 0;
|
|
si.nMax = t->count - 1; // nMax is inclusive
|
|
si.nPos = t->firstVisible;
|
|
SetScrollInfo(t->hwnd, SB_VERT, &si, TRUE);
|
|
}
|
|
|
|
static void vscrollby(struct table *t, intptr_t n)
|
|
{
|
|
vscrollto(t, t->firstVisible + n);
|
|
}
|
|
|
|
static void wheelscroll(struct table *t, WPARAM wParam)
|
|
{
|
|
int delta;
|
|
int lines;
|
|
UINT scrollAmount;
|
|
|
|
delta = GET_WHEEL_DELTA_WPARAM(wParam);
|
|
if (SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &scrollAmount, 0) == 0)
|
|
abort();
|
|
if (scrollAmount == WHEEL_PAGESCROLL)
|
|
scrollAmount = t->pagesize;
|
|
if (scrollAmount == 0) // no mouse wheel scrolling (or t->pagesize == 0)
|
|
return;
|
|
// the rest of this is basically http://blogs.msdn.com/b/oldnewthing/archive/2003/08/07/54615.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/08/11/54624.aspx
|
|
// see those pages for information on subtleties
|
|
delta += t->wheelCarry;
|
|
lines = delta * ((int) scrollAmount) / WHEEL_DELTA;
|
|
t->wheelCarry = delta - lines * WHEEL_DELTA / ((int) scrollAmount);
|
|
vscrollby(t, -lines);
|
|
}
|
|
|
|
static void vscroll(struct table *t, WPARAM wParam)
|
|
{
|
|
SCROLLINFO si;
|
|
intptr_t newpos;
|
|
|
|
ZeroMemory(&si, sizeof (SCROLLINFO));
|
|
si.cbSize = sizeof (SCROLLINFO);
|
|
si.fMask = SIF_POS | SIF_TRACKPOS;
|
|
if (GetScrollInfo(t->hwnd, SB_VERT, &si) == 0)
|
|
abort();
|
|
|
|
newpos = t->firstVisible;
|
|
switch (LOWORD(wParam)) {
|
|
case SB_TOP:
|
|
newpos = 0;
|
|
break;
|
|
case SB_BOTTOM:
|
|
newpos = t->count - t->pagesize;
|
|
break;
|
|
case SB_LINEUP:
|
|
newpos--;
|
|
break;
|
|
case SB_LINEDOWN:
|
|
newpos++;
|
|
break;
|
|
case SB_PAGEUP:
|
|
newpos -= t->pagesize;
|
|
break;
|
|
case SB_PAGEDOWN:
|
|
newpos += t->pagesize;
|
|
break;
|
|
case SB_THUMBPOSITION:
|
|
newpos = (intptr_t) (si.nPos);
|
|
break;
|
|
case SB_THUMBTRACK:
|
|
newpos = (intptr_t) (si.nTrackPos);
|
|
}
|
|
|
|
vscrollto(t, newpos);
|
|
}
|
|
|
|
HANDLER(vscroll)
|
|
{
|
|
switch (uMsg) {
|
|
case WM_VSCROLL:
|
|
vscroll(t, wParam);
|
|
*lResult = 0;
|
|
return TRUE;
|
|
case WM_MOUSEWHEEL:
|
|
wheelscroll(t, wParam);
|
|
*lResult = 0;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|