DriveComboBox.cs
上传用户:nnpulika
上传日期:2013-02-15
资源大小:597k
文件大小:14k
源码类别:

状态条

开发平台:

C#

  1. using System;
  2. using System.Collections;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Windows.Forms;
  7. using System.IO;
  8. using System.Text;
  9. using System.Runtime.InteropServices;
  10. using System.Diagnostics;
  11. using UtilityLibrary.Win32;
  12. using UtilityLibrary.General;
  13. namespace UtilityLibrary.WinControls
  14. {
  15. #region Delegates
  16. public delegate void SelectedDriveChangedHandler(object sender, DriveInfo driveInfo);
  17. #endregion
  18. #region Helper Classes
  19. // Helps to keep information about a drive in one place
  20. public class DriveInfo
  21. {
  22. #region Class Variables
  23. string drivePath = string.Empty; 
  24. string volumeName = string.Empty;
  25. string fileSystemName = string.Empty;
  26. string displayName = string.Empty;
  27. string typeName = string.Empty;
  28. uint fileSystemFlags = 0;
  29. uint maxFileNameLength = 0;
  30. uint serialNumber = 0;
  31. int iconIndex = -1;
  32. #endregion
  33. #region Constructors
  34. public DriveInfo(string drivePath, string volumeName)
  35. {
  36. this.drivePath = drivePath;
  37. this.volumeName = volumeName;
  38. }
  39. #endregion
  40. #region Properties
  41. public string DrivePath
  42. {
  43. get { return drivePath; }
  44. }
  45. public string VolumeName
  46. {
  47. get { return volumeName; }
  48. }
  49. public string DisplayName
  50. {
  51. set { displayName = value; }
  52. get { return displayName; }
  53. }
  54. public string TypeName
  55. {
  56. set { typeName = value; }
  57. get { return typeName; }
  58. }
  59. public string FileSystemName
  60. {
  61. set { fileSystemName = value; }
  62. get { return fileSystemName; }
  63. }
  64. public int IconIndex
  65. {
  66. set { iconIndex = value; }
  67. get { return iconIndex; }
  68. }
  69. public uint FileSystemFlags
  70. {
  71. set { fileSystemFlags = value; }
  72. get { return fileSystemFlags; }
  73. }
  74. public uint MaxFileNameLength
  75. {
  76. set { maxFileNameLength = value; }
  77. get { return maxFileNameLength; }
  78. }
  79. public uint SerialNumber
  80. {
  81. set { serialNumber = value; }
  82. get { return serialNumber; }
  83. }
  84. #endregion
  85. }
  86. #endregion
  87. /// <summary>
  88. /// Summary description for DriveComboBox.
  89. /// </summary>
  90. [ToolboxItem(false)]
  91. public class DriveComboBox : ComboBoxBase
  92. {
  93. #region Events
  94. public event SelectedDriveChangedHandler SelectedDriveChanged;
  95. #endregion
  96. #region Class Variables
  97. // Keeps track of all drives
  98. ArrayList driveList = new ArrayList();
  99. const int MY_COMPUTER_LEFT_PADDING = 2;
  100. const int DRIVES_LEFT_PADDING = 20;
  101. // Assume a small icon size of 16
  102. const int ICON_SIZE = 16;
  103. private CrystalDecisions.Windows.Forms.CrystalReportViewer crystalReportViewer1;
  104. IntPtr hImageList = IntPtr.Zero;
  105. #endregion
  106. #region Constructors
  107. public DriveComboBox()
  108. {
  109. DrawMode = DrawMode.OwnerDrawVariable;
  110. DropDownStyle = ComboBoxStyle.DropDownList;
  111. // Override parent, we don't want to do all the painting ourselves
  112. // since we want to let the edit control deal with the text for editing
  113. // the parent class ComboBoxBase knows to do the right stuff with 
  114. // non-editable comboboxes as well as editable comboboxes as long
  115. // as we change these flags below
  116. SetStyle(ControlStyles.AllPaintingInWmPaint
  117. |ControlStyles.UserPaint|ControlStyles.Opaque, false);
  118. Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, 
  119. System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
  120. SelectedIndexChanged += new EventHandler(OnSelectedIndexChanged);
  121. InitializeDriveComboBox();
  122. }
  123. void InitializeDriveComboBox()
  124. {
  125. GetLogicalDrives();
  126. int count = driveList.Count;
  127. for ( int i = 0; i < count; i++ )
  128. {
  129. DriveInfo di = (DriveInfo)driveList[i];
  130. Debug.Assert(di != null);
  131. Items.Add(di.DisplayName);
  132. }
  133. }
  134. #endregion
  135. #region Overrides
  136. protected override void OnMeasureItem(MeasureItemEventArgs e)
  137. {
  138.             e.ItemHeight = ICON_SIZE + 2;
  139. base.OnMeasureItem(e);
  140. }
  141. protected override void DrawComboBoxItem(Graphics g, Rectangle bounds, int Index, bool selected, bool editSel)
  142. {
  143. // Call base class to do the "Flat ComboBox" drawing
  144. base.DrawComboBoxItem(g, bounds, Index, selected, editSel);
  145. if ( Index != -1) 
  146. {
  147. DriveInfo driveInfo = (DriveInfo)driveList[Index];
  148. Debug.Assert(driveInfo != null);
  149. Brush brush;
  150. brush = new SolidBrush(SystemColors.MenuText);
  151. int gap = 0;
  152. if ( Index == 0 )
  153. // This is "My Computer" item
  154. gap = MY_COMPUTER_LEFT_PADDING;
  155. else
  156. gap = DRIVES_LEFT_PADDING;
  157. if (editSel )
  158. gap-=3;
  159. // Draw image
  160. int iconIndex = driveInfo.IconIndex;
  161. if ( iconIndex != -1 )
  162. {
  163. // Use the System Image icon itself to do the drawing to avoid
  164. // those awful black lines on the icons
  165. IntPtr hDC = g.GetHdc();
  166. WindowsAPI.ImageList_DrawEx(hImageList, iconIndex, hDC, 
  167. bounds.Left+gap, bounds.Top+(bounds.Height-ICON_SIZE)/2, 0, 0,
  168. ImageListDrawColors.CLR_NONE, ImageListDrawColors.CLR_NONE, ImageListDrawFlags.ILD_NORMAL);
  169. // --it could not be the same size that the icons we are getting from SHGetFileInfo-- 
  170. gap += ICON_SIZE + 2;
  171. g.ReleaseHdc(hDC);
  172. }
  173. Size textSize = TextUtil.GetTextSize(g, driveInfo.DisplayName, Font);
  174. int top = bounds.Top + (bounds.Height - textSize.Height)/2;
  175. g.DrawString(driveInfo.DisplayName, Font, brush, new Point(bounds.Left + gap, top));
  176. brush.Dispose();
  177. }
  178. }
  179. protected override void DrawComboBoxItemEx(Graphics g, Rectangle bounds, int Index, bool selected, bool editSel)
  180. {
  181. // This "hack" is necessary to avoid a clipping bug that comes from the fact that sometimes
  182. // we are drawing using the Graphics object for the edit control in the combobox and sometimes
  183. // we are using the graphics object for the combobox itself. If we use the same function to do our custom
  184. // drawing it is hard to adjust for the clipping because of these limitations
  185. base.DrawComboBoxItemEx(g, bounds, Index, selected, editSel);
  186. if ( Index != -1)
  187. {
  188. DriveInfo driveInfo = (DriveInfo)driveList[Index];
  189. Debug.Assert(driveInfo != null);
  190. SolidBrush brush;
  191. brush = new SolidBrush(SystemColors.MenuText);
  192.                 
  193. Rectangle rc = bounds;
  194. int gap = 0;
  195. if ( Index == 0 )
  196. // This is "My Computer" item
  197. gap = MY_COMPUTER_LEFT_PADDING;
  198. else
  199. gap = DRIVES_LEFT_PADDING;
  200. // Draw image
  201. int iconIndex = driveInfo.IconIndex;
  202. if ( iconIndex != -1 )
  203. {
  204. // Use the System Image icon itself to do the drawing to avoid
  205. // those awful black lines on the icons
  206. IntPtr hDC = g.GetHdc();
  207. WindowsAPI.ImageList_DrawEx(hImageList, iconIndex, hDC, 
  208. bounds.Left+gap, bounds.Top+(bounds.Height-ICON_SIZE)/2, 0, 0,
  209. ImageListDrawColors.CLR_NONE, ImageListDrawColors.CLR_NONE, ImageListDrawFlags.ILD_NORMAL);
  210. // --it could not be the same size that the icons we are getting from SHGetFileInfo-- 
  211. gap += ICON_SIZE + 2;
  212. g.ReleaseHdc(hDC);
  213. }
  214. Size textSize = TextUtil.GetTextSize(g, driveInfo.DisplayName, Font);
  215. int top = bounds.Top + (bounds.Height - textSize.Height)/2;
  216. Rectangle clipRect = new Rectangle(bounds.Left + gap, top, bounds.Width - ARROW_WIDTH, top + textSize.Height);
  217. g.DrawString(driveInfo.DisplayName, Font, brush, clipRect);
  218. brush.Dispose();
  219. }
  220. }
  221. protected override void DrawDisableState()
  222. {
  223. // Draw the combobox state disable
  224. base.DrawDisableState();
  225. // Draw the specific disable state to
  226. // this derive class
  227. using ( Graphics g = CreateGraphics() )
  228. {
  229. Rectangle rc = ClientRectangle;
  230.                 int selIndex = SelectedIndex;
  231. int gap = 0;
  232. if ( selIndex == 0 )
  233. gap = MY_COMPUTER_LEFT_PADDING;
  234. else
  235. gap = DRIVES_LEFT_PADDING;
  236. DriveInfo driveInfo = (DriveInfo)driveList[selIndex];
  237. int iconIndex = driveInfo.IconIndex;
  238. using ( Brush b = new SolidBrush(SystemColors.ControlDark) )
  239. {
  240. if ( iconIndex != -1 )
  241. {
  242. // Use the System Image icon itself to do the drawing to avoid
  243. // those awful black lines on the icons
  244. IntPtr hDC = g.GetHdc();
  245. WindowsAPI.ImageList_DrawEx(hImageList, iconIndex, hDC, 
  246. rc.Left+gap, rc.Top+(rc.Height-ICON_SIZE)/2, 0, 0,
  247. ImageListDrawColors.CLR_NONE, ImageListDrawColors.CLR_NONE, ImageListDrawFlags.ILD_BLEND50);
  248. // --it could not be the same size that the icons we are getting from SHGetFileInfo-- 
  249. gap += ICON_SIZE + 2;
  250. g.ReleaseHdc(hDC);
  251. }
  252. Size textSize = TextUtil.GetTextSize(g, driveInfo.DisplayName, Font);
  253. // Clipping rectangle
  254. int top = rc.Top + (rc.Height - textSize.Height)/2;
  255. Rectangle clipRect = new Rectangle(rc.Left + gap, 
  256. top, rc.Width  -  ARROW_WIDTH, top+textSize.Height);
  257. g.DrawString(driveInfo.DisplayName, Font, b, clipRect);
  258. }
  259. }
  260. }
  261. #endregion
  262. #region Implementation
  263. void GetLogicalDrives()
  264. {
  265. // Get all drives
  266. string[] logicalDrives = Directory.GetLogicalDrives();
  267. // Add the Computer item as the root of all drives
  268. // not really necesarry but it looks kind of cool
  269. DriveInfo driveInfo = new DriveInfo(string.Empty ,"My Computer");
  270. string dName;
  271. string tName;
  272. int ii;
  273. IntPtr idlPtr;
  274. int result = WindowsAPI.SHGetSpecialFolderLocation(IntPtr.Zero, ShellSpecialFolder.CSIDL_DRIVES, out idlPtr);
  275. // Get Folder information
  276. GetSpecialFolderShellInfo(idlPtr, out dName, out tName, out ii);
  277.             // Release pointer that was allocated by the COM memory allocator
  278. IMalloc alloc = null;
  279. WindowsAPI.SHGetMalloc(out alloc);
  280. Debug.Assert(alloc != null);
  281.             alloc.Free(idlPtr);
  282. // Free pointer memory allocator
  283. IUnknown iUnknown = (IUnknown)alloc;
  284. iUnknown.Release();
  285. driveInfo.IconIndex = ii;
  286. driveInfo.DisplayName = dName;
  287. driveInfo.FileSystemName = tName;
  288.             driveList.Add(driveInfo);
  289. // Fill drives array with available drives
  290. foreach (string drivePath in logicalDrives )
  291. {
  292. uint serialNumber;
  293. uint maxFileNameLength;
  294. uint fileSystemFlags;
  295. string volumeName;
  296. string fileSystemName;
  297. GetDriveVolumeInfo(drivePath, out volumeName, out fileSystemName, 
  298. out serialNumber, out maxFileNameLength, out fileSystemFlags);
  299. // Construct DriveInfo object and add it to our list
  300. driveInfo = new DriveInfo(drivePath, volumeName);
  301. driveList.Add(driveInfo);
  302. // Set the rest of the properties
  303.                 driveInfo.SerialNumber = serialNumber;
  304. driveInfo.MaxFileNameLength = maxFileNameLength;
  305. driveInfo.FileSystemFlags = fileSystemFlags;
  306. // Add other information
  307. string displayName;
  308. string typeName;
  309. int iconIndex;
  310. GetDriveShellInfo(drivePath, out displayName, out typeName, out iconIndex);
  311. // Save it into the object
  312. driveInfo.DisplayName = displayName;
  313. driveInfo.TypeName = typeName;
  314. driveInfo.IconIndex = iconIndex;
  315. }
  316. }
  317. void GetDriveVolumeInfo(string drivePath, out string volumeName, out string fileSystemName, 
  318. out uint serialNumber, out uint maxFileNameLength, out uint fileSystemFlags)
  319. {
  320. // Make the buffer big enough
  321. const int BUFFER_SIZE = 1024;
  322. // Buffers
  323. StringBuilder volumeNameBuffer = new StringBuilder(BUFFER_SIZE);
  324. StringBuilder fileSystemNameBuffer = new StringBuilder(BUFFER_SIZE);
  325. // Get the Information
  326. int retval = WindowsAPI.GetVolumeInformation(drivePath, volumeNameBuffer, BUFFER_SIZE, out serialNumber,  out maxFileNameLength, 
  327. out fileSystemFlags, fileSystemNameBuffer, BUFFER_SIZE);
  328. volumeName = volumeNameBuffer.ToString();
  329. fileSystemName = fileSystemNameBuffer.ToString();
  330.                     
  331. }
  332. void GetDriveShellInfo(string drivePath, out string displayName, out string typeName, out int iconIndex)
  333. {
  334. SHFILEINFO shfi = new SHFILEINFO();
  335.                         
  336. // Load a System Small icon image
  337. hImageList = WindowsAPI.SHGetFileInfo( drivePath, 0, out shfi, (uint)Marshal.SizeOf(typeof(SHFILEINFO)), 
  338. ShellFileInfoFlags.SHGFI_SYSICONINDEX | ShellFileInfoFlags.SHGFI_SMALLICON |
  339. ShellFileInfoFlags.SHGFI_DISPLAYNAME | ShellFileInfoFlags.SHGFI_TYPENAME );
  340. iconIndex = shfi.iIcon;
  341. displayName = shfi.szDisplayName;
  342. typeName = shfi.szTypeName;
  343.        }
  344. void GetSpecialFolderShellInfo(IntPtr idl, out string displayName, out string typeName, out int iconIndex)
  345. {
  346. SHFILEINFO shfi = new SHFILEINFO();
  347.                         
  348. // Load a System Small icon image
  349. hImageList = WindowsAPI.SHGetFileInfo(idl, 0, out shfi, (uint)Marshal.SizeOf(typeof(SHFILEINFO)), 
  350. ShellFileInfoFlags.SHGFI_SYSICONINDEX | ShellFileInfoFlags.SHGFI_SMALLICON |
  351. ShellFileInfoFlags.SHGFI_DISPLAYNAME | ShellFileInfoFlags.SHGFI_TYPENAME | ShellFileInfoFlags.SHGFI_PIDL );
  352. iconIndex = shfi.iIcon;
  353. displayName = shfi.szDisplayName;
  354. typeName = shfi.szTypeName;
  355. }
  356. void OnSelectedIndexChanged(object sender, EventArgs e)
  357. {
  358. FireSelectedDriveChanged();
  359. }
  360. private void InitializeComponent()
  361. {
  362. this.crystalReportViewer1 = new CrystalDecisions.Windows.Forms.CrystalReportViewer();
  363. // 
  364. // crystalReportViewer1
  365. // 
  366. this.crystalReportViewer1.ActiveViewIndex = -1;
  367. this.crystalReportViewer1.Location = new System.Drawing.Point(17, 17);
  368. this.crystalReportViewer1.Name = "crystalReportViewer1";
  369. this.crystalReportViewer1.ReportSource = null;
  370. this.crystalReportViewer1.TabIndex = 0;
  371. }
  372. void FireSelectedDriveChanged()
  373. {
  374. if ( SelectedDriveChanged != null )
  375. {
  376. int index = SelectedIndex;
  377. if ( index != -1 )
  378. {
  379. DriveInfo di = (DriveInfo)driveList[index];
  380. Debug.Assert(di != null);
  381. SelectedDriveChanged(this, di);
  382. }
  383. }
  384. }
  385. #endregion
  386. }
  387. }