Mam listę zrobioną na podstawie CListCtrl (chodzi o kolorowanie wierszy) i mam checkboxy na liście
żeby nie było zaznaczania na kliku, przeniosłem akcję na zdarzenie dblClick - dzięki temu aby dać focusa liście nie trzeba od razu zaznaczać elementu listy
ale na liście mam checkboxy i i chciałbym, aby kliknięcie w checkbox (tylko w checkbox) działało jak dblclik dla listy, jako że z MFC zaczynam zabawę to część kodu skopiowałem część sam napisałem i zaciąłem się w tym miejscu.
Zrobione jest to w następujący sposób
1-jest klasa dziedzicząca po CListCtrl, w której jest metoda DrawItem
void CListControlColor::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rcItem(lpDrawItemStruct->rcItem);
UINT uiFlags = ILD_TRANSPARENT;
CImageList* pImageList;
int nItem = lpDrawItemStruct->itemID;
BOOL bFocus = (GetFocus() == this);
COLORREF clrTextSave = pDC->GetTextColor ();
COLORREF clrBkSave = pDC->GetBkColor ();
COLORREF clrImage = GetItemBkColor(lpDrawItemStruct->itemID);
static _TCHAR szBuff[MAX_PATH];
// get item data
LV_ITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
lvi.iItem = nItem;
lvi.iSubItem = 0;
lvi.pszText = szBuff;
lvi.cchTextMax = sizeof(szBuff);
lvi.stateMask = 0xFFFF; // get all state flags
GetItem(&lvi);
BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);
// set colors if item is selected
CRect rcAllLabels;
GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);
CRect rcLabel;
GetItemRect(nItem, rcLabel, LVIR_LABEL);
rcAllLabels.left = rcLabel.left;
if (bSelected)
{
CBrush brBkgnd ( GetSysColor ( COLOR_HIGHLIGHT ) );
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
pDC->FillRect(rcAllLabels, &brBkgnd);
}
else
{
pDC->SetTextColor(GetItemTextColor(lpDrawItemStruct->itemID));
COLORREF crBkgnd = GetItemBkColor(lpDrawItemStruct->itemID);
if ( crBkgnd == CLR_DEFAULT )
crBkgnd = GetSysColor ( COLOR_WINDOW );
CBrush brBkgnd ( crBkgnd );
// if(GetStyle()|LVS_EX_GRIDLINES)
// rcAllLabels.DeflateRect(1,1,1,1);
if(GetStyle()|LVS_EX_CHECKBOXES)
{
}
pDC->FillRect(rcAllLabels, &brBkgnd );
}
// set color and mask for the icon
if (lvi.state & LVIS_CUT)
{
clrImage = GetItemBkColor(lpDrawItemStruct->itemID);
uiFlags |= ILD_BLEND50;
}
else if (bSelected)
{
clrImage = ::GetSysColor(COLOR_HIGHLIGHT);
uiFlags |= ILD_BLEND50;
}
// draw state icon
UINT nStateImageMask = lvi.state & LVIS_STATEIMAGEMASK;
if (nStateImageMask)
{
int nImage = (nStateImageMask>>12) - 1;
pImageList = GetImageList(LVSIL_STATE);
if (pImageList)
{
pImageList->Draw(pDC, nImage,
CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT);
}
}
// draw normal and overlay icon
CRect rcIcon;
GetItemRect(nItem, rcIcon, LVIR_ICON);
pImageList = GetImageList(LVSIL_SMALL);
if (pImageList)
{
UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
if (rcItem.left<rcItem.right-1)
{
ImageList_DrawEx(pImageList->m_hImageList, lvi.iImage,
pDC->m_hDC,rcIcon.left,rcIcon.top, 16, 16,
GetItemBkColor(lpDrawItemStruct->itemID), clrImage, uiFlags | nOvlImageMask);
}
}
// draw item label
GetItemRect(nItem, rcItem, LVIR_LABEL);
// rcItem.right -= 16;
rcLabel = rcItem;
rcLabel.left += OFFSET_FIRST;
rcLabel.right -= OFFSET_FIRST;
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH;
GetColumn(0, &lvc);
UINT nJustify = DT_LEFT;
switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
{
case LVCFMT_RIGHT:
nJustify = DT_RIGHT;
break;
case LVCFMT_CENTER:
nJustify = DT_CENTER;
break;
default:
break;
}
pDC->DrawText ( szBuff, -1, rcLabel, nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_MODIFYSTRING | DT_END_ELLIPSIS );
// draw labels for extra columns
for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
{
rcItem.left = rcItem.right;
rcItem.right += lvc.cx;
if ( GetItemText ( nItem, nColumn, szBuff, sizeof ( szBuff ) ) == 0 )
continue;
rcLabel = rcItem;
rcLabel.left += OFFSET_OTHER;
rcLabel.right -= OFFSET_OTHER;
nJustify = DT_LEFT;
switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
{
case LVCFMT_RIGHT:
nJustify = DT_RIGHT;
break;
case LVCFMT_CENTER:
nJustify = DT_CENTER;
break;
default:
break;
}
pDC->DrawText ( szBuff, -1, rcLabel, nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_MODIFYSTRING | DT_END_ELLIPSIS );
}
// draw focus rectangle if item has focus
if (lvi.state & LVIS_FOCUSED && bFocus)
pDC->DrawFocusRect(rcAllLabels);
// set original colors if item was selected
if (bSelected)
{
pDC->SetTextColor(clrTextSave);
pDC->SetBkColor(clrBkSave);
}
}
są z nią powiązane inne metody, ale nie będę ich wklejał - szkoda miejsca
2 - na dialogu mam metodę OnDblclkListTimetable, która wygląda następująco i zaznacza checkbox w wierszu
void CDlgListControl::OnDblclkListTimetable(NMHDR* pNMHDR, LRESULT* pResult)
{
BOOL bItemState=TRUE;
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );
m_ctrListRozkladLinia.ScreenToClient(&point);
LVHITTESTINFO lvinfo;
lvinfo.pt = point;
lvinfo.flags = LVHT_ABOVE;
lvinfo.pt.x;
lvinfo.pt.y;
if(nItem != -1)
{
// m_ctrListRozkladLinia.EnableWindow(FALSE);
bItemState = (m_ctrList.GetCheck(nItem)==TRUE)?FALSE:TRUE;
}
*pResult = 0;
}
3 - chcę to rozgraniczyć, tak aby dbclick pozostał dla wierszy, a click działał dla checkboxa
jako, że nie za bardzo i nie do końca rozumiem kod (szczególnie DrawItem) to próbowałem metoda prób i błędów, jedyne co osiągnąłem to efekt, że częśc wiersza należąca do pierwszej kolumny działa na click, a pozostałe na dblclick - co więcej zwykła lista, bez dziedziczenia ma takie rozgraniczenie - na checkboxa i wiersz - ale nie wiem co jest źle na tej dziedziczonej że czegoś takiego nie ma i jak takie coś zrobić
siędzę już nad tym trochę czasu i nie wiem jak się do tego zabrać co zrobić itp itd
może ktoś miałby pomysl - chętnie poczytam