LRESULT DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect) { LRESULT Result = 0; DWORD Style = GetClassLongPtrW(hWnd, GCL_STYLE); DWORD ExStyle; SIZE WindowBorders; RECT OrigRect; if (Rect == NULL) { return Result; } OrigRect = *Rect; if (CalcSizeStruct) { if (Style & CS_VREDRAW) { Result |= WVR_VREDRAW; } if (Style & CS_HREDRAW) { Result |= WVR_HREDRAW; } Result |= WVR_VALIDRECTS; } Style = GetWindowLongPtrW(hWnd, GWL_STYLE); ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE); if (!(Style & WS_MINIMIZE)) { HMENU menu = GetMenu(hWnd); if (UserHasWindowEdge(Style, ExStyle)) { UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE); InflateRect(Rect, -WindowBorders.cx, -WindowBorders.cy); } else if ((ExStyle & WS_EX_STATICEDGE) || (Style & WS_BORDER)) { InflateRect(Rect, -1, -1); } if ((Style & WS_CAPTION) == WS_CAPTION) { if (ExStyle & WS_EX_TOOLWINDOW) Rect->top += GetSystemMetrics(SM_CYSMCAPTION); else Rect->top += GetSystemMetrics(SM_CYCAPTION); } if (menu && !(Style & WS_CHILD)) { HDC hDC = GetWindowDC(hWnd); if(hDC) { RECT CliRect = *Rect; CliRect.bottom -= OrigRect.top; CliRect.right -= OrigRect.left; CliRect.left -= OrigRect.left; CliRect.top -= OrigRect.top; Rect->top += MenuDrawMenuBar(hDC, &CliRect, hWnd, TRUE); ReleaseDC(hWnd, hDC); } } if (ExStyle & WS_EX_CLIENTEDGE) { InflateRect(Rect, -2 * GetSystemMetrics(SM_CXBORDER), -2 * GetSystemMetrics(SM_CYBORDER)); } if(Style & (WS_VSCROLL | WS_HSCROLL)) { SCROLLBARINFO sbi; SETSCROLLBARINFO ssbi; sbi.cbSize = sizeof(SCROLLBARINFO); if((Style & WS_VSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_VSCROLL, &sbi)) { int i; LONG sx = Rect->right; sx -= GetSystemMetrics(SM_CXVSCROLL); for(i = 0; i <= CCHILDREN_SCROLLBAR; i++) ssbi.rgstate[i] = sbi.rgstate[i]; if(sx <= Rect->left) ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN; else ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN; NtUserSetScrollBarInfo(hWnd, OBJID_VSCROLL, &ssbi); if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN) Style &= ~WS_VSCROLL; } else Style &= ~WS_VSCROLL; if((Style & WS_HSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_HSCROLL, &sbi)) { int i; LONG sy = Rect->bottom; sy -= GetSystemMetrics(SM_CYHSCROLL); for(i = 0; i <= CCHILDREN_SCROLLBAR; i++) ssbi.rgstate[i] = sbi.rgstate[i]; if(sy <= Rect->top) ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN; else ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN; NtUserSetScrollBarInfo(hWnd, OBJID_HSCROLL, &ssbi); if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN) Style &= ~WS_HSCROLL; } else Style &= ~WS_HSCROLL; } if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL)) { if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) Rect->left += GetSystemMetrics(SM_CXVSCROLL); else Rect->right -= GetSystemMetrics(SM_CXVSCROLL); Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL); } else { if (Style & WS_VSCROLL) { if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) Rect->left += GetSystemMetrics(SM_CXVSCROLL); else Rect->right -= GetSystemMetrics(SM_CXVSCROLL); } else if (Style & WS_HSCROLL) Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL); } if (Rect->top > Rect->bottom) Rect->bottom = Rect->top; if (Rect->left > Rect->right) Rect->right = Rect->left; } else { Rect->right = Rect->left; Rect->bottom = Rect->top; } return Result; }
/*********************************************************************** * IntScrollHandleScrollEvent * * Handle a mouse or timer event for the scrollbar. * 'Pt' is the location of the mouse event in drawing coordinates */ static VOID FASTCALL IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) { static POINT PrevPt; /* Previous mouse position for timer events */ static UINT TrackThumbPos; /* Thumb position when tracking started. */ static INT LastClickPos; /* Position in the scroll-bar of the last button-down event. */ static INT LastMousePos; /* Position in the scroll-bar of the last mouse event. */ DWORD HitTest; HWND WndOwner, WndCtl; BOOL Vertical; HDC Dc; SCROLLBARINFO ScrollBarInfo; SETSCROLLBARINFO NewInfo; if (! IntGetScrollBarInfo(Wnd, SBType, &ScrollBarInfo)) { return; } if (SCROLL_NOWHERE == ScrollTrackHitTest && WM_LBUTTONDOWN != Msg) { return; } NewInfo.nTrackPos = ScrollTrackingVal; NewInfo.reserved = ScrollBarInfo.reserved; memcpy(NewInfo.rgstate, ScrollBarInfo.rgstate, (CCHILDREN_SCROLLBAR + 1) * sizeof(DWORD)); if (SB_CTL == SBType && 0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & (SBS_SIZEGRIP | SBS_SIZEBOX))) { switch(Msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ HideCaret(Wnd); /* hide caret while holding down LBUTTON */ SetCapture(Wnd); PrevPt = Pt; ScrollTrackHitTest = HitTest = SCROLL_THUMB; break; case WM_MOUSEMOVE: GetClientRect(GetParent(GetParent(Wnd)), &ScrollBarInfo.rcScrollBar); PrevPt = Pt; break; case WM_LBUTTONUP: ReleaseCapture(); ScrollTrackHitTest = HitTest = SCROLL_NOWHERE; if (Wnd == GetFocus()) { ShowCaret(Wnd); } break; case WM_SYSTIMER: Pt = PrevPt; break; } return; } Dc = GetDCEx(Wnd, 0, DCX_CACHE | ((SB_CTL == SBType) ? 0 : DCX_WINDOW)); if (SB_VERT == SBType) { Vertical = TRUE; } else if (SB_HORZ == SBType) { Vertical = FALSE; } else { Vertical = (0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & SBS_VERT)); } WndOwner = (SB_CTL == SBType) ? GetParent(Wnd) : Wnd; WndCtl = (SB_CTL == SBType) ? Wnd : NULL; switch (Msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ HideCaret(Wnd); /* hide caret while holding down LBUTTON */ ScrollTrackVertical = Vertical; ScrollTrackHitTest = HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, FALSE ); LastClickPos = Vertical ? (Pt.y - ScrollBarInfo.rcScrollBar.top) : (Pt.x - ScrollBarInfo.rcScrollBar.left); LastMousePos = LastClickPos; TrackThumbPos = ScrollBarInfo.xyThumbTop; PrevPt = Pt; if (SB_CTL == SBType && 0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & WS_TABSTOP)) { SetFocus(Wnd); } SetCapture(Wnd); ScrollBarInfo.rgstate[ScrollTrackHitTest] |= STATE_SYSTEM_PRESSED; NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); break; case WM_MOUSEMOVE: HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, TRUE); PrevPt = Pt; break; case WM_LBUTTONUP: HitTest = SCROLL_NOWHERE; ReleaseCapture(); /* if scrollbar has focus, show back caret */ if (Wnd == GetFocus()) { ShowCaret(Wnd); } ScrollBarInfo.rgstate[ScrollTrackHitTest] &= ~STATE_SYSTEM_PRESSED; NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); break; case WM_SYSTIMER: Pt = PrevPt; HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, FALSE); break; default: return; /* Should never happen */ } switch (ScrollTrackHitTest) { case SCROLL_NOWHERE: /* No tracking in progress */ break; case SCROLL_TOP_ARROW: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEUP, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; case SCROLL_TOP_RECT: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEUP, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; case SCROLL_THUMB: if (WM_LBUTTONDOWN == Msg) { ScrollTrackingWin = Wnd; ScrollTrackingBar = SBType; ScrollTrackingPos = TrackThumbPos + LastMousePos - LastClickPos; ScrollTrackingVal = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, ScrollTrackingPos); NewInfo.nTrackPos = ScrollTrackingVal; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); IntScrollDrawMovingThumb(Dc, &ScrollBarInfo, Vertical); } else if (WM_LBUTTONUP == Msg) { ScrollTrackingWin = 0; ScrollTrackingVal = 0; IntDrawScrollInterior(Wnd, Dc, SBType, Vertical, &ScrollBarInfo); } else /* WM_MOUSEMOVE */ { UINT Pos; if (! IntScrollPtInRectEx(&ScrollBarInfo.rcScrollBar, Pt, Vertical)) { Pos = LastClickPos; } else { Pt = IntScrollClipPos(&ScrollBarInfo.rcScrollBar, Pt); Pos = Vertical ? (Pt.y - ScrollBarInfo.rcScrollBar.top) : (Pt.x - ScrollBarInfo.rcScrollBar.left); } if (Pos != LastMousePos || ! ScrollMovingThumb) { LastMousePos = Pos; ScrollTrackingPos = TrackThumbPos + Pos - LastClickPos; ScrollTrackingVal = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, ScrollTrackingPos); NewInfo.nTrackPos = ScrollTrackingVal; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); IntScrollDrawMovingThumb(Dc, &ScrollBarInfo, Vertical); SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, ScrollTrackingVal), (LPARAM) WndCtl); } } break; case SCROLL_BOTTOM_RECT: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEDOWN, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; case SCROLL_BOTTOM_ARROW: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEDOWN, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; } if (WM_LBUTTONDOWN == Msg) { if (SCROLL_THUMB == HitTest) { UINT Val = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, TrackThumbPos + LastMousePos - LastClickPos); SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, Val), (LPARAM) WndCtl); } } if (WM_LBUTTONUP == Msg) { HitTest = ScrollTrackHitTest; ScrollTrackHitTest = SCROLL_NOWHERE; /* Terminate tracking */ if (SCROLL_THUMB == HitTest) { UINT Val = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, TrackThumbPos + LastMousePos - LastClickPos); SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, Val), (LPARAM) WndCtl); } SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_ENDSCROLL, (LPARAM) WndCtl); } ReleaseDC(Wnd, Dc); }