This one reworks the {Insert,Delete}Column code. The InsertColumn still doesn't work properly due to a bug in Header control. This is not a step back, as both were badly broken before. ChangeLog -- Rework the {Insert,Delete}Column functions -- Drawing optimizations when adding/removing columns -- More cleanups, and simplifications. Index: dlls/comctl32/listview.c =================================================================== RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v retrieving revision 1.158 diff -u -r1.158 listview.c --- dlls/comctl32/listview.c 1 Oct 2002 18:06:15 -0000 1.158 +++ dlls/comctl32/listview.c 2 Oct 2002 00:41:08 -0000 @@ -162,7 +162,6 @@ WNDPROC EditWndProc; INT nEditLabelItem; DWORD dwHoverTime; - INT nColumnCount; /* the number of columns in this control */ DWORD lastKeyPressTimestamp; WPARAM charCode; @@ -269,18 +268,14 @@ static void LISTVIEW_AlignLeft(LISTVIEW_INFO *); static void LISTVIEW_AlignTop(LISTVIEW_INFO *); static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *, INT); -static void LISTVIEW_AddSelection(LISTVIEW_INFO *, INT); static INT LISTVIEW_GetItemHeight(LISTVIEW_INFO *); static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *, INT, LPPOINT); static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *, INT, LPRECT); -static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *, INT, INT, INT, LPRECT); static INT LISTVIEW_GetItemWidth(LISTVIEW_INFO *); static INT LISTVIEW_GetLabelWidth(LISTVIEW_INFO *, INT); static LRESULT LISTVIEW_GetColumnWidth(LISTVIEW_INFO *, INT); static BOOL LISTVIEW_GetOrigin(LISTVIEW_INFO *, LPPOINT); static BOOL LISTVIEW_GetViewRect(LISTVIEW_INFO *, LPRECT); -static BOOL LISTVIEW_RemoveColumn(HDPA, INT); -static BOOL LISTVIEW_RemoveSubItem(HDPA, INT); static void LISTVIEW_SetGroupSelection(LISTVIEW_INFO *, INT); static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL); static BOOL LISTVIEW_SetItemPosition(LISTVIEW_INFO *, INT, LONG, LONG); @@ -1496,7 +1491,6 @@ } else { - /*FIXME: should this be Label or FullText */ UnionRect(&Boundary, &Icon, &Label); } @@ -1665,8 +1659,7 @@ *lprcView = infoPtr->rcView; OffsetRect(lprcView, ptOrigin.x, ptOrigin.y); - TRACE("(left=%d, top=%d, right=%d, bottom=%d)\n", - lprcView->left, lprcView->top, lprcView->right, lprcView->bottom); + TRACE("lprcView=%s\n", debugrect(lprcView)); return TRUE; } @@ -2100,7 +2093,7 @@ do { - sel = DPA_GetPtr(infoPtr->hdpaSelectionRanges,0); + sel = DPA_GetPtr(infoPtr->hdpaSelectionRanges, 0); if (sel) LISTVIEW_RemoveSelectionRange(infoPtr, sel->lower, sel->upper); } while (infoPtr->hdpaSelectionRanges->nItemCount > 0); @@ -2239,31 +2232,6 @@ /*** * DESCRIPTION: - * Adds a single selection. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] INT : item index - * - * RETURN: - * None - */ -static void LISTVIEW_AddSelection(LISTVIEW_INFO *infoPtr, INT nItem) -{ - LVITEMW item; - - item.state = LVIS_SELECTED; - item.stateMask = LVIS_SELECTED; - - LISTVIEW_SetItemState(infoPtr,nItem,&item); - - LISTVIEW_SetItemFocus(infoPtr, nItem); - infoPtr->nSelectionMark = nItem; -} - - -/*** - * DESCRIPTION: * Sets a single group selection. * * PARAMETER(S): @@ -2490,82 +2458,6 @@ return 0; } -/*** - * DESCRIPTION: - * Removes a column. - * - * PARAMETER(S): - * [IO] HDPA : dynamic pointer array handle - * [I] INT : column index (subitem index) - * - * RETURN: - * SUCCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem) -{ - BOOL bResult = TRUE; - HDPA hdpaSubItems; - INT i; - - for (i = 0; i < hdpaItems->nItemCount; i++) - { - hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i); - if (hdpaSubItems != NULL) - { - if (!LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem)) - { - bResult = FALSE; - } - } - } - - return bResult; -} - -/*** - * DESCRIPTION: - * Removes a subitem at a given position. - * - * PARAMETER(S): - * [IO] HDPA : dynamic pointer array handle - * [I] INT : subitem index - * - * RETURN: - * SUCCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem) -{ - LISTVIEW_SUBITEM *lpSubItem; - INT i; - - for (i = 1; i < hdpaSubItems->nItemCount; i++) - { - lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); - if (lpSubItem != NULL) - { - if (lpSubItem->iSubItem == nSubItem) - { - /* free string */ - if (is_textW(lpSubItem->hdr.pszText)) - COMCTL32_Free(lpSubItem->hdr.pszText); - - /* free item */ - COMCTL32_Free(lpSubItem); - - /* free dpa memory */ - if (DPA_DeletePtr(hdpaSubItems, i) == NULL) - return FALSE; - } - else if (lpSubItem->iSubItem > nSubItem) - return TRUE; - } - } - - return TRUE; -} - /*** * DESCRIPTION: [INTERNAL] @@ -2743,7 +2635,7 @@ hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); if (!hdpaSubItems && hdpaSubItems != (HDPA)-1) return FALSE; - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem); + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); if (!lpItem) return FALSE; /* determine what fields will change */ @@ -3066,8 +2958,7 @@ INT textLeft; INT nLabelWidth = 0; - TRACE("(hdc=%x, nItem=%d, nSubItem=%d)\n", hdc, - nItem, nSubItem); + TRACE("(hdc=%x, nItem=%d, nSubItem=%d)\n", hdc, nItem, nSubItem); /* get information needed for drawing the item */ lvItem.mask = LVIF_TEXT; @@ -3095,7 +2986,7 @@ } /* set item colors */ - if (ListView_GetItemState(infoPtr->hwndSelf,nItem,LVIS_SELECTED) && Selected) + if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED) && Selected) { if (infoPtr->bFocus) { @@ -3124,9 +3015,8 @@ SetTextColor(hdc, infoPtr->clrText); } - TRACE("drawing text %s, l=%d, t=%d, rect=(%d,%d)-(%d,%d)\n", - debugstr_w(lvItem.pszText), textLeft, rcItem.top, - rcItem.left, rcItem.top, rcItem.right, rcItem.bottom); + TRACE("drawing text %s, len=%d, rect=%s\n", + debugstr_w(lvItem.pszText), textLeft, debugrect(&rcItem)); ExtTextOutW(hdc, textLeft, rcItem.top, textoutOptions, &rcItem, lvItem.pszText, lstrlenW(lvItem.pszText), NULL); @@ -3558,11 +3448,13 @@ /* cache column info */ nColumnCount = Header_GetItemCount(infoPtr->hwndHeader); - infoPtr->nColumnCount = nColumnCount; /* update nColumnCount */ lprcCols = COMCTL32_Alloc(nColumnCount * sizeof(RECT)); if (!lprcCols) return; - for (j = 0; j < nColumnCount; j++) + for (j = 0; j < nColumnCount; j++) + { Header_GetItemRect(infoPtr->hwndHeader, j, &lprcCols[j]); + TRACE("lprcCols[%d]=%s\n", j, debugrect(&lprcCols[j])); + } /* Get scroll info once before loop */ LISTVIEW_GetOrigin(infoPtr, &ptOrig); @@ -3685,7 +3577,6 @@ /* get number of fully visible columns */ nColumnCount = nListWidth / nItemWidth; if (nListWidth % nItemWidth) nColumnCount++; - infoPtr->nColumnCount = nColumnCount; nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr); nItem = ListView_GetTopIndex(infoPtr->hwndSelf); TRACE("nColumnCount=%d, nCountPerColumn=%d, start item=%d\n", @@ -3741,8 +3632,6 @@ DWORD cditemmode = CDRF_DODEFAULT; TRACE("\n"); - infoPtr->nColumnCount = 1; /* set this to an arbitrary value to prevent */ - /* DrawItem from erasing the incorrect background area */ /* nothing to draw, return here */ if(GETITEMCOUNT(infoPtr) == 0) @@ -4130,10 +4019,67 @@ */ static BOOL LISTVIEW_DeleteColumn(LISTVIEW_INFO *infoPtr, INT nColumn) { - if (!Header_DeleteItem(infoPtr->hwndHeader, nColumn)) return FALSE; + UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; + RECT rcCol, rcOld; + + TRACE("nColumn=%d\n", nColumn); + + if (nColumn <= 0) return FALSE; + + if (uView == LVS_REPORT) + { + if (!Header_GetItemRect(infoPtr->hwndHeader, nColumn, &rcCol)) + return FALSE; + + if (!Header_DeleteItem(infoPtr->hwndHeader, nColumn)) + return FALSE; + } if (!(infoPtr->dwStyle & LVS_OWNERDATA)) - LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn); + { + LISTVIEW_SUBITEM *lpSubItem, *lpDelItem; + HDPA hdpaSubItems; + INT nItem, nSubItem, i; + + for (nItem = 0; nItem < infoPtr->hdpaItems->nItemCount; nItem++) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (!hdpaSubItems) continue; + nSubItem = 0; + lpDelItem = 0; + for (i = 1; i < hdpaSubItems->nItemCount; i++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); + if (!lpSubItem) break; + if (lpSubItem->iSubItem == nColumn) + { + nSubItem = i; + lpDelItem = lpSubItem; + } + else if (lpSubItem->iSubItem > nColumn) + { + lpSubItem->iSubItem--; + } + } + + /* if we found our subitem, zapp it */ + if (nSubItem > 0) + { + /* free string */ + if (is_textW(lpDelItem->hdr.pszText)) + COMCTL32_Free(lpDelItem->hdr.pszText); + + /* free item */ + COMCTL32_Free(lpDelItem); + + /* free dpa memory */ + DPA_DeletePtr(hdpaSubItems, nSubItem); + } + } + } + + /* we need to worry about display issues in report mode only */ + if (uView != LVS_REPORT) return TRUE; /* Need to reset the item width when deleting a column */ infoPtr->nItemWidth = LISTVIEW_GetItemWidth(infoPtr); @@ -4141,8 +4087,11 @@ /* update scrollbar(s) */ LISTVIEW_UpdateScroll(infoPtr); - /* FIXME: invalidate only fromthe deleted column to the right */ - LISTVIEW_InvalidateList(infoPtr); + /* scroll to cover the deleted column, and invalidate for redraw */ + rcOld = infoPtr->rcList; + rcOld.left = rcCol.left; + ScrollWindowEx(infoPtr->hwndSelf, -(rcCol.right - rcCol.left), 0, + &rcOld, &rcOld, 0, 0, SW_ERASE | SW_INVALIDATE); return TRUE; } @@ -4899,24 +4848,24 @@ */ static LRESULT LISTVIEW_GetColumnWidth(LISTVIEW_INFO *infoPtr, INT nColumn) { - UINT uView = LISTVIEW_GetType(infoPtr); - INT nColumnWidth = 0; - HDITEMW hdi; + INT nColumnWidth = 0; + HDITEMW hdi; - if (uView == LVS_LIST) - { - nColumnWidth = infoPtr->nItemWidth; - } - else if (uView == LVS_REPORT) - { - /* get column width from header */ - ZeroMemory(&hdi, sizeof(hdi)); - hdi.mask = HDI_WIDTH; - if (Header_GetItemW(infoPtr->hwndHeader, nColumn, &hdi)) - nColumnWidth = hdi.cxy; - } + switch(LISTVIEW_GetType(infoPtr)) + { + case LVS_LIST: + nColumnWidth = infoPtr->nItemWidth; + break; + case LVS_REPORT: + hdi.mask = HDI_WIDTH; + if (Header_GetItemW(infoPtr->hwndHeader, nColumn, &hdi)) + nColumnWidth = hdi.cxy; + break; + default: + /* we don't have a 'column' in [SMALL]ICON mode */ + } - return nColumnWidth; + return nColumnWidth; } /*** @@ -5456,8 +5405,7 @@ } -static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *infoPtr, INT nItem, INT nSubItem, INT -flags, LPRECT lprc) +static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *infoPtr, INT nItem, INT nSubItem, INT flags, LPRECT lprc) { UINT uView = LISTVIEW_GetType(infoPtr); INT count; @@ -5475,7 +5423,7 @@ } else { - int top = min(infoPtr->nColumnCount, nSubItem - 1); + int top = min(Header_GetItemCount(infoPtr->hwndHeader), nSubItem - 1); LISTVIEW_GetItemRect(infoPtr,nItem,lprc); for (count = 0; count < top; count++) @@ -5964,9 +5912,10 @@ set_subitem: if (subitem) { + INT nColumnCount = Header_GetItemCount(infoPtr->hwndHeader); lpInt->ht.iSubItem = 0; rcSubItem.right = rcSubItem.left; - for (j = 0; j < infoPtr->nColumnCount; j++) + for (j = 0; j < nColumnCount; j++) { rcSubItem.left = rcSubItem.right; rcSubItem.right += LISTVIEW_GetColumnWidth(infoPtr, j); @@ -6116,127 +6065,161 @@ static LRESULT LISTVIEW_InsertColumnT(LISTVIEW_INFO *infoPtr, INT nColumn, LPLVCOLUMNW lpColumn, BOOL isW) { - INT nNewColumn = -1; - HDITEMW hdi; + RECT rcOld, rcCol; + INT nNewColumn; + HDITEMW hdi; - TRACE("(nColumn=%d, lpColumn=%s, isW=%d)\n", nColumn, debuglvcolumn_t(lpColumn, isW), isW); + TRACE("(nColumn=%d, lpColumn=%s, isW=%d)\n", nColumn, debuglvcolumn_t(lpColumn, isW), isW); - if (lpColumn != NULL) - { - /* initialize memory */ - ZeroMemory(&hdi, sizeof(hdi)); + if (!lpColumn) return -1; + hdi.mask = hdi.fmt = 0; if (lpColumn->mask & LVCF_FMT) { - /* format member is valid */ - hdi.mask |= HDI_FORMAT; + /* format member is valid */ + hdi.mask |= HDI_FORMAT; - /* set text alignment (leftmost column must be left-aligned) */ - if (nColumn == 0) - { - hdi.fmt |= HDF_LEFT; - } - else - { - if (lpColumn->fmt & LVCFMT_LEFT) - { - hdi.fmt |= HDF_LEFT; - } + /* set text alignment (leftmost column must be left-aligned) */ + if (nColumn == 0 || lpColumn->fmt & LVCFMT_LEFT) + hdi.fmt |= HDF_LEFT; else if (lpColumn->fmt & LVCFMT_RIGHT) - { - hdi.fmt |= HDF_RIGHT; - } + hdi.fmt |= HDF_RIGHT; else if (lpColumn->fmt & LVCFMT_CENTER) - { - hdi.fmt |= HDF_CENTER; - } - } + hdi.fmt |= HDF_CENTER; - if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) - { - hdi.fmt |= HDF_BITMAP_ON_RIGHT; - /* ??? */ - } + if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) + hdi.fmt |= HDF_BITMAP_ON_RIGHT; - if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) - { - /* ??? */ - } + if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) + { + hdi.fmt |= HDF_IMAGE; + hdi.iImage = I_IMAGECALLBACK; + } - if (lpColumn->fmt & LVCFMT_IMAGE) - { - hdi.fmt |= HDF_IMAGE; - hdi.iImage = I_IMAGECALLBACK; - } + if (lpColumn->fmt & LVCFMT_IMAGE) + ; /* FIXME: enable images for *(sub)items* this column */ } if (lpColumn->mask & LVCF_WIDTH) { - hdi.mask |= HDI_WIDTH; - if(lpColumn->cx == LVSCW_AUTOSIZE_USEHEADER) - { - /* make it fill the remainder of the controls width */ - HDITEMW hdit; - RECT rcHeader; - INT item_index; - - ZeroMemory(&hdit, sizeof(hdit)); - - /* get the width of every item except the current one */ - hdit.mask = HDI_WIDTH; - hdi.cxy = 0; + hdi.mask |= HDI_WIDTH; + if(lpColumn->cx == LVSCW_AUTOSIZE_USEHEADER) + { + /* make it fill the remainder of the controls width */ + HDITEMW hdit; + RECT rcHeader; + INT item_index; + + /* get the width of every item except the current one */ + hdit.mask = HDI_WIDTH; + hdi.cxy = 0; + + for(item_index = 0; item_index < (nColumn - 1); item_index++) + if (Header_GetItemW(infoPtr->hwndHeader, item_index, (LPARAM)(&hdit))) + hdi.cxy += hdit.cxy; + + /* retrieve the layout of the header */ + GetClientRect(infoPtr->hwndSelf, &rcHeader); + TRACE("start cxy=%d rcHeader=%s\n", hdi.cxy, debugrect(&rcHeader)); - for(item_index = 0; item_index < (nColumn - 1); item_index++) { - Header_GetItemW(infoPtr->hwndHeader, item_index, (LPARAM)(&hdit)); - hdi.cxy+=hdit.cxy; + hdi.cxy = (rcHeader.right - rcHeader.left) - hdi.cxy; } - - /* retrieve the layout of the header */ - GetClientRect(infoPtr->hwndSelf, &rcHeader); -/* GetWindowRect(infoPtr->hwndHeader, &rcHeader);*/ - TRACE("start cxy=%d left=%d right=%d\n", hdi.cxy, rcHeader.left, rcHeader.right); - - hdi.cxy = (rcHeader.right - rcHeader.left) - hdi.cxy; - } - else - hdi.cxy = lpColumn->cx; + else + hdi.cxy = lpColumn->cx; } if (lpColumn->mask & LVCF_TEXT) { - hdi.mask |= HDI_TEXT | HDI_FORMAT; - hdi.pszText = lpColumn->pszText; - hdi.cchTextMax = textlenT(lpColumn->pszText, isW); - hdi.fmt |= HDF_STRING; + hdi.mask |= HDI_TEXT | HDI_FORMAT; + hdi.fmt |= HDF_STRING; + hdi.pszText = lpColumn->pszText; + hdi.cchTextMax = textlenT(lpColumn->pszText, isW); } if (lpColumn->mask & LVCF_IMAGE) { - hdi.mask |= HDI_IMAGE; - hdi.iImage = lpColumn->iImage; + hdi.mask |= HDI_IMAGE; + hdi.iImage = lpColumn->iImage; } if (lpColumn->mask & LVCF_ORDER) { - hdi.mask |= HDI_ORDER; - hdi.iOrder = lpColumn->iOrder; + hdi.mask |= HDI_ORDER; + hdi.iOrder = lpColumn->iOrder; } /* insert item in header control */ nNewColumn = SendMessageW(infoPtr->hwndHeader, isW ? HDM_INSERTITEMW : HDM_INSERTITEMA, (WPARAM)nColumn, (LPARAM)&hdi); + if (nNewColumn == -1) return -1; + if (!Header_GetItemRect(infoPtr->hwndHeader, nNewColumn, &rcCol)) return -1; + + /* now we have to actually adjust the data */ + if (!(infoPtr->dwStyle & LVS_OWNERDATA) && infoPtr->hdpaItems->nItemCount > 0) + { + LISTVIEW_SUBITEM *lpSubItem, *lpMainItem, **lpNewItems = 0; + HDPA hdpaSubItems; + INT nItem, i; + + /* preallocate memory, so we can fail gracefully */ + if (nNewColumn == 0) + { + lpNewItems = COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM *) * infoPtr->hdpaItems->nItemCount); + if (!lpNewItems) return -1; + for (i = 0; i < infoPtr->hdpaItems->nItemCount; i++) + if (!(lpNewItems[i] = COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM)))) break; + if (i != infoPtr->hdpaItems->nItemCount) + { + for(; i >=0; i--) COMCTL32_Free(lpNewItems[i]); + COMCTL32_Free(lpNewItems); + return -1; + } + } + + for (nItem = 0; nItem < infoPtr->hdpaItems->nItemCount; nItem++) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (!hdpaSubItems) continue; + for (i = 1; i < hdpaSubItems->nItemCount; i++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); + if (!lpSubItem) break; + if (lpSubItem->iSubItem >= nNewColumn) + lpSubItem->iSubItem++; + } + + /* if we found our subitem, zapp it */ + if (nNewColumn == 0) + { + lpMainItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, 0); + lpSubItem = lpNewItems[nItem]; + lpSubItem->hdr = lpMainItem->hdr; + lpSubItem->iSubItem = 1; + ZeroMemory(&lpMainItem->hdr, sizeof(lpMainItem->hdr)); + lpMainItem->iSubItem = 0; + DPA_InsertPtr(hdpaSubItems, 1, lpSubItem); + } + } + COMCTL32_Free(lpNewItems); + } + + /* we don't have to worry abiut display issues in non-report mode */ + if ((infoPtr->dwStyle & LVS_TYPEMASK) != LVS_REPORT) return nNewColumn; + /* Need to reset the item width when inserting a new column */ infoPtr->nItemWidth = LISTVIEW_GetItemWidth(infoPtr); LISTVIEW_UpdateScroll(infoPtr); - /* FIXME: invalidate from inserted column to right */ - LISTVIEW_InvalidateList(infoPtr); - } - - return nNewColumn; + /* scroll to cover the deleted column, and invalidate for redraw */ + rcOld = infoPtr->rcList; + rcOld.left = rcCol.left; + ScrollWindowEx(infoPtr->hwndSelf, rcCol.right - rcCol.left, 0, + &rcOld, &rcOld, 0, 0, SW_ERASE | SW_INVALIDATE); + + return nNewColumn; } /* LISTVIEW_InsertCompare: callback routine for comparing pszText members of the LV_ITEMS @@ -7566,7 +7549,7 @@ { /* now we can scroll the list */ ScrollWindowEx(infoPtr->hwndSelf, dx, dy, &infoPtr->rcList, - &infoPtr->rcList, 0, 0, SW_INVALIDATE); + &infoPtr->rcList, 0, 0, SW_ERASE | SW_INVALIDATE); /* if we have focus, adjust rect */ if (infoPtr->bFocus && !IsRectEmpty(&infoPtr->rcFocus)) OffsetRect(&infoPtr->rcFocus, dx, dy); @@ -8041,7 +8024,17 @@ if (bGroupSelect) LISTVIEW_AddGroupSelection(infoPtr, nItem); else - LISTVIEW_AddSelection(infoPtr, nItem); + { + LVITEMW item; + + item.state = LVIS_SELECTED; + item.stateMask = LVIS_SELECTED; + + LISTVIEW_SetItemState(infoPtr,nItem,&item); + + LISTVIEW_SetItemFocus(infoPtr, nItem); + infoPtr->nSelectionMark = nItem; + } } else if (wKey & MK_CONTROL) {