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

📄 collapsiblepanel.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 4 页
字号:
#if !defined(AFX_COLLAPSIBLEPANEL_H__20031129_797C_31F4_B029_0080AD509054__INCLUDED_)
#define AFX_COLLAPSIBLEPANEL_H__20031129_797C_31F4_B029_0080AD509054__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// Collapsible Panel - Windows XP Explorer widget
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2003 Bjarke Viksoe.
// Scroll support kindly added by Anatoly Ivasyuk (aivasyuk@dtlink.com)
//
// This code may be used in compiled form in any way you desire. This
// source 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 __ATLCTRLS_H__
  #error CollapsiblePanel.h requires atlctrls.h to be included first
#endif

#ifndef __ATLGDIX_H__
  #error This control requires my atlgdix.h to be included first
#endif

#if (_WIN32_IE < 0x0400)
  #error This control requires _WIN32_IE >= 0x0400
#endif


// Control notifications
#define CPN_EXPANDING     1
#define CPN_EXPANDED      2

// Extended Panel style
#define CPS_EX_NOANIMATE       0x00000001
#define CPS_EX_FLATSTYLE       0x00000002
#define CPS_EX_DEEPDISABLE     0x00000004
#define CPS_EX_SHAREIMAGELIST  0x00000008
#define CPS_EX_OWNERDRAW       0x00000010
#define CPS_EX_NOEXPANDBUTTON  0x00000020
#define CPS_EX_EXPANDCLICK     0x00000040
#define CPS_EX_NOSCROLLBAR     0x00000080
#define CPS_EX_SELHIGHLIGHT    0x00000100


