?? customtabctrl.h
字號:
if( m_iCurSel > 0 )
{
pT->SetCurSel(m_iCurSel-1);
}
return 0;
case VK_RIGHT:
if( m_iCurSel < (int)m_Items.GetCount()-1 )
{
pT->SetCurSel(m_iCurSel+1);
}
return 0;
case VK_ESCAPE:
if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
{
pT->CancelItemDrag(true);
return 0;
}
break;
}
bHandled = FALSE;
return 0;
}
LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// DDB: 2002/04/22
// The code was doing GetFont and SetFont, but wasn't actually
// properly dealing with implementing it if the window
// was not a subclassed static control.
return (LRESULT)(HFONT)m_font;
}
LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
// DDB: 2002/04/22
// The code was doing GetFont and SetFont, but wasn't actually
// properly dealing with implementing it if the window
// was not a subclassed static control.
//
// Also, we're managing the lifetime of our font
// (i.e., we're going to DeleteObject it in our destructor),
// so if someone calls SetFont, keep a copy of the
// font instead of just "pointing" to it
LOGFONT lfCopy = {0};
::GetObject((HFONT)wParam, sizeof(LOGFONT), &lfCopy);
if(!m_font.IsNull()) m_font.DeleteObject();
m_font.CreateFontIndirect(&lfCopy);
if(LOWORD(lParam))
{
this->Invalidate();
}
return 0;
}
LRESULT OnStyleChanged(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(wParam == GWL_STYLE)
{
LPSTYLESTRUCT pStyles = (LPSTYLESTRUCT)lParam;
if(pStyles)
{
T* pT = static_cast<T*>(this);
// Tooltips
if((((pStyles->styleOld) & CTCS_TOOLTIPS) != CTCS_TOOLTIPS) &&
(((pStyles->styleNew) & CTCS_TOOLTIPS) == CTCS_TOOLTIPS))
{
this->ActivateTooltips(TRUE);
}
else if((((pStyles->styleOld) & CTCS_TOOLTIPS) == CTCS_TOOLTIPS) &&
(((pStyles->styleNew) & CTCS_TOOLTIPS) != CTCS_TOOLTIPS))
{
this->ActivateTooltips(FALSE);
}
// Scroll to fit
if((((pStyles->styleOld) & CTCS_SCROLL) != CTCS_SCROLL) &&
(((pStyles->styleNew) & CTCS_SCROLL) == CTCS_SCROLL))
{
if(m_tooltip.IsWindow())
{
m_tooltip.AddTool(m_hWnd, _T("Scroll Right"), &rcDefault, (UINT)ectcToolTip_ScrollRight);
m_tooltip.AddTool(m_hWnd, _T("Scroll Left"), &rcDefault, (UINT)ectcToolTip_ScrollLeft);
}
//pT->UpdateLayout();
//this->Invalidate();
}
else if((((pStyles->styleOld) & CTCS_SCROLL) == CTCS_SCROLL) &&
(((pStyles->styleNew) & CTCS_SCROLL) != CTCS_SCROLL))
{
if(m_tooltip.IsWindow())
{
m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollRight);
m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollLeft);
}
m_iScrollOffset = 0;
//pT->UpdateLayout();
//this->Invalidate();
}
// Close Button
if((((pStyles->styleOld) & CTCS_CLOSEBUTTON) != CTCS_CLOSEBUTTON) &&
(((pStyles->styleNew) & CTCS_CLOSEBUTTON) == CTCS_CLOSEBUTTON))
{
if(m_tooltip.IsWindow())
{
m_tooltip.AddTool(m_hWnd, _T("Close"), &rcDefault, (UINT)ectcToolTip_Close);
}
//pT->UpdateLayout();
//this->Invalidate();
}
else if((((pStyles->styleOld) & CTCS_CLOSEBUTTON) == CTCS_CLOSEBUTTON) &&
(((pStyles->styleNew) & CTCS_CLOSEBUTTON) != CTCS_CLOSEBUTTON))
{
if(m_tooltip.IsWindow())
{
m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_Close);
}
//pT->UpdateLayout();
//this->Invalidate();
}
pT->UpdateLayout();
this->Invalidate();
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
switch(wParam)
{
case ectcTimer_ScrollRight:
if(ectcOverflowRight != (m_dwState & ectcOverflowRight))
{
this->KillTimer(ectcTimer_ScrollRight);
}
else // ectcOverflowRight == (m_dwState & ectcOverflowRight)
{
if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
{
// We're scrolling because they're dragging a tab near the edge.
// First kill the timer, then update the drag
// (which might set the timer again)
this->KillTimer(ectcTimer_ScrollRight);
POINT ptCursor = {0};
::GetCursorPos(&ptCursor);
this->ScreenToClient(&ptCursor);
pT->ContinueItemDrag(ptCursor);
}
else if(ectcMouseDownL_ScrollRight == (m_dwState & ectcMouseDown) &&
ectcMouseOver_ScrollRight == (m_dwState & ectcMouseOver))
{
// We're scrolling because they're holding down the scroll button
pT->ScrollRight(true);
if(ectcScrollRepeat_None == (m_dwState & ectcScrollRepeat))
{
this->KillTimer(ectcTimer_ScrollRight);
}
}
}
break;
case ectcTimer_ScrollLeft:
if(ectcOverflowLeft != (m_dwState & ectcOverflowLeft))
{
this->KillTimer(ectcTimer_ScrollLeft);
}
else // ectcOverflowLeft == (m_dwState & ectcOverflowLeft)
{
if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
{
// We're scrolling because they're dragging a tab near the edge.
// First kill the timer, then update the drag
// (which might set the timer again)
this->KillTimer(ectcTimer_ScrollLeft);
POINT ptCursor = {0};
::GetCursorPos(&ptCursor);
this->ScreenToClient(&ptCursor);
pT->ContinueItemDrag(ptCursor);
}
else if(ectcMouseDownL_ScrollLeft == (m_dwState & ectcMouseDown) &&
ectcMouseOver_ScrollLeft == (m_dwState & ectcMouseOver))
{
// We're scrolling because they're holding down the scroll button
pT->ScrollLeft(true);
if(ectcScrollRepeat_None == (m_dwState & ectcScrollRepeat))
{
this->KillTimer(ectcTimer_ScrollLeft);
}
}
}
break;
default:
bHandled = FALSE;
break;
}
return 0;
}
LRESULT OnSetRedraw(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
// If someone sends us WM_SETREDRAW with FALSE, we can avoid
// doing an update layout until they set it back to TRUE.
if(wParam)
{
if(ectcEnableRedraw != (m_dwState & ectcEnableRedraw))
{
// Redrawing was turned off, but now its being
// turned back on again
m_dwState |= ectcEnableRedraw;
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
// The caller will typically call InvalidateRect
// or RedrawWindow after sending WM_SETREDRAW with TRUE,
// so we won't do that here (but we will UpdateLayout,
// so that we'll be ready to redraw)
}
}
else
{
if(ectcEnableRedraw == (m_dwState & ectcEnableRedraw))
{
// Redrawing was turned on, but now its being turned off
m_dwState &= ~ectcEnableRedraw;
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnGetToolTipInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
LPNMTTDISPINFO pToolTipInfo = (LPNMTTDISPINFO)pnmh;
if(pToolTipInfo)
{
// The way we implement tooltips for tab items
// is to have as many "tools" as there are tabs.
// The relationship of tool ID => tab index is:
// tool ID = tab index + 1 (to avoid 0 as an ID)
//
// We supply the RECT elsewhere and the text here
UINT id = pToolTipInfo->hdr.idFrom;
if(id > 0 && id <= m_Items.GetCount())
{
TItem* pItem = m_Items[id-1];
ATLASSERT(pItem != NULL);
if(pItem)
{
if(pItem->UsingToolTip())
{
pToolTipInfo->lpszText = const_cast<LPTSTR>(pItem->GetToolTipRef());
}
else if(pItem->UsingText())
{
pToolTipInfo->lpszText = const_cast<LPTSTR>(pItem->GetTextRef());
}
}
}
}
return 0;
}
// Overridables
public:
void Initialize(void)
{
ATLASSERT(::IsWindow(m_hWnd));
this->SendMessage(WM_SETTINGCHANGE, 0, 0);
this->InitializeTooltips();
// NOTE: you can change the style at any time
// for a number of the cool tab control styles
// (tool tips, close button, scroll buttons, etc.)
DWORD dwStyle = this->GetStyle();
this->ActivateTooltips(CTCS_TOOLTIPS == (dwStyle & CTCS_TOOLTIPS));
if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
{
if(m_tooltip.IsWindow())
{
m_tooltip.AddTool(m_hWnd, _T("Scroll Right"), &rcDefault, (UINT)ectcToolTip_ScrollRight);
m_tooltip.AddTool(m_hWnd, _T("Scroll Left"), &rcDefault, (UINT)ectcToolTip_ScrollLeft);
}
}
if(CTCS_CLOSEBUTTON == (dwStyle & CTCS_CLOSEBUTTON))
{
if(m_tooltip.IsWindow())
{
m_tooltip.AddTool(m_hWnd, _T("Close"), &rcDefault, (UINT)ectcToolTip_Close);
}
}
}
void Uninitialize(void)
{
T* pT = static_cast<T*>(this);
DWORD dwStyle = this->GetStyle();
if(m_tooltip.IsWindow())
{
if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
{
m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollRight);
m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollLeft);
}
if(CTCS_CLOSEBUTTON == (dwStyle & CTCS_CLOSEBUTTON))
{
m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_Close);
}
}
pT->DeleteAllItems();
if(m_tooltip.IsWindow())
{
// Also sets the contained m_hWnd to NULL
m_tooltip.DestroyWindow();
}
else
{
m_tooltip = NULL;
}
}
TItem* CreateNewItem(void* pInitData = NULL)
{
pInitData; // avoid level 4 warning
#if defined (_CPPUNWIND) & (defined(_ATL_EXCEPTIONS) | defined(_AFX))
TItem* pNewItem = NULL;
try { pNewItem = new TItem; }
catch (...) { ATLTRACE(_T("!! Exception thrown in CCustomTabCtrl::CreateNewItem\r\n")); }
#else
TItem* pNewItem = new TItem;
#endif
return pNewItem;
}
void DeleteItem(TItem* pOldItem)
{
#if defined (_CPPUNWIND) & (defined(_ATL_EXCEPTIONS) | defined(_AFX))
try { delete pOldItem; }
catch (...) { ATLTRACE(_T("!! Exception thrown in CCustomTabCtrl::DeleteItem\r\n")); }
#else
delete pOldItem;
#endif
}
void UpdateLayout(void)
{
if( !m_hWnd ||
!::IsWindow(m_hWnd) ||
(ectcEnableRedraw != (m_dwState & ectcEnableRedraw)))
{
return;
}
this->GetClientRect(&m_rcTabItemArea);
T* pT = static_cast<T*>(this);
DWORD dwStyle = this->GetStyle();
pT->CalcSize_NonClient(&m_rcTabItemArea);
if(CTCS_CLOSEBUTTON == (dwStyle & CTCS_CLOSEBUTTON))
{
if( (m_iCurSel >= 0) && ((size_t)m_iCurSel < m_Items.GetCount()) )
{
TItem* pItem = m_Items[m_iCurSel];
ATLASSERT(pItem != NULL);
if((pItem != NULL) && pItem->CanClose())
{
pT->CalcSize_CloseButton(&m_rcTabItemArea);
}
}
}
if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
{
pT->CalcSize_ScrollButtons(&m_rcTabItemArea);
pT->UpdateLayout_ScrollToFit(m_rcTabItemArea);
pT->UpdateScrollOverflowStatus();
}
else
{
pT->UpdateLayout_Default(m_rcTabItemArea);
}
pT->UpdateTabItemTooltipRects();
}
void CalcSize_NonClient(LPRECT prcTabItemArea)
{
}
void CalcSize_CloseButton(LPRECT prcTabItemArea)
{
}
void CalcSize_ScrollButtons(LPRECT prcTabItemArea)
{
}
void UpdateLayout_Default(RECT rcTabItemArea)
{
UpdateLayout_ScrollToFit(rcTabItemArea);
}
void UpdateLayout_ScrollToFit(RECT rcTabItemArea)
{
CClientDC dc(m_hWnd);
HFONT hOldFont = dc.SelectFont(this->GetFont());
int height = rcTabItemArea.bottom-rcTabItemArea.top;
// Reposition tabs
size_t nCount = m_Items.GetCount();
int xpos = m_settings.iIndent;
for( size_t i=0; i<nCount; ++i )
{
TItem* pItem = m_Items[i];
ATLASSERT(pItem != NULL);
if(pItem)
{
RECT rc = {xpos, 0, xpos, height};
if( pItem->UsingText() )
{
RECT rcText = { 0 };
CString sText = pItem->GetText();
dc.DrawText(sText, sText.GetLength(), &rcText, DT_SINGLELI
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -