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

📄 tab.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
      InflateRect(selectedRect, SELECTED_TAB_OFFSET, 0);

    /* If it also a bit higher. */
    if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL))
    {
      selectedRect->left   -= 2; /* the border is thicker on the right */
      selectedRect->right  += SELECTED_TAB_OFFSET;
    }
    else if (lStyle & TCS_VERTICAL)
    {
      selectedRect->left   -= SELECTED_TAB_OFFSET;
      selectedRect->right  += 1;
    }
    else if (lStyle & TCS_BOTTOM)
    {
      selectedRect->bottom += SELECTED_TAB_OFFSET;
    }
    else /* not TCS_BOTTOM and not TCS_VERTICAL */
    {
      selectedRect->top    -= SELECTED_TAB_OFFSET;
      selectedRect->bottom -= 1;
    }
  }

  /* Check for visibility */
  if (lStyle & TCS_VERTICAL)
    return (itemRect->top < clientRect.bottom) && (itemRect->bottom > clientRect.top);
  else
    return (itemRect->left < clientRect.right) && (itemRect->right > clientRect.left);
}

static inline BOOL
TAB_GetItemRect(TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
  return TAB_InternalGetItemRect(infoPtr, (INT)wParam, (LPRECT)lParam, (LPRECT)NULL);
}

/******************************************************************************
 * TAB_KeyUp
 *
 * This method is called to handle keyboard input
 */
static LRESULT TAB_KeyUp(TAB_INFO* infoPtr, WPARAM keyCode)
{
  int       newItem = -1;

  switch (keyCode)
  {
    case VK_LEFT:
      newItem = infoPtr->uFocus - 1;
      break;
    case VK_RIGHT:
      newItem = infoPtr->uFocus + 1;
      break;
  }

  /*
   * If we changed to a valid item, change the selection
   */
  if (newItem >= 0 &&
      newItem < infoPtr->uNumItem &&
      infoPtr->uFocus != newItem)
  {
    if (!TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGING))
    {
      infoPtr->iSelected = newItem;
      infoPtr->uFocus    = newItem;
      TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGE);

      TAB_EnsureSelectionVisible(infoPtr);
      TAB_InvalidateTabArea(infoPtr);
    }
  }

  return 0;
}

/******************************************************************************
 * TAB_FocusChanging
 *
 * This method is called whenever the focus goes in or out of this control
 * it is used to update the visual state of the control.
 */
static void TAB_FocusChanging(const TAB_INFO *infoPtr)
{
  RECT      selectedRect;
  BOOL      isVisible;

  /*
   * Get the rectangle for the item.
   */
  isVisible = TAB_InternalGetItemRect(infoPtr,
				      infoPtr->uFocus,
				      NULL,
				      &selectedRect);

  /*
   * If the rectangle is not completely invisible, invalidate that
   * portion of the window.
   */
  if (isVisible)
  {
      TRACE("invalidate (%d,%d)-(%d,%d)\n",
	    selectedRect.left,selectedRect.top,
	    selectedRect.right,selectedRect.bottom);
    InvalidateRect(infoPtr->hwnd, &selectedRect, TRUE);
  }
}

static INT TAB_InternalHitTest (
  TAB_INFO* infoPtr,
  POINT     pt,
  UINT*     flags)

{
  RECT rect;
  INT iCount;

  for (iCount = 0; iCount < infoPtr->uNumItem; iCount++)
  {
    TAB_InternalGetItemRect(infoPtr, iCount, &rect, NULL);

    if (PtInRect(&rect, pt))
    {
      *flags = TCHT_ONITEM;
      return iCount;
    }
  }

  *flags = TCHT_NOWHERE;
  return -1;
}

static inline LRESULT
TAB_HitTest (TAB_INFO *infoPtr, LPTCHITTESTINFO lptest)
{
  return TAB_InternalHitTest (infoPtr, lptest->pt, &lptest->flags);
}

/******************************************************************************
 * TAB_NCHitTest
 *
 * Napster v2b5 has a tab control for its main navigation which has a client
 * area that covers the whole area of the dialog pages.
 * That's why it receives all msgs for that area and the underlying dialog ctrls
 * are dead.
 * So I decided that we should handle WM_NCHITTEST here and return
 * HTTRANSPARENT if we don't hit the tab control buttons.
 * FIXME: WM_NCHITTEST handling correct ? Fix it if you know that Windows
 * doesn't do it that way. Maybe depends on tab control styles ?
 */
