3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
6 * FILE: subsys/win32k/ntuser/window.c
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
10 * 06-06-2001 CSH Created
12 /* INCLUDES ******************************************************************/
21 /* GLOBAL VARIABLES **********************************************************/
23 static HBITMAP hUpArrow;
24 static HBITMAP hDnArrow;
25 static HBITMAP hLfArrow;
26 static HBITMAP hRgArrow;
27 static HBITMAP hUpArrowD;
28 static HBITMAP hDnArrowD;
29 static HBITMAP hLfArrowD;
30 static HBITMAP hRgArrowD;
31 static HBITMAP hUpArrowI;
32 static HBITMAP hDnArrowI;
33 static HBITMAP hLfArrowI;
34 static HBITMAP hRgArrowI;
36 #define TOP_ARROW(flags,pressed) \
37 (((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
38 #define BOTTOM_ARROW(flags,pressed) \
39 (((flags)&ESB_DISABLE_DOWN) ? hDnArrowI : ((pressed) ? hDnArrowD:hDnArrow))
40 #define LEFT_ARROW(flags,pressed) \
41 (((flags)&ESB_DISABLE_LEFT) ? hLfArrowI : ((pressed) ? hLfArrowD:hLfArrow))
42 #define RIGHT_ARROW(flags,pressed) \
43 (((flags)&ESB_DISABLE_RIGHT) ? hRgArrowI : ((pressed) ? hRgArrowD:hRgArrow))
45 #define SCROLL_MIN_THUMB 6 /* Minimum size of the thumb in pixels */
46 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when holding the button down */
47 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
48 #define SCROLL_TIMER 0 /* Scroll timer id */
50 /* What to do after SCROLL_SetScrollInfo() */
51 #define SA_SSI_HIDE 0x0001
52 #define SA_SSI_SHOW 0x0002
53 #define SA_SSI_REFRESH 0x0004
54 #define SA_SSI_REPAINT_ARROWS 0x0008
56 /* Scroll-bar hit testing */
57 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
58 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
59 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
60 #define SCROLL_THUMB 0x03 /* Thumb rectangle */
61 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
62 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
64 static BOOL SCROLL_MovingThumb = FALSE; /* Is the moving thumb being displayed? */
66 /* Thumb-tracking info */
67 static HWND SCROLL_TrackingWin = 0;
68 static INT SCROLL_TrackingBar = 0;
69 static INT SCROLL_TrackingPos = 0;
70 /* static INT SCROLL_TrackingVal = 0; */
71 static DWORD SCROLL_trackHitTest; /* Hit test code of the last button-down event */
72 static BOOL SCROLL_trackVertical;
74 /* INTERNAL FUNCTIONS *********************************************************/
76 HBRUSH DefWndControlColor (HDC hDC, UINT ctlType);
78 /* Ported from WINE20020904 */
79 /* Draw the scroll bar interior (everything except the arrows). */
81 SCROLL_DrawInterior (HWND hwnd, HDC hdc, INT nBar, BOOL vertical, INT
82 arrowSize, PSCROLLBARINFO psbi)
84 INT thumbSize = psbi->xyThumbBottom - psbi->xyThumbTop;
87 HBRUSH hSaveBrush, hBrush;
88 BOOLEAN top_selected = FALSE, bottom_selected = FALSE;
89 DbgPrint("[SCROLL_DrawInterior:%d]\n", nBar);
90 if(psbi->rgstate[SCROLL_TOP_RECT] & STATE_SYSTEM_PRESSED)
94 if(psbi->rgstate[SCROLL_BOTTOM_RECT] & STATE_SYSTEM_PRESSED)
96 bottom_selected = TRUE;
99 /* Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
100 * The window-owned scrollbars need to call DefWndControlColor
101 * to correctly setup default scrollbar colors
103 if ( nBar == SB_CTL )
105 hBrush = (HBRUSH) NtUserSendMessage (GetParent (hwnd), WM_CTLCOLORSCROLLBAR, (WPARAM) hdc, (LPARAM) hwnd);
107 hBrush = GetSysColorBrush(COLOR_SCROLLBAR);
111 /* hBrush = NtUserGetControlColor (hdc, CTLCOLOR_SCROLLBAR); FIXME
112 */ /* DefWndControlColor */
113 hBrush = GetSysColorBrush(COLOR_SCROLLBAR);
116 hSavePen = SelectObject (hdc, GetSysColorPen (COLOR_WINDOWFRAME));
117 hSaveBrush = SelectObject (hdc, hBrush);
119 /* Calculate the scroll rectangle */
122 rc.top = psbi->rcScrollBar.top + arrowSize;
123 rc.bottom = psbi->rcScrollBar.bottom - arrowSize;
124 rc.left = psbi->rcScrollBar.left;
125 rc.right = psbi->rcScrollBar.right;
129 rc.top = psbi->rcScrollBar.top;
130 rc.bottom = psbi->rcScrollBar.bottom;
131 rc.left = psbi->rcScrollBar.left + arrowSize;
132 rc.right = psbi->rcScrollBar.right - arrowSize;
135 /* Draw the scroll rectangles and thumb */
136 if (!psbi->xyThumbBottom) /* No thumb to draw */
145 /* cleanup and return */
146 SelectObject (hdc, hSavePen);
147 SelectObject (hdc, hSaveBrush);
151 psbi->xyThumbTop -= arrowSize;
160 top_selected ? 0x0f0000 : PATCOPY);
161 rc.top += psbi->xyThumbTop;
166 rc.bottom - rc.top - thumbSize,
167 bottom_selected ? 0x0f0000 : PATCOPY);
168 rc.bottom = rc.top + thumbSize;
177 top_selected ? 0x0f0000 : PATCOPY);
178 rc.left += psbi->xyThumbTop;
182 rc.right - rc.left - thumbSize,
184 bottom_selected ? 0x0f0000 : PATCOPY);
185 rc.right = rc.left + thumbSize;
189 DrawEdge (hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE);
192 SelectObject (hdc, hSavePen);
193 SelectObject (hdc, hSaveBrush);
196 /* Ported from WINE20020904 */
198 SCROLL_DrawMovingThumb (HDC hdc, RECT * rect, BOOL vertical, int arrowSize, int thumbSize, PSCROLLBARINFO psbi)
200 INT pos = SCROLL_TrackingPos;
204 max_size = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
206 max_size = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
208 max_size -= arrowSize + thumbSize;
212 else if (pos > max_size)
215 SCROLL_DrawInterior (SCROLL_TrackingWin, hdc, SCROLL_TrackingBar, vertical, arrowSize, psbi);
217 SCROLL_MovingThumb = !SCROLL_MovingThumb;
220 /* Ported from WINE20020904 */
221 /* Draw the scroll bar arrows. */
223 SCROLL_DrawArrows (HDC hdc, PSCROLLBARINFO info,
224 RECT * rect, INT arrowSize, BOOL vertical,
225 BOOL top_pressed, BOOL bottom_pressed)
228 int scrollDirFlag1, scrollDirFlag2;
233 scrollDirFlag1 = DFCS_SCROLLUP;
234 scrollDirFlag2 = DFCS_SCROLLDOWN;
235 r1.bottom = r1.top + arrowSize;
236 r2.top = r2.bottom - arrowSize;
240 scrollDirFlag1 = DFCS_SCROLLLEFT;
241 scrollDirFlag2 = DFCS_SCROLLRIGHT;
242 r1.right = r1.left + arrowSize;
243 r2.left = r2.right - arrowSize;
246 DrawFrameControl (hdc, &r1, DFC_SCROLL,
247 scrollDirFlag1 | (top_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0)
248 /* | (info.flags&ESB_DISABLE_LTUP ? DFCS_INACTIVE : 0) */
250 DrawFrameControl (hdc, &r2, DFC_SCROLL,
251 scrollDirFlag2 | (bottom_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0)
252 /* | (info.flags&ESB_DISABLE_RTDN ? DFCS_INACTIVE : 0) */
256 /* Ported from WINE20020904 */
257 /* Redraw the whole scrollbar. */
259 SCROLL_DrawScrollBar (HWND hwnd, HDC hdc, INT nBar,
260 BOOL arrows, BOOL interior)
265 BOOL Save_SCROLL_MovingThumb = SCROLL_MovingThumb;
268 info.cbSize = sizeof(SCROLLBARINFO);
274 NtUserGetScrollBarInfo (hwnd, OBJID_HSCROLL, &info);
278 NtUserGetScrollBarInfo (hwnd, OBJID_VSCROLL, &info);
281 vertical = (GetWindowLongW(hwnd,GWL_STYLE)&SBS_VERT) != 0;
282 NtUserGetScrollBarInfo (hwnd, OBJID_CLIENT, &info);
286 DASSERT(!"SCROLL_DrawScrollBar() called with invalid nBar");
291 thumbSize = info.xyThumbBottom - info.xyThumbTop;
294 arrowSize = GetSystemMetrics(SM_CXVSCROLL);
296 arrowSize = GetSystemMetrics(SM_CYHSCROLL);
298 if (IsRectEmpty (&(info.rcScrollBar))) goto END;
300 if (Save_SCROLL_MovingThumb && (SCROLL_TrackingWin == hwnd) && (SCROLL_TrackingBar == nBar))
302 SCROLL_DrawMovingThumb (hdc, &(info.rcScrollBar), vertical, arrowSize, thumbSize, &info);
305 /* Draw the arrows */
306 if (arrows && arrowSize)
308 if (SCROLL_trackVertical == TRUE /* && GetCapture () == hwnd */)
310 SCROLL_DrawArrows (hdc, &info, &(info.rcScrollBar), arrowSize, vertical,
311 (SCROLL_trackHitTest == SCROLL_TOP_ARROW),
312 (SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW));
316 SCROLL_DrawArrows (hdc, &info, &(info.rcScrollBar), arrowSize, vertical, FALSE, FALSE);
322 SCROLL_DrawInterior (hwnd, hdc, nBar, vertical, arrowSize, &info);
325 if (Save_SCROLL_MovingThumb &&
326 (SCROLL_TrackingWin == hwnd) && (SCROLL_TrackingBar == nBar))
327 SCROLL_DrawMovingThumb (hdc, &info.rcScrollBar, vertical, arrowSize, thumbSize, &info);
328 /* if scroll bar has focus, reposition the caret */
330 /* if (hwnd == GetFocus () && (nBar == SB_CTL))
334 SetCaretPos (info.dxyLineButton + 1, info.rcScrollBar.top + 1);
336 else if (nBAR == SB_VERT)
338 SetCaretPos (info.rcScrollBar.top + 1, info.dxyLineButton + 1);
342 /* WIN_ReleaseWndPtr(wndPtr); */
346 SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
352 rect.left -= lpRect->right - lpRect->left;
353 rect.right += lpRect->right - lpRect->left;
357 rect.top -= lpRect->bottom - lpRect->top;
358 rect.bottom += lpRect->bottom - lpRect->top;
360 return PtInRect( &rect, pt );
364 SCROLL_HitTest( HWND hwnd, INT nBar, POINT pt, BOOL bDragging )
368 INT arrowSize, thumbSize, thumbPos;
369 BOOL vertical = (nBar == SB_VERT); /* FIXME - ((Window->Style & SBS_VERT) != 0) */
371 NtUserGetWindowRect(hwnd, &wndrect);
373 sbi.cbSize = sizeof(SCROLLBARINFO);
374 NtUserGetScrollBarInfo(hwnd, vertical ? OBJID_VSCROLL : OBJID_HSCROLL, &sbi);
376 OffsetRect(&sbi.rcScrollBar, wndrect.left, wndrect.top);
378 if ( (bDragging && !SCROLL_PtInRectEx( &sbi.rcScrollBar, pt, vertical )) ||
379 (!PtInRect( &sbi.rcScrollBar, pt )) ) return SCROLL_NOWHERE;
381 thumbPos = sbi.xyThumbTop;
382 thumbSize = sbi.xyThumbBottom - thumbPos;
383 arrowSize = sbi.dxyLineButton;
387 if (pt.y < sbi.rcScrollBar.top + arrowSize) return SCROLL_TOP_ARROW;
388 if (pt.y >= sbi.rcScrollBar.bottom - arrowSize) return SCROLL_BOTTOM_ARROW;
389 if (!thumbPos) return SCROLL_TOP_RECT;
390 pt.y -= sbi.rcScrollBar.top;
391 if (pt.y < thumbPos) return SCROLL_TOP_RECT;
392 if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
394 else /* horizontal */
396 if (pt.x < sbi.rcScrollBar.left + arrowSize) return SCROLL_TOP_ARROW;
397 if (pt.x >= sbi.rcScrollBar.right - arrowSize) return SCROLL_BOTTOM_ARROW;
398 if (!thumbPos) return SCROLL_TOP_RECT;
399 pt.x -= sbi.rcScrollBar.left;
400 if (pt.x < thumbPos) return SCROLL_TOP_RECT;
401 if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
407 /* FUNCTIONS ******************************************************************/
414 EnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows)
416 return NtUserEnableScrollBar(hWnd, wSBflags, wArrows);
424 GetScrollBarInfo(HWND hwnd, LONG idObject, PSCROLLBARINFO psbi)
431 SetLastError(ERROR_INVALID_PARAMETER);
435 RtlCopyMemory(&sbi, psbi, sizeof(SCROLLBARINFO));
436 ret = NtUserGetScrollBarInfo (hwnd, idObject, psbi);
439 RtlCopyMemory(psbi, &sbi, sizeof(SCROLLBARINFO));
450 GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
456 ((lpsi->cbSize != sizeof(SCROLLINFO)) && (lpsi->cbSize != sizeof(SCROLLINFO) - sizeof(si.nTrackPos))))
458 SetLastError(ERROR_INVALID_PARAMETER);
462 RtlZeroMemory(&si, sizeof(SCROLLINFO));
463 si.cbSize = lpsi->cbSize;
464 si.fMask = lpsi->fMask;
466 res = (WINBOOL)NtUserGetScrollInfo(hwnd, fnBar, &si);
470 RtlCopyMemory(lpsi, &si, lpsi->cbSize);
481 GetScrollPos (HWND hWnd, int nBar)
487 si.cbSize = sizeof(SCROLLINFO);
489 ret = NtUserGetScrollInfo(hWnd, nBar, &si);
500 GetScrollRange (HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos)
505 if(!lpMinPos || !lpMaxPos)
507 SetLastError(ERROR_INVALID_PARAMETER);
511 si.cbSize = sizeof(SCROLLINFO);
512 si.fMask = SIF_RANGE;
513 ret = NtUserGetScrollInfo(hWnd, nBar, &si);
528 SetScrollInfo (HWND hwnd, int fnBar, LPCSCROLLINFO lpsi, WINBOOL fRedraw)
533 ((lpsi->cbSize != sizeof(SCROLLINFO)) && (lpsi->cbSize != sizeof(SCROLLINFO) - sizeof(si.nTrackPos))))
535 SetLastError(ERROR_INVALID_PARAMETER);
538 RtlCopyMemory(&si, lpsi, lpsi->cbSize);
539 return (int)NtUserSetScrollInfo(hwnd, fnBar, &si, fRedraw);
547 SetScrollPos (HWND hWnd, int nBar, int nPos, WINBOOL bRedraw)
553 si.cbSize = sizeof(SCROLLINFO);
556 /* call NtUserGetScrollInfo() because we need to return the previous position */
557 ret = NtUserGetScrollInfo(hWnd, nBar, &si);
566 /* finally set the new position */
567 NtUserSetScrollInfo(hWnd, nBar, &si, bRedraw);
579 SetScrollRange (HWND hWnd,
580 int nBar, int nMinPos, int nMaxPos, WINBOOL bRedraw)
584 si.cbSize = sizeof(SCROLLINFO);
585 si.fMask = SIF_RANGE;
589 NtUserSetScrollInfo(hWnd, nBar, &si, bRedraw);
590 /* FIXME - check if called successfully */
600 ShowScrollBar (HWND hWnd, int wBar, WINBOOL bShow)
602 return (WINBOOL)NtUserShowScrollBar (hWnd, wBar, bShow);