📄 theaderctrlex.cpp
字号:
/************************************
REVISION LOG ENTRY
Revision By: Mihai Filimon
Revised on 5/22/98 9:21:13 AM
Comments: THeaderCtrlEx.cpp : implementation file
************************************/
#include "stdafx.h"
#include "THeaderCtrlEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTHeaderCtrlEx
#define ORDERCOLUMN(b) ((BOOL)LOBYTE(b))
#define POSITIONCOLUMN(b) ((int)HIBYTE(b))
// Function name : CTHeaderCtrlEx::CTHeaderCtrlEx
// Description : constructor
// Return type : -
CTHeaderCtrlEx::CTHeaderCtrlEx()
{
m_nLastPosition = 0;
}
// Function name : CTHeaderCtrlEx::~CTHeaderCtrlEx
// Description : destructor
// Return type : -
CTHeaderCtrlEx::~CTHeaderCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CTHeaderCtrlEx, CHeaderCtrl)
//{{AFX_MSG_MAP(CTHeaderCtrlEx)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTHeaderCtrlEx message handlers
// Function name : CTHeaderCtrlEx::SignMoreSortColumns
// Description : Called from DrawItem, If position<4 will mark header columns with their respective positions
// Return type : void
// Argument : CDC & dc
// Argument : int nPosition
// Argument : CRect& rectWhere
void CTHeaderCtrlEx::SignMoreSortColumns(CDC & dc, int nPosition, CRect& rectWhere)
{
if (nPosition < 4)
{
const static dxSign = 1;
const static dxSignDelay = 1;
CRect sign = rectWhere;
sign.right = sign.left + dxSign;
sign.OffsetRect((rectWhere.Width() - (nPosition * dxSign + (nPosition - 1) * dxSignDelay)) / 2, 0);
if (sign.left >= rectWhere.left)
{
CBrush brush(RGB(0,0,0));
for (int j = 0; j < nPosition; j++)
{
dc.FillRect(sign, &brush);
sign.OffsetRect(dxSign + dxSignDelay, 0);
}
}
}
}
// Function name : CTHeaderCtrlEx::DrawItem
// Description : Call for ownerdraw item.
// Return type : void
// Argument : LPDRAWITEMSTRUCT lpDrawItemStruct
void CTHeaderCtrlEx::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CDC dc;
dc.Attach( lpDrawItemStruct->hDC );
// Get the column rect
CRect rcLabel( lpDrawItemStruct->rcItem );
// Save DC
int nSavedDC = dc.SaveDC();
// Set clipping region to limit drawing within column
CRgn rgn;
rgn.CreateRectRgnIndirect( &rcLabel );
dc.SelectObject( &rgn );
rgn.DeleteObject();
// Labels are offset by a certain amount
// This offset is related to the width of a space character
int offset = dc.GetTextExtent(_T("X"), 1 ).cx * 1;
// Get the column text and format
TCHAR buf[256];
HD_ITEM hditem;
hditem.mask = HDI_TEXT | HDI_FORMAT;
hditem.pszText = buf;
hditem.cchTextMax = 255;
GetItem( lpDrawItemStruct->itemID, &hditem );
// Determine format for drawing column label
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER;
if( hditem.fmt & HDF_CENTER)
uFormat |= DT_CENTER;
else if( hditem.fmt & HDF_RIGHT)
uFormat |= DT_RIGHT;
else
uFormat |= DT_LEFT;
// Adjust the rect if the mouse button is pressed on it
if( lpDrawItemStruct->itemState == ODS_SELECTED )
{
rcLabel.left++;
rcLabel.top += 2;
rcLabel.right++;
}
BOOL bAsc = true;
int nPosition = 0;
BOOL bIsSortColumn = GetColumnOrder(lpDrawItemStruct->itemID, bAsc, nPosition);
int dxRectArrow = bIsSortColumn ? 2*offset : 0;
// Adjust the rect further if Sort arrow is to be displayed
rcLabel.right -= dxRectArrow;
rcLabel.left += offset;
rcLabel.right -= offset;
// Draw column label
if( rcLabel.left < rcLabel.right )
dc.DrawText(buf,-1,rcLabel, uFormat);
// Draw the Sort arrow
if( bIsSortColumn )
{
rcLabel.right += offset;
CRect rectArrow = rcLabel;
int dyRectArrow = (int)((double)rectArrow.Height() / 5 * 2);
rectArrow.OffsetRect(0, (rectArrow.Height() - dyRectArrow) / 2);
rectArrow.bottom = rectArrow.top + dyRectArrow;
rectArrow.left = rcLabel.right;
rectArrow.right = rectArrow.left + dyRectArrow;
// Set up pens to use for drawing the triangle
CPen penLight(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
CPen penShadow(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
CPen *pOldPen = dc.SelectObject( &penLight );
CRect rectSign = rectArrow;
if (rectSign.left > rcLabel.left)
/* In this version do not exist SelectClipRgn, Wait for new version...*/
{
if (bAsc)
for (int i = 0; i < 2; i++)
{
dc.MoveTo(rectArrow.TopLeft());
dc.LineTo(rectArrow.right,rectArrow.top);
dc.LineTo((rectArrow.left + rectArrow.right) / 2,rectArrow.bottom);
dc.LineTo(rectArrow.TopLeft());
dc.SelectObject( &penShadow );
rectArrow.OffsetRect(-2,-1);
}
else
for (int i = 0; i < 2; i++)
{
dc.MoveTo(rectArrow.left,rectArrow.bottom);
dc.LineTo((rectArrow.left + rectArrow.right) / 2,rectArrow.top);
dc.LineTo(rectArrow.BottomRight());
dc.LineTo(rectArrow.left,rectArrow.bottom);
dc.SelectObject( &penShadow );
rectArrow.OffsetRect(-2,-1);
}
rectSign.left = (rectArrow.left + rectArrow.right) / 2 - offset;
rectSign.right = rectSign.left + 2 * offset;
rectSign.top = rectArrow.bottom;
rectSign.bottom = rectSign.top + 4;
if (m_mapSortColumns.GetCount() > 1)
SignMoreSortColumns(dc, nPosition, rectSign);
}
// Restore the pen
dc.SelectObject( pOldPen );
}
// Restore dc
dc.RestoreDC( nSavedDC );
// Detach the dc before returning
dc.Detach();
}
// Function name : CTHeaderCtrlEx::SetColumnFormat
// Description : Set or reset format of item iColumn from header
// Return type : void
// Argument : int iColumn
// Argument : int format
// Argument : BOOL bOr
void CTHeaderCtrlEx::SetColumnFormat(int iColumn, int format, BOOL bOr)
{
// Change the item to (not)owner drawn
HD_ITEM hditem;
hditem.mask = HDI_FORMAT;
if (GetItem( iColumn, &hditem ))
{
hditem.fmt = bOr ? hditem.fmt | format : hditem.fmt & ~format;
SetItem( iColumn, &hditem );
}
}
// Function name : CTHeaderCtrlEx::GetPositionColumn
// Description :
// Return type : BOOL ; Return TRUE, if exist sort column with position nPosition
// Argument : int nPosition
// Argument : BOOL & bAsc ; Set bAsc and nColumn with sort column found.
// Argument : int & nColumn
BOOL CTHeaderCtrlEx::GetPositionColumn(int nPosition, BOOL & bAsc, int & nColumn) const
{
POSITION position = m_mapSortColumns.GetStartPosition();
while (position)
{
WORD value;
m_mapSortColumns.GetNextAssoc(position, nColumn, value);
if (POSITIONCOLUMN(value) == nPosition)
{
bAsc = ORDERCOLUMN(value);
return TRUE;
}
}
return FALSE;
}
// Function name : CTHeaderCtrlEx::GetColumnOrder
// Description :
// Return type : BOOL ; Return TRUE if sort column nColumn exist
// Argument : int nColumn
// Argument : BOOL & bAsc ; sort column found
// Argument : int& nPosition
BOOL CTHeaderCtrlEx::GetColumnOrder(int nColumn, BOOL & bAsc, int& nPosition) const
{
WORD value;
BOOL result = m_mapSortColumns.Lookup(nColumn, value);
if (result)
{
bAsc = ORDERCOLUMN(value);
nPosition = POSITIONCOLUMN(value);
}
return result;
}
// Function name : CTHeaderCtrlEx::SetColumnOrder
// Description : Set column iColumn as sort column ascending or descending
// Return type : BOOL ; always TRUE for now
// Argument : int iColumn ; column to set
// Argument : BOOL bAsc ; sorting direction: ascendent or descendent
BOOL CTHeaderCtrlEx::SetColumnOrder(int iColumn, BOOL bAsc)
{
BYTE position = NULL;
WORD value = NULL;
if (m_mapSortColumns.Lookup(iColumn, value))
position = POSITIONCOLUMN(value);
else
position = ++m_nLastPosition;
m_mapSortColumns[iColumn] = MAKEWORD(bAsc, position);
SetColumnFormat(iColumn, HDF_OWNERDRAW, SET);
// Invalidate header control so that it gets redrawn
Invalidate();
return TRUE;
}
// Function name : CTHeaderCtrlEx::DeleteColumnOrder
// Description : Delete sort column iColumn
// Return type : void
// Argument : int iColumn ; column number
void CTHeaderCtrlEx::DeleteColumnOrder(int iColumn)
{
SetColumnFormat(iColumn, HDF_OWNERDRAW, REMOVE);
BOOL bAscRemove; int nPositionRemove;
if (GetColumnOrder(iColumn, bAscRemove, nPositionRemove))
{
m_mapSortColumns.RemoveKey(iColumn);
POSITION position = m_mapSortColumns.GetStartPosition();
while (position)
{
WORD value;
int column;
m_mapSortColumns.GetNextAssoc(position, column, value);
if (POSITIONCOLUMN(value) > nPositionRemove)
m_mapSortColumns[column] = MAKEWORD(ORDERCOLUMN(value),POSITIONCOLUMN(value) - 1);
}
m_nLastPosition--;
Invalidate();
}
}
// Function name : CTHeaderCtrlEx::ResetSortColumns
// Description : Remove all sort columns
// Return type : void
// Argument : BOOL bInvalidate ; If TRUE force to invalidate header
void CTHeaderCtrlEx::ResetSortColumns(BOOL bInvalidate)
{
m_mapSortColumns.RemoveAll();
m_nLastPosition = 0;
for (int i = 0; i < GetItemCount(); i++)
SetColumnFormat(i,HDF_OWNERDRAW, REMOVE );
if (bInvalidate)
Invalidate();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -