⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scrollbar.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
          }
        else if (0 != (Style & WS_HSCROLL))
          {
            Rect->bottom++;
          }
        Vertical = TRUE;
	break;

      case SB_CTL:
        *Rect = ClientRect;
        Vertical = (0 != (Style & SBS_VERT));
	break;

      default:
        return FALSE;
    }

  if (Vertical)
    {
      Pixels = Rect->bottom - Rect->top;
    }
  else
    {
      Pixels = Rect->right - Rect->left;
    }

  if (Pixels <= 2 * GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
    {
      if (SCROLL_MIN_RECT < Pixels)
        {
          *ArrowSize = (Pixels - SCROLL_MIN_RECT) / 2;
        }
      else
        {
          *ArrowSize = 0;
        }
      *ThumbPos = *ThumbSize = 0;
    }
  else
    {
      SCROLLINFO Info;

      NtUserGetScrollInfo(Wnd, Bar, &Info);
      *ArrowSize = GetSystemMetrics(SM_CXVSCROLL);
      Pixels -= (2 * GetSystemMetrics(SM_CXVSCROLL));

      if (0 != Info.nPage)
        {
          *ThumbSize = MulDiv(Pixels, Info.nPage, (Info.nMax - Info.nMin + 1));
          if (*ThumbSize < SCROLL_MIN_THUMB)
            {
              *ThumbSize = SCROLL_MIN_THUMB;
            }
        }
      else
        {
          *ThumbSize = GetSystemMetrics(SM_CXVSCROLL);
        }

#if 0 /* FIXME */
      if (((pixels -= *ThumbSize ) < 0) ||
          ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
#else
      if ((Pixels -= *ThumbSize ) < 0)
#endif
        {
          /* Rectangle too small or scrollbar disabled -> no thumb */
          *ThumbPos = *ThumbSize = 0;
        }
      else
        {
          INT Max = Info.nMax - max(Info.nPage - 1, 0);
          if (Max <= Info.nMin)
            {
              *ThumbPos = *ArrowSize;
            }
          else
            {
              *ThumbPos = *ArrowSize
                          + MulDiv(Pixels, (Info.nPos - Info.nMin),
                                   (Max - Info.nMin));
            }
        }
    }

  return Vertical;
}

/***********************************************************************
 *           IntScrollGetThumbVal
 *
 * Compute the current scroll position based on the thumb position in pixels
 * from the top of the scroll-bar.
 */
static UINT FASTCALL
IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo,
                     BOOL Vertical, INT Pos)
{
  SCROLLINFO si;
  INT Pixels = Vertical ? ScrollBarInfo->rcScrollBar.bottom
                          - ScrollBarInfo->rcScrollBar.top
                        : ScrollBarInfo->rcScrollBar.right
                          - ScrollBarInfo->rcScrollBar.left;

  si.cbSize = sizeof(SCROLLINFO);
  si.fMask = SIF_RANGE | SIF_PAGE;
  NtUserGetScrollInfo(Wnd, SBType, &si);
  if ((Pixels -= 2 * ScrollBarInfo->dxyLineButton) <= 0)
    {
      return si.nMin;
    }

  if ((Pixels -= (ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop)) <= 0)
    {
      return si.nMin;
    }

  Pos = Pos - ScrollBarInfo->dxyLineButton;
  if (Pos < 0)
    {
      Pos = 0;
    }
  if (Pixels < Pos)
    {
      Pos = Pixels;
    }

  if (0 == si.nPage)
    {
      Pos *= si.nMax - si.nMin;
    }
  else
    {
      Pos *= si.nMax - si.nMin - si.nPage + 1;
    }
  return si.nMin + ((Pos + Pixels / 2) / Pixels);
}

/***********************************************************************
 *           IntScrollClipPos
 */
static POINT IntScrollClipPos(PRECT Rect, POINT Pt)
{
  if (Pt.x < Rect->left)
    {
      Pt.x = Rect->left;
    }
  else if (Rect->right < Pt.x)
    {
      Pt.x = Rect->right;
    }

  if (Pt.y < Rect->top)
    {
      Pt.y = Rect->top;
    }
  else if (Rect->bottom < Pt.y)
    {
      Pt.y = Rect->bottom;
    }

  return Pt;
}

/***********************************************************************
 *           IntScrollDrawSizeGrip
 *
 *  Draw the size grip.
 */
static void FASTCALL
IntScrollDrawSizeGrip(HWND Wnd, HDC Dc)
{
  RECT Rect;

  GetClientRect(Wnd, &Rect);
  FillRect(Dc, &Rect, GetSysColorBrush(COLOR_SCROLLBAR));
  Rect.left = max(Rect.left, Rect.right - GetSystemMetrics(SM_CXVSCROLL) - 1);
  Rect.top  = max(Rect.top, Rect.bottom - GetSystemMetrics(SM_CYHSCROLL) - 1);
  DrawFrameControl(Dc, &Rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
}



/***********************************************************************
 *           IntScrollHandleKbdEvent
 *
 * Handle a keyboard event (only for SB_CTL scrollbars with focus).
 */
static void FASTCALL
IntScrollHandleKbdEvent(
  HWND Wnd /* [in] Handle of window with scrollbar(s) */,
  WPARAM wParam /* [in] Variable input including enable state */,
  LPARAM lParam /* [in] Variable input including input point */)
{
  DPRINT("Wnd=%p wParam=%d lParam=%ld\n", Wnd, wParam, lParam);

  /* hide caret on first KEYDOWN to prevent flicker */
  if (0 == (lParam & PFD_DOUBLEBUFFER_DONTCARE))
    {
      HideCaret(Wnd);
    }

  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(Wnd),
               (0 != (GetWindowLongW(Wnd, GWL_STYLE ) & SBS_VERT) ?
                WM_VSCROLL : WM_HSCROLL), wParam, (LPARAM) Wnd);
}

/***********************************************************************
 *           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 != (GetWindowLongW(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 != (GetWindowLongW(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 != (GetWindowLongW(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);
}


/***********************************************************************
 *           IntScrollCreateScrollBar
 *
 *  Create a scroll bar
 */
static void IntScrollCreateScrollBar(
  HWND Wnd /* [in] Handle of window with scrollbar(s) */,
  LPCREATESTRUCTW lpCreate /* [in] The style and place of the scroll bar */)
{
  SCROLLINFO Info;

  Info.cbSize = sizeof(SCROLLINFO);
  Info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -