123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- // XHeaderCtrl.cpp Version 1.4
- //
- // Author: Hans Dietrich
- // hdietrich@gmail.com
- //
- // This code is based on "Outlook 98-Style FlatHeader Control"
- // by Maarten Hoeben.
- //
- // See http://www.codeguru.com/listview/FlatHeader.shtml
- //
- // License:
- // This software is released into the public domain. You are free to use
- // it in any way you like, except that you may not sell this source code.
- //
- // This software is provided "as is" with no expressed or implied warranty.
- // I accept no liability for any damage or loss of business that this
- // software may cause.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "XHeaderCtrl.h"
- #include "memdc.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CXHeaderCtrl
- IMPLEMENT_DYNCREATE(CXHeaderCtrl, CHeaderCtrl)
- BEGIN_MESSAGE_MAP(CXHeaderCtrl, CHeaderCtrl)
- //{{AFX_MSG_MAP(CXHeaderCtrl)
- ON_WM_ERASEBKGND()
- ON_WM_PAINT()
- ON_WM_SYSCOLORCHANGE()
- ON_WM_LBUTTONDBLCLK()
- //}}AFX_MSG_MAP
- ON_MESSAGE(HDM_INSERTITEMA, OnInsertItem)
- ON_MESSAGE(HDM_INSERTITEMW, OnInsertItem)
- ON_MESSAGE(HDM_DELETEITEM, OnDeleteItem)
- ON_MESSAGE(HDM_SETIMAGELIST, OnSetImageList)
- ON_MESSAGE(HDM_LAYOUT, OnLayout)
- END_MESSAGE_MAP()
- ///////////////////////////////////////////////////////////////////////////////
- // ctor
- CXHeaderCtrl::CXHeaderCtrl()
- {
- m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
- m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);
- m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
- m_crBtnText = ::GetSysColor(COLOR_BTNTEXT);
- m_pListCtrl = NULL; //+++
- m_nFormat = DT_DEFAULT; //+++
- m_rgbText = m_crBtnText; //+++
- m_bDividerLines = TRUE; //+++
- m_bDoubleBuffer = TRUE;
- m_iSpacing = 6;
- m_sizeArrow.cx = 8;
- m_sizeArrow.cy = 8;
- m_sizeImage.cx = 0;
- m_sizeImage.cy = 0;
- m_bStaticBorder = FALSE;
- m_nDontDropCursor = 0;
- m_bResizing = FALSE;
- m_nClickFlags = 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // dtor
- CXHeaderCtrl::~CXHeaderCtrl()
- {
- }
- ///////////////////////////////////////////////////////////////////////////////
- // ModifyProperty
- BOOL CXHeaderCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam)
- {
- switch(wParam)
- {
- case FH_PROPERTY_SPACING:
- m_iSpacing = (int)lParam;
- break;
- case FH_PROPERTY_ARROW:
- m_sizeArrow.cx = LOWORD(lParam);
- m_sizeArrow.cy = HIWORD(lParam);
- break;
- case FH_PROPERTY_STATICBORDER:
- m_bStaticBorder = (BOOL)lParam;
- break;
- case FH_PROPERTY_DONTDROPCURSOR:
- m_nDontDropCursor = (UINT)lParam;
- break;
- default:
- return FALSE;
- }
- Invalidate();
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // DrawCtrl
- void CXHeaderCtrl::DrawCtrl(CDC* pDC)
- {
- CRect rectClip;
- if (pDC->GetClipBox(&rectClip) == ERROR)
- return;
- CRect rectClient, rectItem;
- GetClientRect(&rectClient);
- pDC->FillSolidRect(rectClip, m_cr3DFace);
- int iItems = GetItemCount();
- ASSERT(iItems >= 0);
- CPen penHighLight(PS_SOLID, 1, m_cr3DHighLight);
- CPen penShadow(PS_SOLID, 1, m_cr3DShadow);
- CPen* pPen = pDC->GetCurrentPen();
- CFont* pFont = pDC->SelectObject(GetFont());
- pDC->SetBkColor(m_cr3DFace);
- pDC->SetTextColor(m_crBtnText);
- int iWidth = 0;
- for (int i = 0; i < iItems; i++)
- {
- int iItem = OrderToIndex(i);
- TCHAR szText[FLATHEADER_TEXT_MAX];
- HDITEM hditem;
- hditem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP;
- hditem.pszText = szText;
- hditem.cchTextMax = sizeof(szText);
- VERIFY(GetItem(iItem, &hditem));
- VERIFY(GetItemRect(iItem, rectItem));
- if (rectItem.right >= rectClip.left || rectItem.left <= rectClip.right)
- {
- if (hditem.fmt & HDF_OWNERDRAW)
- {
- DRAWITEMSTRUCT disItem;
- disItem.CtlType = ODT_BUTTON;
- disItem.CtlID = GetDlgCtrlID();
- disItem.itemID = iItem;
- disItem.itemAction = ODA_DRAWENTIRE;
- disItem.itemState = 0;
- disItem.hwndItem = m_hWnd;
- disItem.hDC = pDC->m_hDC;
- disItem.rcItem = rectItem;
- disItem.itemData = 0;
- DrawItem(&disItem);
- }
- else
- {
- rectItem.DeflateRect(m_iSpacing, 0);
- DrawItem(pDC, rectItem, &hditem);
- rectItem.InflateRect(m_iSpacing, 0);
- //if (m_nClickFlags & MK_LBUTTON && m_iHotIndex == iItem && m_hdhtiHotItem.flags & HHT_ONHEADER)
- // pDC->InvertRect(rectItem);
- }
- if (i < iItems-1)
- {
- // draw divider lines
- if (m_bDividerLines) //+++
- {
- pDC->SelectObject(&penShadow);
- pDC->MoveTo(rectItem.right-1, rectItem.top+2);
- pDC->LineTo(rectItem.right-1, rectItem.bottom-2);
- pDC->SelectObject(&penHighLight);
- pDC->MoveTo(rectItem.right, rectItem.top+2);
- pDC->LineTo(rectItem.right, rectItem.bottom-2);
- }
- }
- }
- iWidth += hditem.cxy;
- }
- if (iWidth > 0)
- {
- rectClient.right = rectClient.left + iWidth;
- pDC->Draw3dRect(rectClient, m_cr3DHighLight, m_cr3DShadow);
- }
- pDC->SelectObject(pFont);
- pDC->SelectObject(pPen);
- penHighLight.DeleteObject();
- penShadow.DeleteObject();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // DrawItem
- void CXHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT)
- {
- ASSERT(FALSE); // must override for self draw header controls
- }
- ///////////////////////////////////////////////////////////////////////////////
- // DrawItem
- void CXHeaderCtrl::DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi)
- {
- ASSERT(lphdi->mask & HDI_FORMAT);
- int iWidth = 0;
- CBitmap* pBitmap = NULL;
- BITMAP BitmapInfo;
- if (lphdi->fmt & HDF_BITMAP)
- {
- ASSERT(lphdi->mask & HDI_BITMAP);
- ASSERT(lphdi->hbm);
- pBitmap = CBitmap::FromHandle(lphdi->hbm);
- if (pBitmap)
- VERIFY(pBitmap->GetObject(sizeof(BITMAP), &BitmapInfo));
- }
- rect.left += ((iWidth = DrawImage(pDC, rect, lphdi, FALSE)) != 0) ?
- iWidth + m_iSpacing : 0;
- rect.right -= ((iWidth = DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) != 0) ?
- iWidth + m_iSpacing : 0;
- DrawText(pDC, rect, lphdi);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // DrawImage
- int CXHeaderCtrl::DrawImage(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bRight)
- {
- int iWidth = 0;
- if (lphdi->iImage != XHEADERCTRL_NO_IMAGE)
- {
- CImageList* pImageList = GetImageList();
- if (pImageList && (rect.Width() > 0))
- {
- POINT point;
- point.y = rect.CenterPoint().y - ((m_sizeImage.cy+1) >> 1);
- if (bRight)
- point.x = rect.right - m_sizeImage.cx;
- else
- point.x = rect.left;
- SIZE size;
- size.cx = rect.Width() < m_sizeImage.cx ? rect.Width() : m_sizeImage.cx;
- size.cy = m_sizeImage.cy;
- // save image list background color
- COLORREF rgb = pImageList->GetBkColor();
- // set image list background color to same as header control
- pImageList->SetBkColor(pDC->GetBkColor());
- pImageList->DrawIndirect(pDC, lphdi->iImage, point, size, CPoint(0, 0));
- pImageList->SetBkColor(rgb);
- iWidth = m_sizeImage.cx;
- }
- else if (rect.Width() > 0)
- {
- // no image list, just draw checkbox
- CRect chkboxrect = rect;
- // center the checkbox
- int h = 13; // height and width are the same
- chkboxrect.right = chkboxrect.left + h;
- chkboxrect.top = rect.top + (rect.Height() - h) / 2;
- chkboxrect.bottom = chkboxrect.top + h;
- // fill rect inside checkbox with white
- COLORREF rgbBackground = pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
- pDC->FillSolidRect(&chkboxrect, ::GetSysColor(COLOR_WINDOW));
- // draw border
- CBrush brush(RGB(51,102,153));
- pDC->FrameRect(&chkboxrect, &brush);
- if (lphdi->iImage == XHEADERCTRL_CHECKED_IMAGE)
- {
- CPen blackpen(PS_SOLID, 1, RGB(51,153,51));
- CPen * pOldPen = pDC->SelectObject(&blackpen);
- // draw the checkmark
- int x = chkboxrect.left + 9;
- ASSERT(x < chkboxrect.right);
- int y = chkboxrect.top + 3;
- int i = 0;
- for (i = 0; i < 4; i++)
- {
- pDC->MoveTo(x, y);
- pDC->LineTo(x, y+3);
- x--;
- y++;
- }
- for (i = 0; i < 3; i++)
- {
- pDC->MoveTo(x, y);
- pDC->LineTo(x, y+3);
- x--;
- y--;
- }
- if (pOldPen)
- pDC->SelectObject(pOldPen);
- }
- pDC->SetBkColor(rgbBackground);
- iWidth = chkboxrect.Width();
- }
- else
- {
- // width = 0, do nothing
- }
- }
- return iWidth;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // DrawBitmap
- int CXHeaderCtrl::DrawBitmap(CDC* pDC,
- CRect rect,
- LPHDITEM lphdi,
- CBitmap* pBitmap,
- BITMAP* pBitmapInfo,
- BOOL bRight)
- {
- UNUSED_ALWAYS(lphdi);
- int iWidth = 0;
- if (pBitmap)
- {
- iWidth = pBitmapInfo->bmWidth;
- if (iWidth <= rect.Width() && rect.Width() > 0)
- {
- POINT point;
- point.y = rect.CenterPoint().y - (pBitmapInfo->bmHeight >> 1);
- if (bRight)
- point.x = rect.right - iWidth;
- else
- point.x = rect.left;
- CDC dc;
- if (dc.CreateCompatibleDC(pDC) == TRUE)
- {
- CBitmap * pOldBitmap = dc.SelectObject(pBitmap);
- iWidth = pDC->BitBlt(
- point.x, point.y,
- pBitmapInfo->bmWidth, pBitmapInfo->bmHeight,
- &dc,
- 0, 0,
- SRCCOPY
- ) ? iWidth:0;
- dc.SelectObject(pOldBitmap);
- }
- else
- iWidth = 0;
- }
- else
- iWidth = 0;
- }
- return iWidth;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // DrawText
- int CXHeaderCtrl::DrawText(CDC* pDC, CRect rect, LPHDITEM lphdi)
- {
- CSize size = pDC->GetTextExtent(lphdi->pszText);
- #if 0 // -----------------------------------------------------------
- pDC->SetTextColor(RGB(0,0,255));
- if (rect.Width() > 0 && lphdi->mask & HDI_TEXT && lphdi->fmt & HDF_STRING)
- {
- size = pDC->GetTextExtent(lphdi->pszText);
- // always center column headers
- pDC->DrawText(lphdi->pszText, -1, rect,
- DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
- }
- #endif // -----------------------------------------------------------
- //+++
- if (rect.Width() > 0 && lphdi->mask & HDI_TEXT && lphdi->fmt & HDF_STRING)
- {
- pDC->SetTextColor(m_rgbText);
- UINT nFormat = m_nFormat;
- if (nFormat == DT_DEFAULT)
- {
- // default to whatever alignment the column is set to
- if (lphdi->fmt & LVCFMT_CENTER)
- nFormat = DT_CENTER;
- else if (lphdi->fmt & LVCFMT_RIGHT)
- nFormat = DT_RIGHT;
- else
- nFormat = DT_LEFT;
- }
- pDC->DrawText(lphdi->pszText, -1, rect,
- nFormat | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER);
- }
- size.cx = rect.Width() > size.cx ? size.cx : rect.Width();
- return size.cx > 0 ? size.cx : 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnInsertItem
- LRESULT CXHeaderCtrl::OnInsertItem(WPARAM, LPARAM)
- {
- return Default();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnDeleteItem
- LRESULT CXHeaderCtrl::OnDeleteItem(WPARAM, LPARAM)
- {
- return Default();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnSetImageList
- LRESULT CXHeaderCtrl::OnSetImageList(WPARAM, LPARAM lParam)
- {
- CImageList* pImageList;
- pImageList = CImageList::FromHandle((HIMAGELIST)lParam);
- IMAGEINFO info;
- if (pImageList->GetImageInfo(0, &info))
- {
- m_sizeImage.cx = info.rcImage.right - info.rcImage.left;
- m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;
- }
- return Default();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnLayout
- LRESULT CXHeaderCtrl::OnLayout(WPARAM, LPARAM lParam)
- {
- LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam;
- if (m_bStaticBorder)
- lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2;
- return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnSysColorChange
- void CXHeaderCtrl::OnSysColorChange()
- {
- XLISTCTRL_TRACE(_T("in CXHeaderCtrl::OnSysColorChange\n"));
- CHeaderCtrl::OnSysColorChange();
-
- m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
- m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);
- m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
- m_crBtnText = ::GetSysColor(COLOR_BTNTEXT);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnEraseBkgnd
- BOOL CXHeaderCtrl::OnEraseBkgnd(CDC* pDC)
- {
- UNUSED_ALWAYS(pDC);
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnPaint
- void CXHeaderCtrl::OnPaint()
- {
- CPaintDC dc(this);
- if (m_bDoubleBuffer)
- {
- CMemDC MemDC(&dc);
- DrawCtrl(&MemDC);
- }
- else
- DrawCtrl(&dc);
- }
- void CXHeaderCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
- {
- XLISTCTRL_TRACE(_T("in CXHeaderCtrl::OnLButtonDblClk\n"));
- SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
- //CHeaderCtrl::OnLButtonDown(nFlags, point);
- }
|