OSDN Git Service

MDITabBar: Show close button when hovering over tabs
authorsdottaka <sdottaka@sourceforge.net>
Sun, 22 Jun 2014 14:10:07 +0000 (23:10 +0900)
committersdottaka <sdottaka@sourceforge.net>
Sun, 22 Jun 2014 14:10:07 +0000 (23:10 +0900)
--HG--
branch : stable

Src/Common/MDITabBar.cpp
Src/Common/MDITabBar.h

index 40fa032..9af6b81 100644 (file)
@@ -27,6 +27,10 @@ BEGIN_MESSAGE_MAP(CMDITabBar, CControlBar)
        ON_WM_PAINT()
        ON_NOTIFY_REFLECT_EX(TCN_SELCHANGE, OnSelchange)
        ON_WM_DRAWITEM_REFLECT()
+       ON_WM_MOUSEMOVE()
+       ON_WM_MOUSELEAVE()
+       ON_WM_LBUTTONDOWN()
+       ON_WM_LBUTTONUP()
        //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
@@ -90,10 +94,9 @@ BOOL CMDITabBar::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult)
  */
 void CMDITabBar::OnContextMenu(CWnd *pWnd, CPoint point)
 {
-       TCHITTESTINFO hit;
-       hit.pt = point;
-       ScreenToClient(&hit.pt);
-       int index = HitTest(&hit);
+       CPoint ptClient = point;
+       ScreenToClient(&ptClient);
+       int index = GetItemIndexFromPoint(ptClient);
        if (index < 0) return;
 
        TCITEM tci;
@@ -240,9 +243,7 @@ void CMDITabBar::UpdateTabs()
  */
 void CMDITabBar::OnMButtonDown(UINT nFlags, CPoint point)
 {
-       TCHITTESTINFO hit;
-       hit.pt = point;
-       int index = HitTest(&hit);
+       int index = GetItemIndexFromPoint(point);
        if (index < 0)
                return;
 
@@ -255,34 +256,112 @@ void CMDITabBar::OnMButtonDown(UINT nFlags, CPoint point)
 
 void CMDITabBar::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
 {
-               TCHAR            szBuf[256];
-               TCITEM           item;
-               LPDRAWITEMSTRUCT lpDraw = (LPDRAWITEMSTRUCT)lpDrawItemStruct;
+       TCHAR            szBuf[256];
+       TCITEM           item;
+       LPDRAWITEMSTRUCT lpDraw = (LPDRAWITEMSTRUCT)lpDrawItemStruct;
 
-               item.mask       = TCIF_TEXT | TCIF_PARAM;
-               item.pszText    = szBuf;
-               item.cchTextMax = sizeof(szBuf) / sizeof(TCHAR);
-               TabCtrl_GetItem(this->m_hWnd, lpDraw->itemID, &item);
+       item.mask       = TCIF_TEXT | TCIF_PARAM;
+       item.pszText    = szBuf;
+       item.cchTextMax = sizeof(szBuf) / sizeof(TCHAR);
+       TabCtrl_GetItem(this->m_hWnd, lpDraw->itemID, &item);
 
-               RECT rc = lpDraw->rcItem;
-               if (lpDraw->itemState & ODS_SELECTED)
-               {
-                       rc.left += 9;
-                       rc.top += 2;
-                       FillRect(lpDraw->hDC, &lpDraw->rcItem, (HBRUSH)GetStockObject(WHITE_BRUSH));
-               }
-               else
-               {
-                       rc.left += 5;
-                       rc.top += 3;
-               }
-               rc.left += 16;
-               SetTextColor(lpDraw->hDC, RGB(0, 0, 0));
-               SetBkMode(lpDraw->hDC, TRANSPARENT);
-               HICON hIcon = CWnd::FromHandle((HWND)item.lParam)->GetIcon(TRUE);
-               if (!hIcon)
-                       hIcon = (HICON)GetClassLongPtr((HWND)item.lParam, GCLP_HICONSM);
-               if (hIcon)
-                       DrawIconEx(lpDraw->hDC, rc.left - 16 - 2, 5, hIcon, 16, 16, 0, NULL, DI_NORMAL);
-               DrawText(lpDraw->hDC, szBuf, -1, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+       RECT rc = lpDraw->rcItem;
+       if (lpDraw->itemState & ODS_SELECTED)
+       {
+               rc.left += 9;
+               rc.top += 2;
+               FillRect(lpDraw->hDC, &lpDraw->rcItem, (HBRUSH)GetStockObject(WHITE_BRUSH));
+       }
+       else
+       {
+               rc.left += 5;
+               rc.top += 3;
+       }
+       rc.left += 16;
+       SetTextColor(lpDraw->hDC, RGB(0, 0, 0));
+       SetBkMode(lpDraw->hDC, TRANSPARENT);
+       HICON hIcon = CWnd::FromHandle((HWND)item.lParam)->GetIcon(TRUE);
+       if (!hIcon)
+               hIcon = (HICON)GetClassLongPtr((HWND)item.lParam, GCLP_HICONSM);
+       if (hIcon)
+               DrawIconEx(lpDraw->hDC, rc.left - 16 - 2, 5, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+       DrawText(lpDraw->hDC, szBuf, -1, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+
+       int nItem = GetItemIndexFromPoint(m_rcCurrentCloseButtom.CenterPoint());
+       if (nItem == lpDraw->itemID)
+       {
+               CPoint pt;
+               GetCursorPos(&pt);
+               ScreenToClient(&pt);
+               CRect rc = GetCloseButtonRect(nItem);
+               DrawFrameControl(lpDraw->hDC, &rc, DFC_CAPTION, 
+                       DFCS_CAPTIONCLOSE | DFCS_FLAT | (rc.PtInRect(pt) ? DFCS_HOT : 0) |
+                       ((m_bCloseButtonDown && rc.PtInRect(pt)) ? DFCS_PUSHED : 0));
+       }
+}
+
+void CMDITabBar::OnMouseMove(UINT nFlags, CPoint point)
+{
+       CRect rc = GetCloseButtonRect(GetItemIndexFromPoint(point));
+       InvalidateRect(&rc);
+       if (rc != m_rcCurrentCloseButtom)
+               InvalidateRect(&m_rcCurrentCloseButtom);
+       m_rcCurrentCloseButtom = rc;
+       if (!m_bMouseTracking)
+       {
+               TRACKMOUSEEVENT tme = {0};
+               tme.cbSize = sizeof(TRACKMOUSEEVENT);
+               tme.dwFlags = TME_LEAVE;
+               tme.hwndTrack = m_hWnd;
+               TrackMouseEvent(&tme);
+               m_bMouseTracking = true;
+       }
+}
+
+void CMDITabBar::OnMouseLeave()
+{
+       TRACKMOUSEEVENT tme = {0};
+       tme.cbSize = sizeof(TRACKMOUSEEVENT);
+       tme.dwFlags = TME_LEAVE | TME_CANCEL;
+       tme.hwndTrack = m_hWnd;
+       TrackMouseEvent(&tme);
+       m_bMouseTracking = false;
+       InvalidateRect(&m_rcCurrentCloseButtom);
+       m_rcCurrentCloseButtom = CRect();
+       m_bCloseButtonDown = false;
+}
+
+void CMDITabBar::OnLButtonDown(UINT nFlags, CPoint point)
+{
+       m_bCloseButtonDown = !!m_rcCurrentCloseButtom.PtInRect(point);
+       InvalidateRect(m_rcCurrentCloseButtom);
+       CWnd::OnLButtonDown(nFlags, point);
+}
+
+void CMDITabBar::OnLButtonUp(UINT nFlags, CPoint point)
+{
+       if (m_bCloseButtonDown && m_rcCurrentCloseButtom.PtInRect(point))
+               OnMButtonDown(nFlags, point);
+       InvalidateRect(m_rcCurrentCloseButtom);
+       m_bCloseButtonDown = false;
+       CWnd::OnLButtonUp(nFlags, point);
+}
+
+CRect CMDITabBar::GetCloseButtonRect(int nItem)
+{
+       CRect rc;
+       GetItemRect(nItem, &rc);
+       rc.left = rc.right - 20;
+       rc.right = rc.left + 16;
+       int y = (rc.top + rc.bottom) / 2;
+       rc.top = y - 16 / 2 + 1;
+       rc.bottom = rc.top + 16;
+       return rc;
+}
+
+int CMDITabBar::GetItemIndexFromPoint(CPoint point)
+{
+       TCHITTESTINFO hit;
+       hit.pt = point;
+       return HitTest(&hit);
 }
index 0155c59..e7db8fc 100644 (file)
@@ -22,9 +22,12 @@ private:
 
        BOOL m_bInSelchange;
        CMDIFrameWnd *m_pMainFrame;
+       bool m_bMouseTracking;
+       bool m_bCloseButtonDown;
+       CRect m_rcCurrentCloseButtom;
 
 public:
-       CMDITabBar() : m_bInSelchange(FALSE), m_pMainFrame(NULL) {}
+       CMDITabBar() : m_bInSelchange(FALSE), m_pMainFrame(NULL), m_bMouseTracking(false), m_bCloseButtonDown(false) {}
        virtual ~CMDITabBar() {}
        BOOL Create(CMDIFrameWnd* pParentWnd);
        void UpdateTabs();
@@ -48,6 +51,8 @@ public:
        { ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, TCM_SETCURSEL, nItem, 0L); }
        int HitTest(TCHITTESTINFO* pHitTestInfo) const
        { ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, TCM_HITTEST, 0, (LPARAM) pHitTestInfo); }
+       BOOL GetItemRect(int nItem, LPRECT lpRect) const
+       { ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, TCM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect); }
 
 protected:
        //{{AFX_MSG(CMDITabBar)
@@ -56,8 +61,16 @@ protected:
        afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
        afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
        afx_msg void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
+       afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+       afx_msg void OnMouseLeave();
+       afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+       afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
        //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
+
+private:
+       CRect GetCloseButtonRect(int nItem);
+       int GetItemIndexFromPoint(CPoint pt);
 };
 
 #endif // MDITABBAR_H