Pour faire simple, c'est une classe qui donne une représentation visuelle des clusters d'un volume.
Et mis à part que je me suis battu avec les fonctions graphiques :), il montre l'utilisation et la manipulation des espaces/accès mémoires non managés avec la classe marshal et GCHandle.
J'ai essayé de commenter en partie le code pour simplifier la compréhension de cette source.
Pour plus d'infos:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/deviceiocontrol.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/fsctl_get_volume_bitmap.asp
Utilisation de la classe: 2 lignes et vous obtenez ce qu'il y a en capture :)
Dim cDriveBmp as New DriveBitmap
If cDriveBmp.GetMapVolume("c:") then cDriveBmp.DrawMap(VotrePictureBox,CouleurClustersOccupés,CouleurClustersLibre)
Remarque: J'ai mis le code ci-dessous pour ceux qui ne travaille pas avec la version 2 du framework
Source / Exemple :
Imports System.Runtime.InteropServices
Public Class DriveBitmap
#Region "Variables"
Private m_MapArray As Byte()
Private m_StartingLcn As Int64
Private m_BitmapSize As Decimal
#End Region
#Region "Api"
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As UInteger, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As UInteger, ByVal dwFlagsAndAttributes As UInteger, ByVal hTemplateFile As IntPtr) As IntPtr
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Boolean
Private Declare Auto Function DeviceIoControl Lib "kernel32" (ByVal hDevice As IntPtr, ByVal dwIoControlCode As UInt32, ByVal lpInBuffer As IntPtr, ByVal nInBufferSize As UInt32, ByVal lpOutBuffer As IntPtr, ByVal nOutBufferSize As UInt32, ByRef lpBytesReturned As UInt32, ByVal lpOverlapped As IntPtr) As Boolean
#End Region
#Region "Constantes"
''' <summary>Constante de CreateFile</summary>
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const OPEN_EXISTING = 3
''' <summary>Constante de validité d'un handle</summary>
Const INVALID_HANDLE_VALUE = -1
''' <summary>Utilisé pour récupérer les clusters occupés/libre d'un volume</summary>
Const FSCTL_GET_VOLUME_BITMAP = &H9006F
#End Region
#Region "Méthodes"
''' <summary>Récupère la map des clusters du volume</summary>
''' <param name="drive">Lettre du lecteur. Exemple "c:"</param>
''' <returns>True si réussi; False en cas d'échec</returns>
Function GetMapVolume(ByVal drive As String) As Boolean
Dim bret As Boolean = False 'valeur de retour
Try
'Création d'un handle vers le lecteur
Dim hwndDevice As IntPtr = CreateFile("\\.\" & drive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)
'Si handle est valide on fonce...
If hwndDevice <> INVALID_HANDLE_VALUE Then
Dim lAlloc As Int64 = 0
Dim pAlloc As IntPtr = IntPtr.Zero
Dim unmngedAlloc As GCHandle = GCHandle.Alloc(lAlloc, GCHandleType.Pinned) 'Accès à un espace mémoire non managée
Dim pBuff As IntPtr = unmngedAlloc.AddrOfPinnedObject 'Son adresse
Dim uiSpace As UInt32 = 1024 * 1024 * 64 'Représente une taille sufisante pour récupérer les clusters
Dim uiSize As UInt32 = 0
pAlloc = Marshal.AllocHGlobal(Convert.ToInt32(uiSpace)) 'Alloue un espace mémoire
Dim pDest As IntPtr = pAlloc 'Son adresse
'Appel de la fonction de récupération des clusters libres/occupés
Dim bDevice As Boolean = DeviceIoControl(hwndDevice, FSCTL_GET_VOLUME_BITMAP, pBuff, Convert.ToUInt32(Marshal.SizeOf(lAlloc)), pDest, uiSpace, uiSize, IntPtr.Zero)
'Si tout c'est bien passé on fonce...
If bDevice Then
unmngedAlloc.Free()
CloseHandle(hwndDevice) 'Libère le handle du volume
'Valeur d'entrée du buffer
Dim lStartingLcn As Int64 = Convert.ToInt64(Marshal.PtrToStructure(pDest, GetType(Int64)))
pDest = CType(pDest.ToInt64 + 8, IntPtr)
'Taille du buffer recevant les clusters
Dim lBitmapSize As Decimal = Convert.ToDecimal(Marshal.PtrToStructure(pDest, GetType(Int64)))
'Taille en bytes
Dim iByteSize As Int32 = Convert.ToInt32(lBitmapSize / 8)
iByteSize += 1
Dim pBitmapBegin As IntPtr = CType(pDest.ToInt64 + 8, IntPtr)
'Créer notre tableau de clusters
Dim buffer As Byte() = New Byte(iByteSize) {}
'Copie des clusters dans notre tableau de clusters (buffer)
Marshal.Copy(pBitmapBegin, buffer, 0, iByteSize)
Marshal.FreeHGlobal(pAlloc) 'Libère l'espace mémoire alloué
'Informations sur la map du volume
m_StartingLcn = lStartingLcn
m_BitmapSize = lBitmapSize
m_MapArray = buffer
bret = True 'retourne vrai :)
End If
End If
Catch ex As Exception
'En cas d'erreur :(
MessageBox.Show(ex.Message & ControlChars.CrLf & "Représentation annulé")
End Try
Return bret
End Function
''' <summary>Dessine la représentation des clusters sur le volume</summary>
''' <param name="picture">Objet PictureBox recevant le graphique</param>
''' <param name="UsedClustersColor">Couleur des clusters occupés</param>
''' <param name="FreeClustersColor">Couleur des clusters non occupés</param>
Sub DrawMap(ByRef picture As PictureBox, ByVal UsedClustersColor As Color, ByVal FreeClustersColor As Color)
'Nouveau bitmap
Dim BmpMap As Bitmap = New Bitmap(picture.Width, picture.Height, Imaging.PixelFormat.Format32bppArgb)
Dim ObjPen As Pen = Nothing
'Créer un Graphics est on y associe notre nouvel objet Bitmap
Dim g As Graphics = Graphics.FromImage(BmpMap)
g.Clear(Color.White) 'Efface son contenu
Dim iUsedClusters As Integer
Dim iFreeClusters As Integer
'Détermine le nombre de clusters par pixel
Dim iBytesPerPixel As Integer = m_MapArray.Length / picture.Width
'Et c'est partis............. :)
'On dessine dans notre bitmap
For i As Integer = 0 To picture.ClientSize.Width - 1
iUsedClusters = 0
For j As Integer = i * iBytesPerPixel + 1 To (i + 1) * iBytesPerPixel
'0 = vide
'255 = cluster occupé
Select Case m_MapArray(j)
Case 0
Case 255 : iUsedClusters += 8 'incrémente d'1 oct
Case Else
For curBit As Short = 0 To 7
If GetBit(m_MapArray(j), curBit) Then iUsedClusters += 1 'incrémentation 1bit
Next
End Select
Next
'Calcul le nombre de clusters non occupés
iFreeClusters = iBytesPerPixel * 8 - iUsedClusters
'Définis la couleur qui sera dessiner
ObjPen = New Pen(Color.FromArgb(MixColors(UsedClustersColor, FreeClustersColor, iUsedClusters / (iBytesPerPixel * 8))), 1)
'Point déterminant la position de la ligne
Dim P1 As New Point(i, 0)
Dim P2 As New Point(i, picture.Height)
'Dessine la ligne dans le bitmap
g.DrawLine(ObjPen, P1, P2)
Next
picture.Image = BmpMap 'Et pour finir envois le bitmap final dans notre picturebox :D
g.Dispose() 'Libère
End Sub
Private Function GetBit(ByVal value As Byte, ByVal bit As Integer) As Boolean
Return value And 2 ^ bit
End Function
''' <summary>Mix de couleurs</summary>
''' <param name="color1">Couleur représentant les clusteurs occupés</param>
''' <param name="color2">Couleur représentant les clusteurs libres</param>
''' <param name="opacity">Une ligne vertical sur le graph représente une zone de clusters.
''' Plus cette zone est blanche est plus il y a de clusters libres que d'occupés</param>
''' <returns>La nouvelle couleur mixée</returns>
Private Function MixColors(ByVal color1 As Color, ByVal color2 As Color, ByVal opacity As Decimal) As Integer
'Sépare les couleurs de color1
Dim Red1 As Byte = color1.R
Dim Green1 As Byte = color1.G
Dim Blue1 As Byte = color1.B
'Sépare les couleurs de color2
Dim Red2 As Byte = color2.R
Dim Green2 As Byte = color2.G
Dim Blue2 As Byte = color2.B
'Mélange.... et voici la nouvelle couleur... :)
Dim mixCol As Integer = Color.FromArgb((Red1 * opacity + Red2 * (1 - opacity)), (Green1 * opacity + Green2 * (1 - opacity)), (Blue1 * opacity + Blue2 * (1 - opacity))).ToArgb
Return mixCol
End Function
#End Region
End Class
Conclusion :
Bonne prog à tous :)
Surtout n'hésitez pas à noter ou mettre un commentaire, un conseil ou autre.
Merci
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.