📄 listview.c
字号:
int scrollWidth = 0; int scrollBoundMax; int scrollBoundMin; RECT rect; int hscroll = 0; PLVDATA plvdata; plvdata = (PLVDATA) GetWindowAdditionalData2 (hwnd); GetClientRect (hwnd, &rect); scrollBoundMax = sGetItemWidth (plvdata) - (rect.right - rect.left); scrollBoundMin = 0; //decides the desired value to scroll if (wParam == SB_LINERIGHT || wParam == SB_LINELEFT) hscroll = HSCROLL; else if (wParam == SB_PAGERIGHT || wParam == SB_PAGELEFT) hscroll = rect.right - rect.left; //scroll right if ( (wParam == SB_LINERIGHT || wParam == SB_PAGERIGHT) && plvdata->nOriginalX < scrollBoundMax ) { if ((plvdata->nOriginalX + hscroll) > scrollBoundMax) { scrollWidth = plvdata->nOriginalX - scrollBoundMax; plvdata->nOriginalX = scrollBoundMax; } else { plvdata->nOriginalX += hscroll; scrollWidth = -hscroll; } } //scroll left else if ( (wParam == SB_LINELEFT || wParam == SB_PAGELEFT) && plvdata->nOriginalX > scrollBoundMin) { if ((plvdata->nOriginalX - hscroll) > scrollBoundMin) { plvdata->nOriginalX -= hscroll; scrollWidth = hscroll; } else { scrollWidth = plvdata->nOriginalX - scrollBoundMin; plvdata->nOriginalX = scrollBoundMin; } } //draging else if (wParam == SB_THUMBTRACK) { int scrollNewPos = (int) lParam; if (((scrollNewPos - plvdata->nOriginalX) < HSCROLL) && ((scrollNewPos - plvdata->nOriginalX) > -HSCROLL) && (scrollNewPos > HSCROLL) && ((scrollBoundMax - scrollNewPos) > HSCROLL)) return; if ((scrollNewPos < plvdata->nOriginalX) && (scrollNewPos <= HSCROLL)) { scrollWidth = plvdata->nOriginalX - 0; plvdata->nOriginalX = 0; } else { if ((scrollNewPos > plvdata->nOriginalX) && ((scrollBoundMax - scrollNewPos) < HSCROLL)) { scrollWidth = plvdata->nOriginalX - scrollBoundMax; plvdata->nOriginalX = scrollBoundMax; } else { scrollWidth = plvdata->nOriginalX - scrollNewPos; plvdata->nOriginalX = scrollNewPos; } } } if (scrollWidth != 0) { InvalidateRect (hwnd, NULL, FALSE); lstSetHScrollInfo (plvdata); }}/************************* header operations ********************************/static PLSTHDR lvGetHdrByCol (PLVDATA plvdata, int nCols){ int i; PLSTHDR p1 = plvdata->pLstHead; if ((nCols > plvdata->nCols) || (nCols < 1 )) return NULL; for (i = 1; i < nCols; i++) { p1 = p1->pNext; } return p1;}/* creates a new header */static PLSTHDR lvHdrNew (PLVCOLUMN pcol, PLVDATA plvdata, int *col){ PLSTHDR p1; int nCols = pcol->nCols; if (!LV_BE_VALID_COL(nCols)) { nCols = plvdata->nCols + 1; *col = nCols; } p1 = (PLSTHDR) malloc (sizeof (LSTHDR)); p1->sort = NOTSORTED; p1->pfnCmp = pcol->pfnCompare; p1->Image = pcol->image; p1->flags = pcol->colFlags; if (pcol->pszHeadText != NULL) { p1->pTitle = (char *) malloc (strlen (pcol->pszHeadText) + 1); strcpy (p1->pTitle, pcol->pszHeadText); } else p1->pTitle = NULL; p1->x = sGetFrontSubItemsWidth (nCols - 1, plvdata); if (pcol->width <= 0) p1->width = LV_COLW_DEF; else if (pcol->width < COLWIDTHMIN) p1->width = COLWIDTHMIN; else p1->width = pcol->width; if (nCols == 1) { p1->pNext = plvdata->pLstHead; plvdata->pLstHead = p1; } else { PLSTHDR p2 = lvGetHdrByCol(plvdata, nCols-1); p1->pNext = p2->pNext; p2->pNext = p1; } return p1;}//free a headerstatic void lvHdrFree (PLSTHDR pLstHdr){ if (pLstHdr != NULL) { if (pLstHdr->pTitle != NULL) free (pLstHdr->pTitle); free (pLstHdr); }}//deletes a headerstatic void lvHdrDel (int nCols, PLVDATA plvdata){ PLSTHDR p1 = plvdata->pLstHead; PLSTHDR pdel; if (nCols == 1) { pdel = p1; plvdata->pLstHead = p1->pNext; } else { p1 = lvGetHdrByCol(plvdata, nCols-1); if (!p1) return; pdel = p1->pNext; if (pdel) { p1->pNext = pdel->pNext; lvHdrFree(pdel); } }}/* ========================================================================= * Model & Data section of the listview control. ========================================================================= */static PITEMDATA lvGetItemByRow (PLVDATA plvdata, int nRows){ int i; PITEMDATA pItem = plvdata->pItemHead; if ((nRows > plvdata->nRows) || (nRows < 1 )) return NULL; for (i = 1; i < nRows; i++) { pItem = pItem->pNext; } return pItem;}static PSUBITEMDATA lvGetSubItemByCol (PITEMDATA pItem, int nCols){ int i; PSUBITEMDATA pSubItem; if (!pItem) return NULL; pSubItem = pItem->pSubItemHead; for (i = 1; i < nCols; i++) { pSubItem = pSubItem->pNext; } return pSubItem;}#define lstSelectItem(hwnd, nRows, plvdata) \ lvSetItemSelect (hwnd, nRows, plvdata, TRUE)#define lstUnSelectItem(hwnd, nRows, plvdata) \ lvSetItemSelect (hwnd, nRows, plvdata, FALSE)/* select and make the original one unselected */#define lvSelectItem(hwnd, nRows, plvdata) \ lstUnSelectItem(hwnd, plvdata->nItemSelected, plvdata); \ lstSelectItem(hwnd, nRows, plvdata);/* Sets the item to be selcted or unselected status */static intlvSetItemSelect (HWND hwnd, int nRows, PLVDATA plvdata, BOOL bSel){ PITEMDATA pSel; RECT rect; if ( !(pSel = lvGetItemByRow (plvdata, nRows)) ) return LV_ERR; if (bSel == pSel->bSelected) return LV_ERR; if (bSel) { plvdata->nItemSelected = nRows; } else { plvdata->nItemSelected = 0; } pSel->bSelected = bSel; LV_GET_ITEM_RECT(nRows, rect); InvalidateRect (hwnd, &rect, FALSE); return LV_OKAY;}#if 0#define lvSelectNextItem(hwnd, plvdata) \ lvStepItem(hwnd, plvdata, 1)#define lvSelectPrevItem(hwnd, plvdata) \ lvStepItem(hwnd, plvdata, -1)static voidlvStepItem(HWND hwnd, PLVDATA plvdata, int step){ int prev; prev = plvdata->nItemSelected; if (prev+step <= plvdata->nRows && prev+step > 0) { lstUnSelectItem (hwnd, prev, plvdata); lstSelectItem (hwnd, prev+step, plvdata); }}#endif/**************************** data init and destroy ************************/static void InitListViewData (HWND hwnd){ PLVDATA plvdata = (PLVDATA) GetWindowAdditionalData2 (hwnd); plvdata->nCols = 0; plvdata->nRows = 0; plvdata->hWnd = hwnd; plvdata->pLstHead = NULL; plvdata->pItemHead = NULL; plvdata->nOriginalX = 0; plvdata->nOriginalY = 0; LVSTATUS(hwnd) = LVST_NORMAL; plvdata->pHdrClicked = NULL; plvdata->nItemDraged = 0; plvdata->nItemSelected = 0; plvdata->bkc_selected = LIGHTBLUE; plvdata->nItemHeight = LV_ITEMH_DEF(hwnd); plvdata->nHeadHeight = LV_HDRH_DEF(hwnd); plvdata->str_cmp = strncmp;}//Destroies all the internal datasstatic void lvDataDestory (PLVDATA plvdata){ PITEMDATA p1, p2; PLSTHDR ph, ph2; p1 = plvdata->pItemHead; while (p1 != NULL) { p2 = p1; p1 = p1->pNext; itemDelete (p2); } ph = plvdata->pLstHead; while (ph) { ph2 = ph; ph = ph->pNext; lvHdrFree (ph2); } free (plvdata);}/******************** subitem operations ****************************/static PSUBITEMDATA subitemNew (const char *pszInfoText){ PSUBITEMDATA p1; p1 = (PSUBITEMDATA) malloc (sizeof (SUBITEMDATA)); p1->pNext = NULL; if (pszInfoText != NULL) { p1->pszInfo = (char *) malloc (strlen (pszInfoText) + 1); strcpy (p1->pszInfo, pszInfoText); } else p1->pszInfo = NULL; p1->nTextColor = PIXEL_black; p1->Image = 0; p1->dwFlags = 0; return p1;}static void subitemFree (PSUBITEMDATA pSubItemData){ if (pSubItemData != NULL) { if (pSubItemData->pszInfo != NULL) free (pSubItemData->pszInfo); free (pSubItemData); }}static voidlvAddSubitem (PLVDATA plvdata, int nCols){ int i; PSUBITEMDATA p2, p3; PITEMDATA p1 = plvdata->pItemHead; while (p1) { p2 = subitemNew (NULL); if (nCols == 1) { p2->pNext = p1->pSubItemHead; p1->pSubItemHead = p2; } else { p3 = p1->pSubItemHead; for (i = 1; i < nCols-1; i++) { p3 = p3->pNext; } p2->pNext = p3->pNext; p3->pNext = p2; } p1 = p1->pNext; }}static voidlvDelSubitem (PLVDATA plvdata, int nCols){ int i; PSUBITEMDATA p2, pdel; PITEMDATA p1 = plvdata->pItemHead; while (p1) { if (nCols == 1) { p1->pSubItemHead = p1->pSubItemHead->pNext; } else { p2 = p1->pSubItemHead; for (i = 1; i < nCols-1; i++) { p2 = p2->pNext; } pdel = p2->pNext; p2->pNext = pdel->pNext; subitemFree(pdel); } p1 = p1->pNext; }}static BOOL lvAddColumnToList (PLVCOLUMN pcol, PLVDATA plvdata){ PLSTHDR p1 = NULL; int nCols = pcol->nCols; p1 = lvHdrNew (pcol, plvdata, &nCols); if (!p1) return FALSE; lvAddSubitem (plvdata, nCols); sAddOffsetToTailSubItem (nCols, p1->width, plvdata); plvdata->nCols ++; return TRUE;}static int sGetItemSeq (PLVDATA plvdata){ PITEMDATA p1; int i = 0; p1 = plvdata->pItemHead; while (p1) { i++; if (p1->bSelected) return i; p1 = p1->pNext; } return -1;}//FIXMEstatic int sModifyHeadText (int nCols, const char *pszHeadText, PLVDATA plvdata){ PLSTHDR p1 = NULL; p1 = lvGetHdrByCol(plvdata, nCols); if (!p1 || !pszHeadText) return -1; if (p1->pTitle != NULL) free (p1->pTitle); p1->pTitle = (char *) malloc (sizeof (pszHeadText) + 1); strcpy (p1->pTitle, pszHeadText); return 0;}inline static PSUBITEMDATAlvGetSubItem (int nItem, int nSubItem, PLVDATA plvdata){ PITEMDATA pItem = lvGetItemByRow(plvdata, nItem); return lvGetSubItemByCol(pItem, nSubItem);}/* Sets the properties of the subitem *//* Fills the content of a subitem */static int lvFillSubItem (int nItem, int subItem, const char *pszText, PLVDATA plvdata){ PSUBITEMDATA p1; if ( !(p1 = lvGetSubItem (nItem, subItem, plvdata)) ) return -1; if (pszText == NULL) return -1; if (p1->pszInfo != NULL) free (p1->pszInfo); p1->pszInfo = (char *) malloc (strlen (pszText) + 1); strcpy (p1->pszInfo, pszText); return 0;}/* Sets the text color of the subitem */static int lvSetSubItemTextColor (int nItem, int subItem, int color, PLVDATA plvdata){ PSUBITEMDATA p1; if ( !(p1 = lvGetSubItem (nItem, subItem, plvdata)) ) return -1; p1->nTextColor = color; return 0;}static int lvSetSubItem (PLVSUBITEM pinfo, PLVDATA plvdata){ PSUBITEMDATA p1; if ( !(p1 = lvGetSubItem (pinfo->nItem, pinfo->subItem, plvdata)) ) return -1; if (p1->pszInfo != NULL) free (p1->pszInfo); p1->pszInfo = (char *) malloc (strlen (pinfo->pszText) + 1); strcpy (p1->pszInfo, pinfo->pszText); p1->nTextColor = pinfo->nTextColor; if (pinfo->flags & LVFLAG_BITMAP) p1->dwFlags |= LVIF_BITMAP; if (pinfo->flags & LVFLAG_ICON) p1->dwFlags |= LVIF_ICON; p1->Image = pinfo->image; return 0;}static int lvRemoveColumn (int nCols, PLVDATA plvdata){ int offset; if (!LV_BE_VALID_COL(nCols)) return -1; offset = -(sGetSubItemWidth (nCols, plvdata)); sAddOffsetToTailSubItem (nCols + 1, offset, plvdata); lvHdrDel (nCols, plvdata); lvDelSubitem (plvdata, nCols); plvdata->nCols --; lstSetHScrollInfo (plvdata); InvalidateRect (plvdata->hWnd, NULL, FALSE); return 0;}static PITEMDATA itemNew (int nCols){ PSUBITEMDATA pHead = NULL; PSUBITEMDATA p1 = NULL; PSUBITEMDATA p2 = NULL; PITEMDATA p3 = NULL; int i; int j; j = nCols; if (j >= 1) { pHead = subitemNew (NULL); p1 = pHead; } else return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -