FolderBrowserDialog.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2006 Alexander Olk
  21. //
  22. // Authors:
  23. // Alexander Olk (alex.olk@googlemail.com)
  24. // Gert Driesen (drieseng@users.sourceforge.net)
  25. //
  26. //
  27. // changed (simplified) by Alexander Tsyganenko
  28. using System.ComponentModel;
  29. using System.IO;
  30. namespace System.Windows.Forms
  31. {
  32. public sealed class FolderBrowserDialog : CommonDialog
  33. {
  34. #region Local Variables
  35. private Label descriptionLabel;
  36. private Button cancelButton;
  37. private Button okButton;
  38. private FolderBrowserTreeView folderBrowserTreeView;
  39. private string selectedPath = string.Empty;
  40. #endregion // Local Variables
  41. #region Public Constructors
  42. public FolderBrowserDialog()
  43. {
  44. form = new DialogForm(this);
  45. folderBrowserTreeView = new FolderBrowserTreeView(this);
  46. okButton = new Button();
  47. cancelButton = new Button();
  48. descriptionLabel = new Label();
  49. form.AcceptButton = okButton;
  50. form.CancelButton = cancelButton;
  51. form.SuspendLayout();
  52. form.ClientSize = new Drawing.Size(422, 424);
  53. form.Text = "Browse For Folder";
  54. // descriptionLabel
  55. descriptionLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
  56. descriptionLabel.Location = new Drawing.Point(15, 14);
  57. descriptionLabel.Size = new Drawing.Size(392, 40);
  58. descriptionLabel.Text = string.Empty;
  59. // folderBrowserTreeView
  60. folderBrowserTreeView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
  61. folderBrowserTreeView.Location = new Drawing.Point(15, 60);
  62. folderBrowserTreeView.Size = new Drawing.Size(392, 312);
  63. // okButton
  64. okButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
  65. okButton.Location = new Drawing.Point(253, 385);
  66. okButton.Size = new Drawing.Size(75, 23);
  67. okButton.TabIndex = 1;
  68. okButton.Text = "OK";
  69. // cancelButton
  70. cancelButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
  71. cancelButton.DialogResult = DialogResult.Cancel;
  72. cancelButton.Location = new Drawing.Point(333, 385);
  73. cancelButton.Size = new Drawing.Size(75, 23);
  74. cancelButton.Text = "Cancel";
  75. form.Controls.Add(cancelButton);
  76. form.Controls.Add(okButton);
  77. form.Controls.Add(folderBrowserTreeView);
  78. form.Controls.Add(descriptionLabel);
  79. form.ResumeLayout(false);
  80. okButton.Click += new EventHandler(OnClickOKButton);
  81. cancelButton.Click += new EventHandler(OnClickCancelButton);
  82. form.VisibleChanged += new EventHandler(OnFormVisibleChanged);
  83. form.MinimumSize = new Drawing.Size((int)(310 * form.DpiScale), (int)(254 * form.DpiScale));
  84. }
  85. #endregion // Public Constructors
  86. #region Public Instance Properties
  87. [Browsable(true)]
  88. [DefaultValue("")]
  89. [Localizable(true)]
  90. public string Description
  91. {
  92. set
  93. {
  94. descriptionLabel.Text = value;
  95. }
  96. get
  97. {
  98. return descriptionLabel.Text;
  99. }
  100. }
  101. [Browsable(true)]
  102. [DefaultValue("")]
  103. [Localizable(true)]
  104. public string SelectedPath
  105. {
  106. set
  107. {
  108. if (value == null)
  109. value = string.Empty;
  110. selectedPath = value;
  111. }
  112. get
  113. {
  114. return selectedPath;
  115. }
  116. }
  117. public bool ShowNewFolderButton { get; set; } // not implemented
  118. #endregion // Public Instance Properties
  119. #region Public Instance Methods
  120. public override void Reset()
  121. {
  122. Description = string.Empty;
  123. selectedPath = string.Empty;
  124. }
  125. protected override bool RunDialog()
  126. {
  127. folderBrowserTreeView.SelectedPath = SelectedPath;
  128. return true;
  129. }
  130. #endregion // Public Instance Methods
  131. #region Internal Methods
  132. void OnClickOKButton(object sender, EventArgs e)
  133. {
  134. selectedPath = folderBrowserTreeView.SelectedPath;
  135. form.DialogResult = DialogResult.OK;
  136. }
  137. void OnClickCancelButton(object sender, EventArgs e)
  138. {
  139. form.DialogResult = DialogResult.Cancel;
  140. }
  141. void OnFormVisibleChanged(object sender, EventArgs e)
  142. {
  143. folderBrowserTreeView.Focus();
  144. }
  145. #endregion // Internal Methods
  146. #region Events
  147. #endregion
  148. internal class FolderBrowserTreeView : TreeView
  149. {
  150. private FolderBrowserDialog parentDialog;
  151. private ImageList imageList = new ImageList();
  152. private string selectedPath;
  153. public string SelectedPath
  154. {
  155. get => selectedPath;
  156. set => FindPath(value);
  157. }
  158. public FolderBrowserTreeView(FolderBrowserDialog parent_dialog)
  159. {
  160. parentDialog = parent_dialog;
  161. HideSelection = false;
  162. ImageList = imageList;
  163. SetupImageList();
  164. PopulateTree();
  165. }
  166. private void SetupImageList()
  167. {
  168. imageList.ColorDepth = ColorDepth.Depth32Bit;
  169. imageList.ImageSize = new Drawing.Size((int)(16 * DpiScale), (int)(16 * DpiScale));
  170. imageList.Images.Add(ResourceLoader.GetBitmap("folder.png"));
  171. }
  172. private void PopulateTree()
  173. {
  174. foreach (var drive in Directory.GetLogicalDrives())
  175. {
  176. var node = this.Nodes.Add(drive);
  177. node.Tag = drive;
  178. node.Nodes.Add("?");
  179. }
  180. }
  181. private void FindPath(string path)
  182. {
  183. if (string.IsNullOrEmpty(path))
  184. path = Directory.GetCurrentDirectory();
  185. FindPath(path, this.Nodes);
  186. }
  187. private void FindPath(string path, TreeNodeCollection nodes)
  188. {
  189. foreach (TreeNode node in nodes)
  190. {
  191. var nodePath = node.Tag.ToString();
  192. if (path.StartsWith(nodePath, StringComparison.CurrentCultureIgnoreCase))
  193. {
  194. node.Expand();
  195. this.SelectedNode = node;
  196. FindPath(path, node.Nodes);
  197. }
  198. }
  199. }
  200. private void PopulateTree(string path, TreeNode rootNode)
  201. {
  202. rootNode.Nodes.Clear();
  203. foreach (var folder in Directory.GetDirectories(path))
  204. {
  205. var info = new DirectoryInfo(folder);
  206. if ((info.Attributes & FileAttributes.Hidden) != 0)
  207. continue;
  208. var node = rootNode.Nodes.Add(info.Name);
  209. node.Tag = folder;
  210. node.Nodes.Add("?");
  211. }
  212. }
  213. protected override void OnBeforeExpand(TreeViewCancelEventArgs e)
  214. {
  215. base.OnBeforeExpand(e);
  216. var node = e.Node;
  217. if (node.Nodes.Count == 1 && node.Nodes[0].Text == "?")
  218. {
  219. PopulateTree(node.Tag.ToString(), node);
  220. }
  221. }
  222. protected override void OnAfterSelect(TreeViewEventArgs e)
  223. {
  224. base.OnAfterSelect(e);
  225. var node = e.Node;
  226. if (node == null)
  227. {
  228. parentDialog.okButton.Enabled = false;
  229. }
  230. else
  231. {
  232. parentDialog.okButton.Enabled = true;
  233. selectedPath = node.Tag.ToString();
  234. }
  235. }
  236. }
  237. }
  238. }