static inline LRESULT
TAB_NCHitTest (TAB_INFO *infoPtr, LPARAM lParam)
{
  POINT pt;
  UINT dummyflag;

  pt.x = (short)LOWORD(lParam);
  pt.y = (short)HIWORD(lParam);
  ScreenToClient(infoPtr->hwnd, &pt);

  if (TAB_InternalHitTest(infoPtr, pt, &dummyflag) == -1)
    return HTTRANSPARENT;
  else
    return HTCLIENT;
}

static LRESULT
TAB_LButtonDown (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
  POINT pt;
  INT newItem;
  UINT dummy;

  if (infoPtr->hwndToolTip)
    TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd,
		    WM_LBUTTONDOWN, wParam, lParam);

  if (GetWindowLongW(infoPtr->hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) {
    SetFocus (infoPtr->hwnd);
  }

  if (infoPtr->hwndToolTip)
    TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd,
		    WM_LBUTTONDOWN, wParam, lParam);

  pt.x = (short)LOWORD(lParam);
  pt.y = (short)HIWORD(lParam);

  newItem = TAB_InternalHitTest (infoPtr, pt, &dummy);

  TRACE("On Tab, item %d\n", newItem);

  if (newItem != -1 && infoPtr->iSelected != newItem)
  {
    if (!TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGING))
    {
      infoPtr->iSelected = newItem;
      infoPtr->uFocus    = newItem;
      TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGE);

      TAB_EnsureSelectionVisible(infoPtr);

      TAB_InvalidateTabArea(infoPtr);
    }
  }
  return 0;
}

static inline LRESULT
TAB_LButtonUp (const TAB_INFO *infoPtr)
{
  TAB_SendSimpleNotify(infoPtr, NM_CLICK);

  return 0;
}

static inline LRESULT
TAB_RButtonDown (const TAB_INFO *infoPtr)
{
  TAB_SendSimpleNotify(infoPtr, NM_RCLICK);
  return 0;
}

/******************************************************************************
 * TAB_DrawLoneItemInterior
 *
 * This calls TAB_DrawItemInterior.  However, TAB_DrawItemInterior is normally
 * called by TAB_DrawItem which is normally called by TAB_Refresh which sets
 * up the device context and font.  This routine does the same setup but
 * only calls TAB_DrawItemInterior for the single specified item.
 */
static void
TAB_DrawLoneItemInterior(TAB_INFO* infoPtr, int iItem)
{
  HDC hdc = GetDC(infoPtr->hwnd);
  RECT r, rC;

  /* Clip UpDown control to not draw over it */
  if (infoPtr->needsScrolling)
  {
    GetWindowRect(infoPtr->hwnd, &rC);
    GetWindowRect(infoPtr->hwndUpDown, &r);
    ExcludeClipRect(hdc, r.left - rC.left, r.top - rC.top, r.right - rC.left, r.bottom - rC.top);
  }
  TAB_DrawItemInterior(infoPtr, hdc, iItem, NULL);
  ReleaseDC(infoPtr->hwnd, hdc);
}

/* update a tab after hottracking - invalidate it or just redraw the interior,
 * based on whether theming is used or not */
static inline void hottrack_refresh (TAB_INFO* infoPtr, int tabIndex)
{
    if (tabIndex == -1) return;

    if (GetWindowTheme (infoPtr->hwnd))
    {
        RECT rect;
        TAB_InternalGetItemRect(infoPtr, tabIndex, &rect, NULL);
        InvalidateRect (infoPtr->hwnd, &rect, FALSE);
    }
    else
        TAB_DrawLoneItemInterior(infoPtr, tabIndex);
}

/******************************************************************************
 * TAB_HotTrackTimerProc
 *
 * When a mouse-move event causes a tab to be highlighted (hot-tracking), a
 * timer is setup so we can check if the mouse is moved out of our window.
 * (We don't get an event when the mouse leaves, the mouse-move events just
 * stop being delivered to our window and just start being delivered to
 * another window.)  This function is called when the timer triggers so
 * we can check if the mouse has left our window.  If so, we un-highlight
 * the hot-tracked tab.
 */
