You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
11 KiB
C++

2 years ago
// XTPTabControl.cpp : implementation file
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPToolTipContext.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPColorManager.h"
#include "XTPTabManager.h"
#include "XTPTabControl.h"
#include "XTPTabPaintManager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////////////////////////////////////////////////
// CTabManagerDropTarget
class CXTPTabControl::CTabControlDropTarget : public COleDropTarget
{
public:
CTabControlDropTarget()
{
m_ptDragLastPoint = CPoint(-1, -1);
m_dwDragLastTick = 0;
}
void OnDragLeave(CWnd* /*pWnd*/)
{
m_dwDragLastTick = 0;
m_ptDragLastPoint = CPoint(-1, -1);
}
virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* /*pDataObject*/, DWORD /*dwKeyState*/, CPoint point)
{
CXTPTabControl* pControl = (CXTPTabControl*)pWnd;
ASSERT_VALID(pControl);
if (!pControl->GetPaintManager()->m_bSelectOnDragOver)
return DROPEFFECT_NONE;
if (m_dwDragLastTick != (DWORD)-1 && pControl->GetPaintManager()->m_bSelectOnDragOver == 2)
{
DWORD dwTick = GetTickCount();
if (point != m_ptDragLastPoint)
{
m_dwDragLastTick = dwTick;
m_ptDragLastPoint = point;
}
if (dwTick - m_dwDragLastTick > CXTPTabPaintManager::m_nSelectOnDragOverDelay)
{
m_dwDragLastTick = (DWORD)-1;
}
}
else
{
CXTPTabManagerItem* pItem = pControl->HitTest(point);
if (pItem)
{
pControl->SetSelectedItem(pItem);
}
else
{
m_dwDragLastTick = 0;
}
}
return DROPEFFECT_NONE;
}
protected:
DWORD m_dwDragHoverMode;
DWORD m_dwDragLastTick;
CPoint m_ptDragLastPoint;
};
/////////////////////////////////////////////////////////////////////////////
// CXTPTabControl
CXTPTabControl::CXTPTabControl()
{
m_pPaintManager = new CXTPTabPaintManager();
m_pPaintManager->DisableLunaColors(TRUE);
m_pPaintManager->m_bDrawTextNoPrefix = FALSE;
m_hwndClient = 0;
m_bAllowReorder = FALSE;
m_nLockRedraw = 0;
m_pDropTarget = new CTabControlDropTarget();
m_pImageManager = new CXTPImageManager();
m_pToolTipContext = new CXTPToolTipContext;
CXTPDrawHelpers::RegisterWndClass(0, _T("XTPTabControl"), CS_DBLCLKS);
}
CXTPTabControl::~CXTPTabControl()
{
CMDTARGET_RELEASE(m_pPaintManager);
CMDTARGET_RELEASE(m_pImageManager);
CMDTARGET_RELEASE(m_pToolTipContext);
delete m_pDropTarget;
}
BOOL CXTPTabControl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
if (!CWnd::Create(AfxRegisterWndClass(CS_DBLCLKS, AfxGetApp()->LoadStandardCursor(IDC_ARROW)), NULL, dwStyle, rect, pParentWnd, nID))
return FALSE;
m_pDropTarget->Register(this);
return TRUE;
}
CXTPTabManagerItem* CXTPTabControl::InsertItem(int nItem, LPCTSTR lpszItem, HWND hwndChild /*= NULL*/, int nImage /*= -1*/, CXTPTabManagerItem* pAddItem /* = NULL */)
{
CXTPTabManagerItem* pItem = AddItem(nItem, pAddItem);
pItem->SetCaption(lpszItem);
pItem->SetHandle(hwndChild);
pItem->SetImageIndex(nImage);
if (hwndChild)
::ShowWindow(hwndChild, SW_HIDE);
if (nItem == 0 && m_pSelected == NULL)
{
SetCurSel(0);
}
return pItem;
}
void CXTPTabControl::RedrawControl(LPCRECT lpRect, BOOL /*bAnimate*/)
{
if (!GetSafeHwnd())
return;
if (m_nLockRedraw > 0)
return;
InvalidateRect(lpRect, FALSE);
}
void CXTPTabControl::SetLockRedraw(BOOL bLockRedraw)
{
m_nLockRedraw += bLockRedraw ? +1 : -1;
ASSERT(m_nLockRedraw >= 0);
if (m_nLockRedraw == 0)
Reposition();
}
void CXTPTabControl::Reposition()
{
if (!GetSafeHwnd())
return;
if (m_nLockRedraw > 0)
return;
CXTPClientRect rc(this);
CClientDC dc(this);
GetPaintManager()->RepositionTabControl(this, &dc, rc);
if (m_hwndClient && ::IsWindow(m_hwndClient))
{
GetPaintManager()->AdjustClientRect(this, rc);
::MoveWindow(m_hwndClient, rc.left, rc.top, rc.Width(), rc.Height(), TRUE);
}
Invalidate(FALSE);
}
void CXTPTabControl::OnItemClick(CXTPTabManagerItem* pItem)
{
CXTPTabManager::OnItemClick(pItem);
if (m_hwndClient)
{
if (::GetFocus() != m_hWnd && !::IsChild(m_hwndClient, ::GetFocus()))
{
HWND hWnd = ::GetNextDlgTabItem(m_hwndClient, NULL, FALSE);
::SetFocus(hWnd ? hWnd : m_hwndClient);
}
}
}
void CXTPTabControl::SetSelectedItem(CXTPTabManagerItem* pItem)
{
if (m_pSelected == pItem)
return;
NMHDR nmhdr;
nmhdr.hwndFrom = GetSafeHwnd();
nmhdr.idFrom = GetDlgCtrlID();
nmhdr.code = TCN_SELCHANGING;
CWnd* pOwner = GetOwner();
if (pOwner && IsWindow(pOwner->m_hWnd))
{
if (pOwner->SendMessage(WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr) == TRUE)
return;
}
if (m_hwndClient)
::ShowWindow(m_hwndClient, SW_HIDE);
if (pItem)
{
m_hwndClient = pItem->GetHandle();
}
else
{
m_hwndClient = 0;
}
if (m_hwndClient)
{
::ShowWindow(m_hwndClient, SW_SHOW);
}
CXTPTabManager::SetSelectedItem(pItem);
nmhdr.code = TCN_SELCHANGE;
if (pOwner && IsWindow(pOwner->m_hWnd))
{
pOwner->SendMessage(WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
}
}
void CXTPTabControl::PreSubclassWindow()
{
CWnd::PreSubclassWindow();
Reposition();
}
void CXTPTabControl::SetImageList(CImageList* pImageList)
{
if (pImageList)
{
m_pImageManager->SetIcons(*pImageList, 0, 0, 0, xtpImageNormal);
}
Reposition();
}
void CXTPTabControl::SetImageManager(CXTPImageManager* pImageManager)
{
if (pImageManager)
{
m_pImageManager->InternalRelease();
m_pImageManager = pImageManager;
}
Reposition();
}
BEGIN_MESSAGE_MAP(CXTPTabControl, CWnd)
//{{AFX_MSG_MAP(CXTPTabControl)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_SYSCOLORCHANGE()
ON_WM_MOUSEMOVE()
ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
ON_WM_KEYDOWN()
ON_WM_GETDLGCODE()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPTabControl message handlers
BOOL CXTPTabControl::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
BOOL CXTPTabControl::DrawParentBackground(CDC* pDC, CRect rc)
{
HBRUSH hBrush = (HBRUSH)GetParent()->SendMessage(WM_CTLCOLORSTATIC,
(WPARAM)pDC->GetSafeHdc(), (LPARAM)m_hWnd);
if (hBrush)
{
::FillRect(pDC->GetSafeHdc(), rc, hBrush);
return TRUE;
}
return FALSE;
}
void CXTPTabControl::OnPaint()
{
CPaintDC dcPaint(this);
CXTPBufferDC dc(dcPaint);
GetPaintManager()->DrawTabControl(this, &dc, m_rcControl);
}
LRESULT CXTPTabControl::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
{
CXTPClientRect rc(this);
CDC* pDC = CDC::FromHandle((HDC)wParam);
if (pDC) GetPaintManager()->DrawTabControl(this, pDC, rc);
return 1;
}
void CXTPTabControl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
Reposition();
}
void CXTPTabControl::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
if ((GetStyle() & WS_TABSTOP) && m_pSelected && (m_pSelected == HitTest(point)))
{
SetFocus();
}
PerformClick(m_hWnd, point);
}
void CXTPTabControl::OnNavigateButtonClick(CXTPTabManagerNavigateButton* pButton)
{
CXTPTabManager::OnNavigateButtonClick(pButton->GetID());
CXTPTabManagerItem* pItem = pButton->GetItem() ? pButton->GetItem() : m_pSelected;
if (pItem && (pButton->GetID() == xtpTabNavigateButtonClose) && pItem->IsClosable())
{
DeleteItem(pItem->GetIndex());
}
}
void CXTPTabControl::OnSysColorChange()
{
CWnd::OnSysColorChange();
RefreshXtremeColors();
GetPaintManager()->RefreshMetrics();
Reposition();
}
INT_PTR CXTPTabControl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
return PerformToolHitTest(m_hWnd, point, pTI);
}
void CXTPTabControl::OnMouseMove(UINT nFlags, CPoint point)
{
PerformMouseMove(m_hWnd, point);
CWnd::OnMouseMove(nFlags, point);
}
void CXTPTabControl::OnMouseLeave()
{
PerformMouseMove(m_hWnd, CPoint(-1, -1));
}
BOOL CXTPTabControl::DrawIcon(CDC* pDC, CPoint pt, CXTPTabManagerItem* pItem, BOOL bDraw, CSize& szIcon) const
{
if (!pItem)
return GetPaintManager()->m_bShowIcons;
if (pItem->GetImageIndex() == -1 || GetPaintManager()->m_bShowIcons == FALSE)
return FALSE;
CXTPImageManagerIcon* pImage = m_pImageManager->GetImage(pItem->GetImageIndex(), szIcon.cx);
if (!pImage)
return FALSE;
if (!bDraw)
{
return TRUE;
}
pItem->DrawImage(pDC, CRect(pt, szIcon), pImage);
return TRUE;
}
void CXTPTabControl::SetPaintManager(CXTPTabPaintManager* pPaintManager)
{
delete m_pPaintManager;
m_pPaintManager = pPaintManager;
m_pPaintManager->RefreshMetrics();
Reposition();
}
BOOL CXTPTabControl::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
m_pToolTipContext->FilterToolTipMessage(this, message, wParam, lParam);
return CWnd::OnWndMsg(message, wParam, lParam, pResult);
}
void CXTPTabControl::EnableToolTips(XTPTabToolTipBehaviour behaviour /*= xtpTabToolTipAlways*/)
{
m_pPaintManager->EnableToolTips(behaviour);
}
void CXTPTabControl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
PerformKeyDown(m_hWnd, nChar);
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
UINT CXTPTabControl::OnGetDlgCode()
{
return ::GetFocus() == m_hWnd ? DLGC_WANTARROWS : CWnd::OnGetDlgCode();
}
void CXTPTabControl::OnSetFocus(CWnd* pOldWnd)
{
CWnd::OnSetFocus(pOldWnd);
InvalidateRect(m_rcHeaderRect, FALSE);
}
void CXTPTabControl::OnKillFocus(CWnd* pNewWnd)
{
CWnd::OnKillFocus(pNewWnd);
InvalidateRect(m_rcHeaderRect, FALSE);
}
#ifndef WM_QUERYUISTATE
#define WM_QUERYUISTATE 0x0129
#endif
#ifndef WM_CHANGEUISTATE
#define WM_CHANGEUISTATE 0x0127
#endif
#ifndef UISF_HIDEFOCUS
#define UISF_HIDEFOCUS 0x1
#endif
#ifndef UIS_CLEAR
#define UIS_CLEAR 2
#endif
void CXTPTabControl::SetFocusedItem(CXTPTabManagerItem* pItem)
{
CXTPTabManager::SetFocusedItem(pItem);
if ((::SendMessage(::GetParent(m_hWnd), WM_QUERYUISTATE, 0, 0) & UISF_HIDEFOCUS) != 0)
{
::SendMessage(::GetParent(m_hWnd), WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
}
}
BOOL CXTPTabControl::HeaderHasFocus() const
{
return (GetStyle() & WS_TABSTOP) && (::GetFocus() == m_hWnd)
&& ((::SendMessage(::GetParent(m_hWnd), WM_QUERYUISTATE, 0, 0) & UISF_HIDEFOCUS) == 0);
}
void CXTPTabControl::AdjustRect(BOOL bLarger, LPRECT lpRect) const
{
if (!lpRect)
return;
CRect rc(lpRect);
GetPaintManager()->AdjustClientRect((CXTPTabControl*)this, rc);
if (bLarger)
{
lpRect->top -= rc.top - lpRect->top;
lpRect->left -= rc.left - lpRect->left;
lpRect->bottom -= rc.bottom - lpRect->bottom;
lpRect->right -= rc.right - lpRect->right;
}
else
{
*lpRect = rc;
}
}