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

📄 cooltabctrls.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 3 页
字号:
#ifndef __COOLTABCTRLS_H__
#define __COOLTABCTRLS_H__

#pragma once

/////////////////////////////////////////////////////////////////////////////
// CCoolTabCtrls - A set of Tab Controls with different appearances
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Several improvements done by Daniel Bowen.
// Copyright (c) 2001-2003 Bjarke Viksoe.
//
// Add the following macro to the parent's message map:
//   REFLECT_NOTIFICATIONS()
// CFolderTabCtrl code based on a Paul DiLascia MSJ 1999 article.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

#ifndef __cplusplus
  #error WTL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
  #error CoolTabCtrls.h requires atlapp.h to be included first
#endif

#ifndef __ATLCTRLS_H__
  #error CoolTabCtrls.h requires atlctrls.h to be included first
#endif

#ifndef __ATLGDIX_H__
  #error CoolTabCtrls.h requires atlgdix.h to be included first
#endif

#if (_WIN32_IE < 0x0400)
  #error CoolTabCtrls.h requires _WIN32_IE >= 0x0400
#endif


// New tab notifications
#ifndef TCN_INITIALIZE
   #define TCN_INITIALIZE TCN_FIRST-10
   #define TCN_INSERTITEM TCN_FIRST-11
   #define TCN_DELETEITEM TCN_FIRST-12
#endif // TCN_INITIALIZE

// New masks
#define TCIF_TEXTCOLOR     0x1000 
#define TCIF_BKCOLOR       0x2000 
#define TCIF_TOOLTIP       0x4000
#define TCIF_WIDTH         0x8000

// New tab states
#define TCIS_DISABLED      0x1000
#define TCIS_HIDDEN        0x2000

// Extended tab styles
#define TCS_EX_SCROLLBUTTONS  0x00000010      // Displays scroll-buttons when needed
#define TCS_EX_FLATSCROLL     0x00000020      // Scroll-buttons are shown as flat
#define TCS_EX_CLOSEBUTTON    0x00000040      // Displays close-button to close tabs
#define TCS_EX_SELHIGHLIGHT   0x00000080      // Highlight selected tab with special font
#define TCS_EX_COMPRESSLINE   0x00000100      // Compress tabs if larger than client area

// Layout structure for tab
typedef struct
{
   int cxIndent;                              // Start indent
   int cxButtonSpacing;                       // Gap between buttons
   int cxPadding;                             // Padding between text and button
   int cxMargin;                              // Gap between button and content
   int cxSelMargin;                           // Additional gap for curr. sel. button
   int cxImagePadding;                        // Gap between text and image
   int cxOverlap;                             // Expand currently curr. sel. button
} TCMETRICS;

typedef struct tagCOOLTCITEM : TCITEM
{
   int cx;
   RECT rcSize;
   COLORREF clrText;
   COLORREF clrBkgnd;
   LPTSTR pszTipText;
} COOLTCITEM;


