Changelog: scrollbar.c - add a separate handler routine for each message type The patch was developed without CVS access use patch -p1 from within the top level wine directory to apply License: X11 Andrew --- wine-20020904/controls/scroll.c Tue Oct 8 17:06:43 2002 +++ wine/controls/scroll.c Tue Oct 8 17:52:48 2002 @@ -475,6 +475,7 @@ TOP_ARROW(infoPtr->flags, top_pressed) : LEFT_ARROW(infoPtr->flags, top_pressed)); + if (!hUpArrow) SCROLL_LoadBitmaps(); SetStretchBltMode( hdc, STRETCH_DELETESCANS ); StretchBlt( hdc, rect->left, rect->top, vertical ? rect->right-rect->left : arrowSize, @@ -904,24 +905,30 @@ * SCROLL_HandleKbdEvent * * Handle a keyboard event (only for SB_CTL scrollbars). + * if key event is received, the scrollbar has the focus */ -static void SCROLL_HandleKbdEvent( HWND hwnd, WPARAM wParam ) -{ - WPARAM msg; - - switch(wParam) - { - case VK_PRIOR: msg = SB_PAGEUP; break; - case VK_NEXT: msg = SB_PAGEDOWN; break; - case VK_HOME: msg = SB_TOP; break; - case VK_END: msg = SB_BOTTOM; break; - case VK_UP: msg = SB_LINEUP; break; - case VK_DOWN: msg = SB_LINEDOWN; break; - default: return; - } - SendMessageW( GetParent(hwnd), - (GetWindowLongA( hwnd, GWL_STYLE ) & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL, - msg, (LPARAM)hwnd ); +static void SCROLL_HandleKbdEvent( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +WPARAM wParam /* [in] Variable input including enable state */, +LPARAM lParam /* [in] Variable input including input point */) +{ + TRACE("hwnd=%04x wParam=%d lParam=%ld\n", hwnd, wParam, lParam); + + /* hide caret on first KEYDOWN to prevent flicker */ + if ((lParam & PFD_DOUBLEBUFFER_DONTCARE) == 0) HideCaret(hwnd); + switch(wParam) + { + case VK_PRIOR: wParam = SB_PAGEUP; break; + case VK_NEXT: wParam = SB_PAGEDOWN; break; + case VK_HOME: wParam = SB_TOP; break; + case VK_END: wParam = SB_BOTTOM; break; + case VK_UP: wParam = SB_LINEUP; break; + case VK_DOWN: wParam = SB_LINEDOWN; break; + default: return; + } + SendMessageW(GetParent(hwnd), + ((GetWindowLongA( hwnd, GWL_STYLE ) & SBS_VERT) ? + WM_VSCROLL : WM_HSCROLL), wParam, (LPARAM)hwnd); } @@ -1209,223 +1216,250 @@ } -/*********************************************************************** - * ScrollBarWndProc +/************************************************************************* + * SCROLL_SetFocus + * + * Add focus caret to a CTL scroll bar */ -static LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +static void WINAPI SCROLL_SetFocus( +HWND hwnd /* [in] Handle of window with scrollbar(s) */) { - if (!IsWindow( hwnd )) return 0; - - switch(message) - { - case WM_CREATE: - { - SCROLLBAR_INFO *infoPtr; - CREATESTRUCTW *lpCreat = (CREATESTRUCTW *)lParam; - - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, SB_CTL ))) return -1; - if (lpCreat->style & WS_DISABLED) - { - TRACE("Created WS_DISABLED scrollbar\n"); - infoPtr->flags = ESB_DISABLE_BOTH; - } - - if (lpCreat->style & SBS_SIZEBOX) - { - FIXME("Unimplemented style SBS_SIZEBOX.\n" ); - return 0; - } - if (lpCreat->style & SBS_VERT) - { - if (lpCreat->style & SBS_LEFTALIGN) - MoveWindow( hwnd, lpCreat->x, lpCreat->y, - GetSystemMetrics(SM_CXVSCROLL)+1, lpCreat->cy, FALSE ); - else if (lpCreat->style & SBS_RIGHTALIGN) - MoveWindow( hwnd, - lpCreat->x+lpCreat->cx-GetSystemMetrics(SM_CXVSCROLL)-1, - lpCreat->y, - GetSystemMetrics(SM_CXVSCROLL)+1, lpCreat->cy, FALSE ); - } - else /* SBS_HORZ */ - { - if (lpCreat->style & SBS_TOPALIGN) - MoveWindow( hwnd, lpCreat->x, lpCreat->y, - lpCreat->cx, GetSystemMetrics(SM_CYHSCROLL)+1, FALSE ); - else if (lpCreat->style & SBS_BOTTOMALIGN) - MoveWindow( hwnd, - lpCreat->x, - lpCreat->y+lpCreat->cy-GetSystemMetrics(SM_CYHSCROLL)-1, - lpCreat->cx, GetSystemMetrics(SM_CYHSCROLL)+1, FALSE ); - } - } - if (!hUpArrow) SCROLL_LoadBitmaps(); - TRACE("ScrollBar creation, hwnd=%04x\n", hwnd ); - return 0; - - case WM_ENABLE: - { - SCROLLBAR_INFO *infoPtr; - if ((infoPtr = SCROLL_GetScrollInfo( hwnd, SB_CTL ))) - { - infoPtr->flags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; - SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE); - } + /* Create a caret when a ScrollBar get focus */ + RECT rect; + int arrowSize, thumbSize, thumbPos, vertical; + vertical = SCROLL_GetScrollBarRect( hwnd, SB_CTL, &rect, + &arrowSize, &thumbSize, &thumbPos ); + if (!vertical) + { + CreateCaret(hwnd,1, thumbSize-2, rect.bottom-rect.top-2); + SetCaretPos(thumbPos+1, rect.top+1); } - return 0; - - case WM_LBUTTONDOWN: - { - POINT pt; - pt.x = SLOWORD(lParam); - pt.y = SHIWORD(lParam); - SCROLL_TrackScrollBar( hwnd, SB_CTL, pt ); + else + { + CreateCaret(hwnd,1, rect.right-rect.left-2,thumbSize-2); + SetCaretPos(rect.top+1, thumbPos+1); } - break; - case WM_LBUTTONUP: - case WM_MOUSEMOVE: - case WM_SYSTIMER: - { - POINT pt; - pt.x = SLOWORD(lParam); - pt.y = SHIWORD(lParam); - SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt ); - } - break; - - /* if key event is received, the scrollbar has the focus */ - case WM_KEYDOWN: - /* hide caret on first KEYDOWN to prevent flicker */ - if ((lParam & 0x40000000)==0) - HideCaret(hwnd); - SCROLL_HandleKbdEvent( hwnd, wParam ); - break; + ShowCaret(hwnd); +} - case WM_KEYUP: - ShowCaret(hwnd); - break; - case WM_SETFOCUS: - { - /* Create a caret when a ScrollBar get focus */ - RECT rect; - int arrowSize, thumbSize, thumbPos, vertical; - vertical = SCROLL_GetScrollBarRect( hwnd, SB_CTL, &rect, - &arrowSize, &thumbSize, &thumbPos ); - if (!vertical) - { - CreateCaret(hwnd,1, thumbSize-2, rect.bottom-rect.top-2); - SetCaretPos(thumbPos+1, rect.top+1); - } - else - { - CreateCaret(hwnd,1, rect.right-rect.left-2,thumbSize-2); - SetCaretPos(rect.top+1, thumbPos+1); - } - ShowCaret(hwnd); - } - break; +/************************************************************************* + * SCROLL_KillFocus + * + * Remove focus caret to a CTL scroll bar + */ +static void SCROLL_KillFocus( +HWND hwnd /* [in] Handle of window with scrollbar(s) */) +{ + RECT rect; + int arrowSize, thumbSize, thumbPos, vertical; + vertical = SCROLL_GetScrollBarRect( hwnd, SB_CTL, &rect,&arrowSize, &thumbSize, &thumbPos ); + if (!vertical) + { + rect.left=thumbPos+1; + rect.right=rect.left+thumbSize; + } + else + { + rect.top=thumbPos+1; + rect.bottom=rect.top+thumbSize; + } + HideCaret(hwnd); + InvalidateRect(hwnd,&rect,0); + DestroyCaret(); +} - case WM_KILLFOCUS: - { - RECT rect; - int arrowSize, thumbSize, thumbPos, vertical; - vertical = SCROLL_GetScrollBarRect( hwnd, SB_CTL, &rect,&arrowSize, &thumbSize, &thumbPos ); - if (!vertical){ - rect.left=thumbPos+1; - rect.right=rect.left+thumbSize; - } - else - { - rect.top=thumbPos+1; - rect.bottom=rect.top+thumbSize; - } - HideCaret(hwnd); - InvalidateRect(hwnd,&rect,0); - DestroyCaret(); - } - break; - case WM_ERASEBKGND: - return 1; +/*********************************************************************** + * SCROLL_CreateScrollBar + * + * Create a scroll bar + */ +static void SCROLL_CreateScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +LPCREATESTRUCTW lpCreate /* [in] The style and place of the scroll bar */) +{ + POINT pos, size; + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, SB_CTL); + if (!info) return; + + TRACE("hwnd=%04x lpCreate=%p\n", hwnd, lpCreate); + + if (lpCreate->style & WS_DISABLED) + { + info->flags = ESB_DISABLE_BOTH; + TRACE("Created WS_DISABLED scrollbar\n"); + } + if (lpCreate->style & SBS_SIZEBOX) + { + FIXME("Unimplemented style SBS_SIZEBOX.\n" ); + return; + } - case WM_GETDLGCODE: - return DLGC_WANTARROWS; /* Windows returns this value */ + /* copy the desired positions and size */ + pos.x = lpCreate->x; pos.y = lpCreate->y; + size.x = lpCreate->cx; size.y = lpCreate->cy; + + /* move position based on style */ + if (lpCreate->style & SBS_RIGHTALIGN) + pos.x += size.x - GetSystemMetrics(SM_CXVSCROLL) - 1; + else if (lpCreate->style & SBS_BOTTOMALIGN) + pos.y += size.y - GetSystemMetrics(SM_CYHSCROLL) - 1; + + /* change size based on style */ + if (lpCreate->style & SBS_VERT) + size.x = GetSystemMetrics(SM_CXVSCROLL) + 1; + else + size.y = GetSystemMetrics(SM_CYHSCROLL) + 1; + + MoveWindow(hwnd, pos.x, pos.y, size.x, size.y, FALSE); +} - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint( hwnd, &ps ); - SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, TRUE, TRUE ); - EndPaint( hwnd, &ps ); - } - break; - case SBM_SETPOS16: - case SBM_SETPOS: - return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam ); - - case SBM_GETPOS16: - case SBM_GETPOS: - return GetScrollPos( hwnd, SB_CTL ); - - case SBM_SETRANGE16: - SetScrollRange( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam), - wParam /* FIXME: Is this correct? */ ); - return 0; - - case SBM_SETRANGE: - { - INT oldPos = GetScrollPos( hwnd, SB_CTL ); - SetScrollRange( hwnd, SB_CTL, wParam, lParam, FALSE ); - if (oldPos != GetScrollPos( hwnd, SB_CTL )) return oldPos; - } - return 0; - - case SBM_GETRANGE16: - FIXME("don't know how to handle SBM_GETRANGE16 (wp=%04x,lp=%08lx)\n", wParam, lParam ); - return 0; - - case SBM_GETRANGE: - GetScrollRange( hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam ); - return 0; - - case SBM_ENABLE_ARROWS16: - case SBM_ENABLE_ARROWS: - return EnableScrollBar( hwnd, SB_CTL, wParam ); - - case SBM_SETRANGEREDRAW: - { - INT oldPos = GetScrollPos( hwnd, SB_CTL ); - SetScrollRange( hwnd, SB_CTL, wParam, lParam, TRUE ); - if (oldPos != GetScrollPos( hwnd, SB_CTL )) return oldPos; - } - return 0; - - case SBM_SETSCROLLINFO: - return SetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam ); - - case SBM_GETSCROLLINFO: - return GetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam ); - - case 0x00e5: - case 0x00e7: - case 0x00e8: - case 0x00eb: - case 0x00ec: - case 0x00ed: - case 0x00ee: - case 0x00ef: - ERR("unknown Win32 msg %04x wp=%08x lp=%08lx\n", - message, wParam, lParam ); - break; +/************************************************************************* + * SCROLL_SetScrollRange (USER32.@) + * + * Set scroll range returning old value of position if it has changed + * + * RETURNS + * + * The old position if the position has changed + */ +static LRESULT SCROLL_SetScrollRange( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT minVal /* [in] New minimum value */, +INT maxVal /* [in] New maximum value */, +BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */) +{ + INT oldPos = GetScrollPos(hwnd, SB_CTL); + + SetScrollRange(hwnd, SB_CTL, minVal, maxVal, bRedraw); + if (oldPos != GetScrollPos(hwnd, SB_CTL)) + return oldPos; + else + return 0; +} - default: - if (message >= WM_USER) - WARN("unknown msg %04x wp=%04x lp=%08lx\n", - message, wParam, lParam ); - return DefWindowProcW( hwnd, message, wParam, lParam ); - } - return 0; +/*********************************************************************** + * ScrollBarWndProc + * + * The routine for handling window events + * + * RETURNS + * Zero +*/ +static LRESULT WINAPI ScrollBarWndProc( +HWND hwnd /* [in] Handle of window whose scrollbar(s) will be affected */, +UINT message /* [in] The windows message to be actioned */, +WPARAM wParam /* [in] Variable input including enable state */, +LPARAM lParam /* [in] Variable input including input point */) +{ + TRACE("hwnd=%04x message=%s wParam=%d lParam=%ld\n", + hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam); + + /* handle the windows message */ + if (IsWindow(hwnd)) switch (message) + { + case WM_CREATE: + SCROLL_CreateScrollBar(hwnd, (LPCREATESTRUCTW)lParam); break; + + case WM_ENABLE: + return EnableScrollBar(hwnd, SB_CTL, + wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); + + case WM_LBUTTONDOWN: + { + POINT pt; pt.x = SLOWORD(lParam); pt.y = SHIWORD(lParam); + SCROLL_TrackScrollBar( hwnd, SB_CTL, pt ); + } + break; + + case WM_LBUTTONUP: + case WM_MOUSEMOVE: + case WM_SYSTIMER: + { + POINT pt; pt.x = SLOWORD(lParam); pt.y = SHIWORD(lParam); + SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt ); + } + break; + + case WM_KEYDOWN: + SCROLL_HandleKbdEvent(hwnd, wParam, lParam); break; + + case WM_KEYUP: + ShowCaret(hwnd); break; + + case WM_SETFOCUS: + SCROLL_SetFocus(hwnd); break; + + case WM_KILLFOCUS: + SCROLL_KillFocus(hwnd); break; + + case WM_ERASEBKGND: + return 1; + + case WM_GETDLGCODE: + return DLGC_WANTARROWS; /* Windows returns this value */ + + case WM_PAINT: + /* FIXME: needs to handle all types of bars */ + SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE); break; + + case SBM_SETPOS16: + case SBM_SETPOS: + return SetScrollPos(hwnd, SB_CTL, wParam, (BOOL)lParam); + + case SBM_GETPOS16: + case SBM_GETPOS: + return GetScrollPos(hwnd, SB_CTL); + + case SBM_SETRANGE16: + return SetScrollRange(hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam), wParam); + + case SBM_SETRANGE: + return SCROLL_SetScrollRange(hwnd, wParam, lParam, FALSE); + + case SBM_GETRANGE16: + FIXME("don't know how to handle SBM_GETRANGE16 (wp=%04x, lp=%08lx)\n", + wParam, lParam); + break; + + case SBM_GETRANGE: + GetScrollRange(hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam); + break; + + case SBM_ENABLE_ARROWS16: + case SBM_ENABLE_ARROWS: + return EnableScrollBar(hwnd, SB_CTL, wParam); + + case SBM_SETRANGEREDRAW: + return SCROLL_SetScrollRange(hwnd, wParam, lParam, TRUE); + + case SBM_SETSCROLLINFO: + return SetScrollInfo(hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam); + + case SBM_GETSCROLLINFO: + return GetScrollInfo(hwnd, SB_CTL, (SCROLLINFO *)lParam); + + case 0x00e5: + case 0x00e7: + case 0x00e8: + case 0x00eb: + case 0x00ec: + case 0x00ed: + case 0x00ee: + case 0x00ef: + ERR("unknown Win32 msg %04x wp=%08x lp=%08lx\n", + message, wParam, lParam); + return 0; + + default: + if (message >= WM_USER) + WARN("unknown msg %04x wp=%04x lp=%08lx\n", + message, wParam, lParam); + return DefWindowProcW(hwnd, message, wParam, lParam); + } + return 0; }