|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Disk/Drive API Routines GetDiskFreeSpaceEx: Detailed Drive Info |
||
Posted: | Thursday June 29, 1999 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows NT4 | |
OS restrictions: | Win95, Win98, WinNT4, Win2000 | |
Author: | VBnet - Randy Birch | |
Prerequisites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
None. This code will work against any drive. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Until
Windows 95 OSR2 hit the streets the world was simple, and only the rarest and most expensive hard drives exceeded 2 gigabytes; in fact, a
300-400 megabyte drive was considered high tech server material! Windows 95 provides the GetDiskFreeSpace API to return information about the physical drive,
and GetVolumeInformation to return volume-specific data such as the volumes file system and characteristics.
Today, a two gig drive remains unusual - because 'usual' has now become anything between a 120 to 500 gig drive. This movement to larger drives - and the corresponding larger partitions - happened around mid-way through Win95's life. In an updated Win95 release - Win95 OSR2 GetDiskFreeSpaceEx API was introduced to handle the values returned by larger drives formatted into the (then) new FAT32 partitions (Win9x), or the 4 gig partitions available under Windows NT4. GetDiskFreeSpaceEx, as declared in the MSDN for C developers, uses the ULONG data type for its return values. A 64-bit integer, VB no comparible data type to handle true 64-bit integers. There are workarounds (like creating a Type with two longs), but we do have a specialized 64-bit data type that will fit the bill with some tweaking - the Currency type. The main difference between this and a true ULONG is the need to compensate for the decimal positions that the Currency type adds, but that is not a problem. The code on this page performs several different operations that you may find useful either together or individually, in order to get the drive and volume information from a given system's drives:
Because of the length of some of the code lines, particularly the ones to populate the TreeView, this page is somewhat wider than I prefer. It might be easiest to do a select all on the page an paste it into notepad, or to return to the link that brought you here and open the page in its own window. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS Module Code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Place the following code into the general declarations area of a bas module: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Type VBNET_DRIVE_INFO DrvsAvailable As String DrvType As String DrvSectors As Long 'GetDiskFreeSpace only DrvBytesPerSector As Long 'GetDiskFreeSpace only DrvFreeClusters As Long 'GetDiskFreeSpace only DrvTotalClusters As Long 'GetDiskFreeSpace only DrvSpaceFree As Currency 'GetDiskFreeSpaceEx only DrvSpaceFreeToCaller As Currency 'GetDiskFreeSpaceEx only DrvSpaceUsed As Currency 'GetDiskFreeSpaceEx only DrvSpaceTotal As Currency 'GetDiskFreeSpaceEx only DrvVolumeName As String DrvSerialNo As String DrvFileSystemName As String DrvFileSystemSupport As String DrvFileSystemFlags As Long End Type Public Declare Function GetVolumeInformation Lib "kernel32" _ Alias "GetVolumeInformationA" _ (ByVal lpRootPathName As String, _ ByVal lpVolumeNameBuffer As String, _ ByVal nVolumeNameSize As Long, _ lpVolumeSerialNumber As Long, _ lpMaximumComponentLength As Long, _ lpFileSystemFlags As Long, _ ByVal lpFileSystemNameBuffer As String, _ ByVal nFileSystemNameSize As Long) As Long Public Declare Function GetLogicalDriveStrings Lib "kernel32" _ Alias "GetLogicalDriveStringsA" _ (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long Public Declare Function GetDiskFreeSpaceEx Lib "kernel32" _ Alias "GetDiskFreeSpaceExA" _ (ByVal lpcurrDrive As String, _ lpFreeBytesAvailableToCaller As Currency, _ lpTotalNumberOfBytes As Currency, _ lpTotalNumberOfFreeBytes As Currency) As Long Public Declare Function GetDiskFreeSpace Lib "kernel32" _ Alias "GetDiskFreeSpaceA" _ (ByVal lpRootPathName As String, _ lpSectorsPerCluster As Long, _ lpBytesPerSector As Long, _ lpNumberOfFreeClusters As Long, _ lpTtoalNumberOfClusters As Long) As Long Public Declare Function GetUserName Lib "advapi32" _ Alias "GetUserNameA" _ (ByVal lpBuffer As String, nSize As Long) As Long Public Declare Function GetDriveType Lib "kernel32" _ Alias "GetDriveTypeA" _ (ByVal nDrive As String) As Long 'drive type constants Public Const DRIVE_REMOVABLE As Long = 2 Public Const DRIVE_FIXED As Long = 3 Public Const DRIVE_REMOTE As Long = 4 Public Const DRIVE_CDROM As Long = 5 Public Const DRIVE_RAMDISK As Long = 6 'file system constants Public Const FS_CASE_SENSITIVE As Long = &H1 Public Const FS_CASE_IS_PRESERVED As Long = &H2 Public Const FS_UNICODE_STORED_ON_DISK As Long = &H4 Public Const FS_PERSISTENT_ACLS As Long = &H8 Public Const FS_FILE_COMPRESSION As Long = &H10 Public Const FS_VOL_IS_COMPRESSED As Long = &H8000& Public HasLargeDriveSupport As Boolean Public Function OsHasLargeDriveSupport() As Boolean 'Determines whether the method supports a 'call to the GetDiskFreeSpaceEx API. 'The method first calls the GetDiskFreeSpaceEx API. 'If the call fails (no entry point in kernel32) 'then the function returns false, indicating 'that the app should use the GetDiskFreeSpace 'API instead. GetDiskFreeSpace is limited 'to partitions less than 2 gig. On Local Error GoTo LargeSupport_Error Dim RootPathName As String Dim tmp1 As Currency Dim tmp2 As Currency Dim tmp3 As Currency RootPathName = "C:\" 'get the drive's disk parameters If GetDiskFreeSpaceEx(RootPathName, _ tmp1, _ tmp2, _ tmp3) Then 'GetDiskFreeSpaceEx supported. OsHasLargeDriveSupport = True End If LargeSupport_Exit: Exit Function LargeSupport_Error: 'No large drive support; use 'GetDiskFreeSpace instead OsHasLargeDriveSupport = False Resume LargeSupport_Exit End Function |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Form Code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
To a new from, add: a Combo box (Combo1), two labels
(Label1 and Label2), two command buttons (Command1 and Command2), a
TreeView (Treeview1) and a checkbox (Check1).
Add an ImageList (optional) to the form, and populate with appropriate images. If you chose not to use the ImageList, be sure to remove al the references to the ImageList icon throughout the CreateTreeviewDriveData code. (Alternatively, you can download the base VB6 form and imagelist). The images I used were:
Add two hidden menus to the form as follows:
With the above in place, add the following code to the form: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Option Explicit Const mnuExpand As Integer = 1 Const mnuExpandAll As Integer = 3 Const mnuColapseAll As Integer = 4 Private Sub Form_Load() 'check if the operating system supports 'calls to the GetDiskFreeSpaceEx API HasLargeDriveSupport = OsHasLargeDriveSupport() Label2.Caption = IIf(HasLargeDriveSupport, _ "Large drives are supported; GetDiskFreeSpaceEx will be used", _ "Large drives NOT supported; GetDiskFreeSpace will be used") 'centre form Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 2 'load the drives LoadAvailableDrives Combo1 'select the second combo item, (should be C) Combo1.ListIndex = 1 'initialize the TreeView popup menu. ' 'Note that this is NOT the same as 'calling: ' mnuTVStyle(1).Checked = True 'The above only checks the item, 'without firing the associated 'menu code. mnuTVStyle_Click 1 End Sub Private Sub LoadAvailableDrives(cmbo As ComboBox) Dim lpBuffer As String 'get list of available drives lpBuffer = GetDriveString() 'Separate the drive strings 'and add to the combo. StripNulls 'will continually shorten the 'string. Loop until a single 'remaining terminating null is 'encountered. Do Until lpBuffer = Chr$(0) 'strip off one drive item 'and add to the combo cmbo.AddItem StripNulls(lpBuffer) Loop End Sub Private Function GetDriveString() As String 'returns string of available 'drives each separated by a null Dim sBuffer As String 'possible 26 drives, three characters each, plus trailing null sBuffer = Space$(26 * 4) If GetLogicalDriveStrings(Len(sBuffer), sBuffer) Then 'do not trim off trailing null! GetDriveString = Trim$(sBuffer) End If End Function Function StripNull(startStrg As String) As String 'Take a string separated by Chr(0)'s, and split off 1 item, and 'shorten the string so that the next item is ready for removal. Dim pos As Integer pos = InStr(startStrg, Chr$(0)) If pos Then StripNull = Mid(startStrg, 1, pos - 1) startStrg = Mid(startStrg, pos + 1, Len(startStrg)) End If End Function Function HiWord(dw As Long) As Long If dw And &H80000000 Then HiWord = (dw \ 65535) - 1 Else HiWord = dw \ 65535 End If End Function Function LoWord(dw As Long) As Long If dw And &H8000& Then LoWord = &H8000& Or (dw And &H7FFF&) Else LoWord = dw And &HFFFF& End If End Function Private Sub Command2_Click() Dim thisDrive As String Dim c As Integer If Combo1.ListCount > 0 Then Label1.Caption = "Loading drive stats..." DoEvents 'increase the apparent speed by setting the 'control's visible property to false, then 'clear the TreeView and load the nodes TreeView1.Visible = False If TreeView1.Nodes.count > 0 Then TreeView1.Nodes.Clear For c = 0 To Combo1.ListCount - 1 thisDrive = Left$(Combo1.List(c), 1) CreateTreeviewDriveData thisDrive Next TreeView1.Visible = True End If Label1.Caption = "Select drive and right-click for options." End Sub Private Sub Command1_Click() Dim thisDrive As String thisDrive = Left$(Combo1.List(Combo1.ListIndex), 1) If TreeView1.Nodes.count > 0 Then TreeView1.Nodes.Clear CreateTreeviewDriveData thisDrive Label1.Caption = "Select '" & thisDrive & "' and right-click for options." End Sub Private Sub Combo1_Click() Dim thisDrive As String thisDrive = Left$(Combo1.List(Combo1.ListIndex), 1) If TreeView1.Nodes.count > 0 Then TreeView1.Nodes.Clear CreateTreeviewDriveData thisDrive Label1.Caption = "Select '" & thisDrive & "' and right-click for options." Command1.Caption = "Reload " & Combo1.List(Combo1.ListIndex) End Sub Private Function rgbGetDriveType(RootPathName As String) As String 'returns the type of drive. Select Case GetDriveType(RootPathName) Case 0: rgbGetDriveType = "The drive type cannot be determined." Case 1: rgbGetDriveType = "The root directory does not exist." Case DRIVE_REMOVABLE: Select Case Left(RootPathName, 1) Case "a", "b": rgbGetDriveType = "Floppy drive." Case Else: rgbGetDriveType = "Removable drive." End Select Case DRIVE_FIXED: rgbGetDriveType = "Hard drive; can not be removed." Case DRIVE_REMOTE: rgbGetDriveType = "Remote (network) drive." Case DRIVE_CDROM: rgbGetDriveType = "CD-ROM drive." Case DRIVE_RAMDISK: rgbGetDriveType = "RAM disk." End Select End Function Private Function rgbGetDiskFreeSpace(RootPathName As String, _ VDI As VBNET_DRIVE_INFO) As Long 'returns data about the selected drive. 'Passed is the RootPathName; the other 'variables are filled in here. 'This routine uses the GetDiskFreeSpaceEx API 'if that API is supported, otherwise it uses 'the older GetDiskFreeSpace 'GetDiskFreeSpaceEx only variables Dim BytesFreeToCalller As Currency Dim TotalBytes As Currency Dim TotalFreeBytes As Currency Dim TotalBytesUsed As Currency Dim msg As String On Local Error GoTo DiskFreeSpace_error If HasLargeDriveSupport Then 'use GetDiskFreeSpaceEx 'get the drive's disk parameters If GetDiskFreeSpaceEx(RootPathName, _ BytesFreeToCalller, _ TotalBytes, _ TotalFreeBytes) = 1 Then 'multiplying the returned valued by 10000 'to adjust for the 4 decimal places that the 'currency data type returns. VDI.DrvSpaceTotal = (TotalBytes * 10000) VDI.DrvSpaceFree = (TotalFreeBytes * 10000) VDI.DrvSpaceFreeToCaller = (BytesFreeToCalller * 10000) VDI.DrvSpaceUsed = ((TotalBytes - TotalFreeBytes) * 10000) rgbGetDiskFreeSpace = 1 End If Else 'use the older GetDiskFreeSpace If GetDiskFreeSpace(RootPathName, _ VDI.DrvSectors, _ VDI.DrvBytesPerSector, _ VDI.DrvFreeClusters, _ VDI.DrvTotalClusters) = 1 Then VDI.DrvSpaceTotal = (VDI.DrvSectors * VDI.DrvBytesPerSector * VDI.DrvTotalClusters) VDI.DrvSpaceFree = (VDI.DrvSectors * VDI.DrvBytesPerSector * VDI.DrvFreeClusters) 'DrvSpaceFreeToCaller is not returned so use DrvSpaceFree VDI.DrvSpaceFreeToCaller = VDI.DrvSpaceFree VDI.DrvSpaceUsed = VDI.DrvSpaceTotal - VDI.DrvSpaceFree rgbGetDiskFreeSpace = 1 End If End If DiskFreeSpace_exit: On Local Error GoTo 0 Exit Function DiskFreeSpace_error: If HasLargeDriveSupport Then msg = "An error occurred processing the GetDiskFreeSpaceEx call." & vbNewLine msg = msg & "Check that the variables passed are declared Currency." MsgBox msg, vbExclamation Else msg = "Drive information for drive " & RootPathName & _ " has caused an error." & vbNewLine & vbNewLine & _ "The probable cause is that the drive" & _ "exceeds two gig, generating an overflow " & _ "in the drive space calculations because the " & _ "operating system does not support GetDiskFreeSpaceEx" MsgBox msg, vbExclamation End If rgbGetDiskFreeSpace = False Resume DiskFreeSpace_exit End Function Private Function rgbGetVolumeInformation(RootPathName As String, _ VDI As VBNET_DRIVE_INFO) As Long 'Returns information about the passed drive's 'type, free space, total space, volume information Dim pos As Integer Dim HiWord As Long, HiHexStr As String Dim LoWord As Long, LoHexStr As String Dim VolumeSN As Long Dim MaxFNLen As Long 'create working strings VDI.DrvVolumeName = Space(14) VDI.DrvFileSystemName = Space(32) 'do what it says If GetVolumeInformation(RootPathName, _ VDI.DrvVolumeName, _ Len(VDI.DrvVolumeName), _ VolumeSN, MaxFNLen, _ VDI.DrvFileSystemFlags, _ VDI.DrvFileSystemName, _ Len(VDI.DrvFileSystemName)) Then 'the volume label pos = InStr(VDI.DrvVolumeName, Chr(0)) If pos Then VDI.DrvVolumeName = Left(VDI.DrvVolumeName, pos - 1) If Len(Trim(VDI.DrvVolumeName)) = 0 Then VDI.DrvVolumeName = "(no label)" 'File system type (FAT, NTFS etc) pos = InStr(VDI.DrvFileSystemName, Chr(0)) If pos Then VDI.DrvFileSystemName = Left(VDI.DrvFileSystemName, pos - 1) 'File type parameters VDI.DrvFileSystemSupport = "Supports " & MaxFNLen & "-character filenames" 'Drive volume id VDI.DrvSerialNo = Hex(VolumeSN) 'return success rgbGetVolumeInformation = 1 End If End Function Private Function rgbGetUserName() As String 'returns the name of the user Dim username As String username = Space$(256) If GetUserName(username, Len(username)) Then rgbGetUserName = Left(username, InStr(username, Chr$(0)) - 1) Else rgbGetUserName = "(unknown)" End If End Function Public Sub CreateTreeviewDriveData(thisDrive As String) Dim nodX As Node Dim count As Integer Dim nIcon As Integer Dim thisDriveFull As String Dim TreeName As String Dim TreeCaption As String Dim dCaption As String Dim dummy As String Dim pKey As String Dim OtherInfoKey As String Dim flagExpand As Boolean Const drvFormat As String = "###,###,###,###,##0 b\y\t\e\s" Const cluFormat As String = "###,###,###,###,##0" 'my own structure to hold the drive info Dim VDI As VBNET_DRIVE_INFO 'set the Expand Nodes flag value based on the checkbox flagExpand = Check1.Value = 1 'assign the imagelist to the treeview TreeView1.ImageList = ImageList1 'If this is the first time through the 'routine (the treeview is empty), create 'the text for the root tree item & expand 'the root node. If the treeview has contents, 'just get the current parent key. The parent 'key to the entire tree is stored in 'TreeName'. If TreeView1.Nodes.count = 0 Then 'the root item text will also be the key name TreeName = "Drive Details on '" & rgbGetUserName() & "'" Set nodX = TreeView1.Nodes.Add(, , TreeName, TreeName, 1, 1) 'force the node expanded .. for the 'others, use the flag nodX.Expanded = True Else: TreeName = TreeView1.Nodes.Item(1).Text End If 'increment a counter to create individual 'keynames for use as a parent keyname for 'further subordinate childs thisDriveFull = thisDrive & ":\" count = count + 1 pKey = CStr(count) & "K" & thisDrive 'set the drive icon no from the imagelist, 'and the drive caption. nIcon = rgbGetDriveIconFromType(thisDriveFull) 'If there was no error in the API calls If rgbGetDiskFreeSpace(thisDriveFull, VDI) = 1 And _ rgbGetVolumeInformation(thisDriveFull, VDI) = 1 Then 'display the root drive, and expand as set in the flag Set nodX = TreeView1.Nodes.Add(TreeName, tvwChild, _ pKey, _ "Drive " & thisDriveFull, _ nIcon) nodX.Expanded = flagExpand 'create an individual key. Here I use a form of the 'variable name appended with the count value. This 'ensures that if in a While...Wend loop for all drives, 'each key will be unique. dummy = "DFS" & count & thisDrive dCaption = "File System : " & VDI.DrvFileSystemName Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DVN" & count & thisDrive dCaption = "Volume Label : " & VDI.DrvVolumeName Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DSR" & count & thisDrive dCaption = "Volume Serial No : " & VDI.DrvSerialNo Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DST" & count & thisDrive dCaption = "Total Drive Size : " & Format$(VDI.DrvSpaceTotal, drvFormat) Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DSU" & count & thisDrive dCaption = "Drive Space Used : " & Format$(VDI.DrvSpaceUsed, drvFormat) Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DSF" & count & thisDrive dCaption = "Drive Space Free : " & Format$(VDI.DrvSpaceFree, drvFormat) Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "SFC" & count & thisDrive dCaption = "Space Free To Caller : " & Format$(VDI.DrvSpaceFreeToCaller, drvFormat) Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) 'If GetDiskFreeSpaceEx was used, the 'cluster/sector info was not returned 'so print "n/a" dummy = "DRVS" & count & thisDrive dCaption = "Sectors : " & _ IIf(VDI.DrvSectors, Format$(VDI.DrvSectors, cluFormat), "n/a") Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DBPS" & count & thisDrive dCaption = "Bytes Per Sector : " & _ IIf(VDI.DrvSectors, Format$(VDI.DrvBytesPerSector, cluFormat), "n/a") Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DFCL" & count & thisDrive dCaption = "Free Clusters : " & _ IIf(VDI.DrvSectors, Format$(VDI.DrvFreeClusters, cluFormat), "n/a") Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) dummy = "DTFC" & count & thisDrive dCaption = "Total Clusters : " & _ IIf(VDI.DrvSectors, Format$(VDI.DrvTotalClusters, cluFormat), "n/a") Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, dummy, dCaption, nIcon) 'The "Other Info" goes next, and this item will 'be a parent to the other info data shown below it, 'so the key must be saved and used below. 'The icon is determined by offsetting the 'drive-type icon by 7 (see the imagelist icons). OtherInfoKey = "Other" & count & thisDrive dCaption = "Other Volume Info" Set nodX = TreeView1.Nodes.Add(pKey, tvwChild, OtherInfoKey, dCaption, nIcon + 7) nodX.Expanded = flagExpand 'This is where the "Other Info" goes, so we have to 'create a new indent level, by using the Other Info 'key as the parent. ' 'As these will have no sub-child items, the 'dummy' 'can be omitted leaving a comma as a placeholder Set nodX = TreeView1.Nodes.Add(OtherInfoKey, tvwChild, , rgbGetDriveType(thisDriveFull), 8) Set nodX = TreeView1.Nodes.Add(OtherInfoKey, tvwChild, , VDI.DrvFileSystemSupport, 8) 'these are only set based on flags returned in VDI.DrvFileSystemFlags If VDI.DrvFileSystemFlags And FS_CASE_IS_PRESERVED Then Set nodX = TreeView1.Nodes.Add(OtherInfoKey, _ tvwChild, , _ "case preserved when saved", 8) End If If VDI.DrvFileSystemFlags And FS_CASE_SENSITIVE Then Set nodX = TreeView1.Nodes.Add(OtherInfoKey, _ tvwChild, , _ "supports case-sensitive filenames", 8) End If If VDI.DrvFileSystemFlags And FS_PERSISTENT_ACLS Then Set nodX = TreeView1.Nodes.Add(OtherInfoKey, _ tvwChild, , _ "preserves and enforces ACL", 8) End If If VDI.DrvFileSystemFlags And FS_UNICODE_STORED_ON_DISK Then Set nodX = TreeView1.Nodes.Add(OtherInfoKey, _ tvwChild, , _ "supports Unicode filenames", 8) End If If VDI.DrvFileSystemFlags And FS_FILE_COMPRESSION Then Set nodX = TreeView1.Nodes.Add(OtherInfoKey, _ tvwChild, , _ "supports file-based compression", 8) End If If VDI.DrvFileSystemFlags And FS_VOL_IS_COMPRESSED Then Set nodX = TreeView1.Nodes.Add(OtherInfoKey, _ tvwChild, , _ "specified volume is compressed", 8) End If End If End Sub Private Sub mnuTVEdit_Click(Index As Integer) Dim c As Integer Dim currNodeIndex As Integer 'currNodeIndex represents the 'indentation level of the current node 'Assume that the node is a first-level node. 'This assures that a Collapse All command 'will not close the root. currNodeIndex = 1 'the drive letter 'if the current node is already expanded, 'then assume the node desired is at the 'second indent level If TreeView1.Nodes(1).Expanded Then currNodeIndex = 2 'info Select Case Index Case mnuExpand 'toggle the treeview's visible state 'to avoid the unnecessary repainting 'as each node changes state TreeView1.Visible = False TreeView1.SelectedItem.Expanded = Not TreeView1.SelectedItem.Expanded TreeView1.Visible = True Case mnuExpandAll 'toggle the treeview's visible state 'to avoid the unnecessary repainting 'as each node changes state TreeView1.Visible = False 'expand all the nodes from the current 'node through the last node for the 'given tree item For c = currNodeIndex To TreeView1.Nodes.count If TreeView1.Nodes(c).Children > 0 Then TreeView1.Nodes(c).Expanded = True End If Next TreeView1.Visible = True Case mnuColapseAll 'toggle the treeview's visible state 'to avoid the unnecessary repainting 'as each node changes state TreeView1.Visible = False 'collapse all the nodes from the current 'node through the last node for the 'given tree item For c = currNodeIndex To TreeView1.Nodes.count If TreeView1.Nodes(c).Children > 0 Then TreeView1.Nodes(c).Expanded = False End If Next TreeView1.Visible = True End Select End Sub Private Sub mnuTVStyle_Click(Index As Integer) mnuTVStyle(TreeView1.Style).Checked = False TreeView1.Style = Index mnuTVStyle(Index).Checked = True End Sub Private Sub TreeView1_MouseUp(Button As Integer, _ Shift As Integer, _ x As Single, _ y As Single) If Button = 2 Then PopupMenu mnuBar(1), , , , mnuTVEdit(1) End Sub Private Sub TreeView1_NodeClick(ByVal Node As Node) 'configure the hidden menu items based on the current selection 'set the Expand/Collapse captions If TreeView1.Nodes(Node.Index).Expanded Then mnuTVEdit(mnuExpand).Caption = "&Collapse" Else mnuTVEdit(mnuExpand).Caption = "&Expand" End If mnuTVEdit(mnuExpand).Enabled = Node.Children > 0 End Sub Private Function rgbGetDriveIconFromType(RootPathName As String) As Integer 'returns the index to the imagelist 'where the specified drive icon is. Select Case GetDriveType(RootPathName) Case 0: rgbGetDriveIconFromType = 1 Case 1: Case DRIVE_REMOVABLE: Select Case Left(RootPathName, 1) Case "a", "b": rgbGetDriveIconFromType = 2 Case Else: rgbGetDriveIconFromType = 1 End Select Case DRIVE_FIXED: rgbGetDriveIconFromType = 3 Case DRIVE_REMOTE: rgbGetDriveIconFromType = 6 Case DRIVE_CDROM: rgbGetDriveIconFromType = 4 Case DRIVE_RAMDISK: rgbGetDriveIconFromType = 7 End Select End Function |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comments | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Run the project and select a drive. The drive and its
details will be loaded into the treeview. Label2 reflects the API being used, and the treeview context menu will provide the ability to
change the treeview style, and expand or collapse the nodes.
If you want to test the accuracy of the OsHasLargeDriveSupport() function, you can cause the GetDiskFreeSpaceEx API to fail by changing the Alias from GetDiskFreeSpaceEx to another word, ie GetDiskFreeSpaceExXXX. Just make sure that you have at least one partition that is smaller than 2 gigs to try the code against. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |