* If you discover missing features, or bugs, please note them below.
*
* TODO:
- * - GetListBoxInfo() ReactOS
- * - LB_GETLISTBOXINFO ReactOS
* - LBS_NODATA ReactOS
*/
INT item_height; /* Default item height */
INT page_size; /* Items per listbox page */
INT column_width; /* Column width for multi-column listboxes */
- INT horz_extent; /* Horizontal extent (0 if no hscroll) */
+ INT horz_extent; /* Horizontal extent */
INT horz_pos; /* Horizontal position */
INT nb_tabs; /* Number of tabs in array */
INT *tabs; /* Array of tabs */
INT avg_char_width; /* Average width of characters */
+ INT wheel_remain; /* Left over scroll amount */
BOOL caret_on; /* Is caret on? */
BOOL captured; /* Is mouse captured? */
BOOL in_focus;
if (descr->style & WS_VSCROLL)
SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
- if (descr->horz_extent)
+ if (descr->style & WS_HSCROLL && descr->horz_extent)
{
- info.nMin = 0;
- info.nMax = descr->horz_extent - 1;
info.nPos = descr->horz_pos;
info.nPage = descr->width;
- info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ info.fMask = SIF_POS | SIF_PAGE;
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
- if (descr->style & WS_HSCROLL)
+ SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ }
+ else
+ {
+ if (descr->style & LBS_DISABLENOSCROLL)
+ {
+ info.nMin = 0;
+ info.nMax = 0;
+ info.fMask = SIF_RANGE | SIF_DISABLENOSCROLL;
SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ }
+ else
+ {
+ ShowScrollBar( descr->self, SB_HORZ, FALSE );
+ }
}
}
}
if (index < 0) index = 0;
if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
if (descr->top_item == index) return LB_OKAY;
- if (descr->style & LBS_MULTICOLUMN)
- {
- INT diff = (descr->top_item - index) / descr->page_size * descr->column_width;
- if (scroll && (abs(diff) < descr->width))
- ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
- SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
-
- else
- scroll = FALSE;
- }
- else if (scroll)
+ if (scroll)
{
INT diff;
- if (descr->style & LBS_OWNERDRAWVARIABLE)
+ if (descr->style & LBS_MULTICOLUMN)
+ diff = (descr->top_item - index) / descr->page_size * descr->column_width;
+ else if (descr->style & LBS_OWNERDRAWVARIABLE)
{
INT i;
diff = 0;
else
diff = (descr->top_item - index) * descr->item_height;
- if (abs(diff) < descr->height)
- ScrollWindowEx( descr->self, 0, diff, NULL, NULL, 0, NULL,
- SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
- else
- scroll = FALSE;
+ ScrollWindowEx( descr->self, 0, diff, NULL, NULL, 0, NULL,
+ SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
}
- if (!scroll) InvalidateRect( descr->self, NULL, TRUE );
+ else
+ InvalidateRect( descr->self, NULL, TRUE );
descr->top_item = index;
LISTBOX_UpdateScroll( descr );
return LB_OKAY;
*/
static LRESULT LISTBOX_SetHorizontalExtent( LB_DESCR *descr, INT extent )
{
- if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
+ if (descr->style & LBS_MULTICOLUMN)
return LB_OKAY;
- if (extent <= 0) extent = 1;
if (extent == descr->horz_extent) return LB_OKAY;
TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
descr->horz_extent = extent;
+ if (descr->style & WS_HSCROLL) {
+ SCROLLINFO info;
+ info.cbSize = sizeof(info);
+ info.nMin = 0;
+ info.nMax = descr->horz_extent ? descr->horz_extent - 1 : 0;
+ info.fMask = SIF_RANGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ }
if (descr->horz_pos > extent - descr->width)
LISTBOX_SetHorizontalPos( descr, extent - descr->width );
- else
- LISTBOX_UpdateScroll( descr );
return LB_OKAY;
}
if ((ret = LISTBOX_RemoveItem( descr, (descr->nb_items - 1) )) < 0)
return ret;
}
+
+ InvalidateRect( descr->self, NULL, TRUE );
return LB_OKAY;
}
static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta )
{
- short gcWheelDelta = 0;
UINT pulScrollLines = 3;
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
- gcWheelDelta -= delta;
+ /* if scrolling changes direction, ignore left overs */
+ if ((delta < 0 && descr->wheel_remain < 0) ||
+ (delta > 0 && descr->wheel_remain > 0))
+ descr->wheel_remain += delta;
+ else
+ descr->wheel_remain = delta;
- if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
+ if (descr->wheel_remain && pulScrollLines)
{
- int cLineScroll = (int) min((UINT) descr->page_size, pulScrollLines);
- cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
- LISTBOX_SetTopItem( descr, descr->top_item + cLineScroll, TRUE );
+ int cLineScroll;
+ pulScrollLines = min((UINT) descr->page_size, pulScrollLines);
+ cLineScroll = pulScrollLines * (float)descr->wheel_remain / WHEEL_DELTA;
+ descr->wheel_remain -= WHEEL_DELTA * cLineScroll / (int)pulScrollLines;
+ LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE );
}
return 0;
}
descr->item_height = 1;
descr->page_size = 1;
descr->column_width = 150;
- descr->horz_extent = (descr->style & WS_HSCROLL) ? 1 : 0;
+ descr->horz_extent = 0;
descr->horz_pos = 0;
descr->nb_tabs = 0;
descr->tabs = NULL;
+ descr->wheel_remain = 0;
descr->caret_on = lphc ? FALSE : TRUE;
if (descr->style & LBS_NOSEL) descr->caret_on = FALSE;
descr->in_focus = FALSE;
case LB_SETCURSEL:
if (IS_MULTISELECT(descr)) return LB_ERR;
- LISTBOX_SetCaretIndex( descr, wParam, FALSE );
+ LISTBOX_SetCaretIndex( descr, wParam, TRUE );
ret = LISTBOX_SetSelection( descr, wParam, TRUE, FALSE );
if (ret != LB_ERR) ret = descr->selected_item;
return ret;
LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
return LB_OKAY;
- case LB_GETLISTBOXINFO: //// ReactOS
- if (descr->style & LBS_MULTICOLUMN)
- return descr->column_width;
+ case LB_GETLISTBOXINFO:
+ if (descr->style & LBS_MULTICOLUMN) //// ReactOS
+ return descr->page_size * descr->column_width;
else
- return descr->nb_items;
+ return descr->page_size;
case WM_DESTROY:
return LISTBOX_Destroy( descr );
SEND_NOTIFICATION( descr, LBN_SETFOCUS );
return 0;
case WM_KILLFOCUS:
+ LISTBOX_HandleLButtonUp( descr ); /* Release capture if we have it */
descr->in_focus = FALSE;
+ descr->wheel_remain = 0;
if ((descr->focus_item != -1) && descr->caret_on)
LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
SEND_NOTIFICATION( descr, LBN_KILLFOCUS );