Implemented mouse-wheel scrolling.

This commit is contained in:
Pietro Gagliardi 2014-10-20 10:21:47 -04:00
parent b7e752196a
commit 0029e7127f
1 changed files with 59 additions and 21 deletions

View File

@ -31,15 +31,15 @@ struct table {
intptr_t count; intptr_t count;
intptr_t firstVisible; intptr_t firstVisible;
intptr_t pagesize; intptr_t pagesize;
int wheelCarry;
}; };
static void vscroll(struct table *t, WPARAM wParam) static void vscrollto(struct table *t, intptr_t newpos)
{ {
HFONT thisfont, prevfont; HFONT thisfont, prevfont;
TEXTMETRICW tm; TEXTMETRICW tm;
HDC dc; HDC dc;
SCROLLINFO si; SCROLLINFO si;
intptr_t newpos;
// TODO split into a function // TODO split into a function
dc = GetDC(t->hwnd); dc = GetDC(t->hwnd);
@ -56,6 +56,59 @@ static void vscroll(struct table *t, WPARAM wParam)
if (ReleaseDC(t->hwnd, dc) == 0) if (ReleaseDC(t->hwnd, dc) == 0)
abort(); abort();
if (newpos < 0)
newpos = 0;
if (newpos > (t->count - t->pagesize))
newpos = (t->count - t->pagesize);
// negative because ScrollWindowEx() is "backwards"
if (ScrollWindowEx(t->hwnd, 0, (-(newpos - t->firstVisible)) * tm.tmHeight,
NULL, NULL, 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)); ZeroMemory(&si, sizeof (SCROLLINFO));
si.cbSize = sizeof (SCROLLINFO); si.cbSize = sizeof (SCROLLINFO);
si.fMask = SIF_POS | SIF_TRACKPOS; si.fMask = SIF_POS | SIF_TRACKPOS;
@ -88,26 +141,8 @@ static void vscroll(struct table *t, WPARAM wParam)
case SB_THUMBTRACK: case SB_THUMBTRACK:
newpos = (intptr_t) (si.nTrackPos); newpos = (intptr_t) (si.nTrackPos);
} }
if (newpos < 0)
newpos = 0;
if (newpos > (t->count - t->pagesize))
newpos = (t->count - t->pagesize);
// negative because ScrollWindowEx() is "backwards" vscrollto(t, newpos);
if (ScrollWindowEx(t->hwnd, 0, (-(newpos - t->firstVisible)) * tm.tmHeight,
NULL, NULL, 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 resize(struct table *t) static void resize(struct table *t)
@ -251,6 +286,9 @@ t->selected = 5;t->count=100;//TODO
case WM_VSCROLL: case WM_VSCROLL:
vscroll(t, wParam); vscroll(t, wParam);
return 0; return 0;
case WM_MOUSEWHEEL:
wheelscroll(t, wParam);
return 0;
case WM_SIZE: case WM_SIZE:
resize(t); resize(t);
return 0; return 0;