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);
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(); }