Мне приходит большое количество писем, в которых меня просят объяснить, как работать с дисками. Сегодня я научу тебя этому очень простому трюку. Ты научишься узнавать, сколько и каких дисков установлено в твоём компе и мы даже получим основную информацию о них. Всё это я постараюсь описать как можно подробнее.
Для примера нам понадобиться только один компонент ТListView. Посмотри на рисунок 1, и если ты уже научился делать такое самостоятельно, то можешь пропустить ближайшие пару абзацев.
Рис 1. Пример формы
Итак, ты поставил ТListView на форму и у тебя получился компонент ListView1. В нём нужно изменить следующие свойства:
Align устанавливаем в alClient .
ViewStyle устанавливаем в vsReport .
Рис 2.
Теперь нужно создать колонки. Для этого дважды щёлкни по свойству Columns. Перед тобой откроется окно, как на рисунке 2. Внутри этого окошка нужно нажать на саму левую кнопку, которая создаст новую колонку. Одновременно с созданием Delphi выделить новую строку. Перейди в ObjectInspector и поменяй там свойство Caption на "Имя" и свойство Width сделай побольше (я сделал 100). Создай ещё три колонки и назови их "Тип", "Размер" и "Свободно". Надеюсь, что у тебя получилось нечто похожее на рис 1. Если нет, то попробуй прочесть ещё разок.
Теперь мы переходим непосредственно к программированию. Сегодня будет очень много кода и очень много объяснений, поэтому приготовь пару бутылок пива, с ними программируется на много лучше.
Для начала создадим обработчик события OnShow в нём напишем следующее:
procedure TForm1.FormShow(Sender: TObject);
var
shInfo: TSHFileInfo;
NewItem: TListItem;
i: Integer;
DiskType: Integer;
DiskSize,
FreeSize: Integer;
Drv: Char;
drives: set of 0..25;
begin
Integer(Drives) := GetLogicalDrives;
for i := 0 to 25 do
if (i in Drives) then
begin
Drv := Char(i + Ord('A'));
NewItem := ListView1.Items.Add;
try
SHGetFileInfo(PChar(Drv + ':\'), 0, shInfo, SizeOf(shInfo),
SHGFI_SYSICONINDEX or SHGFI_DISPLAYNAME or SHGFI_TYPENAME);
NewItem.Caption := StrPas(shInfo.szDisplayName);
DiskType := GetDriveType(PChar(Drv + ':\'));
NewItem.SubItems.Add(GetDriveTypeStr(Drv + ':\'));
if (DiskType <> DRIVE_REMOVABLE) and (DiskType <> DRIVE_CDROM) then
begin
DiskSize := GetDiskSize(Drv + ':\');
FreeSize := GetFreeDiskSize(Drv + ':\');
end
else
begin
DiskSize := 0;
FreeSize := 0;
end;
if DiskSize > 0 then
NewItem.SubItems.Add(FormatFloat('###,###,### Mb', DiskSize div 1000))
else NewItem.SubItems.Add('0 Mb');
if FreeSize > 0 then
NewItem.SubItems.Add(FormatFloat('###,###,### Mb', FreeSize div 1000))
else NewItem.SubItems.Add('0 Mb');
NewItem.SubItems.Add('');
NewItem.SubItems.Add(Drv + ':\');
NewItem.SubItems.Add('drv');
except
ListView1.Items.Delete(NewItem.Index);
end;
end;
Теперь начнём построчно разбираться с написанным здесь, но для начала нужно перейти в раздел Uses и добавить там модуль ShellAPI.
Самая первая функция GetLogicalDrives возвращает маску присутствующих в системе дисков. Результат этой функции мы записываем в переменную drives. После этого мы запускаем цикл от 0 до 25 и проверяем, если I-й бит установлен в переменной drives значит устройство с таким номером присутствует:
for i := 0 to 25 do // Запускаем цикл
if (i in Drives) then //Проверка на присутствие устройства
begin
//устройство присутствует
end;
Drv := Char(i + Ord('A')) - эта строка получает букву относящуюся к найденному устройству. Функция Ord возвращает числовое значение ASCII символа. Например, если найдено нулевое устройство, то выполниться условие 0+"числовое значение буквы А", и в переменной Drv окажется числовое значение буквы А. Если найдено устройство с 2, то 2+"числовое значение буквы А" будет равняться числовому значению буквы С, то есть диск С. Почему я узнал, что С=А+2? Да потому, что С - третья буква английского алфавита и её код будет на 2 больше чем у А. Это значит, что D=А+3, Е=А+4 и так далее.
NewItem := ListView1.Items.Add - добавляем новый элемент в ListView1 и запоминаем ссылку на него в переменной NewItem (это чтобы мы могли изменить параметры нового элемента).
SHGetFileInfo позволяет получить информацию о файле или папке:
function SHGetFileInfoA(
pszPath: PansiChar; //Путь к файлу или папке
dwFileAttributes: DWORD;//Сюда занесётся информация о файле
var psfi: TSHFileInfoA;//Размер предыдущего параметра
cbFileInfo, uFlags: UINT// флаги указывающие, какая инфа нам нужна.
): DWORD; stdcall;
В нашем случае, первый параметр - PChar(Drv + ':\') указывает на найденное нами устройство. Второй параметр - переменная типа TSHFileInfo. В неё будет занесён результат. С третьим параметром всё ясно, а вот четвуртый - SHGFI_SYSICONINDEX or SHGFI_DISPLAYNAME or SHGFI_TYPENAME говорит о том, что нам нужна иконка для драйва из системы (сегодня мы её не будем использовать), имя используемое для отображения драйва и тип.
NewItem.Caption := StrPas(shInfo.szDisplayName) - задаём заголовок для созданного нами элемента в ListView1. Функция StrPas приводит строку формата Windows в понятный для Delphi (и для нас) вид.
DiskType := GetDriveType(PChar(Drv + ':\')) - эта функция возвращает тип найденного устройства в виде числа. Есть несколько типов драйвов:
0 - Не известное устройство.
1 - Отсутствует.
DRIVE_REMOVABLE - сменный диск.
DRIVE_FIXED - жёсткий диск.
DRIVE_REMOTE - сетевой диск.
DRIVE_CDROM - CD-ROM.
DRIVE_RAMDISK - диск памяти.
NewItem.SubItems.Add(GetDriveTypeStr(Drv + ':\')); - добавляем к элементу новую колонку, в которой храниться тип драйва. GetDriveTypeStr - это функция, которая выглядит так (Добавь её к проекту):
function TForm1.GetDriveTypeStr(Root: string): string;
var
DrvType: Integer;
begin
DrvType := GetDriveType(PChar(Root));
case DrvType of
0: Result := 'Не знаю такова';
1: Result := 'Отсутствует';
DRIVE_REMOVABLE: Result := 'Съёмный диск';
DRIVE_FIXED: Result := 'Жёсткий';
DRIVE_REMOTE: Result := 'Сетевой';
DRIVE_CDROM: Result := 'CD-ROM';
DRIVE_RAMDISK: Result := 'RAM';
end;
end;
После этого идёт проверка, если диск не съёмный, то можно узнать его размер и свободное на диске место. Для того, чтобы узнать размер, я написал функцию:
function TForm1.GetDiskSize(Root: string): LongInt;
var
SpC, BpS, NfC, TnC: DWORD;
FreeDiskSize: Double;
begin
GetDiskFreeSpace(PChar(Root), SpC, BpS, NfC, TnC);
FreeDiskSize := (TnC * SpC * BpS) / 1024;
Result := Round(FreeDiskSize);
end;
А эта функция для определения свободного места на диске:
function TForm1.GetFreeDiskSize(Root: string): LongInt;
var
SpC, BpS, NfC, TnC: DWORD;
FreeDiskSize: Double;
begin
GetDiskFreeSpace(PChar(Root), SpC, BpS, NfC, TnC);
FreeDiskSize := (NfC * SpC * BpS) / 1024;
Result := Round(FreeDiskSize);
end;
Обе эти функции нужно добавить к проекту. Они очень простые и с ними очень легко разобраться, поэтому я не буду останавливать на них особого внимания. Если хочешь увидеть их описание, то загляни в Windows SDK в меню Help .
Дальший код тебе уже должен быть понятен. Я добавляю ещё две колонки к созданному элементу, в которых будет храниться размер и свободное место на диске.
Запускай программу и любуйся.
Рис 3. Результат работы
Вроде всё. Не буду больше загружать твою голову, а то так можно и заглючить. Если что-то не получается, то забирай исходники примера и пробуй поиграть с ними. Удачи!!!