微软提供的 CListBox 只能响应鼠标双击消息,那如果要响应右键必须要继承 CListBox 这个,然后去响应 WM_RBUTTONUP 或 WM_RBUTTONDOWN 消息,在这个消息映射的函数里面就可以去写右键按下或弹起时的功能了。
图中的列表稍微自绘了一下,顺便也讲一下。调整行高是重写 MeasureItem 函数,如下
void CZZJListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
// TODO: Add your code to determine the size of specified item
lpMeasureItemStruct->itemHeight = 40;
}
绘制列表的项是要重写 DrawItem 函数,如下
void CZZJListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
if (GetCount() < 1)
{
return;
}
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
if (lpDrawItemStruct->itemState & ODS_SELECTED) //某一项被选中
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(180, 230 ,30)); //用颜色填充这一项
}
else
{
//实现项之间灰白相间
if (lpDrawItemStruct->itemID % 2 == 0)
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(220, 220, 220));
}
else
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(255, 255, 255));
}
}
//绘制文字
CString str;
GetText(lpDrawItemStruct->itemID, str);
lpDrawItemStruct->rcItem.left += 10;
pDC->DrawText(str, &lpDrawItemStruct->rcItem, DT_VCENTER | DT_SINGLELINE);
}
MeasureItem 和 DrawItem 都是虚函数。
下面正式讲响应鼠标右键消息。一般按下右键后,都希望同时选中鼠标指向的那一项,那么可以向当前鼠标的位置发送一个鼠标单击事件,那样就相当于鼠标在那个位置点击的左键,固然可以选中。代码如下
void CZZJListBox::OnRButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//如果列表中一项的没有,则不响应
if (0 == GetCount())
{
CListBox::OnRButtonUp(nFlags, point);
return;
}
//发送鼠标单击消息
SendMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(point.x, point.y));
SendMessage(WM_LBUTTONUP, 0, MAKELPARAM(point.x, point.y));
//得到当前选中项的字符串
int curSel = GetCurSel();
CString str;
GetText(curSel, str);
//弹出式菜单
CMenu menu;
menu.CreatePopupMenu();
menu.AppendMenu(MF_STRING, IDM_ITEM1, str);
menu.AppendMenu(MF_SEPARATOR, 0, _T(""));
menu.AppendMenu(MF_STRING, IDM_ITEM2, _T("删除"));
menu.AppendMenu(MF_STRING, IDM_ITEM3, _T("查看详情..."));
ClientToScreen(&point);
int nSel = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, point.x, point.y, this);
menu.DestroyMenu();
switch (nSel)
{
case IDM_ITEM2:
DeleteString(curSel);
break;
case IDM_ITEM3:
GetText(curSel, str);
MessageBox(str);
break;
default:
break;
}
CListBox::OnRButtonUp(nFlags, point);
}
完成之后就可以使用这个类,记得给列表改下属性,不然自绘效果不会生效的:
最后,调用 InsertString 或 AddString 测试。