#include "stdafx.h" #include "GfxOutBarCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define IDC_CURSOR_HAND 8899 ///////////////////////////////////////////////////////////////////////////// // CGfxOutBarCtrl IMPLEMENT_DYNCREATE(CGfxOutBarCtrl, CWnd) CGfxOutBarCtrl::CGfxOutBarCtrl() { //背景色 m_crBackground = RGB(255,255,255); //字体颜色 m_crText = RGB(27,79,116); //字体 m_pFont = NULL; //目录高度 m_nFolderHeight = 20; //当前选中目录索引 m_nCurSelFolder = 1; //最后高亮的目录索引 iLastFolderHighlighted = -1; //当前鼠标滑过的目录 iHoverFolder = -1; hHandCursor = AfxGetApp()->LoadCursor(IDC_CURSOR_HAND); iSelcon = NULL; } CGfxOutBarCtrl::~CGfxOutBarCtrl() { for (int t = 0; t < m_arFolder.GetSize(); t++) { if (m_arFolder.GetAt(t)) delete (CBm_arFolder*) m_arFolder.GetAt(t); } m_arFolder.RemoveAll(); } BEGIN_MESSAGE_MAP(CGfxOutBarCtrl, CWnd) //{{AFX_MSG_MAP(CGfxOutBarCtrl) ON_WM_CREATE() ON_WM_PAINT() ON_WM_ERASEBKGND() ON_WM_LBUTTONDOWN() ON_WM_SETCURSOR() ON_WM_SIZE() //}}AFX_MSG_MAP ON_WM_MOUSEMOVE() ON_WM_TIMER() ON_WM_MOUSEWHEEL() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CGfxOutBarCtrl message handlers void CGfxOutBarCtrl::SetFolderImage(LPCTSTR lpszPath) { CEnBitmap bmpTemp; bmpTemp.LoadImage(lpszPath); bmpTemp.DrawImage(m_bmpNormalFolder,1,1,1,2); bmpTemp.DrawImage(m_bmpHoverFolder,1,2,1,2); bmpTemp.DeleteObject(); }; void CGfxOutBarCtrl::SetSelIcon(LPCTSTR lpszIconPath) { iSelcon=(HICON)::LoadImage(AfxGetApp()->m_hInstance,lpszIconPath,IMAGE_ICON,16,16,LR_LOADFROMFILE); } void CGfxOutBarCtrl::SetFolderText(const int index, const TCHAR * text) { ASSERT(index >= 0 && index < GetFolderCount()); CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(index); if (pbf->cName) { delete [] pbf->cName; pbf->cName = NULL; } pbf->cName = new TCHAR [lstrlen(text)+1]; lstrcpy(pbf->cName, text); } BOOL CGfxOutBarCtrl::Create(DWORD dwStyle, const RECT & rect, CWnd * pParentWnd, UINT nID) { return CWnd::CreateEx(0, NULL, NULL, dwStyle|WS_CHILD, rect, pParentWnd, nID); } int CGfxOutBarCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here return 0; } void CGfxOutBarCtrl::OnPaint() { CRect rc; GetClientRect(&rc); CPaintDC dc(this); CDC memDC; memDC.CreateCompatibleDC(&dc); CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height()); CBitmap * oldbmp = memDC.SelectObject(&bmp);; memDC.FillSolidRect(rc,m_crBackground); int nFolders=m_arFolder.GetSize(); for(int i=0;i= 0 && iIndex < max); if (iIndex >= 0 && iIndex < max) { CRect rc; GetClientRect(rc); if (iIndex > m_nCurSelFolder) rect.SetRect(rc.left, rc.bottom - ((max - iIndex)) * m_nFolderHeight, rc.right, rc.bottom - (max - iIndex - 1) * m_nFolderHeight); else rect.SetRect(rc.left, rc.top + iIndex * m_nFolderHeight, rc.right, rc.top + (1 + iIndex) * m_nFolderHeight); return true; } return false; } bool CGfxOutBarCtrl::PtInFolderHeadRect(CPoint pt) const { int max = m_arFolder.GetSize(); ASSERT(m_nCurSelFolder >= 0 && m_nCurSelFolder < max); CRect rcClient; GetClientRect(rcClient); CRect rcTop, rcBottom; rcTop.SetRect(rcClient.left, rcClient.top, rcClient.right, rcClient.top + (m_nCurSelFolder + 1) * m_nFolderHeight); rcBottom.SetRect(rcClient.left, rcClient.bottom - ( max - m_nCurSelFolder) * m_nFolderHeight, rcClient.right, rcClient.bottom ); if ( rcTop.PtInRect(pt) || rcBottom.PtInRect(pt) ) return true; return false; } int CGfxOutBarCtrl::AddFolder(const TCHAR * cFolderName, const DWORD exData) { CBm_arFolder * pbf = new CBm_arFolder(cFolderName, exData); ASSERT(pbf); m_arFolder.Add((void *)pbf); return m_arFolder.GetSize() - 1; } int CGfxOutBarCtrl::AddFolderBar(const TCHAR * pFolder, CWnd * pSon, const DWORD exData) { CBm_arFolder * pbf = new CBm_arFolder(pFolder, exData); ASSERT(pbf); pbf->pChild = pSon; m_arFolder.Add((void *)pbf); return m_arFolder.GetSize() - 1; } CGfxOutBarCtrl::CBm_arFolder::CBm_arFolder(const TCHAR * name, DWORD exData) { cName = NULL; dwData = exData; if (name) { cName = new TCHAR[lstrlen(name)+1]; ASSERT(cName); lstrcpy(cName, name); } pChild = NULL; } CGfxOutBarCtrl::CBm_arFolder::~CBm_arFolder() { if (cName) delete [] cName; } void CGfxOutBarCtrl::GetInsideRect(CRect & rect) const { GetClientRect(rect); if (m_arFolder.GetSize() > 0) { int max = m_arFolder.GetSize(); rect.top += m_nFolderHeight * (m_nCurSelFolder + 1);//+ 2; rect.bottom -= (max - m_nCurSelFolder - 1)*m_nFolderHeight +1; return; } } int CGfxOutBarCtrl::HitTestEx(const CPoint & point, int &index) { int max = m_arFolder.GetSize(), t; CRect rc; for (t = 0; t < max; t++) { GetFolderRect(t, rc); if (rc.PtInRect(point)) { index = t; return htFolder; } } index = -1; return htNothing; } void CGfxOutBarCtrl::OnLButtonDown(UINT nFlags, CPoint point) { if (GetFocus() != this) SetFocus(); int index, ht = HitTestEx(point, index); if (ht == htFolder) { bool bHigh = true; if (::GetCapture() == NULL) { SetCapture(); ASSERT(this == GetCapture()); AfxLockTempMaps(); while (TRUE) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (CWnd::GetCapture() != this) break; switch (msg.message) { case WM_LBUTTONUP: { CPoint pt(msg.lParam); int idx, ht1 = HitTestEx(pt, idx); if (ht1 == htFolder && idx != m_nCurSelFolder) { //idx = (idx == m_nCurSelFolder)?(idx+1):idx; if(idx = 0 && index < GetFolderCount()); if (index == m_nCurSelFolder) return; CWnd * pc = GetFolderChild(); if (pc) pc->ShowWindow(SW_HIDE); m_nCurSelFolder = index; pc = GetFolderChild(); if (pc) { CRect rc; GetInsideRect(rc); pc->MoveWindow(rc); pc->ShowWindow(SW_SHOW); } Invalidate(); } int CGfxOutBarCtrl::GetFolderCount() const { return m_arFolder.GetSize(); } int CGfxOutBarCtrl::GetSelFolder() const { return m_nCurSelFolder; } void CGfxOutBarCtrl::RemoveFolder(const int index) { ASSERT(index >= 0 && index < GetFolderCount()); CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(index); delete pbf; m_arFolder.RemoveAt(index); if (m_nCurSelFolder >= index) m_nCurSelFolder = index - 1; if (m_nCurSelFolder < 0 && GetFolderCount() > 0) m_nCurSelFolder = 0; Invalidate(); } BOOL CGfxOutBarCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { CPoint pt(GetMessagePos()); ScreenToClient(&pt); int index, ht = HitTestEx(pt, index); if (ht == htFolder) { SetCursor(hHandCursor); return true; } return CWnd::OnSetCursor(pWnd, nHitTest, message); } void CGfxOutBarCtrl::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); int t, max = GetFolderCount(); CRect rc; GetInsideRect(rc); for (t = 0; t < max; t++) { CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(t); CWnd * pc = GetFolderChild(t); if (pc) pc->SetWindowPos(0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER); } } CWnd * CGfxOutBarCtrl::GetFolderChild(int iFolder) { if (GetFolderCount()) { if (iFolder < 0) iFolder = m_nCurSelFolder; CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(iFolder); return pbf->pChild; } return NULL; } void CGfxOutBarCtrl::SetAutoFolder(IN const DWORD& dwTime) { SetTimer(2, dwTime, NULL); } DWORD CGfxOutBarCtrl::GetFolderData(int iFolder) { if (iFolder < 0) iFolder = m_nCurSelFolder; CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(iFolder); return pbf->dwData; } void CGfxOutBarCtrl::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (GetFocus() != this && PtInFolderHeadRect(point)) SetFocus(); int ht = HitTestEx(point, iHoverFolder); if (ht == htFolder) { HighlightFolder(iHoverFolder); SetTimer(1,100,NULL); } m_curpoint = point; CWnd::OnMouseMove(nFlags, point); } void CGfxOutBarCtrl::DrawFolder(CDC * pDC, const int iIdx, CRect rect) { if(iIdx < 0) return; CBm_arFolder *pBf=(CBm_arFolder*)m_arFolder.GetAt(iIdx); if (iHoverFolder == iIdx) { if(m_bmpHoverFolder.m_hObject != NULL) m_bmpHoverFolder.ExtendDraw(pDC,rect,20,5); } else { if(m_bmpNormalFolder.m_hObject != NULL) m_bmpNormalFolder.ExtendDraw(pDC,rect,20,5); } if(m_nCurSelFolder == iIdx && iSelcon != NULL) { ::DrawIconEx(*pDC,rect.left+2,rect.top +(m_nFolderHeight-16)/2,iSelcon,16,16,0,NULL,DI_NORMAL); } //Draw Folder Name In Folder if(m_pFont == NULL) m_pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT)); pDC->SelectObject(m_pFont); pDC->SetTextColor(m_crText); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(pBf->cName,rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE); } void CGfxOutBarCtrl::HighlightFolder(const int index) { if (iLastFolderHighlighted == index) return; CClientDC dc(this); if (iLastFolderHighlighted >= 0) { CRect rc; if (GetFolderRect(iLastFolderHighlighted, rc)) { DrawFolder(&dc,iLastFolderHighlighted,rc); } } if (index >= 0) { CRect rc; if (GetFolderRect(index, rc)) { DrawFolder(&dc,index,rc); } } iLastFolderHighlighted = index; } void CGfxOutBarCtrl::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (nIDEvent == 1) { CPoint pt(GetMessagePos()); ScreenToClient(&pt); CRect rc; GetClientRect(&rc); int ht = HitTestEx(pt, iHoverFolder); if (ht != htFolder || !(rc.PtInRect(pt))) { HighlightFolder(-1); KillTimer(1); } } if ( nIDEvent == 2 ) {// 鼠标在folderheader上x毫秒自动打开; if (GetFocus() != this && PtInFolderHeadRect(m_curpoint)) SetFocus(); int index, ht = HitTestEx(m_curpoint, index); if (ht == htFolder) { bool bHigh = true; if (::GetCapture() == NULL) { SetCapture(); ASSERT(this == GetCapture()); AfxLockTempMaps(); if(index = m_arFolder.GetSize() ) return FALSE; ScreenToClient(&pt); if ( !PtInFolderHeadRect(pt) ) { return FALSE; } INT nIndex = m_nCurSelFolder; if (::GetCapture() == NULL) { SetCapture(); AfxLockTempMaps(); CBm_arFolder *pChild = NULL; if ( zDelta > 0 ) {// 向上滚动; if ( m_nCurSelFolder == 0 ) { ReleaseCapture(); AfxUnlockTempMaps(FALSE); return TRUE; } nIndex--; pChild = (CBm_arFolder *)m_arFolder.GetAt(nIndex); if ( pChild ) { SetSelFolder(nIndex); } } else {// 向下滚动; if ( m_nCurSelFolder == GetFolderCount() - 1) { ReleaseCapture(); AfxUnlockTempMaps(FALSE); return TRUE; } nIndex++; pChild = (CBm_arFolder *)m_arFolder.GetAt(nIndex); if ( pChild ) { SetSelFolder(nIndex); } } ReleaseCapture(); AfxUnlockTempMaps(FALSE); } Invalidate(); return CWnd::OnMouseWheel(nFlags, zDelta, pt); }