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

📄 collapsiblepanel.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 4 页
字号:
      dc.SelectFont(hOldFont);
   }
};

class CCollapsiblePanelCtrl : public CCollapsiblePanelImpl<CCollapsiblePanelCtrl>
{
public:
   DECLARE_WND_CLASS(_T("WTL_CollapsiblePanel"))
};
template< class T, class TBase = CWindow, class TWinTraits = CControlWinTraits >
////////////////////////////////////////////////////////////////////////////////////
class ATL_NO_VTABLE CTabPanelImpl : 
	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_cxButton;                   // Width 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
		m_iCurSel=iIndex;
		::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);
		for(int i=0;i< m_aPanels.GetSize();i++){
			if(i==iIndex)continue;
			::ShowWindow(m_aPanels[i].hWnd, SW_HIDE);
		}
		// 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(GetParent(),&rc);
		::OffsetRect(&rc, 0, -GetScrollPos(SB_VERT));
		::InflateRect(&rc, -m_szMargin.cx, -m_szMargin.cy);
		rc.top += m_cyButton ;
		
		
		rc.bottom = rc.top + m_aPanels[iIndex].cy;
		if( bIncludeButton ) rc.top -= m_cyButton;
		if( !bIncludeButton && (GetStyle() & WS_BORDER) != 0 ) ::InflateRect(&rc, -1, -1);
		
		

		
		
		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_cxButton = 125;
		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
		if( m_cxLastWidth == 0 ) return;
		// Need to recreate all buttons because view changed
		for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
			if( m_aPanels[i].hbmpButton != NULL ) {
				::DeleteObject(m_aPanels[i].hbmpButton);
				m_aPanels[i].hbmpButton = NULL;
			}
		}
		// Calculate button size
		CClientDC dc = m_hWnd;
		HFONT hOldFont = dc.SelectFont(GetFont());
		TEXTMETRIC tm = { 0 };
		dc.GetTextMetrics(&tm);
		dc.SelectFont(hOldFont);
		SIZE szIcons = { 0 };
		if( !m_Images.IsNull() ) m_Images.GetIconSize(szIcons);
		m_cyBar = max(16 + 6, tm.tmHeight + 6);
		m_cyButton = max(m_cyBar, szIcons.cy + IMAGE_GAP);
		// Repaint
		Invalidate();
	}
	void _RecalcScrollBar()
	{
		// Scrollbar support by Anatoly Ivasyuk.
		// Check that we can manipulate the scrollbar
		if( (m_dwExtStyle & CPS_EX_NOSCROLLBAR) == 0 )
		{
			// Get the location of the last panel in the list
			RECT rc = GetPanelRect(GetItemCount() - 1, FALSE);
			// Update the scroll bar based on the total height
			SCROLLINFO si;
			si.cbSize = sizeof(si);
			si.fMask = SIF_RANGE | SIF_PAGE;
			si.nMin = 0;
			si.nMax = rc.bottom + m_szMargin.cy;
			si.nPage = m_cyLastHeight - GetScrollPos(SB_VERT);
			SetScrollInfo(SB_VERT, &si, TRUE);
		}
	}
	void _RearrangePanels()
	{
		for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
			RECT rc = GetPanelRect(i, FALSE);
			::SetWindowPos(m_aPanels[i].hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);
		}
		Invalidate();

⌨️ 快捷键说明

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