Blame | Last modification | View Log
////////////////////////////////////////////////////////////////////////////// File: CFlatHeaderCtrl.cpp// Version: 1.0.7//// Author: Maarten Hoeben// E-mail: hoeben@nwn.com//// Implementation of the CFlatHeaderCtrl and associated classes.//// This code may be used in compiled form in any way you desire. This// file may be redistributed unmodified by any means PROVIDING it is// not sold for profit without the authors written consent, and// providing that this notice and the authors name and all copyright// notices remains intact.//// An email letting me know how you are using it would be nice as well.//// This file is provided "as is" with no expressed or implied warranty.// The author accepts no liability for any damage/loss of business that// this product may cause.//// Version history//// 1.0.0 - Initial release// 1.0.1 - 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.// 1.0.2 - Fixed another destroy warning// - Fixed InsertItem array exception handling// - Fixed incorrect header width painting// - Changed DrawItem argument passing// - Changed HDITEMEX struct item names// - Added handler for HDM_SETIMAGELIST (precalculate image dimensions)// - Changed DrawImage to clip images// - Changed InsertItem ASSERT check to position limitation// - Added new-style "HotDivider" arrows// - Fixed some GDI objects// - Added 'don't drop cursor' support to indicate drag&drop// outside control// - Added drag&drop target window support// - Changed CFHDragWnd to support externally created items// - Removed topmost-style from CFHDropWnd// - Fixed OnSetHotDivider order bug// - Added extended styles// - Added item width estimation function// 1.0.3 - Added WM_CANCELMODE handler// 1.0.4 - Changed copyright message// - Added tooltip style// 1.0.5 - Added persistent style// - Added definitions for drop result// - Added height manipulation functions// 1.0.6 - Fixed bitmap drawing resource leak// - Added proper font handling.// 1.0.7 - Little changes to Min/Max implementation// - Fixed ghost drag problem related to button down on header// area outside valid items.// - Added Get/SetItemExStyle() functions.// - Added code for auto column sizing, enable through// FH_PROPERTY_ENABLEAUTOSIZE property.// - Added AutoSizeItems() function to force auto column resizing// programatically.//////////////////////////////////////////////////////////////////////////////// FlatHeaderCtrl.cpp : implementation file//#include "stdafx.h"#include "FlatHeaderCtrl.h"#include <afxpriv.h>#include "MemDC.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CFHDragWndCFHDragWnd::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 classwndclass.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();}m_pFlatHeaderCtrl = NULL;m_iItem = -1;m_lphdiItem = NULL;}CFHDragWnd::~CFHDragWnd(){}BEGIN_MESSAGE_MAP(CFHDragWnd, CWnd)//{{AFX_MSG_MAP(CFHDragWnd)ON_WM_PAINT()ON_WM_ERASEBKGND()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CFHDragWnd message handlersBOOL CFHDragWnd::Create(CRect rect, CFlatHeaderCtrl* pFlatHeaderCtrl, INT iItem, LPHDITEM lphdiItem){ASSERT_VALID(pFlatHeaderCtrl);ASSERT(pFlatHeaderCtrl->IsKindOf(RUNTIME_CLASS(CFlatHeaderCtrl)));m_pFlatHeaderCtrl = pFlatHeaderCtrl;m_iItem = iItem;m_lphdiItem = lphdiItem;DWORD dwStyle = WS_POPUP|WS_DISABLED;DWORD dwExStyle = WS_EX_TOOLWINDOW|WS_EX_TOPMOST;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_bDoubleBuffer){CMemDC MemDC(&dc);OnDraw(&MemDC);}elseOnDraw(&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_lphdiItem,m_pFlatHeaderCtrl->m_iSortColumn == m_iItem,m_pFlatHeaderCtrl->m_bSortAscending);pDC->SelectObject(pFont);pDC->SelectObject(pPen);}void CFHDragWnd::PostNcDestroy(){CWnd::PostNcDestroy();delete this;}/////////////////////////////////////////////////////////////////////////////// CFHDropWndCFHDropWnd::CFHDropWnd(COLORREF crColor){m_brush.CreateSolidBrush(crColor);// Register the window class if it has not already been registered.WNDCLASS wndclass;HINSTANCE hInst = AfxGetInstanceHandle();if(!(::GetClassInfo(hInst, FHDROPWND_CLASSNAME, &wndclass))){// otherwise we need to register a new classwndclass.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)m_brush;wndclass.lpszMenuName = NULL;wndclass.lpszClassName = FHDROPWND_CLASSNAME;if (!AfxRegisterClass(&wndclass))AfxThrowResourceException();}}CFHDropWnd::~CFHDropWnd(){}BEGIN_MESSAGE_MAP(CFHDropWnd, CWnd)//{{AFX_MSG_MAP(CFHDropWnd)ON_WM_ERASEBKGND()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CFHDropWnd message handlersBOOL CFHDropWnd::Create(INT iHeight){m_iHeight = iHeight + 20;DWORD dwStyle = WS_POPUP|WS_DISABLED;DWORD dwExStyle = WS_EX_TOOLWINDOW ;BOOL bResult = CreateEx(dwExStyle, FHDROPWND_CLASSNAME, NULL, dwStyle,0, 0, 12, m_iHeight,NULL, NULL, NULL );CRgn rgn1, rgn2;POINT ptArrow[7];ptArrow[0].x = 8; ptArrow[0].y = 0;ptArrow[1].x = 8; ptArrow[1].y = 4;ptArrow[2].x = 11; ptArrow[2].y = 4;ptArrow[3].x = 6; ptArrow[3].y = 9;ptArrow[4].x = 1; ptArrow[4].y = 4;ptArrow[5].x = 4; ptArrow[5].y = 4;ptArrow[6].x = 4; ptArrow[6].y = 0;rgn1.CreatePolygonRgn(ptArrow, 7, ALTERNATE);ptArrow[0].x = 4; ptArrow[0].y = m_iHeight;ptArrow[1].x = 4; ptArrow[1].y = m_iHeight-4;ptArrow[2].x = 0; ptArrow[2].y = m_iHeight-4;ptArrow[3].x = 6; ptArrow[3].y = m_iHeight-10;ptArrow[4].x = 12; ptArrow[4].y = m_iHeight-4;ptArrow[5].x = 8; ptArrow[5].y = m_iHeight-4;ptArrow[6].x = 8; ptArrow[6].y = m_iHeight;rgn2.CreatePolygonRgn(ptArrow, 7, ALTERNATE);m_rgn.CreateRectRgn(0, 0, 12, iHeight);m_rgn.CombineRgn(&rgn1, &rgn2, RGN_OR);SetWindowRgn(m_rgn, FALSE);rgn1.DeleteObject();rgn2.DeleteObject();return bResult;}void CFHDropWnd::PostNcDestroy(){m_rgn.DeleteObject();CWnd::PostNcDestroy();delete this;}BOOL CFHDropWnd::OnEraseBkgnd(CDC* pDC){pDC->FillRect(CRect(0, 0, 12, m_iHeight), &m_brush);return TRUE;}void CFHDropWnd::SetWindowPos(INT x, INT y){CWnd::SetWindowPos(&wndTop,x-6, y-(m_iHeight/2),0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE);}/////////////////////////////////////////////////////////////////////////////// CFlatHeaderCtrlIMPLEMENT_DYNCREATE(CFlatHeaderCtrl, CHeaderCtrl)CFlatHeaderCtrl::CFlatHeaderCtrl(){m_bDoubleBuffer = TRUE;m_iSpacing = 6;m_sizeArrow.cx = 8;m_sizeArrow.cy = 8;m_sizeImage.cx = 0;m_sizeImage.cy = 0;m_bStaticBorder = FALSE;m_nDontDropCursor = 0;m_hDropTarget = NULL;m_rcDropTarget.SetRectEmpty();m_iDropResult = FHDR_ONHEADER;m_iHotIndex = -1;m_bHotItemResizable = FALSE;m_bAutoSize = FALSE;m_bAutoSizing = FALSE;m_bResizing = FALSE;m_iResizingWidth = 0;m_iHotDivider = -1;m_crHotDivider = 0x000000FF;m_pDropWnd = NULL;m_bButtonDownOnItem = FALSE;m_bDragging = FALSE;m_pDragWnd = NULL;m_nClickFlags = 0;m_bSortAscending = FALSE;m_iSortColumn = -1;m_arrayHdrItemEx.SetSize(0, 8);m_iHeight = -1;m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);m_cr3DFace = ::GetSysColor(COLOR_3DFACE);m_crText = ::GetSysColor(COLOR_BTNTEXT);m_font.CreateStockObject(DEFAULT_GUI_FONT);}CFlatHeaderCtrl::~CFlatHeaderCtrl(){if(m_font.m_hObject)m_font.DeleteObject();if(m_pDropWnd != NULL){m_pDropWnd->DestroyWindow();m_pDropWnd = NULL;}if(m_pDragWnd != NULL){m_pDragWnd->DestroyWindow();m_pDragWnd = NULL;}}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_SETIMAGELIST, OnSetImageList)ON_MESSAGE(HDM_SETHOTDIVIDER, OnSetHotDivider)ON_MESSAGE(HDM_LAYOUT, OnLayout)ON_NOTIFY_EX(TTN_NEEDTEXTA, 0, OnToolTipNotify)ON_NOTIFY_EX(TTN_NEEDTEXTW, 0, OnToolTipNotify)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()ON_WM_CANCELMODE()//}}AFX_MSG_MAPON_MESSAGE(WM_SETFONT, OnSetFont)ON_MESSAGE(WM_GETFONT, OnGetFont)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CFlatHeaderCtrl attributesBOOL 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;case FH_PROPERTY_DONTDROPCURSOR:m_nDontDropCursor = (UINT)lParam;break;case FH_PROPERTY_DROPTARGET:m_hDropTarget = (HWND)lParam;break;case FH_PROPERTY_ENABLETOOLTIPS:EnableToolTips((BOOL)lParam);break;case FH_PROPERTY_ENABLEAUTOSIZE:m_bAutoSize = (BOOL)lParam;if(m_bAutoSize == TRUE)AutoSizeItems();break;default:return FALSE;}Invalidate();return TRUE;}BOOL CFlatHeaderCtrl::GetItemEx(INT iPos, HDITEMEX* phditemex) const{if(iPos >= m_arrayHdrItemEx.GetSize())return FALSE;HDITEM hditem;hditem.mask = HDI_WIDTH;VERIFY(GetItem(iPos, &hditem));HDITEMEX& hditemex = m_arrayHdrItemEx[iPos];phditemex->nStyle = hditemex.nStyle;phditemex->iMinWidth = hditemex.nStyle&HDF_EX_FIXEDWIDTH ? hditem.cxy:hditemex.iMinWidth;phditemex->iMaxWidth = hditemex.nStyle&HDF_EX_FIXEDWIDTH ? hditem.cxy:hditemex.iMaxWidth;phditemex->strToolTip = hditemex.strToolTip;return TRUE;}BOOL CFlatHeaderCtrl::SetItemEx(INT iPos, HDITEMEX* phditemex){if(iPos>=m_arrayHdrItemEx.GetSize())return FALSE;BOOL bUpdate = FALSE;HDITEM hditem;hditem.mask = HDI_WIDTH;if(!GetItem(iPos, &hditem))return FALSE;HDITEMEX hditemex = *phditemex;if(hditemex.nStyle&HDF_EX_AUTOWIDTH){TCHAR szText[FLATHEADER_TEXT_MAX];HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP;hdi.pszText = szText;hdi.cchTextMax = sizeof(szText);VERIFY(GetItem(iPos, &hdi));hditem.cxy = GetItemWidth(&hdi, hditemex.nStyle&HDF_EX_INCLUDESORT ? TRUE:FALSE);bUpdate = TRUE;}if(!(hditemex.nStyle&HDF_EX_FIXEDWIDTH)){if(hditem.cxy < hditemex.iMinWidth){hditem.cxy = hditemex.iMinWidth;bUpdate = TRUE;}if(hditem.cxy > hditemex.iMaxWidth && hditemex.iMaxWidth > 0){hditem.cxy = hditemex.iMaxWidth;bUpdate = TRUE;}}if(bUpdate)SetItem(iPos, &hditem);m_arrayHdrItemEx.SetAt(iPos, hditemex);return TRUE;}UINT CFlatHeaderCtrl::GetItemExStyle(INT iPos){ASSERT(iPos < m_arrayHdrItemEx.GetSize());return m_arrayHdrItemEx[iPos].nStyle;}BOOL CFlatHeaderCtrl::SetItemExStyle(INT iPos, UINT nStyle){if(iPos >= m_arrayHdrItemEx.GetSize())return FALSE;m_arrayHdrItemEx[iPos].nStyle = nStyle;return TRUE;}INT CFlatHeaderCtrl::GetItemWidth(LPHDITEM lphdi, BOOL bIncludeSort){INT iWidth = 0;CBitmap* pBitmap = NULL;BITMAP biBitmap;if(lphdi->fmt&HDF_BITMAP){ASSERT(lphdi->mask&HDI_BITMAP);ASSERT(lphdi->hbm);pBitmap = CBitmap::FromHandle(lphdi->hbm);if(pBitmap)VERIFY(pBitmap->GetObject(sizeof(BITMAP), &biBitmap));}iWidth += m_iSpacing;iWidth += lphdi->fmt&HDF_IMAGE ? m_sizeImage.cx+m_iSpacing:0;iWidth += lphdi->fmt&HDF_BITMAP ? biBitmap.bmWidth+m_iSpacing:0;iWidth += bIncludeSort ? m_sizeArrow.cx+m_iSpacing:0;if(lphdi->mask&HDI_TEXT && lphdi->fmt&HDF_STRING){CClientDC dc(this);CFont* pFont = dc.SelectObject(GetFont());iWidth += dc.GetTextExtent(lphdi->pszText).cx + m_iSpacing;dc.SelectObject(pFont);}return iWidth;}void CFlatHeaderCtrl::SetSortColumn(INT iPos, BOOL bSortAscending){ASSERT(iPos < GetItemCount());m_bSortAscending = bSortAscending;m_iSortColumn = iPos;Invalidate();}INT CFlatHeaderCtrl::GetSortColumn(BOOL* pbSortAscending){if(pbSortAscending)*pbSortAscending = m_bSortAscending;return m_iSortColumn;}INT CFlatHeaderCtrl::GetDropResult(){return m_iDropResult;}INT CFlatHeaderCtrl::GetHeight(){if(m_iHeight <= 0){CRect rect;GetWindowRect(rect);return rect.Height();}elsereturn m_iHeight;}void CFlatHeaderCtrl::SetHeight(INT iHeight){m_iHeight = iHeight;}BOOL CFlatHeaderCtrl::IsAutoSizing(){return m_bAutoSizing;}/////////////////////////////////////////////////////////////////////////////// CFlatHeaderCtrl operationsvoid CFlatHeaderCtrl::AutoSizeItems(){AutoSizeItemsImpl();}/////////////////////////////////////////////////////////////////////////////// CFlatHeaderCtrl implementation#define MAXWIDTH(x) (x>0 ? x:16384)typedef struct structFHAutoSize{INT iIndex;INT iWidth;INT iMinWidth;INT iMaxWidth;} FHAUTOSIZE, LPFHAUTOSIZE;void CFlatHeaderCtrl::AutoSizeItemsImpl(INT iItem){ASSERT(iItem >= -1);INT i, iItems = GetItemCount(), iTemp;INT iOrder = -1;if(iItems <= 0)return;HDITEM hditem;HDITEMEX hditemex;if(iItem >= 0){hditem.mask = HDI_ORDER;GetItem(iItem, &hditem);iOrder = hditem.iOrder;if(iOrder == iItems-1){iItem = -1;iOrder = -1;}}CArray<FHAUTOSIZE, FHAUTOSIZE&> arrayItems;arrayItems.SetSize(iItems);INT iWidth = 0;INT iMinWidth = 0;INT iMaxWidth = 0;for(i=iOrder+1; i<iItems; i++){INT iIndex = OrderToIndex(i);hditem.mask = HDI_WIDTH;VERIFY(GetItem(iIndex, &hditem));VERIFY(GetItemEx(iIndex, &hditemex));FHAUTOSIZE fhas;fhas.iIndex = iIndex;fhas.iWidth = hditem.cxy;fhas.iMinWidth = hditemex.iMinWidth;fhas.iMaxWidth = hditemex.iMaxWidth;arrayItems[i] = fhas;iWidth += fhas.iWidth;iMinWidth += fhas.iMinWidth;iMaxWidth += MAXWIDTH(fhas.iMaxWidth);}ASSERT(GetParent() != NULL);CRect rectClient;GetParent()->GetClientRect(rectClient);if(rectClient.Width() <= 0)return;INT iClientWidth = max(rectClient.Width(), iMinWidth);if(iItem >= 0){CRect rectItem;GetItemRect(iItem, rectItem);iClientWidth -= rectItem.right;}if(iOrder >= 0){FHAUTOSIZE& fhas = arrayItems[iOrder];iTemp = min(fhas.iWidth, iClientWidth - iMinWidth);iTemp = max(fhas.iMinWidth, iTemp);iTemp = min(MAXWIDTH(fhas.iMaxWidth), iTemp);arrayItems[iOrder].iWidth = iTemp;iWidth -= iTemp;iClientWidth -= iTemp;}iWidth = max(1, iWidth);INT iResult = 0;for(i=iOrder+1; i<iItems; i++){FHAUTOSIZE& fhas = arrayItems[i];iTemp = max(fhas.iMinWidth, (fhas.iWidth * iClientWidth)/iWidth);iTemp = min(MAXWIDTH(fhas.iMaxWidth), iTemp);arrayItems[i].iWidth = iTemp;iResult += iTemp;}if(iResult != iClientWidth){INT iLast = -1;i = iOrder+1;while(iResult != iClientWidth && iResult != iLast){FHAUTOSIZE& fhas = arrayItems[i];iTemp = fhas.iWidth;if(iResult < iClientWidth && iTemp < MAXWIDTH(fhas.iMaxWidth)){iTemp = min(iTemp+1, MAXWIDTH(fhas.iMaxWidth));iResult += iTemp - fhas.iWidth;}else if(iResult > iClientWidth && iTemp > fhas.iMinWidth){iTemp = max(iTemp-1, fhas.iMinWidth);iResult -= fhas.iWidth - iTemp;}iLast = iResult;arrayItems[i].iWidth = iTemp;i = i+1 < iItems ? i+1:iOrder+1;}}m_bAutoSizing = TRUE;for(i=iOrder+1; i<iItems; i++){hditem.mask = HDI_WIDTH;hditem.cxy = arrayItems[i].iWidth;VERIFY(SetItem(arrayItems[i].iIndex, &hditem));}m_bAutoSizing = FALSE;}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);}}iWidth += hditem.cxy;}if(iWidth > 0){rectClient.right = rectClient.left + iWidth;pDC->Draw3dRect(rectClient, m_cr3DHighLight, m_cr3DShadow);}pDC->SelectObject(pFont);pDC->SelectObject(pPen);penHighLight.DeleteObject();penShadow.DeleteObject();}void CFlatHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT){ASSERT(FALSE); // must override for self draw header controls}void CFlatHeaderCtrl::DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bSort, BOOL bSortAscending){ASSERT(lphdi->mask&HDI_FORMAT);INT iWidth = 0;CBitmap* pBitmap = NULL;BITMAP BitmapInfo;if(lphdi->fmt&HDF_BITMAP){ASSERT(lphdi->mask&HDI_BITMAP);ASSERT(lphdi->hbm);pBitmap = CBitmap::FromHandle(lphdi->hbm);if(pBitmap)VERIFY(pBitmap->GetObject(sizeof(BITMAP), &BitmapInfo));}switch(lphdi->fmt&HDF_JUSTIFYMASK){case HDF_LEFT:rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0;if(lphdi->fmt&HDF_IMAGE && !iWidth)break;rect.right -= bSort ? m_iSpacing+m_sizeArrow.cx : 0;rect.left += (iWidth = DrawText(pDC, rect, lphdi)) ? iWidth+m_iSpacing : 0;if(bSort){rect.right += m_iSpacing+m_sizeArrow.cx;rect.left += DrawArrow(pDC, rect, bSortAscending, FALSE)+m_iSpacing;}DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE);break;case HDF_CENTER:rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0;if(lphdi->fmt&HDF_IMAGE && !iWidth)break;rect.left += bSort ? m_iSpacing+m_sizeArrow.cx : 0;rect.right -= (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) ? iWidth+m_iSpacing:0;if(bSort){rect.left -= m_iSpacing+m_sizeArrow.cx;rect.right -= DrawArrow(pDC, rect, bSortAscending, TRUE)+2*m_iSpacing;}DrawText(pDC, rect, lphdi);break;case HDF_RIGHT:if(!(lphdi->fmt&HDF_BITMAP_ON_RIGHT))rect.left += (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, FALSE)) ? iWidth+m_iSpacing:0;rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0;if(lphdi->fmt&HDF_IMAGE && !iWidth)break;rect.left += bSort && (lphdi->fmt&HDF_BITMAP_ON_RIGHT) ? m_iSpacing+m_sizeArrow.cx : 0;if(lphdi->fmt&HDF_BITMAP_ON_RIGHT)rect.right -= (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) ? iWidth+m_iSpacing:0;if(bSort){rect.left -= (lphdi->fmt&HDF_BITMAP_ON_RIGHT) ? m_iSpacing+m_sizeArrow.cx:0;rect.right -= DrawArrow(pDC, rect, bSortAscending, TRUE)+2*m_iSpacing;}DrawText(pDC, rect, lphdi);break;}}INT CFlatHeaderCtrl::DrawImage(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bRight){CImageList* pImageList = GetImageList();INT iWidth = 0;if(lphdi->mask&HDI_IMAGE && lphdi->fmt&HDF_IMAGE){ASSERT(pImageList);ASSERT(lphdi->iImage>=0 && lphdi->iImage<pImageList->GetImageCount());if(rect.Width()>0){POINT point;point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1);if(bRight)point.x = rect.right - m_sizeImage.cx;elsepoint.x = rect.left;SIZE size;size.cx = rect.Width()<m_sizeImage.cx ? rect.Width():m_sizeImage.cx;size.cy = m_sizeImage.cy;pImageList->DrawIndirect(pDC, lphdi->iImage, point, size, CPoint(0, 0));iWidth = m_sizeImage.cx;}}return iWidth;}INT CFlatHeaderCtrl::DrawBitmap(CDC* pDC, CRect rect, LPHDITEM lphdi, 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;elsepoint.x = rect.left;CDC dc;if(dc.CreateCompatibleDC(pDC) == TRUE){CBitmap* pBitmapDC = (CBitmap*)dc.SelectObject(pBitmap);ASSERT(pBitmapDC);iWidth = pDC->BitBlt(point.x, point.y,pBitmapInfo->bmWidth, pBitmapInfo->bmHeight,&dc, 0, 0, SRCCOPY) ? iWidth:0;dc.SelectObject(pBitmapDC);}elseiWidth = 0;}elseiWidth = 0;}return iWidth;}INT CFlatHeaderCtrl::DrawText(CDC* pDC, CRect rect, LPHDITEM lphdi){CSize size;if(rect.Width()>0 && lphdi->mask&HDI_TEXT && lphdi->fmt&HDF_STRING){size = pDC->GetTextExtent(lphdi->pszText);switch(lphdi->fmt&HDF_JUSTIFYMASK){case HDF_LEFT:case HDF_LEFT|HDF_RTLREADING:pDC->DrawText(lphdi->pszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);break;case HDF_CENTER:case HDF_CENTER|HDF_RTLREADING:pDC->DrawText(lphdi->pszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);break;case HDF_RIGHT:case HDF_RIGHT|HDF_RTLREADING:pDC->DrawText(lphdi->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 triangleCPen penLight(PS_SOLID, 1, m_cr3DHighLight);CPen penShadow(PS_SOLID, 1, m_cr3DShadow);CPen *pPen = pDC->SelectObject(&penLight);if(bSortAscending){// Draw triangle pointing upwardspDC->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 downwardspDC->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 penpDC->SelectObject(pPen);penLight.DeleteObject();penShadow.DeleteObject();}return iWidth;}INT CFlatHeaderCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const{INT iResult = CHeaderCtrl::OnToolHitTest(point, pTI);if(iResult != -1)return iResult;HDHITTESTINFO hdhti;hdhti.pt = point;iResult = ::SendMessage(GetSafeHwnd(), HDM_HITTEST, 0, (LPARAM)(&hdhti));if(iResult > -1){GetItemRect(iResult, &pTI->rect);pTI->cbSize = sizeof(TOOLINFO);pTI->hwnd = GetSafeHwnd();pTI->uFlags = TTF_ALWAYSTIP;pTI->lpszText = LPSTR_TEXTCALLBACK;pTI->uId = FLATHEADER_TT_MAGIC;}return iResult;}/////////////////////////////////////////////////////////////////////////////// CHeaderCtrl message handlersLRESULT CFlatHeaderCtrl::OnInsertItem(WPARAM wParam, LPARAM lParam){HDITEMEX hditemex;hditemex.iMinWidth = 0;hditemex.iMaxWidth = 0;LRESULT lResult = -1;WORD wItems = m_arrayHdrItemEx.GetSize();wParam = wParam<=wItems ? wParam:wItems;try{m_arrayHdrItemEx.InsertAt(wParam, hditemex);lResult = Default();if(lResult < 0) // Cleanupm_arrayHdrItemEx.RemoveAt(wParam);}catch(CMemoryException* e){e->Delete();}return lResult;}LRESULT CFlatHeaderCtrl::OnDeleteItem(WPARAM wParam, LPARAM lParam){ASSERT((INT)wParam < m_arrayHdrItemEx.GetSize());m_arrayHdrItemEx.RemoveAt(wParam);return Default();}LRESULT CFlatHeaderCtrl::OnSetImageList(WPARAM wParam, LPARAM lParam){CImageList* pImageList;pImageList = CImageList::FromHandle((HIMAGELIST)lParam);IMAGEINFO info;if(pImageList->GetImageInfo(0, &info)){m_sizeImage.cx = info.rcImage.right - info.rcImage.left;m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;}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);INT iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti));if(iHotIndex >= 0){HDITEM hditem;hditem.mask = HDI_ORDER;VERIFY(GetItem(iHotIndex, &hditem));m_iHotDivider = hditem.iOrder;CRect rectItem;VERIFY(GetItemRect(iHotIndex, rectItem));if(hdhti.pt.x > rectItem.CenterPoint().x)m_iHotDivider++;}elsem_iHotDivider = -1;}elsem_iHotDivider = (INT)lParam;RECT rect;GetClientRect(&rect);INT iItems = GetItemCount();if(m_iHotDivider >= 0 && m_iHotDivider<=iItems+1){if(m_pDropWnd == NULL){m_pDropWnd = new CFHDropWnd(m_crHotDivider);if(m_pDropWnd)m_pDropWnd->Create(rect.bottom - rect.top);}if(m_pDropWnd != NULL){POINT pt;pt.y = (rect.bottom-rect.top)/2;if(m_iHotDivider<iItems){GetItemRect(OrderToIndex(m_iHotDivider), &rect);pt.x = rect.left - 1;}else{GetItemRect(OrderToIndex(iItems-1), &rect);pt.x = rect.right;}ClientToScreen(&pt);m_pDropWnd->SetWindowPos(pt.x, pt.y);}}else{if(m_pDropWnd != NULL){m_pDropWnd->DestroyWindow();m_pDropWnd = NULL;}}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;LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);if(m_iHeight > 0)lphdlayout->pwpos->cy = m_iHeight;if(m_bAutoSize && !m_bResizing)AutoSizeItemsImpl();return lResult;}BOOL CFlatHeaderCtrl::OnToolTipNotify(UINT nId, NMHDR *pNMHDR, LRESULT *pResult){TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;if(pNMHDR->idFrom == (UINT)FLATHEADER_TT_MAGIC &&!m_arrayHdrItemEx[m_iHotIndex].strToolTip.IsEmpty()) {USES_CONVERSION;wcscpy((WCHAR*)pTTT->lpszText, A2W((LPCTSTR)m_arrayHdrItemEx[m_iHotIndex].strToolTip));pTTT->lpszText = pTTT->szText;return TRUE;}elsereturn FALSE;}/////////////////////////////////////////////////////////////////////////////// CFlatHeaderCtrl message handlersvoid CFlatHeaderCtrl::OnSysColorChange(){CHeaderCtrl::OnSysColorChange();m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);m_cr3DFace = ::GetSysColor(COLOR_3DFACE);m_crText = ::GetSysColor(COLOR_BTNTEXT);}LRESULT CFlatHeaderCtrl::OnGetFont(WPARAM wParam, LPARAM lParam){return (LRESULT)m_font.m_hObject;}LRESULT CFlatHeaderCtrl::OnSetFont(WPARAM wParam, LPARAM lParam){LRESULT lResult = Default();CFont *pFont = CFont::FromHandle((HFONT)wParam);if(pFont){LOGFONT lf;pFont->GetLogFont(&lf);m_font.DeleteObject();m_font.CreateFontIndirect(&lf);}return lResult;}BOOL CFlatHeaderCtrl::OnEraseBkgnd(CDC* pDC){return TRUE;}void CFlatHeaderCtrl::OnPaint(){CPaintDC dc(this);if (m_bDoubleBuffer){CMemDC MemDC(&dc);DrawCtrl(&MemDC);}elseDrawCtrl(&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.nStyle&HDF_EX_FIXEDWIDTH ? FALSE:TRUE;}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_hdiHotItem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP|HDI_ORDER|HDI_LPARAM;m_hdiHotItem.pszText = m_szHotItemText;m_hdiHotItem.cchTextMax = sizeof(m_szHotItemText);VERIFY(GetItem(m_iHotIndex, &m_hdiHotItem));VERIFY(GetItemEx(m_iHotIndex, &m_hdieHotItem));if(m_hdhtiHotItem.flags&HHT_ONHEADER){RECT rectItem;VERIFY(GetItemRect(m_iHotIndex, &rectItem));InvalidateRect(&rectItem);m_bButtonDownOnItem = TRUE;}if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN)){if(!m_bHotItemResizable)return;m_bButtonDownOnItem = TRUE;HDITEMEX hditemex;VERIFY(GetItemEx(m_iHotIndex, &hditemex));CRect rectItem;GetItemRect(m_iHotIndex, rectItem);INT iMinWidth = hditemex.iMinWidth;INT iMaxWidth = hditemex.iMaxWidth;if(m_bAutoSize == TRUE){HDITEM hditem;INT iItems = GetItemCount();if(m_iHotOrder < iItems-1){INT i, iMin = 0, iMax = 0;m_iResizingWidth = 0;for(i=m_iHotOrder+1; i<iItems; i++){INT iIndex = OrderToIndex(i);hditem.mask = HDI_WIDTH;VERIFY(GetItem(iIndex, &hditem));VERIFY(GetItemEx(iIndex, &hditemex));m_iResizingWidth += hditem.cxy;m_arrayResizing.SetAtGrow(i, hditem.cxy);iMin += hditemex.iMinWidth;iMax += MAXWIDTH(hditemex.iMaxWidth);}CRect rectClient;GetClientRect(rectClient);i = iMax;iMax = rectClient.right+1 - iMin;iMin = rectClient.right+1 - i;iMaxWidth = min(MAXWIDTH(iMaxWidth), iMax - rectItem.left);iMinWidth = max(iMinWidth, iMin - rectItem.left);}}ClientToScreen(rectItem);if(iMinWidth > 0 || iMaxWidth > 0){CRect rectClip;GetClipCursor(rectClip);POINT point;GetCursorPos(&point);INT iOffset = point.x - rectItem.right;rectClip.left = rectItem.left + iMinWidth + iOffset;rectClip.right = rectItem.left + MAXWIDTH(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;m_bButtonDownOnItem = FALSE;if(m_iHotIndex >= 0){CWnd* pWnd = GetParent();ASSERT(pWnd != NULL);if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN)){if(m_bResizing)ClipCursor(NULL);}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_hdiHotItem;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];elsepiArray[iCount+i] = piArray[j++];}SetOrderArray(iCount, (LPINT)&piArray[iCount]);delete piArray;}elseAfxThrowMemoryException();}if(m_pDragWnd != NULL){m_pDragWnd->DestroyWindow();m_pDragWnd = NULL;}if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())ReleaseCapture();m_bDragging = FALSE;OnSetHotDivider(FALSE, -1);Invalidate();}else{RECT rectItem;VERIFY(GetItemRect(m_iHotIndex, &rectItem));InvalidateRect(&rectItem);}}}CHeaderCtrl::OnLButtonUp(nFlags, point);if(m_bResizing && m_bAutoSize)AutoSizeItemsImpl(m_iHotIndex);m_bResizing = FALSE;}void CFlatHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point){if(m_bButtonDownOnItem && 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++;SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));m_iDropResult = FHDR_ONHEADER;}else{pt = point;ClientToScreen(&pt);if(m_hdieHotItem.nStyle&HDF_EX_PERSISTENT){SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));m_iDropResult = FHDR_PERSISTENT;}else{if(!(m_hDropTarget && m_rcDropTarget.PtInRect(pt))){if(m_nDontDropCursor)SetCursor(AfxGetApp()->LoadCursor(m_nDontDropCursor));elseSetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));m_iDropResult = FHDR_DROPPED;}else{SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));m_iDropResult = FHDR_ONTARGET;}}}if(iHotOrder == m_iHotOrder || iHotOrder == m_iHotOrder+1)iHotOrder = -1;if(iHotOrder != m_iHotDivider)OnSetHotDivider(FALSE, iHotOrder);}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_hdiHotItem;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, &m_hdiHotItem);}BOOL bVisible = FALSE;if(m_hDropTarget != NULL){bVisible = ::GetWindowLong(m_hDropTarget, GWL_STYLE)&WS_VISIBLE ? TRUE:FALSE;HWND hParent = ::GetParent(m_hDropTarget);if(hParent)bVisible = ::GetWindowLong(hParent, GWL_STYLE)&WS_VISIBLE ? TRUE:FALSE;}if(m_hDropTarget != NULL && bVisible)VERIFY(::GetWindowRect(m_hDropTarget, m_rcDropTarget));elsem_rcDropTarget.SetRectEmpty();}SetCapture();m_bDragging = TRUE;}}}}}void CFlatHeaderCtrl::OnCancelMode(){CWnd::OnCancelMode();if(m_bDragging){m_nClickFlags = 0;if(m_pDragWnd != NULL){m_pDragWnd->DestroyWindow();m_pDragWnd = NULL;}if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())ReleaseCapture();m_bDragging = FALSE;OnSetHotDivider(FALSE, -1);Invalidate();}}