📄 listview.c
字号:
for (i = 1; i <= j - 1; i++) { p2 = subitemNew (NULL); p1->pNext = p2; p1 = p2; } p3 = (PITEMDATA) malloc (sizeof (ITEMDATA)); p3->pNext = NULL; p3->bSelected = FALSE; p3->pSubItemHead = pHead; return p3;}static int itemDelete (PITEMDATA pItem){ PSUBITEMDATA p1 = NULL; PSUBITEMDATA p2 = NULL; p1 = pItem->pSubItemHead; while (p1 != NULL) { p2 = p1; p1 = p1->pNext; subitemFree (p2); } pItem->pSubItemHead = NULL; free (pItem); return 0;}static int sAddItemToList (int nItem, PITEMDATA pnew, PLVDATA plvdata){ int i; PITEMDATA p1 = pnew; PITEMDATA p2 = NULL; PITEMDATA p3 = NULL; if (plvdata->nRows > LV_ROW_MAX) return -1; if ((nItem < 1) || (nItem > plvdata->nRows)) nItem = plvdata->nRows + 1; if (p1 == NULL) return -1; if (nItem == 1) { p2 = plvdata->pItemHead; plvdata->pItemHead = p1; p1->pNext = p2; } else { i = nItem; p2 = plvdata->pItemHead; while (i != 2) { i = i - 1; p2 = p2->pNext; } p3 = p2->pNext; p2->pNext = p1; p1->pNext = p3; } plvdata->nRows ++; if (nItem <= plvdata->nItemSelected) plvdata->nItemSelected++; return nItem;}static int sRemoveItemFromList (int nItem, PLVDATA plvdata){ PITEMDATA p1 = NULL; PITEMDATA pp1 = NULL; if ((nItem < 1) || (nItem > plvdata->nRows) || (plvdata->nRows < 1)) return -1; if (nItem == 1) { p1 = plvdata->pItemHead; plvdata->pItemHead = plvdata->pItemHead->pNext; } else { pp1 = lvGetItemByRow (plvdata, nItem-1); p1 = pp1->pNext; pp1->pNext = p1->pNext; } if (p1->bSelected) plvdata->nItemSelected = 0; itemDelete (p1); plvdata->nRows --; /* if () { plvdata->nOriginalY -= plvdata->nItemHeight; } */ lstSetVScrollInfo (plvdata); InvalidateRect (plvdata->hWnd, NULL, FALSE); return 0;}static int sRemoveAllItem (PLVDATA plvdata){ PITEMDATA p1 = NULL; PITEMDATA p2 = NULL; p1 = plvdata->pItemHead; while (p1 != NULL) { p2 = p1; p1 = p1->pNext; itemDelete (p2); } plvdata->nRows = 0; plvdata->pItemHead = NULL; //plvdata->nOriginalX = 0; lstSetVScrollInfo (plvdata); //lstSetHScrollInfo (plvdata); InvalidateRect (plvdata->hWnd, NULL, FALSE); return 0;}static int lvFindItem (PLVFINDINFO pFindInfo, PLVDATA plvdata){ PITEMDATA p1; PSUBITEMDATA p2; int i = 0, j = 0; if (pFindInfo == NULL) return -1; if ( !(p1 = lvGetItemByRow (plvdata, pFindInfo->iStart)) ) p1 = plvdata->pItemHead; while (p1 != NULL) { p2 = p1->pSubItemHead; i = pFindInfo->nCols; if (pFindInfo->flags & LVFF_ADDDATA) { if (pFindInfo->addData != p1->addData) continue; } if (pFindInfo->flags & LVFF_TEXT) { while ((p2 != NULL) && (i > 0)) { if (plvdata->str_cmp (p2->pszInfo, pFindInfo->pszInfo[i - 1], (size_t)-1) != 0) break; i--; p2 = p2->pNext; } } j++; p1 = p1->pNext; if (i == 0) return j; } return -1;}static int sGetSubItemWidth (int nCols, PLVDATA plvdata){ PLSTHDR p; int nPosition; nPosition = nCols; if ((nCols < 1) || (nCols > plvdata->nCols)) { return -1; } p = plvdata->pLstHead; while (nPosition != 1) { nPosition--; p = p->pNext; } return p->width;}static int sGetItemWidth (PLVDATA plvdata){ PLSTHDR p; int width; p = plvdata->pLstHead; width = 0; while (p != NULL) { width += p->width; p = p->pNext; } return width;}/* * gets the previous nClos items width */inline static int sGetFrontSubItemsWidth (int nCols, PLVDATA plvdata){ PLSTHDR p1 = lvGetHdrByCol(plvdata, nCols); if (p1) return p1->x + p1->width; return -1;}/* be care, doesn't check p and offset */inline static int sAddOffsetToSubItem (PLSTHDR p, int offset){ p->width += offset; return 0;}/* offset the tail subitems from nCols */static int sAddOffsetToTailSubItem (int nCols, int offset, PLVDATA plvdata){ PLSTHDR p; p = lvGetHdrByCol (plvdata, nCols); if (!p) return -1; while (p) { p->x += offset; p = p->pNext; } return 0;}static void lvSetColumnWidth (int nCols, int width, PLVDATA plvdata){ int offset; PLSTHDR ph = lvGetHdrByCol (plvdata, nCols); if (!ph) return; if (width < COLWIDTHMIN) width = COLWIDTHMIN; offset = width - ph->width; sAddOffsetToSubItem(ph, offset); sAddOffsetToTailSubItem (nCols+1, offset, plvdata);}/* The default comparision function for compare two items */static int lvDefCompare (int row1, int row2, int ncol, PLVDATA plvdata){ PITEMDATA p1, p2; PSUBITEMDATA psub1, psub2; p1 = lvGetItemByRow (plvdata, row1); p2 = lvGetItemByRow (plvdata, row2); psub1 = lvGetSubItemByCol (p1, ncol); psub2 = lvGetSubItemByCol (p2, ncol); if (plvdata->str_cmp) return plvdata->str_cmp (psub1->pszInfo, psub2->pszInfo, (size_t)-1); else return strcasecmp (psub1->pszInfo, psub2->pszInfo);}static void lvMoveItem (int old_row, int new_row, PLVDATA plvdata){ PITEMDATA p1, p2, pp1, pp2; if (old_row == new_row) return; p1 = lvGetItemByRow (plvdata, old_row); p2 = lvGetItemByRow (plvdata, new_row); if (!p1 || !p2) return; pp1 = lvGetItemByRow (plvdata, old_row-1); pp2 = lvGetItemByRow (plvdata, new_row-1); if (pp1) pp1->pNext = p1->pNext; else plvdata->pItemHead = p1->pNext; if (pp2) pp2->pNext = p1; else plvdata->pItemHead = p1; p1->pNext = p2;}/* sorting items using a comparision function */static int lvSortItem (PFNLVCOMPARE pfn_user, int nCols, SORTTYPE sort, PLVDATA plvdata){ int i, j; PLSTHDR ph; PFNLVCOMPARE pcmp; LVSORTDATA sortData; /* If pfn_user is not NULL, use it as comparision function; otherwise, * use the one associated with nCols column. */ if (pfn_user) pcmp = pfn_user; else { if ( !(ph = lvGetHdrByCol (plvdata, nCols)) ) return -1; pcmp = ph->pfnCmp; } //FIXME, sortData howto use? sortData.ncol = nCols; //FIXME, more efficient algorithm for (i = 1; i <= plvdata->nRows; i++) { for (j = 1; j < i; j++) { int ret; if (pcmp) { ret = pcmp (i, j, &sortData); if (ret == 0) ret = lvDefCompare (i, j, 1, plvdata); } else { ret = lvDefCompare (i, j, nCols, plvdata); } if ( (sort == LOSORTED && ret < 0) || (sort == HISORTED && ret > 0)) break; } lvMoveItem (i, j, plvdata); } return 0;}/*************************** scroll info ***********************************/static int lstSetVScrollInfo (PLVDATA plvdata){ SCROLLINFO si; RECT rect; GetClientRect (plvdata->hWnd, &rect); if ((rect.bottom - rect.top - plvdata->nHeadHeight) > ((plvdata->nRows) * plvdata->nItemHeight)) { ShowScrollBar (plvdata->hWnd, SB_VERT, FALSE); plvdata->nOriginalY = 0; return 0; } if (plvdata->nOriginalY < 0) plvdata->nOriginalY = 0; si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = plvdata->nRows * plvdata->nItemHeight; si.nMin = 0; si.nPage = rect.bottom - rect.top - plvdata->nHeadHeight; si.nPos = plvdata->nOriginalY; if (si.nPos > si.nMax - si.nPage) { si.nPos = si.nMax - si.nPage; plvdata->nOriginalY = si.nPos; } SetScrollInfo (plvdata->hWnd, SB_VERT, &si, TRUE); ShowScrollBar (plvdata->hWnd, SB_VERT, TRUE); return 0;}static int lstSetHScrollInfo (PLVDATA plvdata){ SCROLLINFO si; RECT rect; GetClientRect (plvdata->hWnd, &rect); if ( !LV_H_OUTWND(plvdata, rect) ) { ShowScrollBar (plvdata->hWnd, SB_HORZ, FALSE); return 0; } si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = sGetItemWidth (plvdata); si.nMin = 0; si.nPage = rect.right - rect.left; si.nPos = plvdata->nOriginalX; if (si.nPos > si.nMax - si.nPage) { si.nPos = si.nMax - si.nPage; plvdata->nOriginalX = si.nPos; } SetScrollInfo (plvdata->hWnd, SB_HORZ, &si, TRUE); ShowScrollBar (plvdata->hWnd, SB_HORZ, TRUE); return 0;}/************************************* Listview drag border action ***********************/static void lvBorderDrag (HWND hwnd, int x, int y){ int mouseX = x, mouseY = y; PLVDATA plvdata; RECT rect, rcClient; int offset; PLSTHDR pDrag; plvdata = (PLVDATA) GetWindowAdditionalData2 (hwnd); pDrag = lvGetHdrByCol (plvdata, plvdata->nItemDraged); GetClientRect (hwnd, &rcClient); ScreenToClient (hwnd, &mouseX, &mouseY); //the column width should not less than the min value if ((pDrag->x - plvdata->nOriginalX + COLWIDTHMIN) > mouseX - 1) return; offset = mouseX - (pDrag->x + pDrag->width-plvdata->nOriginalX); lvSetColumnWidth (plvdata->nItemDraged, pDrag->width+offset, plvdata); rect.left = rcClient.left; rect.right = rcClient.right; rect.top = rcClient.top; rect.bottom = rect.top + plvdata->nHeadHeight+1; InvalidateRect(hwnd, &rect, FALSE); if (offset < 0) { plvdata->nOriginalX += offset; if (plvdata->nOriginalX < 0) plvdata->nOriginalX = 0; } //lstSetHScrollInfo (plvdata);}static void lvToggleSortStatus (PLSTHDR p1){ switch (p1->sort) { case NOTSORTED: p1->sort = LOSORTED; break; case HISORTED: p1->sort = LOSORTED; break; case LOSORTED: p1->sort = HISORTED; break; }}/********************************************** List Report **********************************************/static int sListViewProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam){ PLVDATA plvdata = NULL; DWORD dwStyle; if (message != MSG_CREATE) plvdata = (PLVDATA) GetWindowAdditionalData2 (hwnd); switch (message) { case MSG_CREATE: { dwStyle = GetWindowStyle (hwnd); if (!(plvdata = (PLVDATA) malloc (sizeof (LVDATA)))) return -1; SetWindowAdditionalData2 (hwnd, (DWORD) plvdata); InitListViewData (hwnd); lstSetHScrollInfo (plvdata); lstSetVScrollInfo (plvdata); break; } case MSG_SETCURSOR: { int mouseX = LOSWORD (lParam); int mouseY = HISWORD (lParam); if ((LVSTATUS(hwnd) & LVST_BDDRAG) || (lvInWhichHeadBorder (mouseX, mouseY, NULL, plvdata) > 0)) { SetCursor (GetSystemCursor (IDC_SPLIT_VERT)); return 0; } break; } case MSG_PAINT: { HDC hdc; /*, mem_dc*/; hdc = BeginPaint (hwnd); /* mem_dc = CreateCompatibleDC (hdc); */ /* lvOnDraw (hwnd, mem_dc); */ lvOnDraw (hwnd, hdc); /* BitBlt (mem_dc, 0, 0, 0, 0, hdc, 0, 0, 0); */ /* DeleteCompatibleDC (mem_dc); */ EndPaint (hwnd, hdc); return 0; } case MSG_SETFOCUS: case MSG_KILLFOCUS: if (message == MSG_SETFOCUS) plvdata->bkc_selected = LIGHTBLUE; else plvdata->bkc_selected = GRAYBLUE; if (plvdata->nItemSelected > 0) { RECT rc; LV_GET_ITEM_RECT(plvdata->nItemSelected, rc); InvalidateRect(hwnd, &rc, FALSE); } break; case MSG_GETDLGCODE: return DLGC_WANTARROWS | DLGC_WANTCHARS; case MSG_MOUSEMOVE: { int mouseX = LOSWORD (lParam); int mouseY = HISWORD (lParam); //in head clicked status if (LVSTATUS(hwnd) & LVST_HEADCLICK) { RECT rc; PLSTHDR p1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -