📄 treeview.c
字号:
/*** $Id: treeview.c,v 1.30 2003/09/29 02:52:46 snig Exp $** ** treeview.c: TreeView Control.** ** Copyright (C) 2001, 2002 Zheng Yiran, Wei Yongming.** Copyright (C) 2003 Feynman Software.**** Current maintainer: Wei Yongming.*//*** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//*** TODO:*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#ifdef __MINIGUI_LIB__ #include "common.h" #include "minigui.h" #include "gdi.h" #include "window.h" #include "control.h"#else #include <minigui/common.h> #include <minigui/minigui.h> #include <minigui/gdi.h> #include <minigui/window.h> #include <minigui/control.h>#endif#ifdef _EXT_CTRL_TREEVIEW#include "mgext.h"#include "treeview.h"#define _USE_FIXSTR 1#define TV_BORDER 2#define TV_BOXHALFHEIGHT 4#define TV_BOXGAP 3#define TV_ICONGAP 3#define TV_IDENT 5static HICON icon_fold, icon_unfold;#define ICON_FOLD icon_fold#define ICON_UNFOLD icon_unfoldstatic int TreeViewCtrlProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam);BOOL RegisterTreeViewControl (void){ WNDCLASS WndClass; if (!(icon_fold = LoadSystemIcon (SYSICON_FOLD, 0))) { return FALSE; } if (!(icon_unfold = LoadSystemIcon (SYSICON_UNFOLD, 0))) return FALSE; WndClass.spClassName = CTRL_TREEVIEW; WndClass.dwStyle = WS_NONE; WndClass.dwExStyle = WS_EX_NONE; WndClass.hCursor = GetSystemCursor (0); WndClass.iBkColor = PIXEL_lightwhite; WndClass.WinProc = TreeViewCtrlProc; return RegisterWindowClass (&WndClass);}void TreeViewControlCleanup (void){ UnregisterWindowClass (CTRL_TREEVIEW);}/* * Initialize Treeview. */static BOOL tvInitTVData (HWND hwnd, PTVDATA pData, DWORD dwStyle, PTVITEMINFO root_ii){ PTVITEM tvRoot; HDC hdc; char* text = root_ii ? root_ii->text : "Root"; pData->dwStyle = dwStyle; pData->id = GetDlgCtrlID (hwnd); pData->str_cmp = strncmp; if (!(tvRoot = calloc (1, sizeof (TVITEM)))) return FALSE;#if _USE_FIXSTR tvRoot->text = FixStrAlloc (strlen(text)); if (tvRoot->text == NULL) { free (tvRoot); return FALSE; } strcpy (tvRoot->text, text);#else tvRoot->text = strdup (text);#endif tvRoot->dwFlags = TVIF_ROOT | TVIF_SELECTED; if (root_ii && root_ii->dwFlags & TVIF_FOLD) { tvRoot->dwFlags |= TVIF_FOLD; } tvRoot->depth = 0; tvRoot->child = tvRoot->next = tvRoot->parent = NULL; if (pData->dwStyle & TVS_WITHICON) { tvRoot->hIconFold = (root_ii ? root_ii->hIconFold : ICON_FOLD); tvRoot->hIconUnfold = (root_ii ? root_ii->hIconUnfold : ICON_UNFOLD); } hdc = GetClientDC (hwnd); pData->nItemHeight = GetFontHeight (hdc); pData->nVisItemCount = 1; pData->nItemCount = 1; pData->root = tvRoot; pData->pItemSelected = tvRoot; pData->nItemTop = 0; pData->nLeft = 0; GetTextExtent (hdc, tvRoot->text, -1, &tvRoot->text_ext); pData->nWidth = TV_BOXGAP + pData->nItemHeight + tvRoot->text_ext.cx; if (pData->dwStyle & TVS_WITHICON) pData->nWidth += pData->nItemHeight + TV_ICONGAP; if (pData->dwStyle & WS_BORDER) pData->nWidth += TV_BORDER * 2; ReleaseDC (hdc); return TRUE;}/* * Get the parent node of the given node. */static PTVITEM getParent (PTVDATA pData, PTVITEM pChild){ if (pChild == pData->root || pChild == NULL) return NULL; return pChild->parent;}/* * Get the node whose next sibling is current node. */static PTVITEM getPrev (PTVDATA pData, PTVITEM pCur){ PTVITEM p, t; p = getParent (pData, pCur); if (p == NULL || p->child == pCur) return NULL; t = p->child; while (t->next != NULL && t->next != pCur) t = t->next; if (t->next != pCur) return NULL; return t;}#if 0static void UnfoldAll (PTVITEM p){ PTVITEM t; if (p == NULL) return; p->dwFlags &= ~TVIF_FOLD; t = p->child; while (t) { UnfoldAll (t); t = t->next; }}#endif/* * Mark all ancestor items unfolded */static void unfold_ancestor (HWND hwnd, PTVDATA pData, PTVITEM item){ PTVITEM parent; parent = item->parent; while (parent) { parent->dwFlags &= ~TVIF_FOLD; NotifyParentEx (hwnd, pData->id, TVN_UNFOLDED, (DWORD)parent); parent = parent->parent; }}static void vis_item_count (PTVITEM p, int* count){ PTVITEM t; (*count)++; if (!(p->dwFlags & TVIF_FOLD)) { t = p->child; while (t) { vis_item_count (t, count); t = t->next; } }} static int getVisItemCount (PTVDATA pData){ int count = 0; if (pData->root == NULL) return 0; vis_item_count (pData->root, &count); return count;}static void TVWidth (PTVDATA pData, PTVITEM p, int* width){ PTVITEM t; int wtemp, h; h = pData->nItemHeight; wtemp = TV_BOXGAP + h + TV_BOXGAP + p->depth * h + p->text_ext.cx; if (pData->dwStyle & TVS_WITHICON) wtemp += h + TV_ICONGAP; if (pData->dwStyle & WS_BORDER) wtemp += TV_BORDER * 2; *width = MAX (wtemp, *width); if (!(p->dwFlags & TVIF_FOLD)) { t = p->child; while (t) { TVWidth (pData, t, width); t = t->next; } }} static int getTVWidth (PTVDATA pData){ int width; TVWidth (pData, pData->root, &width); return width;}/* * Used by RemoveTree(), recursive function */static void RemoveSubTree (PTVDATA pData, PTVITEM p){ PTVITEM q, n; if (p == NULL ) return; q = p->child; while (q != NULL) { n = q->next; RemoveSubTree (pData, q); q = n; } /* free a node which hasn't any child */#if _USE_FIXSTR FreeFixStr (p->text);#else free (p->text);#endif free (p); pData->nItemCount--; }/* * Remove a tree or subtree */static void RemoveTree (HWND hwnd, PTVDATA pData, PTVITEM pChild){ PTVITEM p, q; if (pChild == NULL) return; if (pChild == pData->root) { pData->root = NULL; pData->pItemSelected = NULL; pData->nVisItemCount = 1; pData->nWidth = 1; pData->nItemTop = pData->nLeft = 0; RemoveSubTree (pData, pChild); } else { p = pData->pItemSelected = getParent (pData, pChild); if (pChild == p->child) p->child = pChild->next; else { q = p->child; while (q !=NULL && q->next != pChild) q = q->next; q->next = pChild->next; } RemoveSubTree (pData, pChild); pData->nWidth = getTVWidth (pData); pData->nVisItemCount = getVisItemCount (pData); }}static void tvCleanTVData (HWND hwnd, PTVDATA pData){ RemoveTree (hwnd, pData, pData->root);#if 0 printf ("Item count should be zero now: %d\n", pData->nItemCount);#endif free (pData);}static int is_descendant (PTVITEM root, PTVITEM item, int* depth){ int i; int d; if (root == NULL || item == NULL) return -1; d = item->depth - root->depth; for (i = 0; i < d; i++) { item = item->parent; } if (depth) *depth = d; if (item == root) return 0; return -1;}static PTVITEM findStringDepthFirst (PTVDATA pData, PTVITEM p, const char* string){ PTVITEM q, t = NULL; if (!pData->str_cmp (p->text, string, (size_t)-1)) return p; else { q = p->child; while (q && !(t = findStringDepthFirst (pData, q, string))) q = q->next; } return t;}static PTVITEM findStringInChildren (PTVDATA pData, PTVITEM item, const char* string){ PTVITEM p; p = item->child; while (p) { if (!pData->str_cmp (p->text, string, (size_t)-1)) return p; p = p->next; } return NULL;}static void countPrevNext (PTVDATA pData, PTVITEM prev, int* count){ PTVITEM t; (*count)++; if (!(prev->dwFlags & TVIF_FOLD)) { t = prev->child;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -