source: trunk/EraserUI/FlatHeaderCtrl.cpp @ 57

Revision 57, 31.2 KB checked in by lowjoel, 7 years ago (diff)

Warning fixes for everyone.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
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
34static char THIS_FILE[] = __FILE__;
35#endif
36
37/////////////////////////////////////////////////////////////////////////////
38// CFHDragWnd
39
40CFHDragWnd::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
64CFHDragWnd::~CFHDragWnd()
65{
66}
67
68
69BEGIN_MESSAGE_MAP(CFHDragWnd, CWnd)
70    //{{AFX_MSG_MAP(CFHDragWnd)
71    ON_WM_PAINT()
72    ON_WM_ERASEBKGND()
73    //}}AFX_MSG_MAP
74END_MESSAGE_MAP()
75
76
77/////////////////////////////////////////////////////////////////////////////
78// CFHDragWnd message handlers
79
80BOOL 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
97void 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
110BOOL CFHDragWnd::OnEraseBkgnd(CDC* /*pDC*/)
111{
112    return TRUE;
113}
114
115void 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
139void CFHDragWnd::PostNcDestroy()
140{
141    CWnd::PostNcDestroy();
142    delete this;
143}
144
145/////////////////////////////////////////////////////////////////////////////
146// CFlatHeaderCtrl
147
148IMPLEMENT_DYNCREATE(CFlatHeaderCtrl, CHeaderCtrl)
149
150CFlatHeaderCtrl::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
181CFlatHeaderCtrl::~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
197BEGIN_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
214END_MESSAGE_MAP()
215
216/////////////////////////////////////////////////////////////////////////////
217// CFlatHeaderCtrl attributes
218
219BOOL 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
241BOOL 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
250BOOL 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
277void 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
287INT 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
298void 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
432void CFlatHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT)
433{
434    ASSERT(FALSE);  // must override for self draw header controls
435}
436
437void 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
550INT 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
587INT 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
629INT 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
662INT 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
713LRESULT 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
726LRESULT 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
734LRESULT 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
763LRESULT 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
776BOOL CFlatHeaderCtrl::OnEraseBkgnd(CDC* /*pDC*/)
777{
778    return TRUE;
779}
780
781void 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
794LRESULT
795CFlatHeaderCtrl::OnNcHitTest(CPoint point)
796{
797    m_hdhtiHotItem.pt = point;
798    ScreenToClient(&m_hdhtiHotItem.pt);
799
800    m_iHotIndex = (int)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
820BOOL 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
833void 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
898void 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
910void 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
1011void 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
1021void 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 = (INT)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}
Note: See TracBrowser for help on using the repository browser.