When i draw listview i encountered a problem.
I have a class derived from wtl CListViewCtrl and I am doing all paint by myself.
when select item, the selected item's background Highlight and other normal.
All item is fine except the first item.
I find the problem is when mouse down on the first item, the first item's rect not int clipbox, so when mouse down, the first item not Invalidate();
but other is ok.
#ifndef _SKINX_LISTVIEW_H_
#define _SKINX_LISTVIEW_H_
#pragma once
template< class T, class TBase = CListViewCtrl, class TWinTraits = ATL::CControlWinTraits >
class CSkinXListViewImpl : public CWindowImpl< T, TBase, TWinTraits >
{
public:
void Initialize()
{
m_clrLine = RGB(238,238,238);
m_clrBackGround = RGB(255,255,255);
m_clrSelected = RGB(173,195,231);
}
BOOL SubclassWindow(HWND hWnd)
{
ATLASSERT(m_hWnd == NULL);
ATLASSERT(::IsWindow(hWnd));
BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
if( bRet ) Initialize();
return bRet;
}
BEGIN_MSG_MAP(CSkinXListViewImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnNcCalcSize)
MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
END_MSG_MAP()
LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& )
{
LRESULT lRes = DefWindowProc();
Initialize();
return lRes;
}
LRESULT OnPaint(UINT , WPARAM , LPARAM lParam, BOOL& bHandled){
CPaintDC dc(m_hWnd);
RECT rcClient;
GetClientRect(&rcClient);
HBRUSH hBrushBackGround = CreateSolidBrush(m_clrBackGround);
dc.FillRect(&rcClient, hBrushBackGround);
DeleteObject(hBrushBackGround);
int n = GetItemCount();
for(int nItem = 0; nItem < n; nItem++){
RECT rcItem;
GetItemRect(nItem, &rcItem, LVIR_BOUNDS);
if (GetItemState(nItem, LVIS_SELECTED)){
HBRUSH hBrushItem = CreateSolidBrush(m_clrSelected);
dc.FillRect(&rcItem, hBrushItem);
DeleteObject(hBrushItem);
}
int nSubCount = GetColumnCount();
for(int nSubItem = 0; nSubItem < nSubCount; nSubItem++){
CString str;
GetItemText(nItem, nSubItem, str);
RECT rcSubColumn, rcSubItem;
GetColumnItemRect(nSubItem, &rcSubColumn);
rcSubItem = rcItem;
rcSubItem.left = rcSubColumn.left;
rcSubItem.right = rcSubColumn.right;
dc.SetBkMode(TRANSPARENT);
HFONT hOldFont = dc.SelectFont(GetCtrlFont());
dc.DrawText( str, -1, &rcSubItem, DT_SINGLELINE | DT_VCENTER);
dc.SelectFont(hOldFont);
}
RECT rcLine = { rcItem.left, rcItem.bottom - 1, rcItem.right, rcItem.bottom - 1 };
HPEN hPen = CreatePen(PS_SOLID, 1, m_clrLine);
HPEN hOldPen = dc.SelectPen(hPen);
dc.MoveTo(rcLine.left, rcLine.top);
dc.LineTo(rcLine.right, rcLine.bottom);
dc.SelectPen(hOldPen);
DeleteObject(hPen);
}
return 0;
}
LRESULT OnEraseBackground(UINT , WPARAM , LPARAM , BOOL& )
{
return 1;
}
LRESULT OnNcPaint(UINT uMsg, WPARAM , LPARAM , BOOL& )
{
CWindowDC dc(m_hWnd);
RECT rcClient, rcWindow;
GetWindowRect(&rcWindow);
ScreenToClient(&rcWindow);
GetClientRect(&rcClient);
rcWindow.left += 3;
rcWindow.top += 3;
rcWindow.bottom += 1;
rcWindow.right += 1;
HPEN hPen = ::CreatePen(PS_SOLID, 1, RGB(255,0,0));
HPEN hOldPen = dc.SelectPen(hPen);
dc.Rectangle(&rcWindow);
dc.SelectPen(hOldPen);
DeleteObject(hPen);
Invalidate();
UpdateWindow();
return 0;
}
LRESULT OnNcCalcSize(UINT , WPARAM , LPARAM , BOOL& ){
UpdateWindow();
DefWindowProc();
return 0;
}
HFONT GetCtrlFont()
{
HFONT hFont;
if ( (hFont = (HFONT)::SendMessage(m_hWnd,WM_GETFONT,0,0))==NULL)
hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
return hFont;
}
int GetColumnCount()
{
CHeaderCtrl HeaderCtrl = GetHeader();
return HeaderCtrl.GetItemCount();
}
BOOL GetColumnItemRect(int nIndex, LPRECT lpItemRect){
CHeaderCtrl HeaderCtrl = GetHeader();
return HeaderCtrl.GetItemRect(nIndex, lpItemRect);
}
private:
COLORREF m_clrLine;
COLORREF m_clrBackGround;
COLORREF m_clrSelected;
};
class CListViewCtrlX : public CSkinXListViewImpl<CListViewCtrlX>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_CListViewCtrlX"), GetWndClassName())
};
#endif //_SKINX_LISTVIEW_H_