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 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值