FlatHeaderCtrl.cpp
上传用户:wpp2016
上传日期:2010-02-01
资源大小:1250k
文件大小:32k
源码类别:

Telnet服务器

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////////
  2. // File: CFlatHeaderCtrl.cpp
  3. // Version: 1.0.2.0
  4. //
  5. // Author: Maarten Hoeben
  6. // E-mail: hoeben@nwn.com
  7. //
  8. // Implementation of the CFlatHeaderCtrl and associated classes.
  9. //
  10. // You are free to use, distribute or modify this code
  11. // as long as the header is not removed or modified.
  12. //
  13. // Version history
  14. //
  15. // 1.0.0.1 - Initial release
  16. // 1.0.1.0 - Fixed FHDragWnd destroy warning (thanks Philippe Terrier)
  17. // - Fixed double sent HDN_ITEMCLICK
  18. // - Added a property that adjusts for ListCtrls that use a static
  19. //   border for flat look.
  20. // 1.0.2.0 - Fixed another destroy warning
  21. // - Fixed InsertItem array exception handling
  22. // - Fixed incorrect header width painting
  23. // - Changed DrawItem argument passing
  24. // - Changed HDITEMEX struct item names
  25. // - Added handler for HDM_SETIMAGELIST (precalculate image dimensions)
  26. // - Changed DrawImage to clip images
  27. // - Changed InsertItem ASSERT check to position limitation
  28. // - Added new-style "HotDivider" arrows
  29. // - Fixed some GDI objects
  30. // - Added 'don't drop cursor' support to indicate drag&drop 
  31. //   outside control
  32. // - Added drag&drop target window support
  33. // - Changed CFHDragWnd to support externally created items
  34. // - Removed topmost-style from CFHDropWnd
  35. // - Fixed OnSetHotDivider order bug
  36. // - Added extended styles
  37. // - Added item width estimation function
  38. //
  39. ////////////////////////////////////////////////////////////////////////////
  40. // FlatHeaderCtrl.cpp : implementation file
  41. //
  42. #include "stdafx.h"
  43. #include "FlatHeaderCtrl.h"
  44. #ifdef _DEBUG
  45. #define new DEBUG_NEW
  46. #undef THIS_FILE
  47. static char THIS_FILE[] = __FILE__;
  48. #endif
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CFHDragWnd
  51. CFHDragWnd::CFHDragWnd()
  52. {
  53. // Register the window class if it has not already been registered.
  54. WNDCLASS wndclass;
  55. HINSTANCE hInst = AfxGetInstanceHandle();
  56. if(!(::GetClassInfo(hInst, FHDRAGWND_CLASSNAME, &wndclass)))
  57. {
  58. // otherwise we need to register a new class
  59. wndclass.style = CS_SAVEBITS ;
  60. wndclass.lpfnWndProc = ::DefWindowProc;
  61. wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
  62. wndclass.hInstance = hInst;
  63. wndclass.hIcon = NULL;
  64. wndclass.hCursor = LoadCursor( hInst, IDC_ARROW);
  65. wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); 
  66. wndclass.lpszMenuName = NULL;
  67. wndclass.lpszClassName = FHDRAGWND_CLASSNAME;
  68. if (!AfxRegisterClass(&wndclass))
  69. AfxThrowResourceException();
  70. }
  71. m_pFlatHeaderCtrl = NULL;
  72. m_iItem = -1;
  73. m_lphdiItem = NULL;
  74. }
  75. CFHDragWnd::~CFHDragWnd()
  76. {
  77. }
  78. BEGIN_MESSAGE_MAP(CFHDragWnd, CWnd)
  79. //{{AFX_MSG_MAP(CFHDragWnd)
  80. ON_WM_PAINT()
  81. ON_WM_ERASEBKGND()
  82. //}}AFX_MSG_MAP
  83. END_MESSAGE_MAP()
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CFHDragWnd message handlers
  86. BOOL CFHDragWnd::Create(CRect rect, CFlatHeaderCtrl* pFlatHeaderCtrl, INT iItem, LPHDITEM lphdiItem)
  87. {
  88. ASSERT_VALID(pFlatHeaderCtrl);
  89. ASSERT(pFlatHeaderCtrl->IsKindOf(RUNTIME_CLASS(CFlatHeaderCtrl)));
  90. m_pFlatHeaderCtrl = pFlatHeaderCtrl;
  91. m_iItem = iItem;
  92. m_lphdiItem = lphdiItem;
  93. DWORD dwStyle = WS_POPUP|WS_DISABLED;
  94. DWORD dwExStyle = WS_EX_TOOLWINDOW|WS_EX_TOPMOST;
  95. return CreateEx(dwExStyle, FHDRAGWND_CLASSNAME, NULL, dwStyle, 
  96. rect.left, rect.top, rect.Width(), rect.Height(),
  97. NULL, NULL, NULL );
  98. }
  99. void CFHDragWnd::OnPaint() 
  100. {
  101. CPaintDC dc(this);
  102.     if(m_pFlatHeaderCtrl->m_bDoubleBuffer)
  103.     {
  104.         CMemDC MemDC(&dc);
  105.         OnDraw(&MemDC);
  106.     }
  107.     else
  108.         OnDraw(&dc);
  109. }
  110. BOOL CFHDragWnd::OnEraseBkgnd(CDC* pDC) 
  111. {
  112. return TRUE;
  113. }
  114. void CFHDragWnd::OnDraw(CDC* pDC)
  115. {
  116. CRect rect;
  117. GetClientRect(rect);
  118.     pDC->FillSolidRect(rect, m_pFlatHeaderCtrl->m_cr3DFace);
  119. pDC->Draw3dRect(rect, m_pFlatHeaderCtrl->m_cr3DHighLight, m_pFlatHeaderCtrl->m_cr3DShadow);
  120. CPen* pPen = pDC->GetCurrentPen();
  121. CFont* pFont = pDC->SelectObject(m_pFlatHeaderCtrl->GetFont());
  122. pDC->SetBkColor(m_pFlatHeaderCtrl->m_cr3DFace);
  123. pDC->SetTextColor(m_pFlatHeaderCtrl->m_crText);
  124. rect.DeflateRect(m_pFlatHeaderCtrl->m_iSpacing, 0);
  125. m_pFlatHeaderCtrl->DrawItem(
  126. pDC,
  127. rect,
  128. m_lphdiItem,
  129. m_pFlatHeaderCtrl->m_iSortColumn == m_iItem,
  130. m_pFlatHeaderCtrl->m_bSortAscending
  131. );
  132. pDC->SelectObject(pFont);
  133. pDC->SelectObject(pPen);
  134. }
  135. void CFHDragWnd::PostNcDestroy() 
  136. {
  137. CWnd::PostNcDestroy();
  138. delete this;
  139. }
  140. /////////////////////////////////////////////////////////////////////////////
  141. // CFHDropWnd
  142. CFHDropWnd::CFHDropWnd(COLORREF crColor)
  143. {
  144. m_brush.CreateSolidBrush(crColor);
  145. // Register the window class if it has not already been registered.
  146. WNDCLASS wndclass;
  147. HINSTANCE hInst = AfxGetInstanceHandle();
  148. if(!(::GetClassInfo(hInst, FHDROPWND_CLASSNAME, &wndclass)))
  149. {
  150. // otherwise we need to register a new class
  151. wndclass.style = CS_SAVEBITS ;
  152. wndclass.lpfnWndProc = ::DefWindowProc;
  153. wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
  154. wndclass.hInstance = hInst;
  155. wndclass.hIcon = NULL;
  156. wndclass.hCursor = LoadCursor( hInst, IDC_ARROW );
  157. wndclass.hbrBackground = (HBRUSH)m_brush; 
  158. wndclass.lpszMenuName = NULL;
  159. wndclass.lpszClassName = FHDROPWND_CLASSNAME;
  160. if (!AfxRegisterClass(&wndclass))
  161. AfxThrowResourceException();
  162. }
  163. }
  164. CFHDropWnd::~CFHDropWnd()
  165. {
  166. }
  167. BEGIN_MESSAGE_MAP(CFHDropWnd, CWnd)
  168. //{{AFX_MSG_MAP(CFHDropWnd)
  169. ON_WM_ERASEBKGND()
  170. //}}AFX_MSG_MAP
  171. END_MESSAGE_MAP()
  172. /////////////////////////////////////////////////////////////////////////////
  173. // CFHDropWnd message handlers
  174. BOOL CFHDropWnd::Create(INT iHeight)
  175. {
  176. m_iHeight = iHeight + 20;
  177. DWORD dwStyle = WS_POPUP|WS_DISABLED;
  178. DWORD dwExStyle = WS_EX_TOOLWINDOW ;
  179. BOOL bResult = CreateEx(dwExStyle, FHDROPWND_CLASSNAME, NULL, dwStyle, 
  180. 0, 0, 12, m_iHeight,
  181. NULL, NULL, NULL );
  182. CRgn rgn1, rgn2;
  183. POINT ptArrow[7];
  184. ptArrow[0].x = 8; ptArrow[0].y = 0;
  185. ptArrow[1].x = 8; ptArrow[1].y = 4;
  186. ptArrow[2].x = 11; ptArrow[2].y = 4;
  187. ptArrow[3].x = 6; ptArrow[3].y = 9;
  188. ptArrow[4].x = 1; ptArrow[4].y = 4;
  189. ptArrow[5].x = 4; ptArrow[5].y = 4;
  190. ptArrow[6].x = 4; ptArrow[6].y = 0;
  191. rgn1.CreatePolygonRgn(ptArrow, 7, ALTERNATE);
  192. ptArrow[0].x = 4; ptArrow[0].y = m_iHeight;
  193. ptArrow[1].x = 4; ptArrow[1].y = m_iHeight-4;
  194. ptArrow[2].x = 0; ptArrow[2].y = m_iHeight-4;
  195. ptArrow[3].x = 6; ptArrow[3].y = m_iHeight-10;
  196. ptArrow[4].x = 12; ptArrow[4].y = m_iHeight-4;
  197. ptArrow[5].x = 8; ptArrow[5].y = m_iHeight-4;
  198. ptArrow[6].x = 8; ptArrow[6].y = m_iHeight;
  199. rgn2.CreatePolygonRgn(ptArrow, 7, ALTERNATE);
  200. m_rgn.CreateRectRgn(0, 0, 12, iHeight);
  201. m_rgn.CombineRgn(&rgn1, &rgn2, RGN_OR);
  202. SetWindowRgn(m_rgn, FALSE);
  203. rgn1.DeleteObject();
  204. rgn2.DeleteObject();
  205. return bResult;
  206. }
  207. void CFHDropWnd::PostNcDestroy() 
  208. {
  209. m_rgn.DeleteObject();
  210. CWnd::PostNcDestroy();
  211. delete this;
  212. }
  213. BOOL CFHDropWnd::OnEraseBkgnd(CDC* pDC) 
  214. {
  215. pDC->FillRect(CRect(0, 0, 12, m_iHeight), &m_brush);
  216. return TRUE;
  217. }
  218. void CFHDropWnd::SetWindowPos(INT x, INT y)
  219. {
  220. CWnd::SetWindowPos(
  221. &wndTop, 
  222. x-6, y-(m_iHeight/2),
  223. 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE
  224. );
  225. }
  226. /////////////////////////////////////////////////////////////////////////////
  227. // CFlatHeaderCtrl
  228. IMPLEMENT_DYNCREATE(CFlatHeaderCtrl, CHeaderCtrl)
  229. CFlatHeaderCtrl::CFlatHeaderCtrl()
  230. {
  231. m_bDoubleBuffer = TRUE;
  232. m_iSpacing = 6;
  233. m_sizeArrow.cx = 8;
  234. m_sizeArrow.cy = 8;
  235. m_sizeImage.cx = 0;
  236. m_sizeImage.cy = 0;
  237. m_bStaticBorder = FALSE;
  238. m_nDontDropCursor = 0;
  239. m_hDropTarget = NULL;
  240. m_rcDropTarget.SetRectEmpty();
  241. m_iDropResult = 0;
  242. m_iHotIndex = -1;
  243. m_bHotItemResizable = FALSE;
  244. m_bResizing = FALSE;
  245. m_iHotDivider = -1;
  246. m_crHotDivider = 0x000000FF;
  247. m_pDropWnd = NULL;
  248. m_bDragging = FALSE;
  249. m_pDragWnd = NULL;
  250. m_nClickFlags = 0;
  251. m_bSortAscending = FALSE;
  252. m_iSortColumn = -1;
  253. m_arrayHdrItemEx.SetSize(0, 8);
  254. m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
  255. m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);
  256. m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
  257. m_crText = ::GetSysColor(COLOR_BTNTEXT);
  258. }
  259. CFlatHeaderCtrl::~CFlatHeaderCtrl()
  260. {
  261. if(m_pDropWnd != NULL)
  262. {
  263. m_pDropWnd->DestroyWindow();
  264. m_pDropWnd = NULL;
  265. }
  266. if(m_pDragWnd != NULL)
  267. {
  268. m_pDragWnd->DestroyWindow();
  269. m_pDragWnd = NULL;
  270. }
  271. }
  272. BEGIN_MESSAGE_MAP(CFlatHeaderCtrl, CHeaderCtrl)
  273. //{{AFX_MSG_MAP(CFlatHeaderCtrl)
  274. ON_MESSAGE(HDM_INSERTITEMA, OnInsertItem)
  275. ON_MESSAGE(HDM_INSERTITEMW, OnInsertItem)
  276. ON_MESSAGE(HDM_DELETEITEM, OnDeleteItem)
  277. ON_MESSAGE(HDM_SETIMAGELIST, OnSetImageList)
  278. ON_MESSAGE(HDM_SETHOTDIVIDER, OnSetHotDivider)
  279. ON_MESSAGE(HDM_LAYOUT, OnLayout)
  280. ON_WM_NCHITTEST()
  281. ON_WM_SETCURSOR()
  282. ON_WM_LBUTTONDOWN()
  283. ON_WM_LBUTTONDBLCLK()
  284. ON_WM_PAINT()
  285. ON_WM_SYSCOLORCHANGE()
  286. ON_WM_ERASEBKGND()
  287. ON_WM_LBUTTONUP()
  288. ON_WM_MOUSEMOVE()
  289. //}}AFX_MSG_MAP
  290. END_MESSAGE_MAP()
  291. /////////////////////////////////////////////////////////////////////////////
  292. // CFlatHeaderCtrl attributes
  293. BOOL CFlatHeaderCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam)
  294. {
  295. switch(wParam)
  296. {
  297. case FH_PROPERTY_SPACING:
  298. m_iSpacing = (INT)lParam;
  299. break;
  300. case FH_PROPERTY_ARROW:
  301. m_sizeArrow.cx = LOWORD(lParam);
  302. m_sizeArrow.cy = HIWORD(lParam);
  303. break;
  304. case FH_PROPERTY_STATICBORDER:
  305. m_bStaticBorder = (BOOL)lParam;
  306. break;
  307. case FH_PROPERTY_DONTDROPCURSOR:
  308. m_nDontDropCursor = (UINT)lParam;
  309. break;
  310. case FH_PROPERTY_DROPTARGET:
  311. m_hDropTarget = (HWND)lParam;
  312. break;
  313. default:
  314. return FALSE;
  315. }
  316. Invalidate();
  317. return TRUE;
  318. }
  319. BOOL CFlatHeaderCtrl::GetItemEx(INT iPos, HDITEMEX* phditemex) const
  320. {
  321. if(iPos>=m_arrayHdrItemEx.GetSize())
  322. return FALSE;
  323. *phditemex = m_arrayHdrItemEx[iPos];
  324. return TRUE;
  325. }
  326. BOOL CFlatHeaderCtrl::SetItemEx(INT iPos, HDITEMEX* phditemex)
  327. {
  328. if(iPos>=m_arrayHdrItemEx.GetSize())
  329. return FALSE;
  330. BOOL bUpdate = FALSE;
  331. HDITEM hditem;
  332. hditem.mask = HDI_WIDTH;
  333. if(!GetItem(iPos, &hditem))
  334. return FALSE;
  335. HDITEMEX hditemex = *phditemex;
  336. if(hditemex.nStyle&HDF_EX_AUTOWIDTH)
  337. {
  338. TCHAR szText[FLATHEADER_TEXT_MAX];
  339. HDITEM hdi;
  340. hdi.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP;
  341. hdi.pszText = szText;
  342. hdi.cchTextMax = sizeof(szText);
  343. VERIFY(GetItem(iPos, &hdi));
  344. hditem.cxy = GetItemWidth(&hdi, hditemex.nStyle&HDF_EX_INCLUDESORT ? TRUE:FALSE);
  345. bUpdate = TRUE;
  346. }
  347. if((!(hditemex.nStyle&HDF_EX_FIXEDWIDTH)) && (hditemex.iMinWidth<=hditemex.iMaxWidth))
  348. {
  349. if(hditem.cxy < hditemex.iMinWidth)
  350. {
  351. hditem.cxy = hditemex.iMinWidth;
  352. bUpdate = TRUE;
  353. }
  354. if(hditem.cxy > hditemex.iMaxWidth)
  355. {
  356. hditem.cxy = hditemex.iMaxWidth;
  357. bUpdate = TRUE;
  358. }
  359. }
  360. if(bUpdate)
  361. SetItem(iPos, &hditem);
  362. m_arrayHdrItemEx.SetAt(iPos, hditemex);
  363. return TRUE;
  364. }
  365. INT CFlatHeaderCtrl::GetItemWidth(LPHDITEM lphdi, BOOL bIncludeSort)
  366. {
  367. INT iWidth = 0;
  368. CBitmap* pBitmap = NULL;
  369. BITMAP biBitmap;
  370. if(lphdi->fmt&HDF_BITMAP)
  371. {
  372. ASSERT(lphdi->mask&HDI_BITMAP);
  373. ASSERT(lphdi->hbm);
  374. pBitmap = CBitmap::FromHandle(lphdi->hbm);
  375. if(pBitmap)
  376. VERIFY(pBitmap->GetObject(sizeof(BITMAP), &biBitmap));
  377. }
  378. iWidth += m_iSpacing;
  379. iWidth += lphdi->fmt&HDF_IMAGE ? m_sizeImage.cx+m_iSpacing:0;
  380. iWidth += lphdi->fmt&HDF_BITMAP ? biBitmap.bmWidth+m_iSpacing:0;
  381. iWidth += bIncludeSort ? m_sizeArrow.cx+m_iSpacing:0;
  382. if(lphdi->mask&HDI_TEXT && lphdi->fmt&HDF_STRING)
  383. {
  384. CClientDC dc(this);
  385. CFont* pFont = dc.SelectObject(GetFont());
  386. iWidth += dc.GetTextExtent(lphdi->pszText).cx + m_iSpacing;
  387. dc.SelectObject(pFont);
  388. }
  389. return iWidth;
  390. }
  391. void CFlatHeaderCtrl::SetSortColumn(INT iPos, BOOL bSortAscending)
  392. {
  393. ASSERT(iPos < GetItemCount());
  394. m_bSortAscending = bSortAscending;
  395. m_iSortColumn = iPos;
  396. Invalidate();
  397. }
  398. INT CFlatHeaderCtrl::GetSortColumn(BOOL* pbSortAscending)
  399. {
  400. if(pbSortAscending)
  401. *pbSortAscending = m_bSortAscending;
  402. return m_iSortColumn;
  403. }
  404. INT CFlatHeaderCtrl::GetDropResult()
  405. {
  406. return m_iDropResult;
  407. }
  408. /////////////////////////////////////////////////////////////////////////////
  409. // CFlatHeaderCtrl implementation
  410. void CFlatHeaderCtrl::DrawCtrl(CDC* pDC)
  411. {
  412. CRect rectClip;
  413. if (pDC->GetClipBox(&rectClip) == ERROR)
  414. return;
  415. CRect rectClient, rectItem;
  416. GetClientRect(&rectClient);
  417.     pDC->FillSolidRect(rectClip, m_cr3DFace);
  418. INT iItems = GetItemCount();
  419. ASSERT(iItems >= 0);
  420. CPen penHighLight(PS_SOLID, 1, m_cr3DHighLight);
  421. CPen penShadow(PS_SOLID, 1, m_cr3DShadow);
  422. CPen* pPen = pDC->GetCurrentPen();
  423. CFont* pFont = pDC->SelectObject(GetFont());
  424. pDC->SetBkColor(m_cr3DFace);
  425. pDC->SetTextColor(m_crText);
  426. INT iWidth = 0;
  427. for(INT i=0;i<iItems;i++)
  428. {
  429. INT iItem = OrderToIndex(i);
  430. TCHAR szText[FLATHEADER_TEXT_MAX];
  431. HDITEM hditem;
  432. hditem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP;
  433. hditem.pszText = szText;
  434. hditem.cchTextMax = sizeof(szText);
  435. VERIFY(GetItem(iItem, &hditem));
  436. VERIFY(GetItemRect(iItem, rectItem));
  437. if (rectItem.right >= rectClip.left || rectItem.left <= rectClip.right)
  438. {
  439. if(hditem.fmt&HDF_OWNERDRAW)
  440. {
  441. DRAWITEMSTRUCT disItem;
  442. disItem.CtlType = ODT_BUTTON;
  443. disItem.CtlID = GetDlgCtrlID();
  444. disItem.itemID = iItem;
  445. disItem.itemAction = ODA_DRAWENTIRE;
  446. disItem.itemState = 0;
  447. disItem.hwndItem = m_hWnd;
  448. disItem.hDC = pDC->m_hDC;
  449. disItem.rcItem = rectItem;
  450. disItem.itemData = 0;
  451. DrawItem(&disItem);
  452. }
  453. else
  454. {
  455. rectItem.DeflateRect(m_iSpacing, 0);
  456. DrawItem(pDC, rectItem, &hditem, iItem == m_iSortColumn, m_bSortAscending);
  457. rectItem.InflateRect(m_iSpacing, 0);
  458. if(m_nClickFlags&MK_LBUTTON && m_iHotIndex == iItem && m_hdhtiHotItem.flags&HHT_ONHEADER)
  459. pDC->InvertRect(rectItem);
  460. }
  461. if(i < iItems-1)
  462. {
  463. pDC->SelectObject(&penShadow);
  464. pDC->MoveTo(rectItem.right-1, rectItem.top+2);
  465. pDC->LineTo(rectItem.right-1, rectItem.bottom-2);
  466. pDC->SelectObject(&penHighLight);
  467. pDC->MoveTo(rectItem.right, rectItem.top+2);
  468. pDC->LineTo(rectItem.right, rectItem.bottom-2);
  469. }
  470. }
  471. iWidth += hditem.cxy;
  472. }
  473. if(iWidth > 0)
  474. {
  475. rectClient.right = rectClient.left + iWidth;
  476. pDC->Draw3dRect(rectClient, m_cr3DHighLight, m_cr3DShadow);
  477. }
  478. pDC->SelectObject(pFont);
  479. pDC->SelectObject(pPen);
  480. penHighLight.DeleteObject();
  481. penShadow.DeleteObject();
  482. }
  483. void CFlatHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT)
  484. {
  485. ASSERT(FALSE);  // must override for self draw header controls
  486. }
  487. void CFlatHeaderCtrl::DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bSort, BOOL bSortAscending)
  488. {
  489. ASSERT(lphdi->mask&HDI_FORMAT);
  490. INT iWidth = 0;
  491. CBitmap* pBitmap = NULL;
  492. BITMAP BitmapInfo;
  493. if(lphdi->fmt&HDF_BITMAP)
  494. {
  495. ASSERT(lphdi->mask&HDI_BITMAP);
  496. ASSERT(lphdi->hbm);
  497. pBitmap = CBitmap::FromHandle(lphdi->hbm);
  498. if(pBitmap)
  499. VERIFY(pBitmap->GetObject(sizeof(BITMAP), &BitmapInfo));
  500. }
  501. switch(lphdi->fmt&HDF_JUSTIFYMASK)
  502. {
  503. case HDF_LEFT:
  504. rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0;
  505. if(lphdi->fmt&HDF_IMAGE && !iWidth)
  506. break;
  507. rect.right -= bSort ? m_iSpacing+m_sizeArrow.cx : 0;
  508. rect.left += (iWidth = DrawText(pDC, rect, lphdi)) ? iWidth+m_iSpacing : 0;
  509. if(bSort)
  510. {
  511. rect.right += m_iSpacing+m_sizeArrow.cx;
  512. rect.left += DrawArrow(pDC, rect, bSortAscending, FALSE)+m_iSpacing;
  513. }
  514. DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE);
  515. break;
  516. case HDF_CENTER:
  517. rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0;
  518. if(lphdi->fmt&HDF_IMAGE && !iWidth)
  519. break;
  520. rect.left += bSort ? m_iSpacing+m_sizeArrow.cx : 0;
  521. rect.right -= (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) ? iWidth+m_iSpacing:0;
  522. if(bSort)
  523. {
  524. rect.left -= m_iSpacing+m_sizeArrow.cx;
  525. rect.right -= DrawArrow(pDC, rect, bSortAscending, TRUE)+2*m_iSpacing;
  526. }
  527. DrawText(pDC, rect, lphdi);
  528. break;
  529. case HDF_RIGHT:
  530. if(!(lphdi->fmt&HDF_BITMAP_ON_RIGHT))
  531. rect.left += (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, FALSE)) ? iWidth+m_iSpacing:0;
  532. rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0;
  533. if(lphdi->fmt&HDF_IMAGE && !iWidth)
  534. break;
  535. rect.left += bSort && (lphdi->fmt&HDF_BITMAP_ON_RIGHT) ? m_iSpacing+m_sizeArrow.cx : 0;
  536. if(lphdi->fmt&HDF_BITMAP_ON_RIGHT)
  537. rect.right -= (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) ? iWidth+m_iSpacing:0;
  538. if(bSort)
  539. {
  540. rect.left -= (lphdi->fmt&HDF_BITMAP_ON_RIGHT) ? m_iSpacing+m_sizeArrow.cx:0;
  541. rect.right -= DrawArrow(pDC, rect, bSortAscending, TRUE)+2*m_iSpacing;
  542. }
  543. DrawText(pDC, rect, lphdi);
  544. break;
  545. }
  546. }
  547. INT CFlatHeaderCtrl::DrawImage(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bRight)
  548. {
  549. CImageList* pImageList = GetImageList();
  550. INT iWidth = 0;
  551. if(lphdi->mask&HDI_IMAGE && lphdi->fmt&HDF_IMAGE)
  552. {
  553. ASSERT(pImageList);
  554. ASSERT(lphdi->iImage>=0 && lphdi->iImage<pImageList->GetImageCount());
  555. if(rect.Width()>0)
  556. {
  557. POINT point;
  558. point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1);
  559. if(bRight)
  560. point.x = rect.right - m_sizeImage.cx;
  561. else
  562. point.x = rect.left;
  563. SIZE size;
  564. size.cx = rect.Width()<m_sizeImage.cx ? rect.Width():m_sizeImage.cx;
  565. size.cy = m_sizeImage.cy;
  566. pImageList->DrawIndirect(pDC, lphdi->iImage, point, size, CPoint(0, 0));
  567. iWidth = m_sizeImage.cx;
  568. }
  569. }
  570. return iWidth;
  571. }
  572. INT CFlatHeaderCtrl::DrawBitmap(CDC* pDC, CRect rect, LPHDITEM lphdi, CBitmap* pBitmap, BITMAP* pBitmapInfo, BOOL bRight)
  573. {
  574. INT iWidth = 0;
  575. if(pBitmap)
  576. {
  577. iWidth = pBitmapInfo->bmWidth;
  578. if(iWidth<=rect.Width() && rect.Width()>0)
  579. {
  580. POINT point;
  581. point.y = rect.CenterPoint().y - (pBitmapInfo->bmHeight>>1);
  582. if(bRight)
  583. point.x = rect.right - iWidth;
  584. else
  585. point.x = rect.left;
  586. CDC dc;
  587. if(dc.CreateCompatibleDC(pDC) == TRUE) 
  588. {
  589. VERIFY(dc.SelectObject(pBitmap));
  590. iWidth = pDC->BitBlt(
  591. point.x, point.y, 
  592. pBitmapInfo->bmWidth, pBitmapInfo->bmHeight, 
  593. &dc, 
  594. 0, 0, 
  595. SRCCOPY
  596. ) ? iWidth:0;
  597. }
  598. else iWidth = 0;
  599. }
  600. else
  601. iWidth = 0;
  602. }
  603. return iWidth;
  604. }
  605. INT CFlatHeaderCtrl::DrawText(CDC* pDC, CRect rect, LPHDITEM lphdi)
  606. {
  607. CSize size;
  608. if(rect.Width()>0 && lphdi->mask&HDI_TEXT && lphdi->fmt&HDF_STRING)
  609. {
  610. size = pDC->GetTextExtent(lphdi->pszText);
  611. switch(lphdi->fmt&HDF_JUSTIFYMASK)
  612. {
  613. case HDF_LEFT:
  614. case HDF_LEFT|HDF_RTLREADING:
  615. pDC->DrawText(lphdi->pszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  616. break;
  617. case HDF_CENTER:
  618. case HDF_CENTER|HDF_RTLREADING:
  619. pDC->DrawText(lphdi->pszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  620. break;
  621. case HDF_RIGHT:
  622. case HDF_RIGHT|HDF_RTLREADING:
  623. pDC->DrawText(lphdi->pszText, -1, rect, DT_RIGHT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  624. break;
  625. }
  626. }
  627. size.cx = rect.Width()>size.cx ? size.cx:rect.Width();
  628. return size.cx>0 ? size.cx:0;
  629. }
  630. INT CFlatHeaderCtrl::DrawArrow(CDC* pDC, CRect rect, BOOL bSortAscending, BOOL bRight)
  631. {
  632. INT iWidth = 0;
  633. if(rect.Width()>0 && m_sizeArrow.cx<=rect.Width())
  634. {
  635. iWidth = m_sizeArrow.cx;
  636. rect.top += (rect.Height() - m_sizeArrow.cy - 1)>>1;
  637. rect.bottom = rect.top + m_sizeArrow.cy - 1;
  638. rect.left = bRight ? rect.right-m_sizeArrow.cy:rect.left;
  639. // Set up pens to use for drawing the triangle
  640. CPen penLight(PS_SOLID, 1, m_cr3DHighLight);
  641. CPen penShadow(PS_SOLID, 1, m_cr3DShadow);
  642. CPen *pPen = pDC->SelectObject(&penLight);
  643. if(bSortAscending)
  644. {
  645. // Draw triangle pointing upwards
  646. pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1) + 1, rect.top);
  647. pDC->LineTo(rect.left +  (m_sizeArrow.cx-1), rect.top + m_sizeArrow.cy - 1);
  648. pDC->LineTo(rect.left, rect.top + m_sizeArrow.cy - 1);
  649. pDC->SelectObject(&penShadow);
  650. pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1), rect.top);
  651. pDC->LineTo(rect.left, rect.top + m_sizeArrow.cy - 1);
  652. }
  653. else
  654. {
  655. // Draw triangle pointing downwards
  656. pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1)+1, rect.top + m_sizeArrow.cy - 1);
  657. pDC->LineTo(rect.left +  (m_sizeArrow.cx-1), rect.top);
  658. pDC->SelectObject(&penShadow);
  659. pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1), rect.top + m_sizeArrow.cy - 1);
  660. pDC->LineTo(rect.left, rect.top);
  661. pDC->LineTo(rect.left + m_sizeArrow.cx, rect.top);
  662. }
  663. // Restore the pen
  664. pDC->SelectObject(pPen);
  665. penLight.DeleteObject();
  666. penShadow.DeleteObject();
  667. }
  668. return iWidth;
  669. }
  670. /////////////////////////////////////////////////////////////////////////////
  671. // CHeaderCtrl message handlers
  672. LRESULT CFlatHeaderCtrl::OnInsertItem(WPARAM wParam, LPARAM lParam)
  673. {
  674. HDITEMEX hditemex;
  675. hditemex.iMinWidth = 0;
  676. hditemex.iMaxWidth = -1;
  677. LRESULT lResult = -1;
  678. WORD wItems = m_arrayHdrItemEx.GetSize();
  679. wParam = wParam<=wItems ? wParam:wItems;
  680. try
  681. {
  682. m_arrayHdrItemEx.InsertAt(wParam, hditemex);
  683. lResult = Default();
  684. if(lResult < 0) // Cleanup
  685. m_arrayHdrItemEx.RemoveAt(wParam);
  686. }
  687. catch(CMemoryException* e)
  688. {
  689. e->Delete();
  690. }
  691. return lResult;
  692. }
  693. LRESULT CFlatHeaderCtrl::OnDeleteItem(WPARAM wParam, LPARAM lParam)
  694. {
  695. ASSERT((INT)wParam < m_arrayHdrItemEx.GetSize());
  696. m_arrayHdrItemEx.RemoveAt(wParam);
  697. return Default();
  698. }
  699. LRESULT CFlatHeaderCtrl::OnSetImageList(WPARAM wParam, LPARAM lParam)
  700. {
  701. CImageList* pImageList;
  702. pImageList = CImageList::FromHandle((HIMAGELIST)lParam);
  703. IMAGEINFO info;
  704. if(pImageList->GetImageInfo(0, &info))
  705. {
  706. m_sizeImage.cx = info.rcImage.right - info.rcImage.left;
  707. m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;
  708. }
  709. return Default();
  710. }
  711. LRESULT CFlatHeaderCtrl::OnSetHotDivider(WPARAM wParam, LPARAM lParam)
  712. {
  713. if(wParam)
  714. {
  715. HDHITTESTINFO hdhti;
  716. hdhti.pt.x = LOWORD(lParam);
  717. hdhti.pt.y = HIWORD(lParam);
  718. ScreenToClient(&hdhti.pt);
  719. INT iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti));
  720. if(iHotIndex >= 0)
  721. {
  722. HDITEM hditem;
  723. hditem.mask = HDI_ORDER;
  724. VERIFY(GetItem(iHotIndex, &hditem));
  725. m_iHotDivider = hditem.iOrder;
  726. CRect rectItem;
  727. VERIFY(GetItemRect(iHotIndex, rectItem));
  728. if(hdhti.pt.x > rectItem.CenterPoint().x)
  729. m_iHotDivider++;
  730. }
  731. else
  732. m_iHotDivider = -1;
  733. }
  734. else
  735. m_iHotDivider = (INT)lParam;
  736. RECT rect;
  737. GetClientRect(&rect);
  738. INT iItems = GetItemCount();
  739. if(m_iHotDivider >= 0 && m_iHotDivider<=iItems+1)
  740. {
  741. if(m_pDropWnd == NULL)
  742. {
  743. m_pDropWnd = new CFHDropWnd(m_crHotDivider);
  744. if(m_pDropWnd)
  745. m_pDropWnd->Create(rect.bottom - rect.top);
  746. }
  747. if(m_pDropWnd != NULL)
  748. {
  749. POINT pt;
  750. pt.y = (rect.bottom-rect.top)/2;
  751. if(m_iHotDivider<iItems)
  752. {
  753. GetItemRect(OrderToIndex(m_iHotDivider), &rect);
  754. pt.x = rect.left - 1;
  755. }
  756. else
  757. {
  758. GetItemRect(OrderToIndex(iItems-1), &rect);
  759. pt.x = rect.right;
  760. }
  761. ClientToScreen(&pt);
  762. m_pDropWnd->SetWindowPos(pt.x, pt.y);
  763. }
  764. }
  765. else
  766. {
  767. if(m_pDropWnd != NULL)
  768. {
  769. m_pDropWnd->DestroyWindow();
  770. m_pDropWnd = NULL;
  771. }
  772. }
  773. return(LRESULT)m_iHotDivider;
  774. }
  775. LRESULT CFlatHeaderCtrl::OnLayout(WPARAM wParam, LPARAM lParam)
  776. {
  777. LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam;
  778. if(m_bStaticBorder)
  779. lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2;
  780. return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
  781. }
  782. /////////////////////////////////////////////////////////////////////////////
  783. // CFlatHeaderCtrl message handlers
  784. void CFlatHeaderCtrl::OnSysColorChange() 
  785. {
  786. CHeaderCtrl::OnSysColorChange();
  787. m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
  788. m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);
  789. m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
  790. m_crText = ::GetSysColor(COLOR_BTNTEXT);
  791. }
  792. BOOL CFlatHeaderCtrl::OnEraseBkgnd(CDC* pDC) 
  793. {
  794. return TRUE;
  795. }
  796. void CFlatHeaderCtrl::OnPaint() 
  797. {
  798.     CPaintDC dc(this);
  799.     if (m_bDoubleBuffer)
  800.     {
  801.         CMemDC MemDC(&dc);
  802.         DrawCtrl(&MemDC);
  803.     }
  804.     else
  805.         DrawCtrl(&dc);
  806. }
  807. UINT CFlatHeaderCtrl::OnNcHitTest(CPoint point) 
  808. {
  809. m_hdhtiHotItem.pt = point;
  810. ScreenToClient(&m_hdhtiHotItem.pt);
  811. m_iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&m_hdhtiHotItem));
  812. if(m_iHotIndex >= 0)
  813. {
  814. HDITEM hditem;
  815. hditem.mask = HDI_ORDER;
  816. VERIFY(GetItem(m_iHotIndex, &hditem));
  817. m_iHotOrder = hditem.iOrder;
  818. HDITEMEX hditemex;
  819. if(GetItemEx(m_iHotIndex, &hditemex))
  820. m_bHotItemResizable = hditemex.nStyle&HDF_EX_FIXEDWIDTH ? FALSE:TRUE;
  821. }
  822. return CHeaderCtrl::OnNcHitTest(point);
  823. }
  824. BOOL CFlatHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  825. {
  826. if(m_iHotIndex>=0 && m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN) && !m_bHotItemResizable)
  827. {
  828. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  829. return TRUE;
  830. }
  831. return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, message);
  832. }
  833. void CFlatHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  834. {
  835. m_nClickFlags = nFlags;
  836. m_ptClickPoint = point;
  837. if(m_iHotIndex >= 0)
  838. {
  839. m_hdiHotItem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP|HDI_ORDER|HDI_LPARAM;
  840. m_hdiHotItem.pszText = m_szHotItemText;
  841. m_hdiHotItem.cchTextMax = sizeof(m_szHotItemText);
  842. VERIFY(GetItem(m_iHotIndex, &m_hdiHotItem));
  843. if(m_hdhtiHotItem.flags&HHT_ONHEADER)
  844. {
  845. RECT rectItem;
  846. VERIFY(GetItemRect(m_iHotIndex, &rectItem));
  847. InvalidateRect(&rectItem);
  848. }
  849. if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN))
  850. {
  851. if(!m_bHotItemResizable)
  852. return;
  853. HDITEMEX hditemex;
  854. VERIFY(GetItemEx(m_iHotIndex, &hditemex));
  855. CRect rectItem;
  856. GetItemRect(m_iHotIndex, rectItem);
  857. ClientToScreen(rectItem);
  858. if(hditemex.iMinWidth <= hditemex.iMaxWidth)
  859. {
  860. CRect rectClip;
  861. GetClipCursor(rectClip);
  862. POINT point;
  863. GetCursorPos(&point);
  864. INT iOffset = point.x - rectItem.right;
  865. rectClip.left = rectItem.left + hditemex.iMinWidth + iOffset;
  866. rectClip.right = rectItem.left + hditemex.iMaxWidth + iOffset;
  867. ClipCursor(rectClip);
  868. }
  869. m_bResizing = TRUE;
  870. }
  871. }
  872. CHeaderCtrl::OnLButtonDown(nFlags, point);
  873. }
  874. void CFlatHeaderCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
  875. {
  876. if(m_iHotIndex>=0 && m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN) && !m_bHotItemResizable)
  877. return;
  878. CHeaderCtrl::OnLButtonDblClk(nFlags, point);
  879. }
  880. void CFlatHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
  881. {
  882. m_nClickFlags = nFlags;
  883. m_ptClickPoint = point;
  884. if(m_iHotIndex >= 0)
  885. {
  886. CWnd* pWnd = GetParent();
  887. if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN))
  888. {
  889. if(m_bResizing)
  890. {
  891. ClipCursor(NULL);
  892. m_bResizing = FALSE;
  893. }
  894. }
  895. if(m_hdhtiHotItem.flags&HHT_ONHEADER)
  896. {
  897. if(m_bDragging)
  898. {
  899. NMHEADER nmhdr;
  900. nmhdr.hdr.hwndFrom = m_hWnd;
  901. nmhdr.hdr.idFrom = GetDlgCtrlID();
  902. nmhdr.hdr.code = HDN_ENDDRAG;
  903. nmhdr.iItem = m_iHotIndex;
  904. nmhdr.iButton = 0;
  905. nmhdr.pitem = &m_hdiHotItem;
  906. if(pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmhdr)==FALSE && m_iHotDivider>=0)
  907. {
  908. INT iCount = GetItemCount();
  909. ASSERT(m_iHotOrder < iCount);
  910. ASSERT(m_iHotDivider <= iCount);
  911. LPINT piArray = new INT[iCount*2];
  912. if(piArray)
  913. {
  914. GetOrderArray((LPINT)piArray, iCount);
  915. for(INT i=0,j=0;i<iCount;i++)
  916. {
  917. if(j == m_iHotOrder)
  918. j++;
  919. if(
  920. (m_iHotOrder<m_iHotDivider && i == m_iHotDivider-1) ||
  921. (m_iHotOrder>=m_iHotDivider && i == m_iHotDivider)
  922. )
  923. piArray[iCount+i] = piArray[m_iHotOrder];
  924. else
  925. piArray[iCount+i] = piArray[j++];
  926. }
  927. SetOrderArray(iCount, (LPINT)&piArray[iCount]);
  928. delete piArray;
  929. }
  930. else
  931. AfxThrowMemoryException();
  932. }
  933. if(m_pDragWnd != NULL)
  934. {
  935. m_pDragWnd->DestroyWindow();
  936. m_pDragWnd = NULL;
  937. }
  938. if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
  939. ReleaseCapture();
  940. m_bDragging = FALSE;
  941. OnSetHotDivider(FALSE, -1);
  942. Invalidate();
  943. }
  944. else
  945. {
  946. RECT rectItem;
  947. VERIFY(GetItemRect(m_iHotIndex, &rectItem));
  948. InvalidateRect(&rectItem);
  949. }
  950. }
  951. }
  952. CHeaderCtrl::OnLButtonUp(nFlags, point);
  953. }
  954. void CFlatHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point) 
  955. {
  956. if(m_nClickFlags&MK_LBUTTON && m_iHotIndex>=0)
  957. {
  958. if(m_bResizing)
  959. CHeaderCtrl::OnMouseMove(nFlags, point);
  960. if(m_hdhtiHotItem.flags&HHT_ONHEADER)
  961. {
  962. if(m_bDragging)
  963. {
  964. if(m_pDragWnd != NULL)
  965. {
  966. CRect rect;
  967. m_pDragWnd->GetWindowRect(&rect);
  968. CPoint pt = point;
  969. ClientToScreen(&pt);
  970. pt.Offset(-(rect.Width()>>1), -(rect.Height()>>1));
  971. m_pDragWnd->SetWindowPos(
  972. &wndTop, 
  973. pt.x, pt.y,
  974. 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE
  975. );
  976. HDHITTESTINFO hdhti;
  977. hdhti.pt.x = point.x;
  978. hdhti.pt.y = point.y;
  979. INT iHotOrder = -1;
  980. INT iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti));
  981. if(iHotIndex >= 0)
  982. {
  983. HDITEM hditem;
  984. hditem.mask = HDI_ORDER;
  985. VERIFY(GetItem(iHotIndex, &hditem));
  986. iHotOrder = hditem.iOrder;
  987. CRect rectItem;
  988. VERIFY(GetItemRect(iHotIndex, rectItem));
  989. if(hdhti.pt.x > rectItem.CenterPoint().x)
  990. iHotOrder++;
  991. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  992. m_iDropResult = 0;
  993. }
  994. else
  995. {
  996. pt = point;
  997. ClientToScreen(&pt);
  998. if(!(m_hDropTarget && m_rcDropTarget.PtInRect(pt)))
  999. {
  1000. if(m_nDontDropCursor)
  1001. SetCursor(AfxGetApp()->LoadCursor(m_nDontDropCursor));
  1002. else
  1003. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));
  1004. m_iDropResult = -1;
  1005. }
  1006. else
  1007. {
  1008. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  1009. m_iDropResult = 1;
  1010. }
  1011. }
  1012. if(iHotOrder == m_iHotOrder || iHotOrder == m_iHotOrder+1)
  1013. iHotOrder = -1;
  1014. if(iHotOrder != m_iHotDivider)
  1015. OnSetHotDivider(FALSE, iHotOrder);
  1016. }
  1017. return;
  1018. }
  1019. else if(GetStyle()&HDS_DRAGDROP)
  1020. {
  1021. INT iDragCX = GetSystemMetrics(SM_CXDRAG);
  1022. INT iDragCY = GetSystemMetrics(SM_CYDRAG);
  1023. CRect rectDrag(
  1024. m_ptClickPoint.x-iDragCX, m_ptClickPoint.y-iDragCY,
  1025. m_ptClickPoint.x+iDragCX, m_ptClickPoint.y+iDragCY
  1026. );
  1027. if(!rectDrag.PtInRect(point))
  1028. {
  1029. NMHEADER nmhdr;
  1030. nmhdr.hdr.hwndFrom = m_hWnd;
  1031. nmhdr.hdr.idFrom = GetDlgCtrlID();
  1032. nmhdr.hdr.code = HDN_BEGINDRAG;
  1033. nmhdr.iItem = m_iHotIndex;
  1034. nmhdr.iButton = 1;
  1035. nmhdr.pitem = &m_hdiHotItem;
  1036. BOOL bBeginDrag = TRUE;
  1037. CWnd* pWnd = GetParent();
  1038. if(pWnd != NULL)
  1039. bBeginDrag = pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmhdr)==FALSE ? TRUE:FALSE;
  1040. if(bBeginDrag)
  1041. {
  1042. ASSERT(m_pDragWnd == NULL);
  1043. m_pDragWnd = new CFHDragWnd;
  1044. if(m_pDragWnd)
  1045. {
  1046. CRect rectItem;
  1047. VERIFY(GetItemRect(m_iHotIndex, rectItem));
  1048. ClientToScreen(&rectItem);
  1049. m_pDragWnd->Create(rectItem, this, m_iHotIndex, &m_hdiHotItem);
  1050. }
  1051. BOOL bVisible = FALSE;
  1052. if(m_hDropTarget != NULL)
  1053. {
  1054. bVisible = ::GetWindowLong(m_hDropTarget, GWL_STYLE)&WS_VISIBLE ? TRUE:FALSE;
  1055. HWND hParent = ::GetParent(m_hDropTarget);
  1056. if(hParent)
  1057. bVisible = ::GetWindowLong(hParent, GWL_STYLE)&WS_VISIBLE ? TRUE:FALSE;
  1058. }
  1059. if(m_hDropTarget != NULL && bVisible)
  1060. VERIFY(::GetWindowRect(m_hDropTarget, m_rcDropTarget));
  1061. else
  1062. m_rcDropTarget.SetRectEmpty();
  1063. }
  1064. SetCapture();
  1065. m_bDragging = TRUE;
  1066. }
  1067. }
  1068. }
  1069. }
  1070. }