📄 treeview.c
字号:
while (t) { countPrevNext (pData, t, count); t = t->next; } }}static int getItemsWithPrev (PTVDATA pData, PTVITEM pCur){ int count = 0; PTVITEM prev = getPrev (pData, pCur); if (prev == NULL) return 0; countPrevNext (pData, prev, &count); return count - 1;}static int getItemsWithNext (PTVDATA pData, PTVITEM pCur){ int count = 0; if (pCur == NULL || pCur->next == NULL) return 0; countPrevNext (pData, pCur, &count); return count - 1;}static PTVITEM ItemFromCount (PTVITEM p, int count, int* cnt){ PTVITEM q, t = NULL; (*cnt)++; if (*cnt == count) return p; else if (p->child != NULL && !(p->dwFlags & TVIF_FOLD)) { q = p->child; while (q != NULL && !(t = ItemFromCount (q, count, cnt))) q = q->next; } else return NULL; return t;}static PTVITEM getItemFromCount (PTVDATA pData, int count){ int cnt = 0; if (pData->root == NULL) return NULL; return ItemFromCount (pData->root, count, &cnt);}static int CountFromItem (PTVITEM p, PTVITEM pTgt, int* count){ int t = 0; PTVITEM q; (*count)++; if (p == pTgt) return *count; else if (p->child != NULL && !(p->dwFlags & TVIF_FOLD)) { q = p->child; while (q != NULL && !(t = CountFromItem (q, pTgt, count))) q = q->next; } else return 0; return t;}static int getCountFromItem (PTVDATA pData, PTVITEM pTgt){ int count = 0; if (pTgt == NULL) return 0; return CountFromItem (pData->root, pTgt, &count);}/* * Add a node */static void InsertChild (HWND hwnd, PTVDATA pData, PTVITEM pParent, PTVITEM pChild){ PTVITEM p, t = NULL; int h, w; HDC hdc; pChild->depth = pParent->depth + 1; pChild->parent = pParent; pChild->child = pChild->next = NULL; if (pParent->child == NULL) pParent->child = pChild; else if (pData->dwStyle & TVS_SORT) { p = pParent->child; while (pData->str_cmp (pChild->text, p->text, (size_t)-1) > 0 && p->next != NULL) { t = p; p = p->next; } if (pData->str_cmp (pChild->text, p->text, (size_t)-1) > 0) p->next = pChild; else if (t == NULL) { pParent->child = pChild; pChild->next = p; } else { t->next = pChild; pChild->next = p; } } else { p = pParent->child; while (p->next != NULL) p = p->next; p->next = pChild; } pData->nItemCount++; pData->nVisItemCount++; hdc = GetClientDC (hwnd); GetTextExtent (hdc, pChild->text, -1, &pChild->text_ext); h = pData->nItemHeight; w = TV_BOXGAP + h + TV_BOXGAP + pChild->text_ext.cx + pChild->depth * h; if (pData->dwStyle & TVS_WITHICON) w += h + TV_ICONGAP; if (pData->dwStyle & WS_BORDER) w += TV_BORDER * 2; pData->nWidth = MAX (w, pData->nWidth); ReleaseDC (hdc);} static void tvDrawItem (HDC hdc, PTVDATA pData, int centerX, int centerY, PTVITEM p, int up, int down){ int h = pData->nItemHeight; SetPenColor (hdc, PIXEL_black); SetBkColor (hdc, PIXEL_lightwhite); if (p->child != NULL) { Rectangle (hdc, centerX - TV_BOXHALFHEIGHT, centerY - TV_BOXHALFHEIGHT, centerX + TV_BOXHALFHEIGHT, centerY + TV_BOXHALFHEIGHT); MoveTo (hdc, centerX - TV_BOXHALFHEIGHT + 2, centerY); LineTo (hdc, centerX + TV_BOXHALFHEIGHT - 1, centerY); if (p->dwFlags & TVIF_FOLD) { MoveTo (hdc, centerX, centerY - TV_BOXHALFHEIGHT + 2); LineTo (hdc, centerX, centerY + TV_BOXHALFHEIGHT - 2); } MoveTo (hdc, centerX, centerY - (h>>1) - h * up); LineTo (hdc, centerX, centerY - TV_BOXHALFHEIGHT); MoveTo (hdc, centerX + TV_BOXHALFHEIGHT, centerY); LineTo (hdc, centerX + (h>>1) + TV_BOXGAP, centerY); if (p->next != NULL) { MoveTo (hdc, centerX, centerY + TV_BOXHALFHEIGHT); LineTo (hdc, centerX, centerY + (h>>1) + h * down); } } else { MoveTo (hdc, centerX, centerY - (h>>1) - h * up); LineTo (hdc, centerX, centerY); LineTo (hdc, centerX + (h>>1) + TV_BOXGAP, centerY); if (p->next != NULL) { MoveTo (hdc, centerX, centerY); LineTo (hdc, centerX, centerY + (h>>1) + h * down); } } centerX += (h>>1) + TV_BOXGAP; if (pData->dwStyle & TVS_WITHICON) { if (!(pData->dwStyle & TVS_ICONFORSELECT) && (!p->child || (p->dwFlags & TVIF_FOLD))) { if ((p->hIconFold)) { DrawIcon (hdc, centerX, centerY - (h>>1), h, h, p->hIconFold); } } else if ((pData->dwStyle & TVS_ICONFORSELECT) && p->dwFlags & TVIF_SELECTED) { if ((p->hIconFold)) { DrawIcon (hdc, centerX, centerY - (h>>1), h, h, p->hIconFold); } } else if ((p->hIconUnfold)) { DrawIcon (hdc, centerX, centerY - (h>>1), h, h, p->hIconUnfold); } centerX += h + TV_ICONGAP; } if (p->dwFlags & TVIF_SELECTED) {#ifndef _GRAY_SCREEN SetBrushColor (hdc, PIXEL_darkblue); SetBkColor (hdc, PIXEL_darkblue);#else SetBrushColor (hdc, PIXEL_black); SetBkColor (hdc, PIXEL_black);#endif SetTextColor (hdc, PIXEL_lightwhite); TextOut (hdc, centerX, centerY - (h>>1), p->text);#ifndef _GRAY_SCREEN if (pData->dwStyle & TVS_FOCUS) { FocusRect (hdc, centerX, centerY - (h>>1), centerX + p->text_ext.cx - 1, centerY + (h>>1) - 1); }#endif } else { SetBrushColor (hdc, PIXEL_lightwhite); SetBkColor (hdc, PIXEL_lightwhite); SetTextColor (hdc, PIXEL_black); TextOut (hdc, centerX, centerY - (h>>1), p->text); }}/* * draw all items. */static void doAll (HDC hdc, PTVDATA pData, PTVITEM p, int cenX, int cenY, int* count, int* depth){ int up, down, h = pData->nItemHeight; PTVITEM t; up = getItemsWithPrev (pData, p); down = getItemsWithNext (pData, p); tvDrawItem (hdc, pData, cenX + *depth * h, cenY + (*count - pData->nItemTop) * h, p, up, down); (*count)++; if (!(p->dwFlags & TVIF_FOLD)) { t = p->child; (*depth)++; while (t) { doAll (hdc, pData, t, cenX, cenY, count, depth); if (*count > pData->nItemTop + pData->nVisCount) return; t = t->next; } (*depth)--; }}static void tvOnDraw (HWND hwnd, HDC hdc, PTVDATA pData){ RECT rcClient; int x, y, w, h; int centerX, centerY; int count = 0, depth = 0; GetClientRect (hwnd, &rcClient); x = rcClient.left; y = rcClient.top; w = RECTW (rcClient); h = RECTH (rcClient); if (pData->dwStyle & WS_BORDER) { x += TV_BORDER; y += TV_BORDER; w -= (TV_BORDER<<1); h -= (TV_BORDER<<1); } SetBrushColor (hdc, PIXEL_lightwhite); FillBox (hdc, rcClient.left, rcClient.top, RECTW (rcClient), RECTH (rcClient)); centerX = x - pData->nLeft + TV_BOXGAP + (pData->nItemHeight>>1); centerY = y + (pData->nItemHeight >> 1); doAll (hdc, pData, pData->root, centerX, centerY, &count, &depth);}static void tvSetVScrollInfo (HWND hwnd, PTVDATA pData, BOOL fRedraw){ SCROLLINFO si; if (pData->nVisCount >= pData->nVisItemCount) { SetScrollPos (hwnd, SB_VERT, 0); EnableScrollBar (hwnd, SB_VERT, FALSE); ShowScrollBar (hwnd, SB_VERT, FALSE); return; } si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = pData->nVisItemCount - 1; si.nMin = 0; si.nPage = MIN (pData->nVisCount, (pData->nVisItemCount - pData->nItemTop)); si.nPos = pData->nItemTop; SetScrollInfo (hwnd, SB_VERT, &si, fRedraw); EnableScrollBar (hwnd, SB_VERT, TRUE); ShowScrollBar (hwnd, SB_VERT, TRUE);} static void tvSetHScrollInfo (HWND hwnd, PTVDATA pData, BOOL fRedraw){ SCROLLINFO si; if (pData->nVisWidth >= pData->nWidth) { SetScrollPos (hwnd, SB_HORZ, 0); ShowScrollBar (hwnd, SB_HORZ, FALSE); EnableScrollBar (hwnd, SB_HORZ, FALSE); return; } si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = pData->nWidth - 1; si.nMin = 0; si.nPage = MIN (pData->nVisWidth, (pData->nWidth - pData->nLeft)); si.nPos = pData->nLeft; SetScrollInfo (hwnd, SB_HORZ, &si, fRedraw); ShowScrollBar (hwnd, SB_HORZ, TRUE); EnableScrollBar (hwnd, SB_HORZ, TRUE);}static void tvRecalcWidthsHelper (HDC hdc, PTVITEM p){ while (p) { GetTextExtent (hdc, p->text, -1, &p->text_ext); if (p->child) tvRecalcWidthsHelper (hdc, p->child); p = p->next; }}static void tvRecalcWidths (HWND hwnd, PTVDATA pData){ HDC hdc = GetClientDC (hwnd); tvRecalcWidthsHelper (hdc, pData->root); ReleaseDC (hdc); pData->nWidth = getTVWidth (pData); pData->nVisItemCount = getVisItemCount (pData); InvalidateRect (hwnd, NULL, FALSE); tvSetVScrollInfo (hwnd, pData, TRUE); tvSetHScrollInfo (hwnd, pData, TRUE);}/* * Recalculate and redraw the control */static void recalc_redraw (HWND hwnd, PTVDATA pData){ pData->nVisItemCount = getVisItemCount (pData); pData->nWidth = getTVWidth (pData); InvalidateRect (hwnd, NULL, FALSE); tvSetVScrollInfo (hwnd, pData, TRUE); tvSetHScrollInfo (hwnd, pData, TRUE);}static void change_selected (HWND hwnd, PTVDATA pData, PTVITEM new_sel){ PTVITEM old_sel = pData->pItemSelected; if (new_sel != old_sel) { if (old_sel) old_sel->dwFlags &= ~TVIF_SELECTED; if (new_sel) new_sel->dwFlags |= TVIF_SELECTED; pData->pItemSelected = new_sel; NotifyParent (hwnd, pData->id, TVN_SELCHANGE); }}static int TreeViewCtrlProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam){ PTVDATA pData; DWORD dwStyle; switch (message) { case MSG_CREATE: { PTVITEMINFO root_ii = (PTVITEMINFO)lParam; dwStyle = GetWindowStyle (hwnd); if (!(pData = (PTVDATA) calloc (1, sizeof (TVDATA)))) return -1; SetWindowAdditionalData2 (hwnd, (DWORD) pData); if (!tvInitTVData (hwnd, pData, dwStyle, root_ii)) { free (pData); return -1; } break; } case MSG_SIZECHANGED: { RECT* prc = (RECT*) lParam; pData = (PTVDATA) GetWindowAdditionalData2 (hwnd); pData->nVisCount = (RECTHP (prc)) / pData->nItemHeight; pData->nVisWidth = RECTWP (prc); } break; case MSG_DESTROY: pData = (PTVDATA) GetWindowAdditionalData2 (hwnd); tvCleanTVData (hwnd, pData); break; case MSG_GETTEXTLENGTH: case MSG_GETTEXT: case MSG_SETTEXT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -