📄 bcgpheaderctrl.cpp
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This is a part of the BCGControlBar Library
// Copyright (C) 1998-2000 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions
// of the accompanying license agreement.
//*******************************************************************************
// BCGHeaderCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "BCGPHeaderCtrl.h"
#include "bcgglobals.h"
#include "BCGPVisualManager.h"
#include "trackmouse.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CBCGPHeaderCtrl, CHeaderCtrl)
/////////////////////////////////////////////////////////////////////////////
// CBCGPHeaderCtrl
CBCGPHeaderCtrl::CBCGPHeaderCtrl()
{
m_bIsMousePressed = FALSE;
m_bMultipleSort = FALSE;
m_bAscending = TRUE;
m_nHighlightedItem = -1;
m_bTracked = FALSE;
m_bIsDlgControl = FALSE;
}
CBCGPHeaderCtrl::~CBCGPHeaderCtrl()
{
}
BEGIN_MESSAGE_MAP(CBCGPHeaderCtrl, CHeaderCtrl)
//{{AFX_MSG_MAP(CBCGPHeaderCtrl)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_CANCELMODE()
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBCGPHeaderCtrl message handlers
void CBCGPHeaderCtrl::OnDrawItem (CDC* pDC, int iItem, CRect rect, BOOL bIsPressed,
BOOL bIsHighlighted)
{
ASSERT_VALID (this);
ASSERT_VALID (pDC);
const int nTextMargin = 5;
//-------------
// Draw border:
//-------------
CBCGPVisualManager::GetInstance ()->OnDrawHeaderCtrlBorder (this, pDC,
rect, bIsPressed, bIsHighlighted);
if (iItem < 0)
{
return;
}
int nSortVal = 0;
if (m_mapColumnsStatus.Lookup (iItem, nSortVal) &&
nSortVal != 0)
{
//-----------------
// Draw sort arrow:
//-----------------
CRect rectArrow = rect;
rectArrow.DeflateRect (5, 5);
rectArrow.left = rectArrow.right - rectArrow.Height ();
if (bIsPressed)
{
rectArrow.right++;
rectArrow.bottom++;
}
rect.right = rectArrow.left - 1;
int dy2 = (int) (.134 * rectArrow.Width ());
rectArrow.DeflateRect (0, dy2);
m_bAscending = nSortVal > 0;
OnDrawSortArrow (pDC, rectArrow);
}
HD_ITEM hdItem;
memset (&hdItem, 0, sizeof (hdItem));
hdItem.mask = HDI_FORMAT | HDI_BITMAP | HDI_TEXT | HDI_IMAGE;
TCHAR szText [256];
hdItem.pszText = szText;
hdItem.cchTextMax = 255;
if (!GetItem (iItem, &hdItem))
{
return;
}
//-----------------------
// Draw bitmap and image:
//-----------------------
if ((hdItem.fmt & HDF_IMAGE) && hdItem.iImage >= 0)
{
// By Max Khiszinsky:
//---------------------------------------
// The column has a image from imagelist:
//---------------------------------------
CImageList* pImageList = GetImageList ();
if (pImageList != NULL)
{
int cx = 0;
int cy = 0;
VERIFY (::ImageList_GetIconSize (*pImageList, &cx, &cy));
CPoint pt = rect.TopLeft ();
pt.x ++;
pt.y = (rect.top + rect.bottom - cy) / 2;
VERIFY (pImageList->Draw (pDC, hdItem.iImage, pt, ILD_NORMAL));
rect.left += cx;
}
}
if ((hdItem.fmt & (HDF_BITMAP | HDF_BITMAP_ON_RIGHT)) && hdItem.hbm != NULL)
{
CBitmap* pBmp = CBitmap::FromHandle (hdItem.hbm);
ASSERT_VALID (pBmp);
BITMAP bmp;
pBmp->GetBitmap (&bmp);
CRect rectBitmap = rect;
if (hdItem.fmt & HDF_BITMAP_ON_RIGHT)
{
rectBitmap.right--;
rect.right = rectBitmap.left = rectBitmap.right - bmp.bmWidth;
}
else
{
rectBitmap.left++;
rect.left = rectBitmap.right = rectBitmap.left + bmp.bmWidth;
}
rectBitmap.top += max (0, (rectBitmap.Height () - bmp.bmHeight) / 2);
rectBitmap.bottom = rectBitmap.top + bmp.bmHeight;
pDC->DrawState (rectBitmap.TopLeft (), rectBitmap.Size (), pBmp, DSS_NORMAL);
}
//-----------
// Draw text:
//-----------
if (hdItem.fmt & HDF_STRING)
{
CRect rectLabel = rect;
rectLabel.DeflateRect (nTextMargin, 0);
CString strLabel = hdItem.pszText;
UINT uiTextFlags = DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX;
if (hdItem.fmt & HDF_CENTER)
{
uiTextFlags |= DT_CENTER;
}
else if (hdItem.fmt & HDF_RIGHT)
{
uiTextFlags |= DT_RIGHT;
}
pDC->DrawText (strLabel, rectLabel, uiTextFlags);
}
}
//***************************************************************************************
void CBCGPHeaderCtrl::SetSortColumn (int iColumn, BOOL bAscending, BOOL bAdd)
{
ASSERT_VALID (this);
if (iColumn < 0)
{
m_mapColumnsStatus.RemoveAll ();
return;
}
if (bAdd)
{
if (!m_bMultipleSort)
{
ASSERT (FALSE);
bAdd = FALSE;
}
}
if (!bAdd)
{
m_mapColumnsStatus.RemoveAll ();
}
m_mapColumnsStatus.SetAt (iColumn, bAscending ? 1 : -1);
RedrawWindow ();
}
//***************************************************************************************
void CBCGPHeaderCtrl::RemoveSortColumn (int iColumn)
{
ASSERT_VALID (this);
m_mapColumnsStatus.RemoveKey (iColumn);
RedrawWindow ();
}
//***************************************************************************************
BOOL CBCGPHeaderCtrl::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
//***************************************************************************************
void CBCGPHeaderCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rectClip;
dc.GetClipBox (rectClip);
CRect rectClient;
GetClientRect (rectClient);
CDC* pDC = &dc;
BOOL bMemDC = FALSE;
CDC dcMem;
CBitmap bmp;
CBitmap* pOldBmp = NULL;
if (dcMem.CreateCompatibleDC (&dc) &&
bmp.CreateCompatibleBitmap (&dc, rectClient.Width (),
rectClient.Height ()))
{
//-------------------------------------------------------------
// Off-screen DC successfully created. Better paint to it then!
//-------------------------------------------------------------
bMemDC = TRUE;
pOldBmp = dcMem.SelectObject (&bmp);
pDC = &dcMem;
}
OnFillBackground (pDC);
CFont* pOldFont = (CFont*) pDC->SelectObject (&globalData.fontRegular);
ASSERT_VALID (pOldFont);
pDC->SetTextColor (globalData.clrBtnText);
pDC->SetBkMode (TRANSPARENT);
CRect rect;
GetClientRect(rect);
CRect rectItem;
int nCount = GetItemCount ();
for (int i = 0; i < nCount; i++)
{
//------------------
// Is item pressed?
//------------------
CPoint ptCursor;
::GetCursorPos (&ptCursor);
ScreenToClient (&ptCursor);
HDHITTESTINFO hdHitTestInfo;
hdHitTestInfo.pt = ptCursor;
int iHit = SendMessage (HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
BOOL bIsHighlighted = iHit == i && (hdHitTestInfo.flags & HHT_ONHEADER);
BOOL bIsPressed = m_bIsMousePressed && bIsHighlighted;
GetItemRect (i, rectItem);
CRgn rgnClip;
rgnClip.CreateRectRgnIndirect (&rectItem);
pDC->SelectClipRgn (&rgnClip);
//-----------
// Draw item:
//-----------
OnDrawItem (pDC, i, rectItem, bIsPressed, m_nHighlightedItem == i);
pDC->SelectClipRgn (NULL);
}
//--------------------
// Draw "tail border":
//--------------------
if (nCount == 0)
{
rectItem = rect;
rectItem.right++;
}
else
{
rectItem.left = rectItem.right;
rectItem.right = rect.right + 1;
}
OnDrawItem (pDC, -1, rectItem, FALSE, FALSE);
pDC->SelectObject (pOldFont);
if (bMemDC)
{
//--------------------------------------
// Copy the results to the on-screen DC:
//--------------------------------------
dc.BitBlt (rectClip.left, rectClip.top, rectClip.Width(), rectClip.Height(),
&dcMem, rectClip.left, rectClip.top, SRCCOPY);
dcMem.SelectObject(pOldBmp);
}
}
//***************************************************************************************
void CBCGPHeaderCtrl::OnFillBackground (CDC* pDC)
{
ASSERT_VALID (this);
ASSERT_VALID (pDC);
CRect rectClient;
GetClientRect (rectClient);
CBCGPVisualManager::GetInstance ()->OnFillHeaderCtrlBackground (this, pDC,
rectClient);
}
//***************************************************************************************
void CBCGPHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bIsMousePressed = TRUE;
CHeaderCtrl::OnLButtonDown(nFlags, point);
}
//***************************************************************************************
void CBCGPHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bIsMousePressed = FALSE;
CHeaderCtrl::OnLButtonUp(nFlags, point);
}
//***************************************************************************************
void CBCGPHeaderCtrl::OnDrawSortArrow (CDC* pDC, CRect rectArrow)
{
ASSERT_VALID (pDC);
ASSERT_VALID (this);
CBCGPVisualManager::GetInstance ()->OnDrawHeaderCtrlSortArrow (this, pDC,
rectArrow, m_bAscending);
}
//*********************************************************************************
void CBCGPHeaderCtrl::EnableMultipleSort (BOOL bEnable)
{
ASSERT_VALID (this);
if (m_bMultipleSort == bEnable)
{
return;
}
m_bMultipleSort = bEnable;
if (!m_bMultipleSort)
{
m_mapColumnsStatus.RemoveAll ();
if (GetSafeHwnd () != NULL)
{
RedrawWindow ();
}
}
}
//*********************************************************************************
int CBCGPHeaderCtrl::GetSortColumn () const
{
ASSERT_VALID (this);
if (m_bMultipleSort)
{
TRACE0("Call CBCGPHeaderCtrl::GetColumnState for muliple sort\n");
ASSERT (FALSE);
return -1;
}
int nCount = GetItemCount ();
for (int i = 0; i < nCount; i++)
{
int nSortVal = 0;
if (m_mapColumnsStatus.Lookup (i, nSortVal) &&
nSortVal != 0)
{
return i;
}
}
return -1;
}
//*********************************************************************************
BOOL CBCGPHeaderCtrl::IsAscending () const
{
ASSERT_VALID (this);
if (m_bMultipleSort)
{
TRACE0("Call CBCGPHeaderCtrl::GetColumnState for muliple sort\n");
ASSERT (FALSE);
return -1;
}
int nCount = GetItemCount ();
for (int i = 0; i < nCount; i++)
{
int nSortVal = 0;
if (m_mapColumnsStatus.Lookup (i, nSortVal) &&
nSortVal != 0)
{
return nSortVal > 0;
}
}
return i;
}
//*********************************************************************************
int CBCGPHeaderCtrl::GetColumnState (int iColumn) const
{
int nSortVal = 0;
m_mapColumnsStatus.Lookup (iColumn, nSortVal);
return nSortVal;
}
//**********************************************************************************
void CBCGPHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if ((nFlags & MK_LBUTTON) == 0)
{
HDHITTESTINFO hdHitTestInfo;
hdHitTestInfo.pt = point;
int nPrevHighlightedItem = m_nHighlightedItem;
m_nHighlightedItem = SendMessage (HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
if ((hdHitTestInfo.flags & HHT_ONHEADER) == 0)
{
m_nHighlightedItem = -1;
}
if (!m_bTracked)
{
m_bTracked = TRUE;
TRACKMOUSEEVENT trackmouseevent;
trackmouseevent.cbSize = sizeof(trackmouseevent);
trackmouseevent.dwFlags = TME_LEAVE;
trackmouseevent.hwndTrack = GetSafeHwnd();
trackmouseevent.dwHoverTime = HOVER_DEFAULT;
::BCGPTrackMouse (&trackmouseevent);
}
if (nPrevHighlightedItem != m_nHighlightedItem)
{
RedrawWindow ();
}
}
CHeaderCtrl::OnMouseMove(nFlags, point);
}
//*****************************************************************************************
LRESULT CBCGPHeaderCtrl::OnMouseLeave(WPARAM,LPARAM)
{
m_bTracked = FALSE;
if (m_nHighlightedItem >= 0)
{
m_nHighlightedItem = -1;
RedrawWindow ();
}
return 0;
}
//*****************************************************************************************
void CBCGPHeaderCtrl::OnCancelMode()
{
CHeaderCtrl::OnCancelMode();
if (m_nHighlightedItem >= 0)
{
m_nHighlightedItem = -1;
RedrawWindow ();
}
}
//********************************************************************************
int CBCGPHeaderCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CHeaderCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
CommonInit ();
return 0;
}
//*********************************************************************************
void CBCGPHeaderCtrl::PreSubclassWindow()
{
CommonInit ();
CHeaderCtrl::PreSubclassWindow();
}
//********************************************************************************
void CBCGPHeaderCtrl::CommonInit ()
{
ASSERT_VALID (this);
for (CWnd* pParentWnd = GetParent (); pParentWnd != NULL;
pParentWnd = pParentWnd->GetParent ())
{
if (pParentWnd->IsKindOf (RUNTIME_CLASS (CDialog)))
{
m_bIsDlgControl = TRUE;
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -