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