1.自绘了CListBox:简记如下:
在DrawItem中自绘,必须设定属性:LBS_OWNERDRAWFIXED |LBS_HASSTRINGS;
如果不设定LBS_HASSTRINGS,那么GetText取得的将是乱码:
三个难点,一是自绘属性加上LBS_OWNERDRAWFIXED后,必须同时重载DrawItem和MeasureItem,我第一次只重载了DrawItem,发现出现堆栈错误。
二是自绘属性中必须有LBS_HASSTRINGS,不然GetText取得的将是乱码.
三是自绘中 dc.Attach(lpDIS->hDC);必须有对应的dc.Detach();,我第一次没有加dc.Detach();结果发现只能显示一项
listbox自绘非常简单:直接贴代码:
void CListBoxEx::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CDC dc ;
dc.Attach(lpDIS->hDC);
CRect rcItem = lpDIS->rcItem ;
CString text;
GetText(lpDIS->itemID, text);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(RGB(0,255,0));
if ((lpDIS->itemState & ODS_SELECTED))
dc.FillSolidRect(&rcItem,RGB(255,0,0));
else
dc.FillSolidRect(&rcItem,RGB(255,255,255));
dc.TextOut(rcItem.left,rcItem.top,text);
dc.Detach();//不分离的话就只能显示一项,其他的要点击后才出来
}
2.自绘的button有三种状态,选中,停留,离开:
绘制也很简单:
一个难点:WM_MOUSELEAVE和WM_MOUSEHOVER不是标准的Windows消息函数,解决方法:可通过_TrackMouseEvent()函数来触发.具体可参看MSDN有详细说明
1.在.h中加入:
bool m_bHover;//悬停
bool m_bSelected;//按下
bool m_bTracking;//跟踪
2.重载DrawItem和PreSubclassWindow;
3.三个消息:
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg LRESULT OnMouseHover(WPARAM wParam,LPARAM lParam);
afx_msg LRESULT OnMouseLeave(WPARAM wParam,LPARAM lParam);
[cpp] view plaincopy
void CSkinButton::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize=sizeof(tme);
tme.dwFlags=TME_HOVER|TME_LEAVE;//发送WM_MOUSEHOVER和WM_MOUSELEAVE
tme.hwndTrack=m_hWnd;////指定要追踪的窗口
tme.dwHoverTime=10;//鼠标在按钮上停留超过10ms,才认为状态为HOVER
m_bTracking=_TrackMouseEvent(&tme);//开启Windows的WM_MOUSELEAVEWM_MOUSEHOVER事件支持
}
CButton::OnMouseMove(nFlags, point);
}
LRESULT CSkinButton::OnMouseLeave(WPARAM wParam,LPARAM lParam)
{
m_bHover=false;
m_bTracking=false;////若已经离开,则停止追踪
return true;
}
LRESULT CSkinButton::OnMouseHover(WPARAM wParam,LPARAM lParam)
{
m_bHover=true;
InvalidateRect(NULL);//一定要调用刷新
return true;
}
4.在PreSubclassWindow初始化各种变量,如
void CSkinButton::PreSubclassWindow()
{
m_bHover=false;
m_bSelected=false;
m_bTracking=false;
ModifyStyle(0,BS_OWNERDRAW);
CButton::PreSubclassWindow();
}
5.在DrawItem中加入最后的自绘代码:
void CSkinButton::DrawItem(LPDRAWITEMSTRUCT lpdi)
{
CDC dc;
dc.Attach(lpdi->hDC);
CRect rc(lpdi->rcItem);
CString szText;
GetWindowText(szText); //获得文本
if (lpdi->itemState & ODS_SELECTED)
{
m_bSelected=true;
}
else
{
m_bSelected=false;
}
if (m_bSelected)//按下时绘制
{
//dc.DrawText(....);
}
else if (m_bHover)//停留时绘制
{
//dc.DrawText(....);
}
else
{
//dc.DrawText(....);
}
dc.Detach();
}