Csharp: TreeView Control
1 // --------------------------------------------------------------------------------------------- 2 #region // Copyright (c) 2004-2005, SIL International. All Rights Reserved. 3 // <copyright from='2004' to='2005' company='SIL International'> 4 // Copyright (c) 2004-2005, SIL International. All Rights Reserved. 5 // 6 // Distributable under the terms of either the Common Public License or the 7 // GNU Lesser General Public License, as specified in the LICENSING.txt file. 8 // </copyright> 9 #endregion 10 // 11 // File: TriStateTreeView.cs 12 // Responsibility: Eberhard Beilharz/Tim Steenwyk 13 // http://www.codeproject.com/Articles/6549/Tri-State-TreeView-Control 14 // <remarks> 15 // </remarks> 16 // --------------------------------------------------------------------------------------------- 17 18 19 using System; 20 using System.Collections.Generic; 21 using System.ComponentModel; 22 using System.Drawing; 23 using System.Data; 24 using System.Linq; 25 using System.Text; 26 using System.Windows.Forms; 27 using Skybound.VisualStyles; 28 using System.Runtime.InteropServices; 29 using System.Collections; 30 31 32 33 namespace TriStateTreeView 34 { 35 public partial class TriStateTreeView : TreeView 36 { 37 /// <summary> 38 /// 塗聚文 20121122 修改 39 /// 捷為工作室 40 /// 41 ///TreeView The check state 42 /// </summary> 43 /// <remarks>The states corresponds to image index</remarks> 44 public enum CheckState 45 { 46 /// <summary>greyed out</summary> 47 GreyChecked = 0, 48 /// <summary>Unchecked</summary> 49 Unchecked = 1, 50 /// <summary>Checked</summary> 51 Checked = 2, 52 } 53 54 #region Redefined Win-API structs and methods 55 /// <summary></summary> 56 [StructLayout(LayoutKind.Sequential, Pack = 1)] 57 public struct TV_HITTESTINFO 58 { 59 /// <summary>Client coordinates of the point to test.</summary> 60 public Point pt; 61 /// <summary>Variable that receives information about the results of a hit test.</summary> 62 public TVHit flags; 63 /// <summary>Handle to the item that occupies the point.</summary> 64 public IntPtr hItem; 65 } 66 67 /// <summary>Hit tests for tree view</summary> 68 [Flags] 69 public enum TVHit 70 { 71 /// <summary>In the client area, but below the last item.</summary> 72 NoWhere = 0x0001, 73 /// <summary>On the bitmap associated with an item.</summary> 74 OnItemIcon = 0x0002, 75 /// <summary>On the label (string) associated with an item.</summary> 76 OnItemLabel = 0x0004, 77 /// <summary>In the indentation associated with an item.</summary> 78 OnItemIndent = 0x0008, 79 /// <summary>On the button associated with an item.</summary> 80 OnItemButton = 0x0010, 81 /// <summary>In the area to the right of an item. </summary> 82 OnItemRight = 0x0020, 83 /// <summary>On the state icon for a tree-view item that is in a user-defined state.</summary> 84 OnItemStateIcon = 0x0040, 85 /// <summary>On the bitmap or label associated with an item. </summary> 86 OnItem = (OnItemIcon | OnItemLabel | OnItemStateIcon), 87 /// <summary>Above the client area. </summary> 88 Above = 0x0100, 89 /// <summary>Below the client area.</summary> 90 Below = 0x0200, 91 /// <summary>To the right of the client area.</summary> 92 ToRight = 0x0400, 93 /// <summary>To the left of the client area.</summary> 94 ToLeft = 0x0800 95 } 96 97 /// <summary></summary> 98 public enum TreeViewMessages 99 { 100 /// <summary></summary> 101 TV_FIRST = 0x1100, // TreeView messages 102 /// <summary></summary> 103 TVM_HITTEST = (TV_FIRST + 17), 104 } 105 106 /// <summary></summary> 107 [DllImport("user32.dll", CharSet = CharSet.Auto)] 108 public static extern int SendMessage(IntPtr hWnd, TreeViewMessages msg, int wParam, ref TV_HITTESTINFO lParam); 109 #endregion 110 111 /// <summary> 112 /// 113 /// </summary> 114 public TriStateTreeView() 115 { 116 InitializeComponent(); 117 118 if (ThemeInformation.VisualStylesEnabled) 119 { 120 Bitmap bmp = new Bitmap(m_TriStateImages.ImageSize.Width, m_TriStateImages.ImageSize.Height); 121 Rectangle rc = new Rectangle(0, 0, bmp.Width, bmp.Height); 122 Graphics graphics = Graphics.FromImage(bmp); 123 124 ThemePaint.Draw(graphics, this, ThemeClasses.Button, ThemeParts.ButtonCheckBox, 125 ThemeStates.CheckBoxCheckedDisabled, rc, rc); 126 m_TriStateImages.Images[0] = bmp; 127 128 ThemePaint.Draw(graphics, this, ThemeClasses.Button, ThemeParts.ButtonCheckBox, 129 ThemeStates.CheckBoxUncheckedNormal, rc, rc); 130 m_TriStateImages.Images[1] = bmp; 131 132 ThemePaint.Draw(graphics, this, ThemeClasses.Button, ThemeParts.ButtonCheckBox, 133 ThemeStates.CheckBoxCheckedNormal, rc, rc); 134 m_TriStateImages.Images[2] = bmp; 135 } 136 137 ImageList = m_TriStateImages; 138 ImageIndex = (int)CheckState.Unchecked; 139 SelectedImageIndex = (int)CheckState.Unchecked; 140 } 141 142 #region Hide no longer appropriate properties from Designer 143 /// ------------------------------------------------------------------------------------ 144 /// <summary> 145 /// 146 /// </summary> 147 /// ------------------------------------------------------------------------------------ 148 [Browsable(false)] 149 public new bool CheckBoxes 150 { 151 get { return base.CheckBoxes; } 152 set { base.CheckBoxes = value; } 153 } 154 155 /// ------------------------------------------------------------------------------------ 156 /// <summary> 157 /// 158 /// </summary> 159 /// ------------------------------------------------------------------------------------ 160 [Browsable(false)] 161 public new int ImageIndex 162 { 163 get { return base.ImageIndex; } 164 set { base.ImageIndex = value; } 165 } 166 167 /// ------------------------------------------------------------------------------------ 168 /// <summary> 169 /// 170 /// </summary> 171 /// ------------------------------------------------------------------------------------ 172 [Browsable(false)] 173 public new ImageList ImageList 174 { 175 get { return base.ImageList; } 176 set { base.ImageList = value; } 177 } 178 179 /// ------------------------------------------------------------------------------------ 180 /// <summary> 181 /// 182 /// </summary> 183 /// ------------------------------------------------------------------------------------ 184 [Browsable(false)] 185 public new int SelectedImageIndex 186 { 187 get { return base.SelectedImageIndex; } 188 set { base.SelectedImageIndex = value; } 189 } 190 #endregion 191 192 #region Overrides 193 /// ------------------------------------------------------------------------------------ 194 /// <summary> 195 /// Called when the user clicks on an item 196 /// </summary> 197 /// <param name="e"></param> 198 /// ------------------------------------------------------------------------------------ 199 protected override void OnClick(EventArgs e) 200 { 201 base.OnClick(e); 202 203 TV_HITTESTINFO hitTestInfo = new TV_HITTESTINFO(); 204 hitTestInfo.pt = PointToClient(Control.MousePosition); 205 206 SendMessage(Handle, TreeViewMessages.TVM_HITTEST, 207 0, ref hitTestInfo); 208 if ((hitTestInfo.flags & TVHit.OnItemIcon) == TVHit.OnItemIcon) 209 { 210 TreeNode node = GetNodeAt(hitTestInfo.pt); 211 if (node != null) 212 ChangeNodeState(node); 213 } 214 } 215 216 /// ------------------------------------------------------------------------------------ 217 /// <summary> 218 /// Toggle item if user presses space bar 219 /// </summary> 220 /// <param name="e"></param> 221 /// ------------------------------------------------------------------------------------ 222 protected override void OnKeyDown(KeyEventArgs e) 223 { 224 base.OnKeyDown(e); 225 226 if (e.KeyCode == Keys.Space) 227 ChangeNodeState(SelectedNode); 228 } 229 #endregion 230 231 #region Private methods 232 /// ------------------------------------------------------------------------------------ 233 /// <summary> 234 /// Checks or unchecks all children 235 /// </summary> 236 /// <param name="node"></param> 237 /// <param name="state"></param> 238 /// ------------------------------------------------------------------------------------ 239 private void CheckNode(TreeNode node, CheckState state) 240 { 241 InternalSetChecked(node, state); 242 243 foreach (TreeNode child in node.Nodes) 244 CheckNode(child, state); 245 } 246 247 /// ------------------------------------------------------------------------------------ 248 /// <summary> 249 /// Called after a node changed its state. Has to go through all direct children and 250 /// set state based on children's state. 251 /// </summary> 252 /// <param name="node">Parent node</param> 253 /// ------------------------------------------------------------------------------------ 254 private void ChangeParent(TreeNode node) 255 { 256 if (node == null) 257 return; 258 259 CheckState state = GetChecked(node.FirstNode); 260 foreach (TreeNode child in node.Nodes) 261 state &= GetChecked(child); 262 263 if (InternalSetChecked(node, state)) 264 ChangeParent(node.Parent); 265 } 266 267 /// ------------------------------------------------------------------------------------ 268 /// <summary> 269 /// Handles changing the state of a node 270 /// </summary> 271 /// <param name="node"></param> 272 /// ------------------------------------------------------------------------------------ 273 protected void ChangeNodeState(TreeNode node) 274 { 275 BeginUpdate(); 276 CheckState newState; 277 if (node.ImageIndex == (int)CheckState.Unchecked || node.ImageIndex < 0) 278 newState = CheckState.Checked; 279 else 280 newState = CheckState.Unchecked; 281 CheckNode(node, newState); 282 ChangeParent(node.Parent); 283 EndUpdate(); 284 } 285 286 /// ------------------------------------------------------------------------------------ 287 /// <summary> 288 /// Sets the checked state of a node, but doesn't deal with children or parents 289 /// </summary> 290 /// <param name="node">Node</param> 291 /// <param name="state">The new checked state</param> 292 /// <returns><c>true</c> if checked state was set to the requested state, otherwise 293 /// <c>false</c>.</returns> 294 /// ------------------------------------------------------------------------------------ 295 private bool InternalSetChecked(TreeNode node, CheckState state) 296 { 297 TreeViewCancelEventArgs args = 298 new TreeViewCancelEventArgs(node, false, TreeViewAction.Unknown); 299 OnBeforeCheck(args); 300 if (args.Cancel) 301 return false; 302 303 node.ImageIndex = (int)state; 304 node.SelectedImageIndex = (int)state; 305 306 OnAfterCheck(new TreeViewEventArgs(node, TreeViewAction.Unknown)); 307 return true; 308 } 309 310 /// ------------------------------------------------------------------------------------ 311 /// <summary> 312 /// Build a list of all of the tag data for checked items in the tree. 313 /// </summary> 314 /// <param name="node"></param> 315 /// <param name="list"></param> 316 /// ------------------------------------------------------------------------------------ 317 private void BuildTagDataList(TreeNode node, ArrayList list) 318 { 319 if (GetChecked(node) == CheckState.Checked && node.Tag != null) 320 list.Add(node.Tag); 321 322 foreach (TreeNode child in node.Nodes) 323 BuildTagDataList(child, list); 324 } 325 /// <summary> 326 /// 選擇的節點的集合 327 /// </summary> 328 /// <param name="node"></param> 329 /// <param name="selectedNodes"></param> 330 private void getBuildTagDataList(TreeNodeCollection nodes, List<TreeNode> selectedNodes) 331 { 332 foreach (TreeNode node in nodes) 333 { 334 if (GetChecked(node) == CheckState.Checked && node.Tag != null) 335 { 336 selectedNodes.Add(node); 337 } 338 getBuildTagDataList(node.Nodes, selectedNodes); 339 } 340 } 341 342 /// <summary> 343 /// 選擇的節點的集合 344 /// </summary> 345 /// <param name="nodes"></param> 346 /// <param name="selectedNodes"></param> 347 public void GetSelectedTreeNode(TreeNodeCollection nodes, List<TreeNode> selectedNodes) 348 { 349 foreach (TreeNode node in nodes) 350 { 351 if (GetChecked(node) == CheckState.Checked && node.Tag != null)//node.Checked 352 { 353 selectedNodes.Add(node); 354 } 355 GetSelectedTreeNode(node.Nodes, selectedNodes); 356 } 357 } 358 /// ------------------------------------------------------------------------------------ 359 /// <summary> 360 /// Look through the tree nodes to find the node that has given tag data and check it. 361 /// </summary> 362 /// <param name="node"></param> 363 /// <param name="tag"></param> 364 /// <param name="state"></param> 365 /// ------------------------------------------------------------------------------------ 366 private void FindAndCheckNode(TreeNode node, object tag, CheckState state) 367 { 368 if (node.Tag != null && node.Tag.Equals(tag)) 369 { 370 SetChecked(node, state); 371 return; 372 } 373 374 foreach (TreeNode child in node.Nodes) 375 FindAndCheckNode(child, tag, state); 376 } 377 #endregion 378 379 #region Public methods 380 /// ------------------------------------------------------------------------------------ 381 /// <summary> 382 /// Gets the checked state of a node 383 /// </summary> 384 /// <param name="node">Node</param> 385 /// <returns>The checked state</returns> 386 /// ------------------------------------------------------------------------------------ 387 public CheckState GetChecked(TreeNode node) 388 { 389 if (node.ImageIndex < 0) 390 return CheckState.Unchecked; 391 else 392 return (CheckState)node.ImageIndex; 393 } 394 395 /// ------------------------------------------------------------------------------------ 396 /// <summary> 397 /// Sets the checked state of a node 398 /// </summary> 399 /// <param name="node">Node</param> 400 /// <param name="state">The new checked state</param> 401 /// ------------------------------------------------------------------------------------ 402 public void SetChecked(TreeNode node, CheckState state) 403 { 404 if (!InternalSetChecked(node, state)) 405 return; 406 CheckNode(node, state); 407 ChangeParent(node.Parent); 408 } 409 410 /// ------------------------------------------------------------------------------------ 411 /// <summary> 412 /// Find a node in the tree that matches the given tag data and set its checked state 413 /// </summary> 414 /// <param name="tag"></param> 415 /// <param name="state"></param> 416 /// ------------------------------------------------------------------------------------ 417 public void CheckNodeByTag(object tag, CheckState state) 418 { 419 if (tag == null) 420 return; 421 foreach (TreeNode node in Nodes) 422 FindAndCheckNode(node, tag, state); 423 } 424 425 /// ------------------------------------------------------------------------------------ 426 /// <summary> 427 /// Return a list of the tag data for all of the checked items in the tree 428 /// </summary> 429 /// <returns></returns> 430 /// ------------------------------------------------------------------------------------ 431 public ArrayList GetCheckedTagData() 432 { 433 ArrayList list = new ArrayList(); 434 435 foreach (TreeNode node in Nodes) 436 BuildTagDataList(node, list); 437 return list; 438 } 439 /// <summary> 440 /// 441 /// </summary> 442 /// <param name="nodes"></param> 443 /// <returns></returns> 444 public List<TreeNode> GetSelectedNodes(TreeNodeCollection nodes) 445 { 446 List<TreeNode> selectedNodes = new List<TreeNode>(); 447 getBuildTagDataList(nodes, selectedNodes); 448 return selectedNodes; 449 } 450 #endregion 451 452 453 } 454 }
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)