?? customtabctrl.h
字號:
case ectcHotTrack_CloseButton:
m_dwState &= ~ectcHotTrack;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcCloseButton);
}
break;
case ectcHotTrack_ScrollRight:
m_dwState &= ~ectcHotTrack;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcScrollRight);
}
break;
case ectcHotTrack_ScrollLeft:
m_dwState &= ~ectcHotTrack;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcScrollLeft);
}
break;
case ectcHotTrack_TabItem:
m_dwState &= ~ectcHotTrack;
m_iHotItem = -1;
if(bRedrawEffectedArea)
{
// In case the derived class actually changes the width
// of a hot tracked tab, invalidate the whole tab window
this->Invalidate();
}
break;
default:
m_dwState &= ~ectcHotTrack;
m_iHotItem = -1;
if(bRedrawEffectedArea)
{
this->Invalidate();
}
break;
}
}
void ClearCurrentMouseDownTracking(bool bRedrawEffectedArea = true)
{
switch(m_dwState & ectcMouseDown)
{
case ectcMouseDownL_CloseButton:
case ectcMouseDownR_CloseButton:
m_dwState &= ~ectcMouseDown;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcCloseButton);
}
break;
case ectcMouseDownL_ScrollRight:
case ectcMouseDownR_ScrollRight:
m_dwState &= ~ectcMouseDown;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcScrollRight);
}
break;
case ectcMouseDownL_ScrollLeft:
case ectcMouseDownR_ScrollLeft:
m_dwState &= ~ectcMouseDown;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcScrollLeft);
}
break;
case ectcMouseDownL_TabItem:
case ectcMouseDownR_TabItem:
m_dwState &= ~ectcMouseDown;
if(bRedrawEffectedArea)
{
// In case the derived class actually changes the width
// of a hot tracked tab, invalidate the whole tab window
this->Invalidate();
//if(m_iActionItem >= 0 && m_iActionItem < m_Items.GetCount())
//{
// RECT rcItemDP;
// this->GetItemRect(m_iActionItem, &rcItemDP);
// this->InvalidateRect(rcItemDP);
//}
}
break;
default:
m_dwState &= ~ectcMouseDown;
if(bRedrawEffectedArea)
{
this->Invalidate();
}
break;
}
}
void ClearCurrentMouseOverTracking(bool bRedrawEffectedArea = true)
{
switch(m_dwState & ectcMouseOver)
{
case ectcMouseOver_CloseButton:
m_dwState &= ~ectcMouseOver;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcCloseButton);
}
break;
case ectcMouseOver_ScrollRight:
m_dwState &= ~ectcMouseOver;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcScrollRight);
}
break;
case ectcMouseOver_ScrollLeft:
m_dwState &= ~ectcMouseOver;
if(bRedrawEffectedArea)
{
this->InvalidateRect(&m_rcScrollLeft);
}
break;
case ectcMouseOver_TabItem:
m_dwState &= ~ectcMouseOver;
if(bRedrawEffectedArea)
{
// In case the derived class actually changes the width
// of a hot tracked tab, invalidate the whole tab window
this->Invalidate();
//if(m_iActionItem >= 0 && m_iActionItem < m_Items.GetCount())
//{
// RECT rcItemDP = {0};
// this->GetItemRect(m_iActionItem, &rcItemDP);
// this->InvalidateRect(rcItemDP);
//}
}
break;
default:
m_dwState &= ~ectcMouseOver;
if(bRedrawEffectedArea)
{
this->Invalidate();
}
break;
}
}
// Drag and drop methods (overrideable)
// In this base class implementation, we mimic the drag rearrange
// of MDI tabs in VS.NET (except, we add scroll support)
public:
void AcceptItemDrag(bool bRedrawEffectedArea = true)
{
T* pT = static_cast<T*>(this);
NMCTC2ITEMS nmh = {{ m_hWnd, this->GetDlgCtrlID(), CTCN_ACCEPTITEMDRAG }, m_iDragItemOriginal, m_iDragItem, {-1,-1}};
::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh);
// In this implementation, the tab is moved as they drag.
pT->StopItemDrag(bRedrawEffectedArea);
}
void CancelItemDrag(bool bRedrawEffectedArea = true)
{
T* pT = static_cast<T*>(this);
// In this implementation, the tab is moved as they drag.
// To cancel the drag, we move the item back to its original place.
if( m_iDragItemOriginal >= 0 &&
m_iDragItem >= 0 &&
m_iDragItemOriginal != m_iDragItem)
{
pT->MoveItem(m_iDragItem, m_iDragItemOriginal, true, false);
pT->EnsureVisible(m_iDragItemOriginal);
}
NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), CTCN_CANCELITEMDRAG }, m_iDragItemOriginal, {-1,-1}};
::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh);
pT->StopItemDrag(bRedrawEffectedArea);
}
void StopItemDrag(bool bRedrawEffectedArea = true)
{
if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
{
m_dwState &= ~ectcDraggingItem;
// Restore the default cursor
::SetCursor((HCURSOR)::GetClassLongPtr(m_hWnd, GCLP_HCURSOR));
if(m_hCursorMove != NULL)
{
::DestroyCursor(m_hCursorMove);
m_hCursorMove = NULL;
}
if(m_hCursorNoDrop != NULL)
{
::DestroyCursor(m_hCursorNoDrop);
m_hCursorNoDrop = NULL;
}
m_iDragItem = -1;
m_iDragItemOriginal = -1;
::ZeroMemory(&m_ptDragOrigin, sizeof(POINT));
if(bRedrawEffectedArea)
{
this->Invalidate();
}
}
}
void BeginItemDrag(int index, POINT ptDragOrigin)
{
T* pT = static_cast<T*>(this);
if(index >= 0)
{
DWORD dwStyle = this->GetStyle();
if(CTCS_DRAGREARRANGE == (dwStyle & CTCS_DRAGREARRANGE))
{
NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), CTCN_BEGINITEMDRAG }, index, {ptDragOrigin.x, ptDragOrigin.y} };
if(FALSE != ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
{
// Returning non-zero prevents our default handling.
// We've possibly already set a couple things that we
// need to cleanup, so call StopItemDrag
pT->StopItemDrag(false);
}
else
{
// returning FALSE let's us do our default handling
// Mark the beginning of a drag operation.
// We should have already done SetCapture, but just
// in case, we'll set it again.
this->SetCapture();
// Set focus so that we get an ESC key press
pT->SetFocus();
// This call to DoDragDrop is just to ensure a dependency on OLE32.dll.
// In the future, if we support true OLE drag and drop,
// we'll really use DoDragDrop.
::DoDragDrop(NULL, NULL, 0, 0);
// To save on resources, we'll load the drag cursor
// only when we need it, and destroy it when the drag is done
HMODULE hOle32 = ::GetModuleHandle(_T("OLE32.dll"));
if(hOle32 != NULL)
{
// Cursor ID identified using resource editor in Visual Studio
int dragCursor = 2;
int noDropCursor = 1;
m_hCursorMove = ::LoadCursor(hOle32, MAKEINTRESOURCE(dragCursor));
m_hCursorNoDrop = ::LoadCursor(hOle32, MAKEINTRESOURCE(noDropCursor));
}
m_dwState |= ectcDraggingItem;
m_iDragItem = index;
m_iDragItemOriginal = index;
m_ptDragOrigin = ptDragOrigin;
}
}
}
}
// Update the drag operation.
// ptCursor should be in client coordinates
void ContinueItemDrag(POINT ptCursor)
{
// We're dragging an item
T* pT = static_cast<T*>(this);
RECT rcClient = {0};
this->GetClientRect(&rcClient);
if(::PtInRect(&rcClient, ptCursor))
{
::SetCursor(m_hCursorMove);
}
else
{
::SetCursor(m_hCursorNoDrop);
}
CTCHITTESTINFO tchti = { 0 };
tchti.pt = ptCursor;
int index = pT->HitTest(&tchti);
if((index != m_iDragItem) && (index >= 0))
{
RECT rcItem = {0};
this->GetItemRect(index, &rcItem);
int itemMiddlePointX = rcItem.left + ((rcItem.right - rcItem.left) / 2);
if((m_iDragItem < index) && (ptCursor.x > itemMiddlePointX))
{
// They're dragging an item from left to right,
// and have dragged it over the half way mark to the right
pT->MoveItem(m_iDragItem, index, true, false);
m_iDragItem = index;
}
else if((m_iDragItem > index) && (ptCursor.x < itemMiddlePointX))
{
// They're dragging an item from right to left,
// and have dragged it over the half way mark to the left
pT->MoveItem(m_iDragItem, index, true, false);
m_iDragItem = index;
}
}
// Now scroll if necessary
DWORD dwStyle = this->GetStyle();
if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
{
RECT rcLeftScrollZone = {rcClient.left, rcClient.top, (m_rcTabItemArea.left + CTCD_SCROLLZONEWIDTH), rcClient.bottom};
RECT rcRightScrollZone = {(m_rcTabItemArea.right - CTCD_SCROLLZONEWIDTH), rcClient.top, rcClient.right, rcClient.bottom};
if( ::PtInRect(&rcLeftScrollZone, ptCursor) &&
(ectcOverflowLeft == (m_dwState & ectcOverflowLeft)))
{
pT->ScrollLeft(true);
this->SetTimer(ectcTimer_ScrollLeft, CTCSR_SLOW);
}
else if(::PtInRect(&rcRightScrollZone, ptCursor) &&
(ectcOverflowRight == (m_dwState & ectcOverflowRight)))
{
pT->ScrollRight(true);
this->SetTimer(ectcTimer_ScrollRight, CTCSR_SLOW);
}
}
}
// Message Handling
public:
// Your derived class should use DECLARE_WND_CLASS or DECLARE_WND_SUPERCLASS, etc.
//DECLARE_WND_CLASS_EX(_T("WTL_CustomTabCtrl"), CS_DBLCLKS, COLOR_WINDOW)
BEGIN_MSG_MAP(CCustomTabCtrl)
CHAIN_MSG_MAP(offscreenDrawClass)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick)
MESSAGE_HANDLER(WM_RBUTTONDOWN, OnRButtonDown)
MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnRButtonDoubleClick)
MESSAGE_HANDLER(WM_MBUTTONDOWN, OnMButtonDown)
MESSAGE_HANDLER(WM_MBUTTONUP, OnMButtonUp)
MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnMButtonDoubleClick)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSettingChange)
MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
MESSAGE_HANDLER(WM_STYLECHANGED, OnStyleChanged)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_SETREDRAW, OnSetRedraw)
NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnGetToolTipInfo)
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
LRESULT lRes = DefWindowProc();
if(lRes == -1)
{
return -1;
}
T* pT = static_cast<T*>(this);
pT->Initialize();
return lRes;
}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->Uninitialize();
bHandled = FALSE;
return 0;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
this->Invalidate();
bHandled = FALSE;
return 0;
}
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
this->Invalidate();
return 0;
}
LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return DefWindowProc(uMsg, wParam, lParam) | DLGC_WANTARROWS;
}
LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
if(m_tooltip.IsWindow())
{
MSG msg = { m_hWnd, uMsg, wParam, lParam };
m_tooltip.RelayEvent(&msg);
}
return 1;
}
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
DWORD dwStyle = this->GetStyle();
POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
T* pT = static_cast<T*>(this);
if(ectcMouseInWindow != (m_dwState & ectcMouseInWindow))
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
if( _TrackMouseEvent(&tme) )
{
m_dwState |= ectcMouseInWindow;
pT->UpdateLayout();
this->Invalidate();
// "OnMouseEnter"
//...
}
}
if( (m_iDragItem >= 0) &&
(ectcMouseInWindow == (m_dwState & ectcMouseInWindow)) &&
(ectcDraggingItem != (m_dwState & ectcDraggingItem)) &&
(ectcMouseDownL_TabItem == (m_dwState & ectcMouseDown)) &&
(m_ptDragOrigin.x != ptCursor.x))
{
pT->BeginItemDrag(m_iDragItem, m_ptDragOrigin);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -