Programowanie w języku Delphi » Artykuły

Pobieranie informacji o napędach systemu

  • 2006-03-02 17:54
  • 5 komentarzy
  • 1773 odsłony
  • Oceń ten tekst jako pierwszy
Aby zidentyfikować napędy zainstalowane w systemie, konieczne jest użycie funkcji WinAPI. W gruncie rzeczy jest to proste, należy jednak poznać kilka fundamentalnych zasad i poznać sposób użycia funkcji WinAPI.

Podstawową funkcją jest GetDriveType. Funkcja ta zawiera jeden parametr, a mianowicie literę dysku dla którego chcesz uzyskać informacje.  

Funkcja ta zwraca takie oto wartości:

0 - Typ napędu niemożliwy do określenia.
1 - Nie istnieje napęd o podanej literze.
DRIVE_REMOVABLE -  Dyskietka lub napęd wymienny
DRIVE_FIXED - Napęd niewymienny
DRIVE_REMOTE -  Napęd sieciowy
DRIVE_CDROM - CD - ROM
DRIVE_RMADISK - Ram-dysk - wirtualny dysk.

W tym artykule napiszemy program, który będzie właśnie podawał informacje dotyczące dysku. Na formularzu umieść komponent ListView - w nim będą zaznaczone dyski. Umieść na formie także komponent ImageList. Dodaj do niego z dwie ikony symbolizujące odpowiednio: ikonę CD oraz ikonę dysku twardego.

Dobrze przejdźmy do rzeczy najważniejszej, czyli uzyskanie informacji o dyskach. Oto procedura OnCreate naszego programu:

procedure TMainForm.FormCreate(Sender: TObject);
var
  i : Integer; // zmienna potrzebna do wykonania petli
  DriveType : Integer;  // informacja o typie dysku
  ListItem: TListItem;
  Bufor:array[0..MAX_PATH] of Char; // zawiera etykiete dysku
  MaxCompLength, FileSystemFlags : DWORD;
begin
{  wykonaj petle analizujac kazda litere dysku }
  for I := Ord('A') to Ord('Z') do
  begin
    DriveType := GetDriveType(PChar(Chr(i) + ':\')); // pobierz typ dysku
 
 
  { jezeli typ  dysku to 0 ( nie mozna okreslic ) lub 1 ( nie istnieje taki dysk ) to pomin w opisie. }
 
    if not (DriveType = 0) and not (DriveType = 1) then
    begin
  {  uzyskaj informacje dotyczace etykiety dysku }
      GetVolumeInformation(PChar(Chr(i) + ':\'), Bufor, SizeOf(Bufor),
      nil, MaxCompLength, FileSystemFlags, nil, 0);
 
      ListItem := ListView.Items.Add; // dodaj pozycje
      ListItem.Caption := Chr(i) + ':\' + ' '  + Bufor; // ustaw tekst
 
   { Tutaj w zaleznosci od rodzaju dysku do komponentu ListView do okreslnej
      pozycji zostaje przypisana okreslona ikonka symoblizujaca dysk.  }
 
      if (DriveType = DRIVE_CDROM) then ListItem.ImageIndex := 0;
      if (DriveType = DRIVE_FIXED) then ListItem.ImageIndex := 1;
      if (DriveType = DRIVE_REMOVABLE) then ListItem.ImageIndex := -1;
    end;                                               
  end;
end;


Wiadomo, że dyski mogą być ponumerowane od A do Z. Na początek do zmiennej DriveType zostaje przypisany rezultat wykonania funkcji GetDriveType. Później następuje sprawdzenie, czy zmienna DriveType nie ma przypadkiem wartości 0 lub 1 co oznaczałoby, że niemożliwe jest określenie dysku - wtedy operacje zostaną pominięte. Jeżeli dysk jest następuje pobranie jego etykiety, a później tworzona jest nowa pozycja w komponencie TListView. To nie wszystko. Trzeba jeszcze wybrać ikonę. Właściwość ImageIndex określa numer ikony. Po prostu dobierana jest odpowiednia ikona w zależności od rodzaju dysku. Bardzo ważna rzecz: trzeba we właściwości LargeImages komponentu ListView wybrać komponent ImageList1.

Dobrze, wiesz już jak uzyskać listę dysków znajdujących się w systemie. Teraz coś trudniejszego mianowicie uzyskanie dokładniejszych informacji o samych dyskach, czyli liczba klasterów, sektory przypadający na klaster itp. To wszystko umożliwia nam funkcja GetDiskFreeSpace. Trzeba w niej podać wszystkie zmienne, które przechowywać będą informacje o właściwościach dysku.  

Zadeklarujmy te zmienne:

var
  DirName: String; // litera dysku
  Sectors: DWORD; // sektory w klasterze  
  Bytes: DWORD; // bajty w sektorze
  FreeClust: DWORD; // wolne klastery
  TotalClust: DWORD; // wszystkie klastery


Dobrze. Teraz trzeba jakoś zdobyć literę zaznaczonej pozycji w komponencie. Zrób to w ten sposób:

DirName := ListView.Selected.Caption[1]; // pobierz pierwszy znak napisu - litere dysku


Po prostu uzyskujemy pierwszy znak zaznaczonej pozycji... Na formularzu umieść 4 etykiety tekstowe, które wyświetlały będą te informacje. Teraz samo wywłanie funkcji GetDiskFreeSpace:  

 {  Funkcja GetDiskFreeSpace podaje rozne informacje dotyczace  danego dysku }
  if GetDiskFreeSpace(PChar(DirName + ':\'), Sectors, Bytes, FreeClust, TotalClust) then
  begin
  {  przypisz dane do etykiet tekstowych }
    lblSectors.Caption := 'Sektory w klastrze: ' + IntToStr(Sectors);
    lblBytes.Caption := 'Bajty w sektorze: ' + IntToStr(Bytes);
    lblFreeClust.Caption := 'Wolne klastry: ' + IntToStr(FreeClust);
    lblTotalClust.Caption := 'Wszystkie klastry: ' + IntToStr(TotalClust);
  { jezeli niemozliwe jest odczytanie wlasciwosci przypisz etykieta symbolom znak ???? }
  end else
  begin
    lblSectors.Caption := '???';
    lblBytes.Caption := '???';
    lblFreeClust.Caption := '???';
    lblTotalClust.Caption := '???';
  end;


Jeżeli nie jest możliwe określenie danych z dysku to na etykietach przypisany zostaje znak ???.

Oto cały kod programu:  

//////////////////////////////////////////////////////////////////
//                                                              //
//               Unit MainFrm for DrivesInfo                    //
//             Copyright ? 2001 by Adam Boduch                  //
//      Service for programmers: http://programowanie.of.pl     //
//                E-mail:  [email protected]                    //
//         29.06.2001 r.                                        //
//                                                              //
//////////////////////////////////////////////////////////////////
 
unit MainFrm;
 
interface
 
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, ImgList, StdCtrls;
 
type
  TMainForm = class(TForm)
    ListView: TListView;
    ImageList1: TImageList;
    lblSectors: TLabel;
    lblBytes: TLabel;
    lblFreeClust: TLabel;
    lblTotalClust: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure ListViewClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  MainForm: TMainForm;
 
implementation
 
{$R *.DFM}
 
procedure TMainForm.FormCreate(Sender: TObject);
var
  i : Integer; // zmienna potrzebna do wykonania petli
  DriveType : Integer;  // informacja o typie dysku
  ListItem: TListItem;
  Bufor:array[0..MAX_PATH] of Char; // zawiera etykiete dysku
  MaxCompLength, FileSystemFlags : DWORD;
begin
{  wykonaj petle analizujac kazda litere dysku }
  for I := Ord('A') to Ord('Z') do
  begin
    DriveType := GetDriveType(PChar(Chr(i) + ':\')); // pobierz typ dysku
 
  { jezeli typ  dysku to 0 ( nie mozna okreslic ) lub 1 ( nie istnieje taki dysk ) to pomin w opisie.  }
 
    if not (DriveType = 0) and not (DriveType = 1) then
    begin
    {  uzyskaj informacje dotyczace etykiety dysku }
      GetVolumeInformation(PChar(Chr(i) + ':\'), Bufor, SizeOf(Bufor),
      nil, MaxCompLength, FileSystemFlags, nil, 0);
 
      ListItem := ListView.Items.Add; // dodaj pozycje
      ListItem.Caption := Chr(i) + ':\' + ' '  + Bufor; // ustaw tekst
   {
      Tutaj w zaleznosci od rodzaju dysku do komponentu ListView do okreslnej
      pozycji zostaje przypisana okreslona ikonka symoblizujaca dysk.
   }
      if (DriveType = DRIVE_CDROM) then ListItem.ImageIndex := 0;
      if (DriveType = DRIVE_FIXED) then ListItem.ImageIndex := 1;
      if (DriveType = DRIVE_REMOVABLE) then ListItem.ImageIndex := -1;
    end;                                               
  end;
end;
 
procedure TMainForm.ListViewClick(Sender: TObject);
var
  DirName: String; // litera dysku
  Sectors: DWORD; // sektory w klastru
  Bytes: DWORD; // bajty w sektorze
  FreeClust: DWORD; // wolne klastery
  TotalClust: DWORD; // wszystkie klastery
begin
  DirName := ListView.Selected.Caption[1]; // pobierz pierwszy znak napisu - litere dysku
 
  {  Funkcja GetDiskFreeSpace podaje rozne informacje dotyczace  danego dysku }
  if GetDiskFreeSpace(PChar(DirName + ':\'), Sectors, Bytes, FreeClust, TotalClust) then
  begin
  {  przypisz dane do etykiet tekstowych }
    lblSectors.Caption := 'Sektory w klastrze: ' + IntToStr(Sectors);
    lblBytes.Caption := 'Bajty w sektorze: ' + IntToStr(Bytes);
    lblFreeClust.Caption := 'Wolne klastry: ' + IntToStr(FreeClust);
    lblTotalClust.Caption := 'Wszystkie klastry: ' + IntToStr(TotalClust);
  { jezeli niemozliwe jest odczytanie wlasciwosci przypisz etykieta symbolom znak ???? }
  end else
  begin
    lblSectors.Caption := '???';
    lblBytes.Caption := '???';
    lblFreeClust.Caption := '???';
    lblTotalClust.Caption := '???';
  end;
end;
 
end.

 
Przydatną może także być funkcja DiskSize, która podaje pojemność dysku oraz DiskFree, która podaje ilość wolnego miejsca na dysku. Funkcje te zwracają rezultat w postaci zmiennej typu Int64. Jako parametr tych funkcji trzeba podać numer dysku. Dysk opatrzony literą A ma numer 1; dysk B - numer 2 itd. Czyli np:

WolneMiejsce.Caption := IntToStr(DiskFree(3)); // wolne miejsce na dysku C: 

5 komentarzy

ŁF 2008-12-12 19:57

hahaha, nagrywarka CD _Read_Only_ Memory ;]

adrianna358 2007-06-18 17:58

Ale po czym można odróżnić napęd CD-ROM od nagrywarki CD-ROM

adrianna358 2007-06-18 17:56

poczym poznać nagrywarke CD-ROM

Abdek 2006-01-16 14:28

Bardzo dobry artykuł. Ale czy można odróżnić napęd CD-ROM od nagrywarki CD-ROM lub DVD

Zitu 2005-05-29 14:46

tego potrzebowałem, dzięki!