📄 flatheaderctrl.cpp
字号:
{
POINT point;
point.y = rect.CenterPoint().y - ((info.rcImage.bottom-info.rcImage.top)>>1);
if(bRight)
point.x = rect.right - iWidth;
else
point.x = rect.left;
pImageList->Draw(pDC, hditem.iImage, point, ILD_NORMAL);
}
else
iWidth = 0;
}
}
return iWidth;
}
INT CFlatHeaderCtrl::DrawBitmap(CDC* pDC, CRect rect, HDITEM hditem, CBitmap* pBitmap, BITMAP* pBitmapInfo, BOOL bRight)
{
INT iWidth = 0;
if(pBitmap)
{
iWidth = pBitmapInfo->bmWidth;
if(iWidth<=rect.Width() && rect.Width()>0)
{
POINT point;
point.y = rect.CenterPoint().y - (pBitmapInfo->bmHeight>>1);
if(bRight)
point.x = rect.right - iWidth;
else
point.x = rect.left;
CDC dc;
if(dc.CreateCompatibleDC(pDC) == TRUE)
{
VERIFY(dc.SelectObject(pBitmap));
iWidth = pDC->BitBlt(
point.x, point.y,
pBitmapInfo->bmWidth, pBitmapInfo->bmHeight,
&dc,
0, 0,
SRCCOPY
) ? iWidth:0;
}
else iWidth = 0;
}
else
iWidth = 0;
}
return iWidth;
}
INT CFlatHeaderCtrl::DrawText(CDC* pDC, CRect rect, HDITEM hditem)
{
CSize size;
if(rect.Width()>0 && hditem.mask&HDI_TEXT && hditem.fmt&HDF_STRING)
{
size = pDC->GetTextExtent(hditem.pszText);
switch(hditem.fmt&HDF_JUSTIFYMASK)
{
case HDF_LEFT:
case HDF_LEFT|HDF_RTLREADING:
pDC->DrawText(hditem.pszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
break;
case HDF_CENTER:
case HDF_CENTER|HDF_RTLREADING:
pDC->DrawText(hditem.pszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
break;
case HDF_RIGHT:
case HDF_RIGHT|HDF_RTLREADING:
pDC->DrawText(hditem.pszText, -1, rect, DT_RIGHT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
break;
}
}
size.cx = rect.Width()>size.cx ? size.cx:rect.Width();
return size.cx>0 ? size.cx:0;
}
INT CFlatHeaderCtrl::DrawArrow(CDC* pDC, CRect rect, BOOL bSortAscending, BOOL bRight)
{
INT iWidth = 0;
if(rect.Width()>0 && m_sizeArrow.cx<=rect.Width())
{
iWidth = m_sizeArrow.cx;
rect.top += (rect.Height() - m_sizeArrow.cy - 1)>>1;
rect.bottom = rect.top + m_sizeArrow.cy - 1;
rect.left = bRight ? rect.right-m_sizeArrow.cy:rect.left;
// Set up pens to use for drawing the triangle
CPen penLight(PS_SOLID, 1, m_cr3DHighLight);
CPen penShadow(PS_SOLID, 1, m_cr3DShadow);
CPen *pPen = pDC->SelectObject(&penLight);
if(bSortAscending)
{
// Draw triangle pointing upwards
pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1) + 1, rect.top);
pDC->LineTo(rect.left + (m_sizeArrow.cx-1), rect.top + m_sizeArrow.cy - 1);
pDC->LineTo(rect.left, rect.top + m_sizeArrow.cy - 1);
pDC->SelectObject(&penShadow);
pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1), rect.top);
pDC->LineTo(rect.left, rect.top + m_sizeArrow.cy - 1);
}
else
{
// Draw triangle pointing downwards
pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1)+1, rect.top + m_sizeArrow.cy - 1);
pDC->LineTo(rect.left + (m_sizeArrow.cx-1), rect.top);
pDC->SelectObject(&penShadow);
pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1), rect.top + m_sizeArrow.cy - 1);
pDC->LineTo(rect.left, rect.top);
pDC->LineTo(rect.left + m_sizeArrow.cx, rect.top);
}
// Restore the pen
pDC->SelectObject(pPen);
}
return iWidth;
}
/////////////////////////////////////////////////////////////////////////////
// CHeaderCtrl message handlers
LRESULT CFlatHeaderCtrl::OnInsertItem(WPARAM wParam, LPARAM lParam)
{
HDITEMEX hditemex;
hditemex.m_iMinWidth = 0;
hditemex.m_iMaxWidth = -1;
ASSERT((INT)wParam <= m_arrayHdrItemEx.GetSize());
m_arrayHdrItemEx.InsertAt(wParam, hditemex);
return Default();
}
LRESULT CFlatHeaderCtrl::OnDeleteItem(WPARAM wParam, LPARAM lParam)
{
ASSERT((INT)wParam < m_arrayHdrItemEx.GetSize());
m_arrayHdrItemEx.RemoveAt(wParam);
return Default();
}
LRESULT CFlatHeaderCtrl::OnSetHotDivider(WPARAM wParam, LPARAM lParam)
{
if(wParam)
{
HDHITTESTINFO hdhti;
hdhti.pt.x = LOWORD(lParam);
hdhti.pt.y = HIWORD(lParam);
ScreenToClient(&hdhti.pt);
m_iHotDivider = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti));
if(m_iHotDivider >= 0)
{
CRect rectItem;
VERIFY(GetItemRect(m_iHotDivider, rectItem));
if(hdhti.pt.x > rectItem.CenterPoint().x)
m_iHotDivider++;
}
}
else
m_iHotDivider = (INT)lParam;
Invalidate();
return(LRESULT)m_iHotDivider;
}
LRESULT CFlatHeaderCtrl::OnLayout(WPARAM wParam, LPARAM lParam)
{
LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam;
if(m_bStaticBorder)
lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2;
return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
}
/////////////////////////////////////////////////////////////////////////////
// CFlatHeaderCtrl message handlers
BOOL CFlatHeaderCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CFlatHeaderCtrl::OnPaint()
{
CPaintDC dc(this);
if (m_bNoFlicker)
{
CMemDC MemDC(&dc);
DrawCtrl(&MemDC);
}
else
DrawCtrl(&dc);
}
UINT CFlatHeaderCtrl::OnNcHitTest(CPoint point)
{
m_hdhtiHotItem.pt = point;
ScreenToClient(&m_hdhtiHotItem.pt);
m_iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&m_hdhtiHotItem));
if(m_iHotIndex >= 0)
{
HDITEM hditem;
hditem.mask = HDI_ORDER;
VERIFY(GetItem(m_iHotIndex, &hditem));
m_iHotOrder = hditem.iOrder;
HDITEMEX hditemex;
if(GetItemEx(m_iHotIndex, &hditemex))
m_bHotItemResizable = hditemex.m_iMinWidth!=hditemex.m_iMaxWidth ? TRUE:FALSE;
}
return CHeaderCtrl::OnNcHitTest(point);
}
BOOL CFlatHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if(m_iHotIndex>=0 && m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN) && !m_bHotItemResizable)
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
return TRUE;
}
return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, message);
}
void CFlatHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_nClickFlags = nFlags;
m_ptClickPoint = point;
if(m_iHotIndex >= 0)
{
m_hditemHotItem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP|HDI_ORDER;
m_hditemHotItem.pszText = m_szHotItemText;
m_hditemHotItem.cchTextMax = sizeof(m_szHotItemText);
VERIFY(GetItem(m_iHotIndex, &m_hditemHotItem));
if(m_hdhtiHotItem.flags&HHT_ONHEADER)
{
RECT rectItem;
VERIFY(GetItemRect(m_iHotIndex, &rectItem));
InvalidateRect(&rectItem);
}
if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN))
{
if(!m_bHotItemResizable)
return;
HDITEMEX hditemex;
VERIFY(GetItemEx(m_iHotIndex, &hditemex));
CRect rectItem;
GetItemRect(m_iHotIndex, rectItem);
ClientToScreen(rectItem);
if(hditemex.m_iMinWidth <= hditemex.m_iMaxWidth)
{
CRect rectClip;
GetClipCursor(rectClip);
POINT point;
GetCursorPos(&point);
INT iOffset = point.x - rectItem.right;
rectClip.left = rectItem.left + hditemex.m_iMinWidth + iOffset;
rectClip.right = rectItem.left + hditemex.m_iMaxWidth + iOffset;
ClipCursor(rectClip);
}
m_bResizing = TRUE;
}
}
CHeaderCtrl::OnLButtonDown(nFlags, point);
}
void CFlatHeaderCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if(m_iHotIndex>=0 && m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN) && !m_bHotItemResizable)
return;
CHeaderCtrl::OnLButtonDblClk(nFlags, point);
}
void CFlatHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
m_nClickFlags = nFlags;
m_ptClickPoint = point;
if(m_iHotIndex >= 0)
{
CWnd* pWnd = GetParent();
if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN))
{
if(m_bResizing)
{
ClipCursor(NULL);
m_bResizing = FALSE;
}
}
if(m_hdhtiHotItem.flags&HHT_ONHEADER)
{
if(m_bDragging)
{
NMHEADER nmhdr;
nmhdr.hdr.hwndFrom = m_hWnd;
nmhdr.hdr.idFrom = GetDlgCtrlID();
nmhdr.hdr.code = HDN_ENDDRAG;
nmhdr.iItem = m_iHotIndex;
nmhdr.iButton = 0;
nmhdr.pitem = &m_hditemHotItem;
if(pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmhdr)==FALSE && m_iHotDivider>=0)
{
INT iCount = GetItemCount();
ASSERT(m_iHotOrder < iCount);
ASSERT(m_iHotDivider <= iCount);
LPINT piArray = new INT[iCount*2];
if(piArray)
{
GetOrderArray((LPINT)piArray, iCount);
for(INT i=0,j=0;i<iCount;i++)
{
if(j == m_iHotOrder)
j++;
if(
(m_iHotOrder<m_iHotDivider && i == m_iHotDivider-1) ||
(m_iHotOrder>=m_iHotDivider && i == m_iHotDivider)
)
piArray[iCount+i] = piArray[m_iHotOrder];
else
piArray[iCount+i] = piArray[j++];
}
SetOrderArray(iCount, (LPINT)&piArray[iCount]);
delete piArray;
}
else
AfxThrowMemoryException();
}
if(m_pDragWnd != NULL)
delete m_pDragWnd;
m_pDragWnd = NULL;
if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
ReleaseCapture();
m_bDragging = FALSE;
m_iHotDivider = -1;
Invalidate();
}
else
{
RECT rectItem;
VERIFY(GetItemRect(m_iHotIndex, &rectItem));
InvalidateRect(&rectItem);
}
}
}
CHeaderCtrl::OnLButtonUp(nFlags, point);
}
void CFlatHeaderCtrl::OnSysColorChange()
{
CHeaderCtrl::OnSysColorChange();
m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);
m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
m_crText = ::GetSysColor(COLOR_BTNTEXT);
}
void CFlatHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_nClickFlags&MK_LBUTTON && m_iHotIndex>=0)
{
if(m_bResizing)
CHeaderCtrl::OnMouseMove(nFlags, point);
if(m_hdhtiHotItem.flags&HHT_ONHEADER)
{
if(m_bDragging)
{
if(m_pDragWnd != NULL)
{
CRect rect;
m_pDragWnd->GetWindowRect(&rect);
CPoint pt = point;
ClientToScreen(&pt);
pt.Offset(-(rect.Width()>>1), -(rect.Height()>>1));
m_pDragWnd->SetWindowPos(
&wndTop,
pt.x, pt.y,
0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE
);
HDHITTESTINFO hdhti;
hdhti.pt.x = point.x;
hdhti.pt.y = point.y;
INT iHotOrder = -1;
INT iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti));
if(iHotIndex >= 0)
{
HDITEM hditem;
hditem.mask = HDI_ORDER;
VERIFY(GetItem(iHotIndex, &hditem));
iHotOrder = hditem.iOrder;
CRect rectItem;
VERIFY(GetItemRect(iHotIndex, rectItem));
if(hdhti.pt.x > rectItem.CenterPoint().x)
iHotOrder++;
}
if(iHotOrder == m_iHotOrder || iHotOrder == m_iHotOrder+1)
iHotOrder = -1;
if(iHotOrder != m_iHotDivider)
{
m_iHotDivider = iHotOrder;
Invalidate();
}
}
return;
}
else if(GetStyle()&HDS_DRAGDROP)
{
INT iDragCX = GetSystemMetrics(SM_CXDRAG);
INT iDragCY = GetSystemMetrics(SM_CYDRAG);
CRect rectDrag(
m_ptClickPoint.x-iDragCX, m_ptClickPoint.y-iDragCY,
m_ptClickPoint.x+iDragCX, m_ptClickPoint.y+iDragCY
);
if(!rectDrag.PtInRect(point))
{
NMHEADER nmhdr;
nmhdr.hdr.hwndFrom = m_hWnd;
nmhdr.hdr.idFrom = GetDlgCtrlID();
nmhdr.hdr.code = HDN_BEGINDRAG;
nmhdr.iItem = m_iHotIndex;
nmhdr.iButton = 1;
nmhdr.pitem = &m_hditemHotItem;
BOOL bBeginDrag = TRUE;
CWnd* pWnd = GetParent();
if(pWnd != NULL)
bBeginDrag = pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmhdr)==FALSE ? TRUE:FALSE;
if(bBeginDrag)
{
ASSERT(m_pDragWnd == NULL);
m_pDragWnd = new CFHDragWnd;
if(m_pDragWnd)
{
CRect rectItem;
VERIFY(GetItemRect(m_iHotIndex, rectItem));
ClientToScreen(&rectItem);
m_pDragWnd->Create(rectItem, this, m_iHotIndex);
}
}
SetCapture();
m_bDragging = TRUE;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -