126 lines
2.6 KiB
C
126 lines
2.6 KiB
C
// 29 november 2014
|
|
|
|
static void hscrollto(struct table *t, intptr_t newpos)
|
|
{
|
|
SCROLLINFO si;
|
|
RECT scrollArea;
|
|
|
|
if (newpos < 0)
|
|
newpos = 0;
|
|
if (newpos > (t->width - t->hpagesize))
|
|
newpos = (t->width - t->hpagesize);
|
|
|
|
scrollArea = realClientRect(t);
|
|
|
|
// negative because ScrollWindowEx() is "backwards"
|
|
if (ScrollWindowEx(t->hwnd, -(newpos - t->hpos), 0,
|
|
&scrollArea, &scrollArea, NULL, NULL,
|
|
SW_ERASE | SW_INVALIDATE) == ERROR)
|
|
abort();
|
|
t->hpos = newpos;
|
|
// TODO text in header controls doesn't redraw?
|
|
|
|
// TODO put this in a separate function? same for vscroll?
|
|
ZeroMemory(&si, sizeof (SCROLLINFO));
|
|
si.cbSize = sizeof (SCROLLINFO);
|
|
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
|
|
si.nPage = t->hpagesize;
|
|
si.nMin = 0;
|
|
si.nMax = t->width - 1; // nMax is inclusive
|
|
si.nPos = t->hpos;
|
|
SetScrollInfo(t->hwnd, SB_HORZ, &si, TRUE);
|
|
|
|
// and finally reposition the header
|
|
repositionHeader(t);
|
|
}
|
|
|
|
static void hscrollby(struct table *t, intptr_t n)
|
|
{
|
|
hscrollto(t, t->hpos + n);
|
|
}
|
|
|
|
// unfortunately horizontal wheel scrolling was only added in Vista
|
|
|
|
static void hscroll(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_HORZ, &si) == 0)
|
|
abort();
|
|
|
|
newpos = t->hpos;
|
|
switch (LOWORD(wParam)) {
|
|
case SB_LEFT:
|
|
newpos = 0;
|
|
break;
|
|
case SB_RIGHT:
|
|
newpos = t->width - t->hpagesize;
|
|
break;
|
|
case SB_LINELEFT:
|
|
newpos--;
|
|
break;
|
|
case SB_LINERIGHT:
|
|
newpos++;
|
|
break;
|
|
case SB_PAGELEFT:
|
|
newpos -= t->hpagesize;
|
|
break;
|
|
case SB_PAGERIGHT:
|
|
newpos += t->hpagesize;
|
|
break;
|
|
case SB_THUMBPOSITION:
|
|
newpos = (intptr_t) (si.nPos);
|
|
break;
|
|
case SB_THUMBTRACK:
|
|
newpos = (intptr_t) (si.nTrackPos);
|
|
}
|
|
|
|
hscrollto(t, newpos);
|
|
}
|
|
|
|
static void recomputeHScroll(struct table *t)
|
|
{
|
|
HDITEMW item;
|
|
intptr_t i;
|
|
int width = 0;
|
|
RECT r;
|
|
SCROLLINFO si;
|
|
|
|
// TODO count dividers
|
|
for (i = 0; i < t->nColumns; i++) {
|
|
ZeroMemory(&item, sizeof (HDITEMW));
|
|
item.mask = HDI_WIDTH;
|
|
if (SendMessageW(t->header, HDM_GETITEM, (WPARAM) i, (LPARAM) (&item)) == FALSE)
|
|
abort();
|
|
width += item.cxy;
|
|
}
|
|
t->width = (intptr_t) width;
|
|
|
|
if (GetClientRect(t->hwnd, &r) == 0)
|
|
abort();
|
|
t->hpagesize = r.right - r.left;
|
|
|
|
ZeroMemory(&si, sizeof (SCROLLINFO));
|
|
si.cbSize = sizeof (SCROLLINFO);
|
|
si.fMask = SIF_PAGE | SIF_RANGE;
|
|
si.nPage = t->hpagesize;
|
|
si.nMin = 0;
|
|
si.nMax = t->width - 1; // - 1 because endpoints inclusive
|
|
SetScrollInfo(t->hwnd, SB_HORZ, &si, TRUE);
|
|
}
|
|
|
|
HANDLER(hscroll)
|
|
{
|
|
switch (uMsg) {
|
|
case WM_HSCROLL:
|
|
hscroll(t, wParam);
|
|
*lResult = 0;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|