template< class T, class TBase = CTabCtrl, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE CCustomTabCtrl : 
   public CWindowImpl< T, TBase, TWinTraits >,
   public COffscreenDrawRect< T >
{
public:
   DECLARE_WND_CLASS(TBase::GetWndClassName())

   CCustomTabCtrl() : 
      m_iCurSel(-1), 
      m_dwExtStyle(0UL), 
      m_hFont(NULL), 
      m_hSelFont(NULL),
      m_nMinWidth(-1)
   {
      ::ZeroMemory(&m_metrics, sizeof(TCMETRICS));
   }

   // Data members

   int m_iCurSel;
   TCMETRICS m_metrics;
   CSimpleValArray< COOLTCITEM* > m_Items;
   CWindow m_wndNotify;
   CToolTipCtrl m_Tip;
   CImageList m_ImageList;
   DWORD m_dwExtStyle;
   UINT m_idDlgCtrl;
   HFONT m_hFont;
   HFONT m_hSelFont;
   int m_nMinWidth;

   // Operations

   BOOL SubclassWindow(HWND hWnd)
   {
      ATLASSERT(m_hWnd==NULL);
      ATLASSERT(::IsWindow(hWnd));
      BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
      if( bRet ) _Init();
      return bRet;
   }

   int InsertItem(int iItem, LPCTSTR pstrText, int iImage = -1)
   {
      TCITEM tci = { 0 };
      tci.mask = TCIF_TEXT | TCIF_IMAGE;
      tci.pszText = const_cast<LPTSTR>(pstrText);
      tci.iImage = iImage;
      return InsertItem(iItem, &tci);
   }
   int InsertItem(int iItem, const LPTCITEM pItem)
   {
      COOLTCITEM tci;
      ::ZeroMemory(&tci, sizeof(tci));
      ::CopyMemory(&tci, pItem, sizeof(TCITEM));
      return InsertItem(iItem, &tci);
   }
   int InsertItem(int iItem, const COOLTCITEM* pItem)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(pItem);
      ATLASSERT(iItem==m_Items.GetSize()); // We only support appending right now
      if( iItem < 0 || iItem > m_Items.GetSize() ) iItem = m_Items.GetSize();
      COOLTCITEM* pNewItem;
      ATLTRY( pNewItem = new COOLTCITEM );
      if( pNewItem == NULL ) return -1;
      ::ZeroMemory(pNewItem, sizeof(COOLTCITEM));
      m_Items.Add(pNewItem);
      int idx = m_Items.GetSize() - 1;
      if( !SetItem(idx, pItem) ) return FALSE;
      // Send notification
      NMHDR nmh = { m_hWnd, m_idDlgCtrl, TCN_INSERTITEM };
      m_wndNotify.SendMessage(WM_NOTIFY, nmh.idFrom, (LPARAM) &nmh);
      // Select if first tab
      if( m_Items.GetSize() == 1 ) SetCurSel(0);
      _Repaint();
      return idx;
   }

   BOOL DeleteAllItems()
   {
      ATLASSERT(::IsWindow(m_hWnd));
      while( GetItemCount() > 0 ) DeleteItem(0); // Slooow!!!
      return TRUE;
   }
   BOOL DeleteItem(int iItem)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( iItem < 0 || iItem >= m_Items.GetSize() ) return FALSE;
      // If currently selected, select something else
      if( iItem < m_iCurSel ) {
         // The item being removed is before the current selection.
         // We still want the same item to be selected, but
         // the index needs to be adjusted to account for the missing item
         m_iCurSel--;
      }
      else if( iItem == m_iCurSel ) {
         SetCurSel( (m_Items.GetSize() > 1) ? 0 : -1 );
      }
      // Remove from structures
      COOLTCITEM* pItem = m_Items[iItem];
      m_Items.RemoveAt(iItem);
      if( pItem->mask & TCIF_TEXT ) ATLTRY( delete [] pItem->pszText );
      if( pItem->mask & TCIF_TOOLTIP ) ATLTRY( delete [] pItem->pszTipText );
      ATLTRY( delete pItem );
      // Send notification
      NMHDR nmh = { m_hWnd, m_idDlgCtrl, TCN_DELETEITEM };
      m_wndNotify.SendMessage(WM_NOTIFY, nmh.idFrom, (LPARAM) &nmh);
      _Repaint();
      return TRUE;
   }

   int SetItem(int iItem, const LPTCITEM pItem)
   {
      COOLTCITEM tci;
      ::ZeroMemory(&tci, sizeof(tci));
      ::CopyMemory(&tci, pItem, sizeof(TCITEM));
      return SetItem(iItem, &tci);
   }
   BOOL SetItem(int iItem, const COOLTCITEM* pItem)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(!::IsBadReadPtr(pItem,sizeof(TCITEM)));
      if( !_ValidateItem(iItem) ) return FALSE;

      // Copy caller's data to the internal structure
      COOLTCITEM* pDstItem = m_Items[iItem];
      UINT mask = pItem->mask;
      if( mask & TCIF_TEXT ) {
         ATLASSERT(!::IsBadStringPtr(pItem->pszText,(UINT)-1));
         if( pDstItem->mask & TCIF_TEXT ) ATLTRY( delete [] pDstItem->pszText );
         ATLTRY( pDstItem->pszText = new TCHAR[ ::lstrlen(pItem->pszText) + 1 ] );
         ::lstrcpy(pDstItem->pszText, pItem->pszText);
      }
      if( mask & TCIF_TOOLTIP ) {
         ATLASSERT(!::IsBadStringPtr(pItem->pszTipText,(UINT)-1));
         if( pDstItem->mask & TCIF_TOOLTIP ) ATLTRY( delete [] pDstItem->pszTipText );
         ATLTRY( pDstItem->pszTipText = new TCHAR[ ::lstrlen(pItem->pszTipText) + 1 ] );
         ::lstrcpy(pDstItem->pszTipText, pItem->pszTipText);
      }
      if( mask & TCIF_STATE ) pDstItem->dwState = pItem->dwState;
      if( mask & TCIF_IMAGE ) pDstItem->iImage = pItem->iImage;
      if( mask & TCIF_PARAM ) pDstItem->lParam = pItem->lParam;
      if( mask & TCIF_WIDTH ) pDstItem->cx = pItem->cx;
      if( mask & TCIF_TEXTCOLOR ) pDstItem->clrText = pItem->clrText;
      if( mask & TCIF_BKCOLOR ) pDstItem->clrBkgnd = pItem->clrBkgnd;
      pDstItem->mask |= mask;

      _Repaint();
      return TRUE;
   }

   BOOL GetItem(int iItem, LPTCITEM pItem) const
   {
      ATLASSERT((pItem->mask & (TCIF_WIDTH|TCIF_TOOLTIP|TCIF_TEXTCOLOR|TCIF_BKCOLOR))==0);
      return GetItem(iItem, reinterpret_cast<COOLTCITEM*>(pItem));
   }
   BOOL GetItem(int iItem, COOLTCITEM* pItem) const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(!::IsBadWritePtr(pItem,sizeof(TCITEM)));
      if( !_ValidateItem(iItem) ) return FALSE;

      // Copy item data
      COOLTCITEM* pSrcItem = m_Items[iItem];
      const UINT mask = pItem->mask;
      const UINT maskSrc = pSrcItem->mask;

      pItem->mask = 0;
      if( mask & TCIF_TEXT ) {
         ATLASSERT(pItem->pszText);
         pItem->mask |= (maskSrc & TCIF_TEXT);
         ::lstrcpyn( pItem->pszText, pSrcItem->pszText == NULL ? _T("") : pSrcItem->pszText, pItem->cchTextMax );
      }
      if( mask & TCIF_IMAGE ) {
         pItem->mask |= (maskSrc & TCIF_IMAGE);
         pItem->iImage = pSrcItem->iImage;
      }
      if( mask & TCIF_PARAM ) {
         pItem->mask |= (maskSrc & TCIF_PARAM);
         pItem->lParam = pSrcItem->lParam;
      }
      if( mask & TCIF_STATE ) {
         pItem->mask |= (maskSrc & TCIF_STATE);
         pItem->dwState = pSrcItem->dwState;
      }
      if( mask & TCIF_TEXTCOLOR ) {
         pItem->mask |= (maskSrc & TCIF_TEXTCOLOR);
         pItem->clrText = pSrcItem->clrText;
      }
      if( mask & TCIF_BKCOLOR ) {
         pItem->mask |= (maskSrc & TCIF_BKCOLOR);
         pItem->clrBkgnd = pSrcItem->clrBkgnd;
      }
      return 0;
   }
   
   int SetCurSel(int iItem)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      // Selecting same tab? Not worth it!
      if( iItem == m_iCurSel ) return m_iCurSel;
      if( iItem < -1 || iItem >= m_Items.GetSize() ) return m_iCurSel;

      RECT rc = { 0 };
      int iOldSel = m_iCurSel;
      // Send notification
      NMHDR nmh = { m_hWnd, m_idDlgCtrl, TCN_SELCHANGING };
      if( m_wndNotify.SendMessage(WM_NOTIFY, nmh.idFrom, (LPARAM) &nmh) == TRUE ) return -1;
      // Repaint old button area
      GetItemRect(iItem, &rc); InvalidateRect(&rc);
      GetItemRect(iOldSel, &rc); InvalidateRect(&rc);

      // Change tab
      m_iCurSel = iItem;
      // Recalc new positions
      T* pT = static_cast<T*>(this);
      pT->UpdateLayout();

      // Repaint whole tab
      GetClientRect(&rc); InvalidateRect(&rc);

      // Send notification
      nmh.code = TCN_SELCHANGE;
      m_wndNotify.SendMessage(WM_NOTIFY, nmh.idFrom, (LPARAM) &nmh);

      return iOldSel;
   }
   int GetCurSel() const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      return m_iCurSel;
   }

   int GetItemCount() const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      return m_Items.GetSize();
   }
   
   void SetImageList(HIMAGELIST hImageList)
   {
      m_ImageList = hImageList;
   }
   CImageList GetImageList() const
   {
      return m_ImageList;
   }
   
   int HitTest(POINT pt) const
   {
      TCHITTESTINFO tchti = { 0 };
      tchti.pt = pt;
      return HitTest(&tchti);
   }
   int HitTest(LPTCHITTESTINFO pinfo) const
   {
      ATLASSERT(!::IsBadWritePtr(pinfo,sizeof(TCHITTESTINFO)));
      for( int i = 0; i < m_Items.GetSize(); i++ ) {
         if( ::PtInRect(&m_Items[i]->rcSize, pinfo->pt) ) {
            pinfo->flags = TCHT_ONITEM;
            return i;
         }
      }
      return -1;
   }

	DWORD GetExtendedStyle() const
	{
		ATLASSERT(::IsWindow(m_hWnd));
		return m_dwExtStyle;
	}
	DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
	{
		ATLASSERT(::IsWindow(m_hWnd));
      DWORD dwOldStyle = m_dwExtStyle;
      m_dwExtStyle = (m_dwExtStyle & ~dwExMask) | dwExStyle;
      _Repaint();
      return dwOldStyle;
	}

   int GetRowCount() const
   {
      return 1;
   }
	CToolTipCtrl GetTooltips() const
   {
      return m_Tip;
   }

   void SetNotify(HWND hWnd)
   {
      ATLASSERT(::IsWindow(hWnd));
      m_wndNotify = hWnd;
   }
   void SetMinTabWidth(int nWidth = -1)
   {
      m_nMinWidth = nWidth;
   }
   DWORD SetItemSize(int iItem, int cx, int cy)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( !_ValidateItem(iItem) ) return 0;
      RECT rcOld = m_Items[iItem]->rcSize;     
      m_Items[iItem].cx = cx;
      m_Items[iItem].mask |= TCIF_WIDTH;
      _Repaint();
      return MAKELONG(rcOld.right - rcOld.left, rcOld.bottom - rcOld.top);
   }

⌨️ 快捷键说明

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