www.pudn.com > TabBar.rar > TabBarCtrl.cpp, change:2006-04-06,size:53716b
// outbar.h : implementation of the CTabBarCtrl class #include "stdafx.h" #include "tabbarctrl.h" #define IDC_TABBARCTRL_REMOVE 60000 #define IDS_TABBARCTRL_REMOVE "Remove" #define IDC_TABBARCTRL_RENAME 60001 #define IDS_TABBARCTRL_RENAME "Rename" #define IDC_TABBARCTRL_ADD 60002 #define IDS_TABBARCTRL_ADD "Add Tab" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CItemTracker class CItemTracker::CItemTracker() { m_nHandleSize = TABBARCTRL_BLOCKTRACKER_BORDERWIDTH; m_nStyle = hatchedBorder; } CItemTracker::~CItemTracker() { } ///////////////////////////////////////////////////////////////////////////// // Operations BOOL CItemTracker::Track(CWnd *pWnd, CPoint Point, BOOL bAllowInvert, CWnd *pWndClipTo /*= NULL*/) { ASSERT_VALID(pWnd); // get these codes from the MFC source codes for calling the subclass TrackHandle() function // perform hit testing on the handles int nHandle = HitTestHandles(Point); if(nHandle < 0) { // didn't hit a handle, so just return FALSE return FALSE; } // otherwise, call helper function to do the tracking m_bAllowInvert = bAllowInvert; return TrackHandle(nHandle, pWnd, Point, pWndClipTo); } BOOL CItemTracker::TrackHandle(int nHandle, CWnd *pWnd, CPoint Point, CWnd *pWndClipTo) { ASSERT_VALID(pWnd); // write more codes is the MFC source codes, but add the mouse state handle ASSERT(nHandle >= 0); ASSERT(nHandle <= 8); // handle 8 is inside the rect // don't handle if capture already set if(::GetCapture() != NULL) return FALSE; AfxLockTempMaps(); // protect maps while looping ASSERT(!m_bFinalErase); // save original width & height in pixels int nWidth = m_rect.Width(); int nHeight = m_rect.Height(); // set capture to the window which received this message pWnd->SetCapture(); ASSERT(pWnd == CWnd::GetCapture()); pWnd->UpdateWindow(); if(pWndClipTo != NULL) pWndClipTo->UpdateWindow(); CRect rectSave = m_rect; // find out what x/y coords we are supposed to modify int *px, *py; int xDiff, yDiff; GetModifyPointers(nHandle, &px, &py, &xDiff, &yDiff); xDiff = Point.x - xDiff; yDiff = Point.y - yDiff; // get DC for drawing CDC* pDrawDC; if(pWndClipTo != NULL) // clip to arbitrary window by using adjusted Window DC pDrawDC = pWndClipTo->GetDCEx(NULL, DCX_CACHE); else // otherwise, just use normal DC pDrawDC = pWnd->GetDC(); ASSERT_VALID(pDrawDC); CRect rectOld; BOOL bMoved = FALSE; pWnd->SetTimer(10, TABBARCTRL_BLOCKTRACKER_DELAYTIME, NULL); BOOL bSetCursor = FALSE; // get messages until capture lost or cancelled/accepted for(;;) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if(CWnd::GetCapture() != pWnd) break; // add codes for setting the cursor if((msg.message == WM_MOUSEMOVE || msg.message == WM_LBUTTONUP || msg.message == WM_TIMER) && bSetCursor) { CPoint MousePoint; GetCursorPos(&MousePoint); CRect ClientRect; pWnd->GetClientRect(&ClientRect); pWnd->ScreenToClient(&MousePoint); if(ClientRect.PtInRect(MousePoint)) ::SetCursor(AfxGetApp()->LoadCursor(IDC_MOVE)); else ::SetCursor(::LoadCursor(NULL, IDC_NO)); } switch(msg.message) { // handle movement/accept messages case WM_TIMER: if(msg.wParam == 10) { pWnd->KillTimer(10); if(!bMoved) { bMoved = TRUE; m_bErase = FALSE; DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd); bSetCursor = TRUE; ::SetCursor(AfxGetApp()->LoadCursor(IDC_MOVE)); } } break; case WM_LBUTTONUP: case WM_MOUSEMOVE: rectOld = m_rect; // handle resize cases (and part of move) if(px != NULL) *px = (int)(short)LOWORD(msg.lParam) - xDiff; if(py != NULL) *py = (int)(short)HIWORD(msg.lParam) - yDiff; // handle move case if(nHandle == hitMiddle) { m_rect.right = m_rect.left + nWidth; m_rect.bottom = m_rect.top + nHeight; } // allow caller to adjust the rectangle if necessary AdjustRect(nHandle, &m_rect); // only redraw and callback if the rect actually changed! m_bFinalErase = (msg.message == WM_LBUTTONUP); if(!rectOld.EqualRect(&m_rect) || m_bFinalErase) { if(bMoved) { m_bErase = TRUE; DrawTrackerRect(&rectOld, pWndClipTo, pDrawDC, pWnd); } OnChangedRect(rectOld); if(msg.message != WM_LBUTTONUP) { bMoved = TRUE; bSetCursor = TRUE; } } if(m_bFinalErase) goto ExitLoop; if(!rectOld.EqualRect(&m_rect)) { m_bErase = FALSE; DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd); } break; // handle cancel messages case WM_KEYDOWN: if(msg.wParam != VK_ESCAPE) break; case WM_RBUTTONDOWN: if(bMoved) { m_bErase = m_bFinalErase = TRUE; DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd); } m_rect = rectSave; goto ExitLoop; // just dispatch rest of the messages default: DispatchMessage(&msg); break; } } ExitLoop: if(pWndClipTo != NULL) pWndClipTo->ReleaseDC(pDrawDC); else pWnd->ReleaseDC(pDrawDC); ReleaseCapture(); AfxUnlockTempMaps(FALSE); // restore rect in case bMoved is still FALSE if(!bMoved) m_rect = rectSave; m_bFinalErase = FALSE; m_bErase = FALSE; // return TRUE only if rect has changed return !rectSave.EqualRect(&m_rect); } void CItemTracker::OnChangedRect(const CRect& /*OldRect*/) { // no default implementation, useful for derived classes m_rect.bottom = m_rect.top + m_FirstRect.Height(); m_rect.right = m_rect.left + m_FirstRect.Width(); } ///////////////////////////////////////////////////////////////////////////// // CFolderAddDlg class CFolderAddDlg::CFolderAddDlg(CWnd *pParent /*=NULL*/) : CDialog(CFolderAddDlg::IDD, pParent) { //{{AFX_DATA_INIT(CFolderAddDlg) // NOTE: the ClassWizard will add member initialization here m_AddFolderName = _T(""); //}}AFX_DATA_INIT } BEGIN_MESSAGE_MAP(CFolderAddDlg, CDialog) //{{AFX_MSG_MAP(CFolderAddDlg) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Overrides void CFolderAddDlg::DoDataExchange(CDataExchange *pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CFolderAddDlg) // NOTE: the ClassWizard will add DDX and DDV calls here DDX_Text(pDX, IDC_TABBARCTRL_ADDFOLDERNAME, m_AddFolderName); //}}AFX_DATA_MAP } BOOL CFolderAddDlg::OnInitDialog() { CDialog::OnInitDialog(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } ///////////////////////////////////////////////////////////////////////////// // CFolderEdit class CFolderEdit::CFolderEdit() { m_bEscapeKeyPressed = FALSE; m_nIndex = -1; m_EditString.Empty(); } CFolderEdit::~CFolderEdit() { } BEGIN_MESSAGE_MAP(CFolderEdit, CEdit) //{{AFX_MSG_MAP(CFolderEdit) ON_WM_CREATE() ON_WM_KILLFOCUS() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Overrides void CFolderEdit::PostNcDestroy() { CEdit::PostNcDestroy(); delete this; } BOOL CFolderEdit::PreTranslateMessage(MSG *pMsg) { if(pMsg->wParam == VK_RETURN) { PostMessage(WM_CLOSE, 0, 0); m_bEscapeKeyPressed = FALSE; return TRUE; } else if(pMsg->wParam == VK_ESCAPE) { PostMessage(WM_CLOSE, 0, 0); m_bEscapeKeyPressed = TRUE; return TRUE; } return CEdit::PreTranslateMessage(pMsg); } ///////////////////////////////////////////////////////////////////////////// // Message handlers int CFolderEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CEdit::OnCreate(lpCreateStruct) == -1) return -1; SendMessage(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0)); return 0; } void CFolderEdit::OnKillFocus(CWnd* /*pNewWnd*/) { PostMessage(WM_CLOSE, 0, 0); if(!m_bEscapeKeyPressed) { GetWindowText(m_EditString); if(!m_EditString.IsEmpty()) GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_FOLDERENDEDIT, (LPARAM)this); } } ///////////////////////////////////////////////////////////////////////////// // CTabBarCtrl class IMPLEMENT_DYNCREATE(CTabBarCtrl, CWnd) CTabBarCtrl::CTabBarCtrl() { m_nFolderBorderWidth = TABBARCTRL_FOLDERBORDERWIDTH; m_FolderLightColor = TABBARCTRL_FOLDERLIGHTBORDER; m_FolderHighlightColor = TABBARCTRL_FOLDERHIGHLIGHTCOLOR; m_FolderShadowColor = TABBARCTRL_FOLDERSHADOWBORDER; m_FolderTextColor = TABBARCTRL_FOLDERTEXTCOLOR; m_FolderBackGroundColor = TABBARCTRL_FOLDERBACKGROUNDCOLOR; m_FolderFrontColor = TABBARCTRL_FOLDERFRONTCOLOR; m_ItemLightColor = TABBARCTRL_ITEMHILIGHTCOLOR; m_ItemShadowColor = TABBARCTRL_ITEMSHADOWCOLOR; m_ItemHighlightColor = TABBARCTRL_ITEMHIGHLIGHTCOLOR; m_ItemSelectedColor = TABBARCTRL_ITEMSELECTEDCOLOR; m_ItemTextColor = TABBARCTRL_ITEMTEXTCOLOR; m_ChildBackGroundColor = TABBARCTRL_CHILDBACKGROUNDCOLOR; m_nFolderHeight = TABBARCTRL_FOLDERHEIGHT; m_nItemBorderWidth = TABBARCTRL_ITEMBORDERWIDTH; m_pImageList = NULL; m_nSelFolder = 0; m_nDelayTime = TABBARCTRL_DELAYTIME; m_nHorzSpace = TABBARCTRL_ITEMHORZSPACE; m_nVertSpace = TABBARCTRL_ITEMVERTSPACE; m_lAnimationTickCount = TABBARCTRL_ANIMATIONTICKCOUNT; m_nRButtonHitItemIndex = -1; m_nRButtonHitFolderIndex = -1; m_bToolTip = TRUE; // get the windows directory CString WndDirString; GetWindowsDirectory(WndDirString.GetBuffer(MAX_PATH), MAX_PATH); WndDirString.ReleaseBuffer(); WndDirString += _T("\\winhlp32.exe"); // this retrieves cursor #106 from winhlp32.exe, which is a hand pointer HMODULE hModule = LoadLibrary(WndDirString); if(hModule) { HCURSOR hHandCursor = LoadCursor(hModule, MAKEINTRESOURCE(106)); if(hHandCursor) m_hHandCursor = CopyCursor(hHandCursor); else TRACE0("unsuccessfully copy cursor from winhlp32.exe(in tabbarctrl.cpp line 350)\n"); } FreeLibrary(hModule); } CTabBarCtrl::~CTabBarCtrl() { for(int i = 0; i < m_FolderList.GetSize(); i++) { if(m_FolderList.GetAt(i)) delete (CTabBarFolder*)m_FolderList.GetAt(i); } m_FolderList.RemoveAll(); if(m_pImageList) m_pImageList->DeleteImageList(); delete m_pImageList; } BEGIN_MESSAGE_MAP(CTabBarCtrl, CWnd) //{{AFX_MSG_MAP(CTabBarCtrl) ON_COMMAND(IDC_TABBARCTRL_ADD, OnAddFolder) ON_COMMAND(IDC_TABBARCTRL_REMOVE, OnRemoveItem) ON_COMMAND(IDC_TABBARCTRL_RENAME, OnRenameItem) ON_MESSAGE(WM_TABBARCTRL_NOTIFY, OnEndFolderEdit) ON_WM_CONTEXTMENU() ON_WM_CREATE() ON_WM_ERASEBKGND() ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_PAINT() ON_WM_SIZE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Operations void CTabBarCtrl::AnimateFolderScroll(int nFromFolder, int nToFolder) { ASSERT(nFromFolder >= 0 && nFromFolder < GetFolderCount()); ASSERT(nToFolder >= 0 && nToFolder < GetFolderCount()); DWORD lparam = nFromFolder & 0x0000ffff; DWORD dwtemp = nToFolder & 0x0000ffff; lparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_FOLDERSCROLLBEGIN, (LPARAM)lparam); // set the default cursor SetCursor(LoadCursor(NULL, IDC_ARROW)); // create three memory device contexts CClientDC DrawDC(this); CDC ScreenDC, FrontDC, BackDC; ScreenDC.CreateCompatibleDC(&DrawDC); FrontDC.CreateCompatibleDC(&DrawDC); BackDC.CreateCompatibleDC(&DrawDC); // get the back ground rectangle and front rectangle CRect FrontRect, BackRect; // get the from folder items rectangle GetInsideRect(FrontRect); // get the to folder rectangle GetFolderRect(BackRect, nToFolder); // get the update rectangle BackRect.UnionRect(BackRect, FrontRect); FrontRect = CRect(0, 0, BackRect.Width(), BackRect.Height()); // create three bitmaps CBitmap ScreenBitmap, FrontBitmap, BackBitmap; ScreenBitmap.CreateCompatibleBitmap(&DrawDC, FrontRect.Width(), FrontRect.Height()); FrontBitmap.CreateCompatibleBitmap(&DrawDC, FrontRect.Width(), FrontRect.Height()); BackBitmap.CreateCompatibleBitmap(&DrawDC, FrontRect.Width(), FrontRect.Height()); // select the bitmaps into the memory device contexts CBitmap* pScreenBitmap = ScreenDC.SelectObject(&ScreenBitmap); CBitmap* pFrontBitmap = FrontDC.SelectObject(&FrontBitmap); CBitmap* pBackBitmap = BackDC.SelectObject(&BackBitmap); // copy the screen bitmap into the memory device context ScreenDC.BitBlt(0, 0, BackRect.Width(), BackRect.Height(), &DrawDC, BackRect.left, BackRect.top, SRCCOPY); BackDC.BitBlt(0, 0, BackRect.Width(), BackRect.Height(), &DrawDC, BackRect.left, BackRect.top, SRCCOPY); // fill the front bitmap with the back ground color FrontDC.FillSolidRect(FrontRect, m_ChildBackGroundColor); // draw the scrolled bitmap into the memory device context if(nToFolder > nFromFolder) { // draw the to folder child window CWnd* pWnd = GetFolderChild(nToFolder); if(pWnd) { CPoint OldPoint = FrontDC.SetViewportOrg(0, m_nFolderHeight * (nToFolder - nFromFolder)); BOOL bPrev = pWnd->ShowWindow(SW_SHOW); pWnd->SendMessage(WM_ERASEBKGND, (WPARAM)FrontDC.GetSafeHdc(), (LPARAM)0); pWnd->SendMessage(WM_PAINT, (WPARAM)FrontDC.GetSafeHdc(), (LPARAM)0); if(!bPrev) pWnd->ShowWindow(SW_HIDE); FrontDC.SetViewportOrg(OldPoint); } else { // redraw the to folder items CRect ItemsRect; GetInsideRect(ItemsRect); CRect LimitRect = ItemsRect; ItemsRect.top = 0; CBitmap ItemsBitmap; ItemsBitmap.CreateCompatibleBitmap(&DrawDC, ItemsRect.Width(), ItemsRect.Height()); CDC ItemsDC; ItemsDC.CreateCompatibleDC(&DrawDC); CBitmap* pItemsBitmap = ItemsDC.SelectObject(&ItemsBitmap); ItemsDC.FillSolidRect(&ItemsRect, m_ChildBackGroundColor); PaintItems(&ItemsDC, nToFolder, LimitRect); FrontDC.BitBlt(ItemsRect.left, m_nFolderHeight * (nToFolder - nFromFolder), ItemsRect.Width(), LimitRect.Height(), &ItemsDC, LimitRect.left, (nFromFolder + 1) * m_nFolderHeight, SRCCOPY); ItemsDC.SelectObject(pItemsBitmap); ItemsDC.DeleteDC(); ItemsBitmap.DeleteObject(); } // draw the folders CRect FolderRect(FrontRect); FolderRect.top = 0; FolderRect.bottom = m_nFolderHeight; for(int i = nFromFolder + 1; i <= nToFolder; i++) { DrawFolder(&FrontDC, i, FolderRect); FolderRect.OffsetRect(0, m_nFolderHeight); } } else { // draw the to folder child window CWnd* pWnd = GetFolderChild(nToFolder); if(pWnd) { CPoint OldPoint = FrontDC.SetViewportOrg(0, m_nFolderHeight); BOOL bPrev = pWnd->ShowWindow(SW_SHOW); pWnd->SendMessage(WM_ERASEBKGND, (WPARAM)FrontDC.GetSafeHdc(), (LPARAM)0); pWnd->SendMessage(WM_PAINT, (WPARAM)FrontDC.GetSafeHdc(), (LPARAM)0); if(!bPrev) pWnd->ShowWindow(SW_HIDE); FrontDC.SetViewportOrg(OldPoint); } else { // redraw the to folder items CRect ItemsRect; GetInsideRect(ItemsRect); CRect LimitRect = ItemsRect; ItemsRect.top = 0; CBitmap ItemsBitmap; ItemsBitmap.CreateCompatibleBitmap(&DrawDC, ItemsRect.Width(), ItemsRect.Height()); CDC ItemsDC; ItemsDC.CreateCompatibleDC(&DrawDC); CBitmap* pItemsBitmap = ItemsDC.SelectObject(&ItemsBitmap); ItemsDC.FillSolidRect(&ItemsRect, m_ChildBackGroundColor); PaintItems(&ItemsDC, nToFolder, LimitRect); FrontDC.BitBlt(ItemsRect.left, m_nFolderHeight, ItemsRect.Width(), LimitRect.Height(), &ItemsDC, LimitRect.left, (nFromFolder + 1) * m_nFolderHeight, SRCCOPY); ItemsDC.SelectObject(pItemsBitmap); ItemsDC.DeleteDC(); ItemsBitmap.DeleteObject(); } // draw the folders CRect FolderRect(FrontRect); FolderRect.top = 0; FolderRect.bottom = m_nFolderHeight; DrawFolder(&FrontDC, nToFolder, FolderRect); } // move the to folder and its child window if(nToFolder > nFromFolder) { for(int i = FrontRect.bottom - (nToFolder - nFromFolder) * m_nFolderHeight; i > 0; i -= TABBARCTRL_FOLDERSCROLLSTEP) { ScreenDC.BitBlt(FrontRect.left, i, FrontRect.Width(), FrontRect.bottom - i, &FrontDC, 0, 0, SRCCOPY); DrawDC.BitBlt(BackRect.left, BackRect.top, BackRect.Width(), BackRect.bottom, &ScreenDC, 0, 0, SRCCOPY); Sleep(m_lAnimationTickCount); } ScreenDC.BitBlt(FrontRect.left, 0, FrontRect.Width(), FrontRect.bottom, &FrontDC, 0, 0, SRCCOPY); DrawDC.BitBlt(BackRect.left, BackRect.top, BackRect.Width(), BackRect.bottom, &ScreenDC, 0, 0, SRCCOPY); } else { for(int i = FrontRect.top; i < FrontRect.bottom - (nFromFolder - nToFolder) * m_nFolderHeight; i += TABBARCTRL_FOLDERSCROLLSTEP) { ScreenDC.BitBlt(FrontRect.left, FrontRect.top, FrontRect.Width(), i - FrontRect.top, &FrontDC, 0, 0, SRCCOPY); ScreenDC.BitBlt(FrontRect.left, i - FrontRect.top, FrontRect.Width(), FrontRect.bottom - (i - FrontRect.top), &BackDC, 0, m_nFolderHeight, SRCCOPY); DrawDC.BitBlt(BackRect.left, BackRect.top, BackRect.Width(), BackRect.Height(), &ScreenDC, 0, 0, SRCCOPY); Sleep(m_lAnimationTickCount); } ScreenDC.BitBlt(FrontRect.left, FrontRect.top, FrontRect.Width(), FrontRect.Height() - (nFromFolder - nToFolder) * m_nFolderHeight, &FrontDC, 0, 0, SRCCOPY); ScreenDC.BitBlt(FrontRect.left, FrontRect.Height() - (nFromFolder - nToFolder) * m_nFolderHeight, FrontRect.Width(), (nFromFolder - nToFolder) * m_nFolderHeight, &BackDC, 0, m_nFolderHeight, SRCCOPY); DrawDC.BitBlt(BackRect.left, BackRect.top, BackRect.Width(), BackRect.Height(), &ScreenDC, 0, 0, SRCCOPY); } // release the gdi resource ScreenDC.SelectObject(pScreenBitmap); FrontDC.SelectObject(pFrontBitmap); BackDC.SelectObject(pBackBitmap); ScreenDC.DeleteDC(); FrontDC.DeleteDC(); BackDC.DeleteDC(); ScreenBitmap.DeleteObject(); FrontBitmap.DeleteObject(); BackBitmap.DeleteObject(); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_FOLDERSCROLLEND, (LPARAM)lparam); } BOOL CTabBarCtrl::CreateToolTip() { CString ClassName = AfxRegisterWndClass(NULL); m_bCreateToolTip = m_ToolTip.CreateEx(0L, ClassName, "ToolTip", WS_BORDER | WS_POPUP, CRect(0, 0, 0, 0), this, 0L); return m_bCreateToolTip; } BOOL CTabBarCtrl::DragItem(CPoint Point, int nItemIndex) { // set the items tracker ReleaseCapture(); DWORD lpparam = nItemIndex & 0x0000ffff; DWORD dwtemp = m_nSelFolder & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_DRAGITEMBEGIN, (LPARAM)lpparam); CRect ItemRect; GetItemRect(ItemRect, nItemIndex, m_nSelFolder); CItemTracker Tracker; Tracker.m_rect = ItemRect; Tracker.m_FirstRect = ItemRect; BOOL bReturn = Tracker.Track(this, Point, FALSE, NULL); if(!bReturn) { InvalidateRect(Tracker.m_rect, FALSE); return FALSE; } // get the capture CPoint MousePoint; GetCursorPos(&MousePoint); ScreenToClient(&MousePoint); CRect ClientRect; GetClientRect(&ClientRect); if(ClientRect.PtInRect(MousePoint) && GetCapture() == NULL) { SetCapture(); ASSERT(this == GetCapture()); } // check if the item is in other folder int nIndex1, ht1 = HitTestEx(MousePoint, nIndex1); if(ht1 == htFolder && nIndex1 != m_nSelFolder) { // change the item AfxLockTempMaps(); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(m_nSelFolder); void* pBarItem = (pBarFolder->m_ItemList.GetAt(nItemIndex)); pBarFolder->m_ItemList.RemoveAt(nItemIndex); pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nIndex1); if(((CTabBarItem*)pBarItem)->m_bSelected) ResetAllSelectedItems(nIndex1); pBarFolder->m_ItemList.Add(pBarItem); AfxUnlockTempMaps(FALSE); lpparam = nItemIndex & 0x0000ffff; dwtemp = nIndex1 & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ITEMMOVE, (LPARAM)lpparam); SetSelectedFolder(nIndex1); bReturn = TRUE; } GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_DRAGITEMEND, (LPARAM)0L); return bReturn; } CWnd* CTabBarCtrl::GetFolderChild(int nFolderIndex) const { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); return pBarFolder->m_pChildWnd; } DWORD CTabBarCtrl::GetFolderData(int nFolderIndex) const { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); return pBarFolder->m_dwExData; } void CTabBarCtrl::GetFolderRect(CRect& FolderRect, int nFolderIndex) { AssertFolderIndex(nFolderIndex); CRect ClientRect; GetClientRect(ClientRect); if(nFolderIndex > m_nSelFolder) FolderRect.SetRect(ClientRect.left, ClientRect.bottom - ((m_FolderList.GetSize() - nFolderIndex)) * m_nFolderHeight, ClientRect.right, ClientRect.bottom - (m_FolderList.GetSize() - nFolderIndex - 1) * m_nFolderHeight); else FolderRect.SetRect(ClientRect.left, ClientRect.top + nFolderIndex * m_nFolderHeight - 1, ClientRect.right, ClientRect.top + (1 + nFolderIndex) * m_nFolderHeight - 1); } CString CTabBarCtrl::GetFolderText(int nFolderIndex) const { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); return pBarFolder->m_FolderString; } int CTabBarCtrl::GetHightedFolder() const { for(int i = 0; i < m_FolderList.GetSize(); i++) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(i); ASSERT(pBarFolder); if(pBarFolder->m_bHighted) return i; } return -1; } int CTabBarCtrl::GetHightedItem(int nFolderIndex) const { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); for(int i = 0; i < pBarFolder->m_ItemList.GetSize(); i++) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); ASSERT(pBarItem); if(pBarItem->m_bHighted) return i; } return -1; } void CTabBarCtrl::GetInsideRect(CRect& ChildRect) { GetClientRect(ChildRect); if(m_FolderList.GetSize() > 0) { ChildRect.top += m_nFolderHeight * (m_nSelFolder + 1) - 1; ChildRect.bottom -= (m_FolderList.GetSize() - m_nSelFolder - 1) * m_nFolderHeight; } } int CTabBarCtrl::GetItemCount(int nFolderIndex) const { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); return pBarFolder->m_ItemList.GetSize(); } DWORD CTabBarCtrl::GetItemData(int nItemIndex, int nFolderIndex) const { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); return pBarItem->m_dwExData; } int CTabBarCtrl::GetItemImage(int nItemIndex, int nFolderIndex) const { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); return pBarItem->m_nImageIndex; } BOOL CTabBarCtrl::GetItemRect(CRect& ItemRect, int nItemIndex, int nFolderIndex) { AssertItemIndex(nItemIndex, nFolderIndex); // get the child window CRect InsideRect; GetInsideRect(InsideRect); // recorde the top left point CPoint TopLeftPoint = InsideRect.TopLeft() + CPoint(m_nHorzSpace, m_nVertSpace); InsideRect.OffsetRect(-InsideRect.left, -InsideRect.top); // get the item size CSize ItemSize = GetItemSize(nItemIndex, nFolderIndex); // check the child window width and height int nHorzItemCount, nVertItemCount; nHorzItemCount = (int)((InsideRect.Width() - m_nHorzSpace) / (m_nHorzSpace + ItemSize.cx)); nVertItemCount = (int)((InsideRect.Height() - m_nVertSpace) / (m_nVertSpace + ItemSize.cy)); // check if the item is visible if(nItemIndex >= nHorzItemCount * nVertItemCount) { ItemRect.SetRectEmpty(); return FALSE; } // get the item position int nVertPosition = (int)(nItemIndex / nHorzItemCount); int nHorzPosition = nItemIndex - nVertPosition * nHorzItemCount; // get item rectangle ItemRect.top = nVertPosition * (ItemSize.cy + m_nVertSpace); ItemRect.left = nHorzPosition * (ItemSize.cx + m_nHorzSpace); ItemRect.bottom = ItemRect.top + ItemSize.cy; ItemRect.right = ItemRect.left + ItemSize.cx; ItemRect.OffsetRect(TopLeftPoint); ItemRect.InflateRect(TABBARCTRL_ITEMBORDERWIDTH, TABBARCTRL_ITEMBORDERWIDTH); return TRUE; } CSize CTabBarCtrl::GetItemSize(int nItemIndex, int nFolderIndex) const { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); CSize ImageSize(0, 0); if(pBarItem->m_nImageIndex >= 0) { ASSERT_VALID(m_pImageList); IMAGEINFO ImageInfo; m_pImageList->GetImageInfo(pBarItem->m_nImageIndex, &ImageInfo); ImageSize = CRect(ImageInfo.rcImage).Size(); } ImageSize += CSize(2, 2); return ImageSize; } CString CTabBarCtrl::GetItemText(int nItemIndex, int nFolderIndex) const { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); return pBarItem->m_ItemString; } CMenu* CTabBarCtrl::GetMenu() { CMenu* PopupMenu; PopupMenu = new CMenu(); CPoint ClientPoint; GetCursorPos(&ClientPoint); ScreenToClient(&ClientPoint); int nIndex, ht = HitTestEx(ClientPoint, nIndex); CMenu Menu; PopupMenu->CreatePopupMenu(); PopupMenu->AppendMenu(MF_STRING, IDC_TABBARCTRL_ADD, IDS_TABBARCTRL_ADD); CString String; if(ht == htItem) { m_nRButtonHitItemIndex = nIndex; m_nRButtonHitFolderIndex = -1; PopupMenu->AppendMenu(MF_STRING, IDC_TABBARCTRL_REMOVE, IDS_TABBARCTRL_REMOVE); if(GetItemCount(m_nSelFolder) <= 1) PopupMenu->EnableMenuItem(IDC_TABBARCTRL_REMOVE, MF_DISABLED | MF_GRAYED); } else if(ht == htFolder) { m_nRButtonHitFolderIndex = nIndex; m_nRButtonHitItemIndex = -1; PopupMenu->AppendMenu(MF_STRING, IDC_TABBARCTRL_REMOVE, IDS_TABBARCTRL_REMOVE); if(m_FolderList.GetSize() <= 1) PopupMenu->EnableMenuItem(IDC_TABBARCTRL_REMOVE, MF_DISABLED | MF_GRAYED); PopupMenu->AppendMenu(MF_STRING, IDC_TABBARCTRL_RENAME, IDS_TABBARCTRL_RENAME); } return PopupMenu; } int CTabBarCtrl::GetSelectedItem(int nFolderIndex) const { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); for(int i = 0; i < pBarFolder->m_ItemList.GetSize(); i++) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); ASSERT(pBarItem); if(pBarItem->m_bSelected) return i; } return -1; } BOOL CTabBarCtrl::HideToolTip() { if(m_ToolTip.IsWindowVisible()) { m_ToolTip.SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER); return TRUE; } return FALSE; } void CTabBarCtrl::HighlightFolder(int nFolderIndex) { // check if it has focus CWnd* pWnd = GetFocus(); if(pWnd != NULL && pWnd != this && IsChild(pWnd)) { TRACE0("the folder do not has focus(in tabbarctrl.cpp line 821)\n"); return; } // check if the last highlighted folder is different from the folder for(int i = 0; i < m_FolderList.GetSize(); i++) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(i); if(pBarFolder->m_bHighted) break; } if(nFolderIndex == -1) { if(i < m_FolderList.GetSize()) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(i); pBarFolder->m_bHighted = FALSE; CRect UpdateRect; GetFolderRect(UpdateRect, i); InvalidateRect(&UpdateRect, FALSE); } } else if(i == m_FolderList.GetSize()) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); pBarFolder->m_bHighted = TRUE; CRect UpdateRect; GetFolderRect(UpdateRect, nFolderIndex); InvalidateRect(&UpdateRect, FALSE); } else if(i != nFolderIndex) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(i); pBarFolder->m_bHighted = FALSE; pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); pBarFolder->m_bHighted = TRUE; CRect OldFolderRect, NewFolderRect; GetFolderRect(OldFolderRect, i); GetFolderRect(NewFolderRect, nFolderIndex); InvalidateRect(&OldFolderRect, FALSE); InvalidateRect(&NewFolderRect, FALSE); } } void CTabBarCtrl::HighlightItem(int nItemIndex) { // check if it has focus CWnd* pWnd = GetFocus(); if(pWnd != NULL && pWnd != this && IsChild(pWnd)) { TRACE0("the item do not has focus(in tabbarctrl.cpp line 870)\n"); return; } CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(m_nSelFolder); // check if the last highlighted item is different from the item for(int i = 0; i < pBarFolder->m_ItemList.GetSize(); i++) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); ASSERT(pBarItem); if(pBarItem->m_bHighted) break; } // get the child window rectangle CRect InsideRect; GetInsideRect(InsideRect); // create the device context CClientDC DrawDC(this); int nDC = DrawDC.SaveDC(); CRgn ItemsRegion; ItemsRegion.CreateRectRgnIndirect(&InsideRect); DrawDC.SelectClipRgn(&ItemsRegion); ItemsRegion.DeleteObject(); // update the window if(nItemIndex == -1) { if(i < pBarFolder->m_ItemList.GetSize()) { CTabBarItem* pBarItem = (CTabBarItem*)(pBarFolder->m_ItemList.GetAt(i)); pBarItem->m_bHighted = FALSE; CRect UpdateRect; GetItemRect(UpdateRect, i, m_nSelFolder); InvalidateRect(&UpdateRect, FALSE); HideToolTip(); } } else if(i == pBarFolder->m_ItemList.GetSize()) { CTabBarItem* pBarItem = (CTabBarItem*)(pBarFolder->m_ItemList.GetAt(nItemIndex)); pBarItem->m_bHighted = TRUE; CRect UpdateRect; if(GetItemRect(UpdateRect, nItemIndex, m_nSelFolder)) InvalidateRect(&UpdateRect, FALSE); ShowToolTip(nItemIndex); } else if(i != nItemIndex) { CRect OldItemRect, NewItemRect; CTabBarItem* pBarItem = (CTabBarItem*)(pBarFolder->m_ItemList.GetAt(i)); pBarItem->m_bHighted = FALSE; pBarItem = (CTabBarItem*)(pBarFolder->m_ItemList.GetAt(nItemIndex)); pBarItem->m_bHighted = TRUE; if(GetItemRect(OldItemRect, i, m_nSelFolder) && GetItemRect(NewItemRect, nItemIndex, m_nSelFolder)) { InvalidateRect(&OldItemRect, FALSE); InvalidateRect(&NewItemRect, FALSE); } ShowToolTip(nItemIndex); } DrawDC.RestoreDC(nDC); } void CTabBarCtrl::OnStartFolderEdit(int nFolderIndex) { ReleaseCapture(); AssertFolderIndex(nFolderIndex); CFolderEdit* pEdit = new CFolderEdit(); pEdit->m_nIndex = nFolderIndex; CRect FolderRect; GetFolderRect(FolderRect, nFolderIndex); FolderRect.DeflateRect(2, 2); pEdit->Create(WS_CHILD | WS_VISIBLE | ES_CENTER | ES_AUTOHSCROLL, FolderRect, this, IDC_TABBARCTRL_RENAME); pEdit->ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); pEdit->SetWindowText(pBarFolder->m_FolderString); pEdit->SetFocus(); pEdit->SetCapture(); } void CTabBarCtrl::ResetAllHightedItems(int nFolderIndex) { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); for(int i = 0; i < pBarFolder->m_ItemList.GetSize(); i++) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); ASSERT(pBarItem); pBarItem->m_bHighted = FALSE; } Invalidate(FALSE); } void CTabBarCtrl::ResetAllSelectedItems(int nFolderIndex) { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); for(int i = 0; i < pBarFolder->m_ItemList.GetSize(); i++) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); ASSERT(pBarItem); pBarItem->m_bSelected = FALSE; } Invalidate(FALSE); } void CTabBarCtrl::SelectItem(int nItemIndex) { // set the selected items if(GetSelectedItem(m_nSelFolder) == nItemIndex) { ResetAllSelectedItems(m_nSelFolder); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_RESETALLITEMS, (LPARAM)0L); } else SetSelectedItem(nItemIndex, m_nSelFolder); } void CTabBarCtrl::SetFolderText(int nFolderIndex, CString TextString) { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); pBarFolder->m_FolderString = TextString; } CImageList* CTabBarCtrl::SetImageList(CImageList *pImageList) { ASSERT_VALID(pImageList); if(m_pImageList) { CImageList* pOldImageList = m_pImageList; m_pImageList->DeleteImageList(); delete m_pImageList; return pOldImageList; } else { m_pImageList = new CImageList(); m_pImageList->Create(pImageList); } return NULL; } void CTabBarCtrl::SetItemData(int nItemIndex, int nFolderIndex, DWORD dwData) { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); pBarItem->m_dwExData = dwData; } void CTabBarCtrl::SetItemImage(int nItemIndex, int nFolderIndex, int nImageIndex) { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); pBarItem->m_nImageIndex = nImageIndex; } void CTabBarCtrl::SetItemText(int nItemIndex, int nFolderIndex, CString TextString) { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); pBarItem->m_ItemString = TextString; } void CTabBarCtrl::SetSelectedFolder(int nFolderIndex) { AssertFolderIndex(nFolderIndex); // check if the current selected folder is different from the folder if(nFolderIndex == m_nSelFolder) return; // hide the current selected folder child window CWnd* pWnd = GetFolderChild(m_nSelFolder); if(pWnd) pWnd->ShowWindow(SW_HIDE); // set the current selected folder ResetAllHightedItems(m_nSelFolder); ResetAllHightedItems(nFolderIndex); // scroll the new folder AnimateFolderScroll(m_nSelFolder, nFolderIndex); m_nSelFolder = nFolderIndex; // set the new selected folder CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(m_nSelFolder); pWnd = pBarFolder->m_pChildWnd; if(pWnd) { CRect ChildRect; GetInsideRect(ChildRect); pWnd->MoveWindow(ChildRect); pWnd->ShowWindow(SW_SHOW); pWnd->Invalidate(FALSE); } // check the current folder state CRect FolderRect; GetFolderRect(FolderRect, m_nSelFolder); CPoint ScreenPoint; GetCursorPos(&ScreenPoint); ScreenToClient(&ScreenPoint); if(!FolderRect.PtInRect(ScreenPoint)) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(m_nSelFolder); pBarFolder->m_bHighted = FALSE; InvalidateRect(FolderRect, FALSE); } GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_FOLDERCHANGE, (LPARAM)m_nSelFolder); } void CTabBarCtrl::SetSelectedItem(int nItemIndex, int nFolderIndex) { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); for(int i = 0; i < pBarFolder->m_ItemList.GetSize(); i++) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); ASSERT(pBarItem); if(pBarItem->m_bSelected) break; } if(i == pBarFolder->m_ItemList.GetSize()) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); pBarItem->m_bSelected = TRUE; CRect UpdateRect; if(GetItemRect(UpdateRect, nItemIndex, nFolderIndex)) InvalidateRect(&UpdateRect, FALSE); } else if(i != nItemIndex) { CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(i); pBarItem->m_bSelected = FALSE; pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); pBarItem->m_bSelected = TRUE; CRect OldItemRect, NewItemRect; GetItemRect(OldItemRect, i, nFolderIndex); GetItemRect(NewItemRect, nItemIndex, nFolderIndex); InvalidateRect(&OldItemRect, FALSE); InvalidateRect(&NewItemRect, FALSE); } DWORD lpparam = nItemIndex & 0x0000ffff; DWORD dwtemp = nFolderIndex & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ITEMCHANGE, (LPARAM)lpparam); } BOOL CTabBarCtrl::ShowToolTip(int nItemIndex) { if(m_bCreateToolTip && m_bToolTip) { // get the tool tip top left point CRect ItemRect; GetItemRect(ItemRect, nItemIndex, m_nSelFolder); ClientToScreen(&ItemRect); CPoint Point; Point.x = (ItemRect.right + ItemRect.left) / 2; Point.y = ItemRect.bottom + 10; // get the tool tip device context CDC* pToolTipDC = m_ToolTip.GetDC(); // create the tool tip font CFont Font; Font.CreateFont(-6, 0, 0, 0, 400, FALSE, FALSE, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, "MS Sans Serif"); CFont* pFont = pToolTipDC->SelectObject(&Font); // get the tool tip text CString ToolTipText = GetItemText(nItemIndex, m_nSelFolder); // get the tool tip top size CSize TextSize = pToolTipDC->GetOutputTextExtent(ToolTipText); CSize Size = CSize(3, 2) + TextSize; // show the tool tip window UINT nFlags = SWP_NOACTIVATE | SWP_NOZORDER; if(m_ToolTip.IsWindowVisible()) m_ToolTip.SetWindowPos(NULL, Point.x, Point.y, Size.cx, Size.cy, nFlags); else m_ToolTip.SetWindowPos(NULL, Point.x, Point.y, Size.cx, Size.cy, nFlags | SWP_SHOWWINDOW); // draw the text int nOldMode = pToolTipDC->SetBkMode(OPAQUE); CRect ToolTipRect(0, 0, Size.cx, Size.cy); pToolTipDC->FillSolidRect(ToolTipRect, GetSysColor(COLOR_INFOBK)); pToolTipDC->DrawText(ToolTipText, ToolTipRect, DT_LEFT); pToolTipDC->SetBkMode(nOldMode); // release the device context pToolTipDC->SelectObject(pFont); Font.DeleteObject(); m_ToolTip.ReleaseDC(pToolTipDC); return TRUE; } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // Overrides int CTabBarCtrl::AddFolder(CString FolderName, DWORD dwExData /*= 0*/) { CTabBarFolder* pBarFolder = new CTabBarFolder(FolderName, dwExData); ASSERT(pBarFolder); int nIndex = m_FolderList.Add((void*)pBarFolder); if(m_FolderList.GetSize() == 1) SetSelectedFolder(0); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ADDFOLDER, (LPARAM)nIndex); return m_FolderList.GetSize() - 1; } int CTabBarCtrl::AddFolderBar(CString FolderName, CWnd *pChildWnd, DWORD dwExData /*= 0*/) { ASSERT_VALID(pChildWnd); CTabBarFolder* pBarFolder = new CTabBarFolder(FolderName, dwExData); ASSERT(pBarFolder); pBarFolder->m_pChildWnd = pChildWnd; int nIndex = m_FolderList.Add((void*)pBarFolder); if(m_FolderList.GetSize() == 1) SetSelectedFolder(0); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ADDFOLDER, (LPARAM)nIndex); return m_FolderList.GetSize() - 1; } BOOL CTabBarCtrl::Create(DWORD dwStyle, CRect Rect, CWnd *pParentWnd, UINT nID) { return CWnd::CreateEx(NULL, NULL, NULL, dwStyle, Rect, pParentWnd, nID); } BOOL CTabBarCtrl::CreateEx(DWORD dwExStyle, DWORD dwStyle, CRect Rect, CWnd *pParentWnd, UINT nID) { return CWnd::CreateEx(dwExStyle, NULL, NULL, dwStyle, Rect, pParentWnd, nID); } void CTabBarCtrl::DrawFolder(CDC *pDrawDC, int nFolderIndex, CRect FolderRect) { AssertFolderIndex(nFolderIndex); ASSERT_VALID(pDrawDC); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); // draw the folder CPen Pen(PS_SOLID, 1, m_FolderBackGroundColor); CPen* pOldPen = pDrawDC->SelectObject(&Pen); pDrawDC->MoveTo(FolderRect.left, FolderRect.top); pDrawDC->LineTo(FolderRect.right, FolderRect.top); pDrawDC->SelectObject(pOldPen); FolderRect.top++; Pen.DeleteObject(); // draw the folder state COLORREF FolderBackGroundColor = m_FolderFrontColor; if(pBarFolder->m_bHighted) FolderBackGroundColor = m_FolderHighlightColor; pDrawDC->FillSolidRect(FolderRect, FolderBackGroundColor); if(pBarFolder->m_bHighted) pDrawDC->Draw3dRect(FolderRect, RGB(0, 0, 0), RGB(255, 255, 255)); else pDrawDC->Draw3dRect(FolderRect, RGB(255, 255, 255), RGB(0, 0, 0)); FolderRect.InflateRect(-1, -1); for(int i = 0; i < m_nFolderBorderWidth; i++) { if(pBarFolder->m_bHighted) pDrawDC->Draw3dRect(FolderRect, m_FolderShadowColor, m_FolderLightColor); else pDrawDC->Draw3dRect(FolderRect, m_FolderLightColor, m_FolderShadowColor); FolderRect.InflateRect(-1, -1); } // draw the folder text int nOldMode = pDrawDC->SetBkMode(TRANSPARENT); CFont* pOldFont = pDrawDC->SelectObject(CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT))); COLORREF OldTextColor = pDrawDC->SetTextColor(m_FolderTextColor); pDrawDC->DrawText(pBarFolder->m_FolderString, FolderRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_PATH_ELLIPSIS); pDrawDC->SetBkMode(nOldMode); pDrawDC->SelectObject(pOldFont); pDrawDC->SetTextColor(OldTextColor); } void CTabBarCtrl::DrawItem(CDC *pDrawDC, int nFolderIndex, CRect ItemRect, int nItemIndex) { AssertItemIndex(nItemIndex, nFolderIndex); ASSERT_VALID(m_pImageList); ASSERT_VALID(pDrawDC); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); CFont* pOldFont = (CFont*)pDrawDC->SelectObject(CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT))); COLORREF OldTextColor = pDrawDC->SetTextColor(m_ItemTextColor); int nOldMode = pDrawDC->SetBkMode(TRANSPARENT); // draw the item state COLORREF ItemBackgroundColor = m_ChildBackGroundColor; if(pBarItem->m_bSelected) ItemBackgroundColor = m_ItemSelectedColor; else if(pBarItem->m_bHighted) ItemBackgroundColor = m_ItemHighlightColor; pDrawDC->FillSolidRect(&ItemRect, ItemBackgroundColor); for(int i = 0; i < m_nItemBorderWidth; i++) { if(pBarItem->m_bSelected) pDrawDC->Draw3dRect(ItemRect, m_ItemShadowColor, m_ItemLightColor); else if(pBarItem->m_bHighted) pDrawDC->Draw3dRect(ItemRect, m_ItemLightColor, m_ItemShadowColor); ItemRect.DeflateRect(1, 1); } // draw the item image if(m_pImageList && m_pImageList->GetImageCount()) { CPoint ImagePoint; IMAGEINFO ImageInfo; m_pImageList->GetImageInfo(pBarItem->m_nImageIndex, &ImageInfo); CSize ImageSize = CRect(ImageInfo.rcImage).Size(); ImagePoint.x = ItemRect.left + (ItemRect.Width() - ImageSize.cx) / 2; ImagePoint.y = ItemRect.top + (ItemRect.Height() - ImageSize.cy) / 2; if(pBarItem->m_bSelected) ImagePoint += CPoint(1, 1); else if(pBarItem->m_bHighted) ImagePoint -= CPoint(1, 1); m_pImageList->Draw(pDrawDC, pBarItem->m_nImageIndex, ImagePoint, ILD_NORMAL); } pDrawDC->SetTextColor(OldTextColor); pDrawDC->SelectObject(pOldFont); pDrawDC->SetBkMode(nOldMode); } int CTabBarCtrl::HitTestEx(CPoint Point, int& nIndex) { CRect HitRect; // test if the folder is hit for(int i = 0; i < m_FolderList.GetSize(); i++) { GetFolderRect(HitRect, i); if (HitRect.PtInRect(Point)) { nIndex = i; return htFolder; } } // test if the item is hit GetInsideRect(HitRect); if(HitRect.PtInRect(Point)) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(m_nSelFolder); ASSERT(pBarFolder); for(i = 0; i < pBarFolder->GetItemCount(); i++) { CRect ItemRect; if(GetItemRect(ItemRect, i, m_nSelFolder) && ItemRect.PtInRect(Point) && HitRect.PtInRect(ItemRect.TopLeft()) && HitRect.PtInRect(ItemRect.BottomRight())) { nIndex = i; return htItem; } } } return htNothing; } int CTabBarCtrl::InsertItem(int nFolderIndex, int nItemIndex, CString ItemName, int nImageIndex /*= -1*/, DWORD dwExData /*= 0*/) { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); int nIndex = pBarFolder->InsertItem(nItemIndex, ItemName, nImageIndex, dwExData); DWORD lpparam = nIndex & 0x0000ffff; DWORD dwtemp = nFolderIndex & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_INSERTITEM, (LPARAM)lpparam); return nIndex; } void CTabBarCtrl::PaintItems(CDC *pDrawDC, int nFolderIndex, CRect LimitRect) { AssertFolderIndex(nFolderIndex); ASSERT_VALID(pDrawDC); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CRect InsideRect; GetInsideRect(InsideRect); int nDC = pDrawDC->SaveDC(); CRgn ItemsRegion; ItemsRegion.CreateRectRgnIndirect(&InsideRect); pDrawDC->SelectClipRgn(&ItemsRegion); ItemsRegion.DeleteObject(); for(int i = 0; i < pBarFolder->GetItemCount(); i++) { CRect ItemRect; if(!GetItemRect(ItemRect, i, nFolderIndex)) return; if(ItemRect.top > LimitRect.bottom) break; else DrawItem(pDrawDC, nFolderIndex, ItemRect, i); } pDrawDC->RestoreDC(nDC); } void CTabBarCtrl::RemoveFolder(int nFolderIndex) { AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); if(pBarFolder->m_pChildWnd) pBarFolder->m_pChildWnd->SendMessage(WM_CLOSE); delete pBarFolder; m_FolderList.RemoveAt(nFolderIndex); if(m_nSelFolder >= nFolderIndex) m_nSelFolder = nFolderIndex - 1; if(m_nSelFolder < 0 && m_FolderList.GetSize() > 0) m_nSelFolder = 0; Invalidate(FALSE); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_REMOVEFOLDER, (LPARAM)nFolderIndex); } void CTabBarCtrl::RemoveItem(int nItemIndex, int nFolderIndex) { AssertItemIndex(nItemIndex, nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); delete pBarItem; pBarFolder->m_ItemList.RemoveAt(nItemIndex); CRect Rect; GetInsideRect(Rect); InvalidateRect(Rect, FALSE); DWORD lpparam = nItemIndex & 0x0000ffff; DWORD dwtemp = nFolderIndex & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_REMOVEITEM, (LPARAM)lpparam); } ///////////////////////////////////////////////////////////////////////////// // Diagnostics void CTabBarCtrl::AssertFolderIndex(int nFolderIndex) const { #ifdef _DEBUG ASSERT(m_FolderList.GetSize() > 0); ASSERT(nFolderIndex >= 0 && nFolderIndex < m_FolderList.GetSize()); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); ASSERT(pBarFolder); #endif } void CTabBarCtrl::AssertItemIndex(int nItemIndex, int nFolderIndex) const { #ifdef _DEBUG AssertFolderIndex(nFolderIndex); CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(nFolderIndex); ASSERT(pBarFolder); ASSERT(pBarFolder->m_ItemList.GetSize() > 0); ASSERT(nItemIndex >= 0 && nItemIndex < pBarFolder->m_ItemList.GetSize()); CTabBarItem* pBarItem = (CTabBarItem*)pBarFolder->m_ItemList.GetAt(nItemIndex); ASSERT(pBarItem); #endif } ///////////////////////////////////////////////////////////////////////////// // Message handlers void CTabBarCtrl::OnAddFolder() { CFolderAddDlg dlg; if(dlg.DoModal() == IDOK) AddFolder(dlg.m_AddFolderName); Invalidate(FALSE); } void CTabBarCtrl::OnContextMenu(CWnd* /*pWnd*/, CPoint Point) { HideToolTip(); CMenu* PopupMenu = GetMenu(); PopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, Point.x, Point.y, this); PopupMenu->DestroyMenu(); } int CTabBarCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { CWnd::OnCreate(lpCreateStruct); CreateToolTip(); return TRUE; } long CTabBarCtrl::OnEndFolderEdit(WPARAM wParam, LPARAM lParam) { if(wParam == NM_TB_FOLDERENDEDIT) { CFolderEdit* pEdit = (CFolderEdit*)lParam; ReleaseCapture(); int nIndex = pEdit->m_nIndex; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_FOLDERENDEDIT, (LPARAM)nIndex); SetFolderText(nIndex, pEdit->m_EditString); CRect FolderRect; GetFolderRect(FolderRect, nIndex); InvalidateRect(FolderRect, FALSE); SetCapture(); } return 0; } BOOL CTabBarCtrl::OnEraseBkgnd(CDC* /*pDrawDC*/) { return TRUE; } void CTabBarCtrl::OnLButtonDown(UINT nFlags, CPoint Point) { // get the focus if(GetFocus() != this) SetFocus(); // capture the cursor if(::GetCapture() == NULL) { SetCapture(); ASSERT(this == GetCapture()); } int nIndex, ht = HitTestEx(Point, nIndex); // handle if the folders is hit if(ht == htFolder) SetSelectedFolder(nIndex); // handle if the items is hit if(ht == htItem) { CTabBarFolder* pBarFolder = (CTabBarFolder*)m_FolderList.GetAt(m_nSelFolder); CTabBarItem* pBarItem = (CTabBarItem*)(pBarFolder->m_ItemList.GetAt(nIndex)); if(pBarItem->m_bSelected) { if(!DragItem(Point, nIndex)) SelectItem(nIndex); } else { SelectItem(nIndex); DragItem(Point, nIndex); } } CWnd::OnLButtonDown(nFlags, Point); } void CTabBarCtrl::OnMouseMove(UINT nFlags, CPoint Point) { // get the focus if(GetFocus() != this) SetFocus(); // capture the cursor if(GetCapture() == NULL) { SetCapture(); ASSERT(this == GetCapture()); } // release the cursor if the cursor is not in the window client rectangle CRect ClientRect; GetClientRect(&ClientRect); if(!ClientRect.PtInRect(Point)) { ReleaseCapture(); HighlightFolder(-1); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ONFOLDER, -1); HighlightItem(-1); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ONITEM, -1); return; } // check if the mouse hit on folders or items int nIndex, ht = HitTestEx(Point, nIndex); if(ht != htFolder && GetHightedFolder() != -1) { SetCursor(LoadCursor(NULL, IDC_ARROW)); HighlightFolder(-1); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ONFOLDER, -1); } if(ht != htItem && GetHightedItem(m_nSelFolder) != -1) { SetCursor(LoadCursor(NULL, IDC_ARROW)); HighlightItem(-1); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ONITEM, -1); } if(ht == htFolder && GetHightedFolder() != nIndex) { SetCursor(m_hHandCursor); HighlightFolder(nIndex); GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ONFOLDER, nIndex); } if(ht == htItem) { if(GetHightedItem(m_nSelFolder) != nIndex) { SetCursor(m_hHandCursor); HighlightItem(nIndex); DWORD lpparam = nIndex & 0x0000ffff; DWORD dwtemp = m_nSelFolder & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_ONITEM, (LPARAM)lpparam); } } CWnd::OnMouseMove(nFlags, Point); } void CTabBarCtrl::OnPaint() { CPaintDC DrawDC(this); // create the memory device context CRect ClientRect; GetClientRect(&ClientRect); CDC MemDC; MemDC.CreateCompatibleDC(&DrawDC); CBitmap Bitmap; Bitmap.CreateCompatibleBitmap(&DrawDC, ClientRect.Width(), ClientRect.Height()); CBitmap* pOldBitmap = MemDC.SelectObject(&Bitmap); // draw all folders on the memory device context CRect FolderRect; for(int i = 0; i < m_FolderList.GetSize(); i++) { GetFolderRect(FolderRect, i); DrawFolder(&MemDC, i, FolderRect); } CRect ChildRect; GetInsideRect(ChildRect); if(!GetFolderChild(m_nSelFolder)) { MemDC.FillSolidRect(ChildRect, m_ChildBackGroundColor); PaintItems(&MemDC, m_nSelFolder, ChildRect); } DrawDC.BitBlt(ClientRect.left, ClientRect.top, ClientRect.Width(), ClientRect.Height(), &MemDC, 0, 0, SRCCOPY); MemDC.SelectObject(pOldBitmap); } void CTabBarCtrl::OnRemoveItem() { if(m_nRButtonHitItemIndex == -1 && m_nRButtonHitFolderIndex != -1) { RemoveFolder(m_nRButtonHitFolderIndex); m_nRButtonHitFolderIndex = -1; } else if(m_nRButtonHitFolderIndex == -1 && m_nRButtonHitItemIndex != -1) { RemoveItem(m_nRButtonHitItemIndex, m_nSelFolder); m_nRButtonHitItemIndex = -1; } Invalidate(FALSE); } void CTabBarCtrl::OnRenameItem() { if(m_nRButtonHitItemIndex == -1 && m_nRButtonHitFolderIndex != -1) OnStartFolderEdit(m_nRButtonHitFolderIndex); } void CTabBarCtrl::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); CRect ChildRect; GetInsideRect(ChildRect); for(int i = 0; i < GetFolderCount(); i++) { CWnd* pWnd = GetFolderChild(i); if(pWnd) pWnd->SetWindowPos(0, ChildRect.left, ChildRect.top, ChildRect.Width(), ChildRect.Height(), SWP_NOZORDER); } } void CTabBarCtrl::OnLButtonDblClk(UINT nFlags, CPoint Point) { int nIndex, ht = HitTestEx(Point, nIndex); if(ht == htItem) { DWORD lpparam = nIndex & 0x0000ffff; DWORD dwtemp = m_nSelFolder & 0x0000ffff; lpparam += dwtemp << 16; GetOwner()->SendMessage(WM_TABBARCTRL_NOTIFY, NM_TB_DBLCLKITEM, (LPARAM)lpparam); } CWnd::OnLButtonDblClk(nFlags, Point); }