📄 flatheaderctrl.cpp
字号:
////////////////////////////////////////////////////////////////////////////
// File: CFlatHeaderCtrl.cpp
// Version: 1.0.1.0
//
// Author: Maarten Hoeben
// E-mail: hoeben@nwn.com
//
// Implementation of the CFlatHeaderCtrl and associated classes.
//
// You are free to use, distribute or modify this code
// as long as the header is not removed or modified.
//
// Version history
//
// 1.0.0.1 - Initial release
// 1.0.1.0 - Fixed FHDragWnd destroy warning (thanks Philippe Terrier)
// - Fixed double sent HDN_ITEMCLICK
// - Added a property that adjusts for ListCtrls that use a static
// border for flat look.
// ? - Fixed some problems with resizing (sami@tolvanen.com). See below.
//
////////////////////////////////////////////////////////////////////////////
// FlatHeaderCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "FlatHeaderCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFHDragWnd
CFHDragWnd::CFHDragWnd()
{
// Register the window class if it has not already been registered.
WNDCLASS wndclass;
HINSTANCE hInst = AfxGetInstanceHandle();
if (!(::GetClassInfo(hInst, FHDRAGWND_CLASSNAME, &wndclass)))
{
// otherwise we need to register a new class
wndclass.style = CS_SAVEBITS ;
wndclass.lpfnWndProc = ::DefWindowProc;
wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
wndclass.hInstance = hInst;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor(hInst, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = FHDRAGWND_CLASSNAME;
if (!AfxRegisterClass(&wndclass))
AfxThrowResourceException();
}
}
CFHDragWnd::~CFHDragWnd()
{
}
BEGIN_MESSAGE_MAP(CFHDragWnd, CWnd)
//{{AFX_MSG_MAP(CFHDragWnd)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFHDragWnd message handlers
BOOL CFHDragWnd::Create(CRect rect, CFlatHeaderCtrl* pFlatHeaderCtrl, INT iItem)
{
ASSERT_VALID(pFlatHeaderCtrl);
ASSERT(pFlatHeaderCtrl->IsKindOf(RUNTIME_CLASS(CFlatHeaderCtrl)));
m_pFlatHeaderCtrl = pFlatHeaderCtrl;
m_iItem = iItem;
DWORD dwStyle = WS_POPUP|WS_DISABLED;
DWORD dwExStyle = WS_EX_TOPMOST|WS_EX_TOOLWINDOW ;
return CreateEx(dwExStyle, FHDRAGWND_CLASSNAME, NULL, dwStyle,
rect.left, rect.top, rect.Width(), rect.Height(),
NULL, NULL, NULL);
}
void CFHDragWnd::OnPaint()
{
CPaintDC dc(this);
/*if (m_pFlatHeaderCtrl->m_bNoFlicker)
{*/
CMemDC MemDC(&dc);
OnDraw(&MemDC);
/*}
else
OnDraw(&dc);*/
}
BOOL CFHDragWnd::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
void CFHDragWnd::OnDraw(CDC* pDC)
{
CRect rect;
GetClientRect(rect);
pDC->FillSolidRect(rect, m_pFlatHeaderCtrl->m_cr3DFace);
pDC->Draw3dRect(rect, m_pFlatHeaderCtrl->m_cr3DHighLight, m_pFlatHeaderCtrl->m_cr3DShadow);
CPen* pPen = pDC->GetCurrentPen();
CFont* pFont = pDC->SelectObject(m_pFlatHeaderCtrl->GetFont());
pDC->SetBkColor(m_pFlatHeaderCtrl->m_cr3DFace);
pDC->SetTextColor(m_pFlatHeaderCtrl->m_crText);
rect.DeflateRect(m_pFlatHeaderCtrl->m_iSpacing, 0);
m_pFlatHeaderCtrl->DrawItem(pDC, rect,
m_pFlatHeaderCtrl->m_hditemHotItem,
(m_pFlatHeaderCtrl->m_iSortColumn == m_iItem),
m_pFlatHeaderCtrl->m_bSortAscending);
pDC->SelectObject(pFont);
pDC->SelectObject(pPen);
}
void CFHDragWnd::PostNcDestroy()
{
CWnd::PostNcDestroy();
delete this;
}
/////////////////////////////////////////////////////////////////////////////
// CFlatHeaderCtrl
IMPLEMENT_DYNCREATE(CFlatHeaderCtrl, CHeaderCtrl)
CFlatHeaderCtrl::CFlatHeaderCtrl()
{
// m_bNoFlicker = TRUE;
m_iSpacing = 6;
m_sizeArrow.cx = 8;
m_sizeArrow.cy = 8;
m_bStaticBorder = FALSE;
m_iHotIndex = -1;
m_bHotItemResizable = TRUE;
m_bResizing = FALSE;
m_iHotDivider = -1;
m_crHotDivider = 0x000000FF;
m_bDragging = FALSE;
m_pDragWnd = NULL;
m_nClickFlags = 0;
m_bSortAscending = FALSE;
m_iSortColumn = -1;
m_arrayHdrItemEx.SetSize(0, 8);
m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);
m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
m_crText = ::GetSysColor(COLOR_BTNTEXT);
}
CFlatHeaderCtrl::~CFlatHeaderCtrl()
{
if (m_pDragWnd != NULL)
{
m_pDragWnd->DestroyWindow();
m_pDragWnd = NULL;
}
}
#if _MFC_VER == 0x0800
//Hack for VS beta version
#undef ON_WM_NCHITTEST
#define ON_WM_NCHITTEST() \
{ WM_NCHITTEST, 0, 0, 0, AfxSig_l_p, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< UINT (AFX_MSG_CALL CWnd::*)(CPoint) > (&ThisClass :: OnNcHitTest)) },
#endif
BEGIN_MESSAGE_MAP(CFlatHeaderCtrl, CHeaderCtrl)
//{{AFX_MSG_MAP(CFlatHeaderCtrl)
ON_MESSAGE(HDM_INSERTITEMA, OnInsertItem)
ON_MESSAGE(HDM_INSERTITEMW, OnInsertItem)
ON_MESSAGE(HDM_DELETEITEM, OnDeleteItem)
ON_MESSAGE(HDM_SETHOTDIVIDER, OnSetHotDivider)
ON_MESSAGE(HDM_LAYOUT, OnLayout)
ON_WM_NCHITTEST()
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_PAINT()
ON_WM_SYSCOLORCHANGE()
ON_WM_ERASEBKGND()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFlatHeaderCtrl attributes
BOOL CFlatHeaderCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case FH_PROPERTY_SPACING:
m_iSpacing = (INT)lParam;
break;
case FH_PROPERTY_ARROW:
m_sizeArrow.cx = LOWORD(lParam);
m_sizeArrow.cy = HIWORD(lParam);
break;
case FH_PROPERTY_STATICBORDER:
m_bStaticBorder = (BOOL)lParam;
break;
default:
return FALSE;
}
Invalidate();
return TRUE;
}
BOOL CFlatHeaderCtrl::GetItemEx(INT iPos, HDITEMEX* phditemex) const
{
if (iPos >= m_arrayHdrItemEx.GetSize())
return FALSE;
*phditemex = m_arrayHdrItemEx[iPos];
return TRUE;
}
BOOL CFlatHeaderCtrl::SetItemEx(INT iPos, HDITEMEX* phditemex)
{
if (iPos >= m_arrayHdrItemEx.GetSize())
return FALSE;
if (phditemex->m_iMinWidth <= phditemex->m_iMaxWidth)
{
HDITEM hditem;
hditem.mask = HDI_WIDTH;
if (!GetItem(iPos, &hditem))
return FALSE;
if (hditem.cxy < phditemex->m_iMinWidth)
hditem.cxy = phditemex->m_iMinWidth;
if (hditem.cxy > phditemex->m_iMaxWidth)
hditem.cxy = phditemex->m_iMaxWidth;
SetItem(iPos, &hditem);
}
m_arrayHdrItemEx.SetAt(iPos, *phditemex);
return TRUE;
}
void CFlatHeaderCtrl::SetSortColumn(INT iPos, BOOL bSortAscending)
{
ASSERT(iPos < GetItemCount());
m_bSortAscending = bSortAscending;
m_iSortColumn = iPos;
Invalidate();
}
INT CFlatHeaderCtrl::GetSortColumn(BOOL* pbSortAscending /*= NULL*/)
{
if (pbSortAscending)
*pbSortAscending = m_bSortAscending;
return m_iSortColumn;
}
/////////////////////////////////////////////////////////////////////////////
// CFlatHeaderCtrl implementation
void CFlatHeaderCtrl::DrawCtrl(CDC* pDC)
{
CRect rectClip;
if (pDC->GetClipBox(&rectClip) == ERROR)
return;
CRect rectClient, rectItem;
GetClientRect(&rectClient);
pDC->FillSolidRect(rectClip, m_cr3DFace);
INT iItems = GetItemCount();
ASSERT(iItems >= 0);
CPen penHighLight(PS_SOLID, 1, m_cr3DHighLight);
CPen penShadow(PS_SOLID, 1, m_cr3DShadow);
CPen* pPen = pDC->GetCurrentPen();
CFont* pFont = pDC->SelectObject(GetFont());
pDC->SetBkColor(m_cr3DFace);
pDC->SetTextColor(m_crText);
INT iWidth = 0;
for (INT i = 0; i < iItems; i++)
{
INT iItem = OrderToIndex(i);
TCHAR szText[FLATHEADER_TEXT_MAX];
HDITEM hditem;
hditem.mask = HDI_WIDTH | HDI_FORMAT | HDI_TEXT | HDI_IMAGE | HDI_BITMAP;
hditem.pszText = szText;
hditem.cchTextMax = sizeof(szText);
VERIFY(GetItem(iItem, &hditem));
VERIFY(GetItemRect(iItem, rectItem));
if (rectItem.right >= rectClip.left || rectItem.left <= rectClip.right)
{
if (hditem.fmt & HDF_OWNERDRAW)
{
DRAWITEMSTRUCT disItem;
disItem.CtlType = ODT_BUTTON;
disItem.CtlID = GetDlgCtrlID();
disItem.itemID = iItem;
disItem.itemAction = ODA_DRAWENTIRE;
disItem.itemState = 0;
disItem.hwndItem = m_hWnd;
disItem.hDC = pDC->m_hDC;
disItem.rcItem = rectItem;
disItem.itemData = 0;
DrawItem(&disItem);
}
else
{
rectItem.DeflateRect(m_iSpacing, 0);
DrawItem(pDC, rectItem, hditem, (iItem == m_iSortColumn), m_bSortAscending);
rectItem.InflateRect(m_iSpacing, 0);
if (m_nClickFlags & MK_LBUTTON &&
m_iHotIndex == iItem &&
m_hdhtiHotItem.flags & HHT_ONHEADER)
{
pDC->InvertRect(rectItem);
}
}
if (i < iItems-1)
{
pDC->SelectObject(&penShadow);
pDC->MoveTo(rectItem.right - 1, rectItem.top + 2);
pDC->LineTo(rectItem.right - 1, rectItem.bottom - 2);
pDC->SelectObject(&penHighLight);
pDC->MoveTo(rectItem.right, rectItem.top + 2);
pDC->LineTo(rectItem.right, rectItem.bottom - 2);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -