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

📄 cooltabctrls.h

📁 remote debug and compile tools
💻 H
📖 第 1 页 / 共 4 页
字号:
   LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
   {
      MSG msg = { m_hWnd, uMsg, wParam, lParam };
      if( m_Tip.IsWindow() ) m_Tip.RelayEvent(&msg);
      bHandled = FALSE;
      return 1;
   }

   LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
   {
      switch( wParam ) {
      case VK_HOME:
         if( m_iCurSel != 0 ) SetCurSel(0);
         return 0;
      case VK_END:
         if( m_Items.GetSize() > 0 ) SetCurSel(m_Items.GetSize() - 1);
         return 0;
      case VK_LEFT:
         if( m_iCurSel > 0 ) SetCurSel(m_iCurSel - 1);
         return 0;
      case VK_RIGHT:
         if( m_iCurSel < m_Items.GetSize() - 1 ) SetCurSel(m_iCurSel + 1);
         return 0;
      }
      bHandled = FALSE;
      return 0;
   }

   // Overridables

   void UpdateLayout()
   {
      int nCount = m_Items.GetSize();
      if( nCount == 0 ) return;

      CClientDC dc(m_hWnd);
      HFONT hOldFont = dc.SelectStockFont(DEFAULT_GUI_FONT);

      RECT rcClient;
      GetClientRect(&rcClient);

      SIZE szIcon = { 0 };
      if( !m_ImageList.IsNull() ) m_ImageList.GetIconSize(szIcon);

      HFONT hFont = GetFont();
      HFONT hSelFont = GetSelFont();
      DWORD dwStyle = GetStyle();

      // Reposition buttons
      int xpos = -m_iScrollPos + m_metrics.cxIndent;
      for( int i = 0; i < nCount; i++ ) {
         COOLTCITEM* pItem = m_Items[i];
         // Hidden button?
         if( (pItem->dwState & TCIS_HIDDEN) != 0 ) continue;
         // Determine width...
         int cx = 0;
         // Expand width according to decorations
         if( pItem->iImage >= 0 && (pItem->mask & TCIF_IMAGE) != 0 && !m_ImageList.IsNull() ) {
            cx += szIcon.cx + (m_metrics.cxImagePadding * 2);
         }
         if( (pItem->mask & TCIF_TEXT) != 0 ) {
            RECT rcText = { 0 };
            dc.SelectFont(i == m_iCurSel ? hSelFont : hFont);
            dc.DrawText(pItem->pszText, ::lstrlen(pItem->pszText), &rcText, DT_SINGLELINE|DT_CALCRECT);
            cx += (rcText.right - rcText.left) + (m_metrics.cxPadding * 2);
         }
         // Add margins
         cx += m_metrics.cxMargin * 2;
         // Selected button is allowed to grow further
         if( m_iCurSel == i ) cx += m_metrics.cxSelMargin * 2;
         // Need separators?
         if( (m_dwExtStyle & TCS_EX_FLATSEPARATORS) != 0 ) cx += 2;
         // Fixed width?
         if( (pItem->mask & TCIF_WIDTH) != 0 ) cx = pItem->cx;
         // Minimum width?
         if( cx < m_nMinWidth ) cx = m_nMinWidth;
         // Finally...
         RECT& rc = pItem->rcItem;
         rc.top = 0;
         rc.bottom = rcClient.bottom - rcClient.top;
         rc.left = xpos;
         rc.right = xpos + cx;
         xpos += cx + m_metrics.cxButtonSpacing;
      }

      // Allow buttons to fill entire row
      int cx = (rcClient.right - rcClient.left) - xpos;
      if( (dwStyle & TCS_RAGGEDRIGHT) != 0 ) {
         if( cx > 0 ) {
            int iDiff = cx / m_Items.GetSize();
            for( int i = 0; i < nCount; i++ ) {
               m_Items[i]->rcItem.right += iDiff;
               if( i > 0 ) m_Items[i]->rcItem.left += iDiff;
               iDiff *= 2;
            }
         }
      }
      // Compress buttons on same line
      if( cx < 0 && (m_dwExtStyle & TCS_EX_COMPRESSLINE) != 0 ) {
         int xpos = m_metrics.cxIndent;
         int iWidth = (rcClient.right - rcClient.left) / nCount;
         for( int i = 0; i < nCount; i++ ) {
            COOLTCITEM* pItem = m_Items[i];
            int cx = min( iWidth, pItem->rcItem.right - pItem->rcItem.left );
            pItem->rcItem.right = xpos + cx;
            pItem->rcItem.left = xpos;
            xpos += cx;
         }
      }
    
      // Expand currently selected button to overlap other buttons.
      // NOTE: To make sense, take the cxIndent/cxMargin/cxSelMargin into
      //       account when choosing a value.
      if( m_iCurSel != - 1 ) ::InflateRect(&m_Items[m_iCurSel]->rcItem, m_metrics.cxOverlap, 0);

      dc.SelectFont(hOldFont);

      // Remove tooltips
      if( m_Tip.IsWindow() ) {
         TOOLINFO ti = { 0 };
         ti.cbSize = sizeof(ti);
         while( m_Tip.EnumTools(0, &ti) ) m_Tip.DelTool(&ti);
      }
      // Recreate tooltip rects
      for( int j = 0; j < nCount; j++ ) {
         if( (m_Items[j]->mask & TCIF_TOOLTIP) != 0 ) {
            if( !m_Tip.IsWindow() ) m_Tip.Create(m_hWnd);
            m_Tip.AddTool(m_hWnd, m_Items[j]->pszTipText, &m_Items[j]->rcItem, j + 1);
         }
         else if( (dwStyle & TCS_TOOLTIPS) != 0 ) {
            if( !m_Tip.IsWindow() ) m_Tip.Create(m_hWnd);
            m_Tip.AddTool(m_hWnd, m_Items[j]->pszText, &m_Items[j]->rcItem, j + 1);
         }
      }
      // Reactivate tooltips
      if( m_Tip.IsWindow() ) m_Tip.Activate(m_Tip.GetToolCount() > 0);

      // Show scrollbuttons
      if( (m_dwExtStyle & TCS_EX_SCROLLBUTTONS) == 0 )
      {
         m_ctrlLeft.ShowWindow(SW_HIDE);
         m_ctrlRight.ShowWindow(SW_HIDE);
      }
      else
      {
         BOOL bLeftNeeded = _IsScrollBarNeeded(HTLEFT);
         RECT rcLeft = { rcClient.right - 38, rcClient.top + 2, rcClient.right - 23, rcClient.bottom - 2 };
         m_ctrlLeft.SetWindowPos(NULL, &rcLeft, SWP_NOZORDER | SWP_NOACTIVATE | (bLeftNeeded ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
         BOOL bRightNeeded = _IsScrollBarNeeded(HTRIGHT);
         RECT rcRight = { rcClient.right - 20, rcClient.top + 2, rcClient.right - 5, rcClient.bottom - 2 };
         m_ctrlRight.SetWindowPos(NULL, &rcRight, SWP_NOZORDER | SWP_NOACTIVATE | (bRightNeeded ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
         if( m_iScrollPos > 0 && !_IsScrollBarNeeded(HTHSCROLL) ) SetScrollPos(0);
      }
   }

   void DoPaint(CDCHandle dc, RECT &rcClip)
   {
      // NOTE: The handling of NM_CUSTOMDRAW is probably not entirely correct
      //       in the code below. But at least it makes a brave attempt to
      //       implement all the states described in MSDN docs.

      // Save current DC selections
      int save = dc.SaveDC();
      ATLASSERT(save!=0);

      // Make sure we don't paint outside client area (possible with paint dc)
      RECT rcClient;
      GetClientRect(&rcClient);
      ::IntersectClipRect(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);

      dc.FillRect(&rcClient, ::GetSysColorBrush(COLOR_3DFACE));

      // Prepare DC
      dc.SelectFont(GetFont());

      T* pT = static_cast<T*>(this);
      LRESULT lResStage;
      NMCUSTOMDRAW nmc = { 0 };
      nmc.hdr.hwndFrom = m_hWnd;
      nmc.hdr.idFrom = m_idDlgCtrl;
      nmc.hdr.code = NM_CUSTOMDRAW;
      nmc.hdc = dc;

      nmc.dwDrawStage = CDDS_PREPAINT;
      lResStage = m_wndNotify.SendMessage(WM_NOTIFY, nmc.hdr.idFrom, (LPARAM) &nmc);
      if( lResStage == CDRF_NOTIFYITEMDRAW || lResStage == CDRF_DODEFAULT ) {
         RECT rc;
         int nCount = m_Items.GetSize();
         // Draw the list items, except the selected one. It is drawn last
         // so it can cover the tabs below it.
         RECT rcIntersect;
         for( int i = 0; i < nCount; i++ ) {
            rc = m_Items[i]->rcItem;
            if( rc.bottom - rc.top == 0 ) pT->UpdateLayout();
            if( i != m_iCurSel ) {
               if( ::IntersectRect(&rcIntersect, &rc, &rcClip) ) {
                  nmc.dwItemSpec = i;
                  nmc.uItemState = 0;
                  if( (m_Items[i]->dwState & TCIS_DISABLED) != 0 ) nmc.uItemState |= CDIS_DISABLED;
                  nmc.rc = rc;
                  pT->ProcessItem(lResStage, nmc);
               }
            }
         }
         if( m_iCurSel != -1 ) {
            rc = m_Items[m_iCurSel]->rcItem;
            if( ::IntersectRect(&rcIntersect, &rc, &rcClip) ) {
               nmc.dwItemSpec = m_iCurSel;
               nmc.uItemState = CDIS_SELECTED;
               nmc.rc = rc;
               pT->ProcessItem(lResStage, nmc);
            }
         }
      }

      if( lResStage == CDRF_NOTIFYPOSTPAINT ) {
         nmc.dwItemSpec = 0;
         nmc.uItemState = 0;
         nmc.dwDrawStage = CDDS_POSTPAINT;
         m_wndNotify.SendMessage(WM_NOTIFY, nmc.hdr.idFrom, (LPARAM) &nmc);
      }

      dc.RestoreDC(save);
   }

   void ProcessItem(LRESULT lResStage, NMCUSTOMDRAW &nmc)
   {
      LRESULT lResItem = CDRF_DODEFAULT;
      if( lResStage == CDRF_NOTIFYITEMDRAW ) {
         nmc.dwDrawStage = CDDS_ITEMPREPAINT;
         lResItem = m_wndNotify.SendMessage(WM_NOTIFY, nmc.hdr.idFrom, (LPARAM) &nmc);
      }
      if( lResItem != CDRF_SKIPDEFAULT ) {
         // Do default item-drawing
         T* pT = static_cast<T*>(this);
         pT->DoItemPaint(nmc);
      }
      if( lResStage == CDRF_NOTIFYITEMDRAW && lResItem == CDRF_NOTIFYPOSTPAINT ) {
         nmc.dwDrawStage = CDDS_ITEMPOSTPAINT;
         m_wndNotify.SendMessage(WM_NOTIFY, nmc.hdr.idFrom, (LPARAM) &nmc);
      }
   }

   void DoItemPaint(NMCUSTOMDRAW &/*nmc*/)
   {
   }
};


/////////////////////////////////////////////////////////////////////////////
//
// The sample tab controls
//
// The follwing samples derive directly from CCustomTabCtrl.
// This means that they can actually use the internal members
// of this class. But they will not! To keep the code clean, I'm only
// using public member methods to access all variables.
//
// You need to add the...
//   REFLECT_NOTIFICATIONS()
// macro to the parent's message map.
//

class CButtonTabCtrl : 
   public CCustomTabCtrl<CButtonTabCtrl>,
   public CCustomDraw<CButtonTabCtrl>
{
public:
   DECLARE_WND_CLASS(_T("WTL_CoolButtonTabCtrl"))

   BEGIN_MSG_MAP(CButtonTabCtrl)
      REFLECTED_NOTIFY_CODE_HANDLER(TCN_INITIALIZE, OnInitialize)
      CHAIN_MSG_MAP(CCustomTabCtrl<CButtonTabCtrl>)
      CHAIN_MSG_MAP_ALT(CCustomDraw<CButtonTabCtrl>, 1)
      DEFAULT_REFLECTION_HANDLER()
   END_MSG_MAP()

   LRESULT OnInitialize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
   {
      TCMETRICS metrics;
      GetMetrics(&metrics);
      metrics.cxButtonSpacing = 3;
      metrics.cxMargin = 10;
      SetMetrics(&metrics);
      return 0;
   }

   DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
   {
      return CDRF_NOTIFYITEMDRAW;   // We need per-item notifications
   }

   DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
   {
      ::SetBkMode(lpNMCustomDraw->hdc, TRANSPARENT);
      ::SetTextColor(lpNMCustomDraw->hdc, ::GetSysColor(COLOR_BTNTEXT));
      
      UINT state = 0;
      if( (lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0 ) state |= DFCS_PUSHED;
      if( (lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0 ) state |= DFCS_INACTIVE;
      ::DrawFrameControl(lpNMCustomDraw->hdc, &lpNMCustomDraw->rc, DFC_BUTTON, DFCS_BUTTONPUSH | state );
      
      TCITEM item = { 0 };
      TCHAR szText[128] = { 0 };
      item.mask = TCIF_TEXT;
      item.pszText = szText;
      item.cchTextMax = (sizeof(szText)/sizeof(TCHAR)) - 1;
      GetItem(lpNMCustomDraw->dwItemSpec, &item);
      if( (lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0 ) {
         lpNMCustomDraw->rc.left += 2;
         lpNMCustomDraw->rc.top += 2;
      }
      ::DrawText(lpNMCustomDraw->hdc, item.pszText, ::lstrlen(item.pszText), &lpNMCustomDraw->rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

      return CDRF_SKIPDEFAULT;
   }
};

class CFolderTabCtrl : 
   public CCustomTabCtrl<CFolderTabCtrl>,
   public CCustomDraw<CFolderTabCtrl>
{
public:
   DECLARE_WND_CLASS(_T("WTL_CoolFolderTabCtrl"))

   CFont m_font;

   enum { CXOFFSET = 8 };     // defined pitch of trapezoid slant
   enum { CXMARGIN = 2 };     // left/right text margin
   enum { CYMARGIN = 1 };     // top/bottom text margin
   enum { CYBORDER = 1 };     // top border thickness

⌨️ 快捷键说明

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