template< class T, class TBase = CWindow, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE CCollapsiblePanelImpl : 
   public CWindowImpl< T, TBase, TWinTraits >,
   public COffscreenDrawRect< T >
{
public:
   enum { ANIMATETIMER_ID = 22 };    // Happens to be my lucky number!
   enum { IMAGE_GAP = 5 };           // Gap between button-base and icon-base

   typedef struct tagPANEL
   {
      HWND hWnd;                     // Handle to view
      int iImage;                    // Image Index into ImageList
      bool bEnabled;                 // Is panel enabled?
      bool bExpanded;                // Is panel expanded?
      LPTSTR pstrTitle;              // Display title
      COLORREF clrText;              // Text color. If CLR_INVALID then use default
      COLORREF clrBar1;              // Bar color. If CLR_INVALID then use default
      COLORREF clrBar2;              // Bar color. If CLR_INVALID then use default
      HBITMAP hbmpButton;            // Bitmap representation of button
      SIZE szChild;                  // Preferred size of child pane
      DWORD dwAnimateStopTime;       // Time when animation should stop
      int cy;                        // Current child height
   } PANEL;

   typedef struct tagPANELTHEME
   {
      COLORREF clrBack;
      COLORREF clrTextActive;
      COLORREF clrTextInactive;
      COLORREF clrTextSel;
      COLORREF clrBarActive1;
      COLORREF clrBarActive2;
      COLORREF clrBarInactive1;
      COLORREF clrBarInactive2;
      COLORREF clrBarSel1;
      COLORREF clrBarSel2;
      COLORREF clrBorder;
      int iArc;
   } PANELTHEME;

   CSimpleArray<PANEL> m_aPanels;    // Collection of panels
   int m_iCurSel;                    // Last known selected panel
   CFont m_fntBold;                  // Caption font
   DWORD m_dwExtStyle;               // Extended style flags
   PANELTHEME m_Theme;               // Color configuration
   CIconHandle m_iconCollapse;       // Icon for expander button
   CIconHandle m_iconExpand;         // Icon for expander button
   bool m_bOwnCollapseIcons;         // We own expand icons?
   CImageList m_Images;              // Images for icons
   CImageList m_ImagesGrey;          // Images for grey icons
   SIZE m_szMargin;                  // Margins between window and panels
   int m_cyPadding;                  // Padding between panels
   int m_cyButton;                   // Height of button (including icon)
   int m_cyBar;                      // Height of bar (colored text/caption)
   WORD m_cxLastWidth;               // Last known width of window
   WORD m_cyLastHeight;              // Last known height of window
   DWORD m_dwAnimateTime;            // How long time to allow animation (in ms)

   // 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 GetCurSel() const
   {
      return m_iCurSel;
   }
   void SetCurSel(int iSel)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      m_iCurSel = iSel;
      _RecalcLayout();

	   
      SetItemExpanded(iSel, !GetItemExpanded(iSel), TRUE);
        
   }
   void RemoveAllItems()
   {
      ATLASSERT(::IsWindow(m_hWnd));
      for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
         if( m_aPanels[i].hbmpButton != NULL ) ::DeleteObject(m_aPanels[i].hbmpButton);
         delete [] m_aPanels[i].pstrTitle;
      }
      m_aPanels.RemoveAll();
      Invalidate();
   }
   int GetItemCount() const
   {
      return m_aPanels.GetSize();
   }
   int InsertItem(HWND hWndView, LPCTSTR pstrTitle, int iImage = -1, COLORREF clrText = CLR_INVALID)
   {
      ATLASSERT(::IsWindow(hWndView));
      ATLASSERT(!::IsBadStringPtr(pstrTitle,-1));
      ATLASSERT(iImage==-1 || !m_Images.IsNull()); // Need to assign ImageList first
      ATLASSERT(((DWORD)::GetWindowLong(hWndView, GWL_STYLE) & WS_CLIPSIBLINGS)!=0); // Must have CLIPSIBLINGS
      // Assign new parent to panel
      ::SetParent(hWndView, m_hWnd);
      // Make sure the panel is resized to the preferred size
      // before it's added so we can know its size when expanding it!
      RECT rc;
      ::GetWindowRect(hWndView, &rc);
      ATLASSERT(rc.right-rc.left>0 && rc.bottom-rc.top>0);
      // Add the item in the list
      PANEL panel = { 0 };
      panel.hWnd = hWndView;
      ATLTRY( panel.pstrTitle = new TCHAR[::lstrlen(pstrTitle) + 1] );
      if( panel.pstrTitle == NULL ) return -1;
      ::lstrcpy(panel.pstrTitle, pstrTitle);
      panel.bExpanded = true;
      panel.bEnabled = true;
      panel.clrText = clrText;
      panel.clrBar1 = CLR_INVALID;
      panel.clrBar2 = CLR_INVALID;
      panel.iImage = iImage;
      panel.szChild.cx = rc.right - rc.left;
      panel.cy = panel.szChild.cy = rc.bottom - rc.top;
      m_aPanels.Add(panel);
      if( IsWindow() ) Invalidate();
      ::ShowWindow(hWndView, SW_SHOWNOACTIVATE);
      return m_aPanels.GetSize() - 1;
   }
   BOOL GetItemExpanded(int iIndex) const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( iIndex < 0 || iIndex >= m_aPanels.GetSize() ) return FALSE;
      return m_aPanels[iIndex].bExpanded == true;
   }
   BOOL SetItemExpanded(int iIndex, BOOL bExpanded, BOOL bAnimate = FALSE)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( iIndex < 0 || iIndex >= m_aPanels.GetSize() ) return FALSE;
      if( m_aPanels[iIndex].bExpanded == (bExpanded == TRUE) ) return TRUE;
      // Send notification
      ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), CPN_EXPANDING), (LPARAM) m_hWnd);
      // Set panel attributes
      PANEL& panel = m_aPanels[iIndex];
      panel.bExpanded = bExpanded == TRUE;
      DWORD dwTick = ::GetTickCount();
      if( bAnimate && (m_dwExtStyle & CPS_EX_NOANIMATE) == 0 ) dwTick += m_dwAnimateTime;
      panel.dwAnimateStopTime = dwTick;
      // Display panel now so animation can be shown
      ::ShowWindow(panel.hWnd, SW_SHOWNOACTIVATE);
      // Start the show
      SetTimer(ANIMATETIMER_ID, 50L);  // 50 ms timer
      SendMessage(WM_TIMER, ANIMATETIMER_ID);
      return TRUE;
   }
   BOOL GetItemEnabled(int iIndex) const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( iIndex < 0 || iIndex >= m_aPanels.GetSize() ) return FALSE;
      return m_aPanels[iIndex].bEnabled == true;
   }
   BOOL SetItemEnabled(int iIndex, BOOL bEnabled)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( iIndex < 0 || iIndex >= m_aPanels.GetSize() ) return FALSE;
      m_aPanels[iIndex].bEnabled = bEnabled == TRUE;
      if( (m_dwExtStyle & CPS_EX_DEEPDISABLE) != 0 ) ::EnableWindow(m_aPanels[iIndex].hWnd, bEnabled);
      _RecalcLayout();
      return TRUE;
   }
   BOOL SetItemColors(int iIndex, COLORREF clrText, COLORREF clrBar1 = CLR_INVALID, COLORREF clrBar2 = CLR_INVALID)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( iIndex < 0 || iIndex >= m_aPanels.GetSize() ) return FALSE;
      m_aPanels[iIndex].clrText = clrText;
      m_aPanels[iIndex].clrBar1 = clrBar1;
      m_aPanels[iIndex].clrBar2 = clrBar2;
      _RecalcLayout();
      return TRUE;
   }
   DWORD SetExtendedPanelStyle(DWORD dwStyle)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      DWORD dwOldStyle = m_dwExtStyle;
      m_dwExtStyle = dwStyle;
      Invalidate();
      return dwOldStyle;
   }
   void SetAnimateTime(DWORD dwAnimateTime)
   {
      m_dwAnimateTime = dwAnimateTime;
   }
   void SetExpandBitmaps(UINT nExpand, UINT nCollapse)
   {
      ATLASSERT(m_iconCollapse.IsNull());
      m_iconExpand.LoadIcon(nExpand);
      m_iconCollapse.LoadIcon(nCollapse);
      m_bOwnCollapseIcons = true;
      ATLASSERT(!m_iconExpand.IsNull());
      ATLASSERT(!m_iconCollapse.IsNull());
   }
   void SetExpandBitmaps(HICON hicoExpand, HICON hicoCollapse)
   {
      ATLASSERT(m_iconCollapse.IsNull());
      ATLASSERT(hicoExpand!=NULL);
      ATLASSERT(hicoCollapse!=NULL);
      m_iconExpand = hicoExpand;
      m_iconCollapse = hicoCollapse;
      m_bOwnCollapseIcons = false;
   }
   CImageList SetImageList(HIMAGELIST hImages, int nImageList)
   {
      CImageList hOldImages;
      switch( nImageList ) {
      case LVSIL_NORMAL:
         hOldImages = m_Images;
         m_Images = hImages;
         break;
      case LVSIL_STATE:
         hOldImages = m_ImagesGrey;
         m_ImagesGrey = hImages;
         break;
      default:
         ATLASSERT(false);
      }
      _RecalcLayout();
      return hOldImages;
   }
   void SetMargins(int cx, int cy)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      m_szMargin.cx = cx;
      m_szMargin.cy = cy;
      _RecalcLayout();
   }
   int GetPadding() const
   {
      return m_cyPadding;
   }
   void SetPadding(int iPadding)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      m_cyPadding = iPadding;
      _RearrangePanels();
      _RecalcScrollBar();
   }
   PANELTHEME GetPanelTheme() const
   {
      return m_Theme;
   }
   void SetPanelTheme(const PANELTHEME Theme)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      m_Theme = Theme;
      _RecalcLayout();
   }
   RECT GetPanelRect(int iIndex, BOOL bIncludeButton) const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      RECT rc = { 0 };
      if( iIndex < 0 || iIndex >= m_aPanels.GetSize() ) return rc;
      GetClientRect(&rc);
      ::OffsetRect(&rc, 0, -GetScrollPos(SB_VERT));
      ::InflateRect(&rc, -m_szMargin.cx, -m_szMargin.cy);
      for( int i = 0; i <= iIndex; i++ ) {
         if( m_aPanels[i].iImage >= 0 ) rc.top += m_cyButton - m_cyBar;
         rc.top += m_cyBar;
         if( i == iIndex ) {
            rc.bottom = rc.top + m_aPanels[i].cy;
            if( bIncludeButton ) rc.top -= m_cyButton;
            if( !bIncludeButton && (GetStyle() & WS_BORDER) != 0 ) ::InflateRect(&rc, -1, -1);
            return rc;
         }
         rc.top += m_aPanels[i].cy + m_cyPadding;
      }
      ATLASSERT(false);
      return rc;
   }

   // Implementation

   void _Init()
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(GetStyle() & WS_CLIPCHILDREN);

      m_iCurSel = -1;
      m_dwExtStyle = 0;
      m_cxLastWidth = 0;
      m_cyLastHeight = 0;

      CFontHandle font = GetFont();
      if( font.IsNull() ) font = AtlGetDefaultGuiFont();
      LOGFONT lf;
      font.GetLogFont(&lf);
      lf.lfWeight += FW_BOLD;
      if( !m_fntBold.IsNull() ) m_fntBold.DeleteObject();
      m_fntBold.CreateFontIndirect(&lf);
      SetFont(m_fntBold);

      m_szMargin.cx = 10;
      m_szMargin.cy = 12;
      m_cyPadding = 8;
      m_cyButton = 12;
      m_cyBar = 12;

      m_dwAnimateTime = 200;

      m_Theme.clrBack = RGB(195,199,211);
      m_Theme.clrTextActive = RGB(0,0,128);
      m_Theme.clrTextInactive = RGB(120,120,120);
      m_Theme.clrTextSel = RGB(255,255,255);
      m_Theme.clrBarActive1 = RGB(255,255,255);
      m_Theme.clrBarActive2 = RGB(214,215,224);
      m_Theme.clrBarInactive1 = RGB(245,245,245);
      m_Theme.clrBarInactive2 = RGB(184,184,184);
      m_Theme.clrBarSel1 = RGB(45,120,245);
      m_Theme.clrBarSel2 = RGB(128,128,128);
      m_Theme.clrBorder = RGB(0,0,0);
      m_Theme.iArc = 10;
   }
   void _RecalcLayout()
   {
      // No need to do this before first WM_SIZE is seen

⌨️ 快捷键说明

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