static void CALLBACK
TAB_HotTrackTimerProc
  (
  HWND hwnd,    /* handle of window for timer messages */
  UINT uMsg,    /* WM_TIMER message */
  UINT_PTR idEvent, /* timer identifier */
  DWORD dwTime  /* current system time */
  )
{
  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);

  if (infoPtr != NULL && infoPtr->iHotTracked >= 0)
  {
    POINT pt;

    /*
    ** If we can't get the cursor position, or if the cursor is outside our
    ** window, we un-highlight the hot-tracked tab.  Note that the cursor is
    ** "outside" even if it is within our bounding rect if another window
    ** overlaps.  Note also that the case where the cursor stayed within our
    ** window but has moved off the hot-tracked tab will be handled by the
    ** WM_MOUSEMOVE event.
    */
    if (!GetCursorPos(&pt) || WindowFromPoint(pt) != hwnd)
    {
      /* Redraw iHotTracked to look normal */
      INT iRedraw = infoPtr->iHotTracked;
      infoPtr->iHotTracked = -1;
      hottrack_refresh (infoPtr, iRedraw);

      /* Kill this timer */
      KillTimer(hwnd, TAB_HOTTRACK_TIMER);
    }
  }
}

/******************************************************************************
 * TAB_RecalcHotTrack
 *
 * If a tab control has the TCS_HOTTRACK style, then the tab under the mouse
 * should be highlighted.  This function determines which tab in a tab control,
 * if any, is under the mouse and records that information.  The caller may
 * supply output parameters to receive the item number of the tab item which
 * was highlighted but isn't any longer and of the tab item which is now
 * highlighted but wasn't previously.  The caller can use this information to
 * selectively redraw those tab items.
 *
 * If the caller has a mouse position, it can supply it through the pos
 * parameter.  For example, TAB_MouseMove does this.  Otherwise, the caller
 * supplies NULL and this function determines the current mouse position
 * itself.
 */
static void
TAB_RecalcHotTrack
  (
  TAB_INFO*       infoPtr,
  const LPARAM*   pos,
  int*            out_redrawLeave,
  int*            out_redrawEnter
  )
{
  int item = -1;


  if (out_redrawLeave != NULL)
    *out_redrawLeave = -1;
  if (out_redrawEnter != NULL)
    *out_redrawEnter = -1;

  if ((GetWindowLongW(infoPtr->hwnd, GWL_STYLE) & TCS_HOTTRACK)
      || GetWindowTheme (infoPtr->hwnd))
  {
    POINT pt;
    UINT  flags;

    if (pos == NULL)
    {
      GetCursorPos(&pt);
      ScreenToClient(infoPtr->hwnd, &pt);
    }
    else
    {
      pt.x = (short)LOWORD(*pos);
      pt.y = (short)HIWORD(*pos);
    }

    item = TAB_InternalHitTest(infoPtr, pt, &flags);
  }

  if (item != infoPtr->iHotTracked)
  {
    if (infoPtr->iHotTracked >= 0)
    {
      /* Mark currently hot-tracked to be redrawn to look normal */
      if (out_redrawLeave != NULL)
        *out_redrawLeave = infoPtr->iHotTracked;

      if (item < 0)
      {
        /* Kill timer which forces recheck of mouse pos */
        KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
      }
    }
    else
    {
      /* Start timer so we recheck mouse pos */
      UINT timerID = SetTimer
        (
        infoPtr->hwnd,
        TAB_HOTTRACK_TIMER,
        TAB_HOTTRACK_TIMER_INTERVAL,
        TAB_HotTrackTimerProc
        );

      if (timerID == 0)
        return; /* Hot tracking not available */
    }

    infoPtr->iHotTracked = item;

    if (item >= 0)
    {
	/* Mark new hot-tracked to be redrawn to look highlighted */
      if (out_redrawEnter != NULL)
        *out_redrawEnter = item;
    }
  }
}

/******************************************************************************
 * TAB_MouseMove
 *
 * Handles the mouse-move event.  Updates tooltips.  Updates hot-tracking.
 */
static LRESULT
TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
  int redrawLeave;
  int redrawEnter;

  if (infoPtr->hwndToolTip)
    TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd,
		    WM_LBUTTONDOWN, wParam, lParam);

  /* Determine which tab to highlight.  Redraw tabs which change highlight
  ** status. */
  TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter);

  hottrack_refresh (infoPtr, redrawLeave);
  hottrack_refresh (infoPtr, redrawEnter);

  return 0;
}

/******************************************************************************
 * TAB_AdjustRect
 *
 * Calculates the tab control's display area given the window rectangle or

⌨️ 快捷键说明

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