Советы пользователям Delphi и C++Builder

Часть 2. Немного о внешних устройствах и операционной системе

Наталия Елманова
Компьютер Пресс - CD, 1999, N 3
Copyright © N.Elmanova & ComputerPress Magazine.

В данной статье содержатся советы, позволяющие решить некоторые из множества проблем, возникающие при использовании внешних устройств в приложениях Delphi и С++Builder.

Совет 4. Определение наличия дискеты или компакт-диска в дисководе

Нередко в процессе работы приложения следует произвести запись на дискету или считать данные с компакт-диска. Во избежание возникновения сообщений об ошибке при отсутствии диска или дискеты либо об отсутствии свободного места на диске следует определить, готово ли устройство, и каков объем свободного пространства на нем.

Для получения информации о диске можно использовать функцию Windows API GetVolumeInformation. Эта функция возвращает информацию об имени и метке тома, а также характеристиках его файловой системы.

Для получения информации о наличии свободного места на диске можно использовать функцию GetDiskFreeSpace. Эта функция возвращает информацию о числе свободных кластеров и секторов и размерах сектора и кластера для данного диска. Число свободных байт равно числу свободных кластеров, умноженному на число секторовв кластере и на число байт в секторе.

Создадим простейший пример, определяющий тип устройства, его готовность и количество свободных байт. На форму приложения поместим компонент TDriveComboBox со страницы Win31 и четыре метки.

Рис. 1. Форма приложения для получения информации о дисках

Создадим обработчик события OnChange компонента TDriveComboBox. В случае C++Builder он выглядит следующим образом:

void __fastcall TForm1::DriveComboBox1Change(TObject *Sender)
{
DWORD VolSN,MaxCompLen,FSFlags, FC,SPC,BPS,NC;
char VolName[255],FSName[100];
AnsiString s=UpperCase(DriveComboBox1->Drive)+":\\";
Label1->Caption=s;
if (GetVolumeInformation(s.c_str(),VolName,255,&VolSN,&MaxCompLen, &FSFlags,FSName,100))
  {
   Label2->Caption="Имя тома: "+AnsiString(VolName);
   Label3->Caption="Файловая система: "+AnsiString(FSName);
   if (GetDiskFreeSpace(s.c_str(), &SPC,&FC,&BPS,&NC))
   {
     Label4->Caption="Свободных байт: "+IntToStr(SPC*FC*BPS);
   }
   else
   {
    Label4->Caption="";
   }
  }
else
  {
   Label2->Caption="Диск не готов";
   Label3->Caption="";
   Label4->Caption="";
  }
}

В случае Delphi этот же обработчик события выглядит так:

procedure TForm1.DriveComboBox1Change(Sender: TObject);
var
 VolName: array [0..255] of char;
 FSName : array [0..100] of char;
 VolSN: PDWORD;
 MaxCompLen,FSFlags: Cardinal;
 FC,SPC,BPS,NC:DWORD;
 s: string;
begin
 VolSN:=nil;
 s:=UpperCase(DriveComboBox1.Drive)+':\';
 Label1.Caption:=s;
 if (GetVolumeInformation(PChar(s),VolName,255,
 VolSN,   MaxCompLen, FSFlags,FSName,100)) then 
  begin
    Label2.Caption:='Имя тома: '+AnsiString(VolName);
    Label3.Caption:='Файловая система: '+AnsiString(FSName) ;
    if GetDiskFreeSpace(PChar(s),SPC,BPS,FC,NC) then
     Label4.Caption:='Свободных байт:  '+IntToStr(SPC*FC*BPS)
    else  Label4.Caption:=''
  end 
  else    
   begin
    Label2.Caption:='Диск не готов';
    Label3.Caption:='';
    Label4.Caption:=''
   end;
end;

Запустив приложение, мы можем выбирать устройство из списка доступных устройств и получать информацию о готовности устройства, метке тома и числе свободных байт.

Рис. 2. Приложение для вывода информации о дисках на этапе выполнения

Совет 5. Получение сведений о видеорежиме

Приложения, активно использующие работу с графикой или видеофрагментами, нередко нуждаются в информации о текущем цветовом разрешении видеоадаптера. Каким образом получить такие сведения?

Обычно для этой цели используется функция Windows API GetDeviceCaps, использующая в качестве входного параметра контекст графического устройства (каковым является экран). В данном примере мы воспользуемся обычной формой VCL для доступа к этому контексту, используя ее свойство Canvas.

В качестве второго параметра этой функции используется именованная целая константа, в зависимости от значения которой возвращается одно из значений, связанных с параметрами графического устройства. В данном случае нас интересуют цветовое разрешение в битах на пиксел и число поддерживаемых системой цветов. Последнее зависит от числа оттенков цвета. Число оттенков равно 2 в степени, равной цветовому разрешению в битах на пиксел. Число же поддерживаемых системой цветов равно числу оттенков, возведенному в степень, равную числу цветовых плоскостей. Следовательно, для вычисления числа поддерживаемых цветов функцию GetDeviceCaps следует вызвать дважды - один раз для получения информации о цветовом разрешении, другой раз - о числе цветовых плоскостей.

Создадим простейшее приложение для определения этих параметров. С этой целью поместим на форму кнопку и несколько меток.

Рис. 3. Форма приложения для определения цветового разрешения экрана.

Создадим обработчик события, связанный с нажатием на кнопку. В C++Builder он выглядит следующим образом:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 long int TC,BPP,CP,VR;
 BPP=GetDeviceCaps(Form1->Canvas->Handle,BITSPIXEL);
 CP=GetDeviceCaps(Form1->Canvas->Handle,PLANES);
 TC=pow(pow(2,BPP),CP);
 Label1->Caption="Бит на пиксел: "+IntToStr(BPP);
 if (TC<3) 
 {
   Label2->Caption="Монохромный дисплей ";
 } 
 else
 {
  Label2->Caption="Число цветов: "+IntToStr(TC);
 }  ;
}

Аналогичный код для Delphi имеет вид:

procedure TForm1.Button1Click(Sender: TObject);
Var    TC,BPP,CP,VR,x:  integer; x2:real;
begin
 BPP:=GetDeviceCaps(Form1.Canvas.Handle,BITSPIXEL);
 CP:=GetDeviceCaps(Form1.Canvas.Handle,PLANES);
 x2:=intpower(2,BPP);
 x2:=intpower(x2,CP); TC:=round(x2);
 Label1.Caption:='Бит на пиксел: '+IntToStr(BPP);
 if (TC<3) then  Label2.Caption:='Монохромный дисплей ' else
 Label2.Caption:='Число цветов: '+IntToStr(TC);
end;

Запущенное приложение выглядит примерно так:

Рис. 4. Приложение для определения цветового разрешения экрана.

Помимо цветового разрешения и числа поддерживаемых цветов c помощью функции GetDeviceCaps можно получить много другой информации о графических устройствах, например, о разрешении в пикселах на дюйм, числе поддерживаемых шрифтов и др. При работе в Windows NT можно даже определить частоту развертки монитора.

Совет 6. Получение сведений о частоте развертки монитора

Модифицируем ранее созданный пример, добавив определение типа операционной системы, и, если это Windows NT - определение частоты развертки. С этой целью необходимо в первую очередь определить тип операционной системы.

Как определить тип операционной системы? Для этой цели воспользуемся функцией Windows API GetVersionEx. Но, прежде чем ее вызвать, следует создать структуру типа OSVERSIONINFO, содержащую сведения об имении версии операционной системы (подробное описание этой структуры можно найти в справке по функциям Windows API, поставляемой с обоими средствами разработки), и корректно определить ее размер с помощью функции sizeof.

Поместим еще одну метку на форму нашего примера и изменим обработчик события, связанного с нажатием на кнопку: В случае C++Builder он теперь имеет вид:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 long int TC,BPP,CP,VR;
 OSVERSIONINFO OV;
 BPP=GetDeviceCaps(Form1->Canvas->Handle,BITSPIXEL);
 CP=GetDeviceCaps(Form1->Canvas->Handle,PLANES);
 TC=pow(pow(2,BPP),CP);
 Label1->Caption="Бит на пиксел: "+IntToStr(BPP);
 if (TC<3)
 {     
   Label2->Caption="Монохромный дисплей ";
 }  
 else
 {
  Label2->Caption="Число цветов: "+IntToStr(TC); 
 }  ;
 OV.dwOSVersionInfoSize=sizeof(OV);
 GetVersionEx(&OV);
 if (OV.dwPlatformId==VER_PLATFORM_WIN32_NT)
 {
  VR=GetDeviceCaps(Form1->Canvas->Handle,VREFRESH);
  Label3->Caption="Частота развертки: "+IntToStr(VR)+" Гц";
 }
 else
 {
  Label3->Caption="Частота развертки не определется в данной ОС";
 }
}

Соответствующий код для Delphi выглядит так:

procedure TForm1.Button1Click(Sender: TObject);
Var    TC,BPP,CP,VR,x:  integer; x1,x2:real;
OV: TOSVersionInfo;
begin
BPP:=GetDeviceCaps(Form1.Canvas.Handle,BITSPIXEL);
CP:=GetDeviceCaps(Form1.Canvas.Handle,PLANES);
x2:=intpower(2,BPP);
x2:=intpower(x2,CP); TC:=round(x2);
Label1.Caption:='Бит на пиксел: '+IntToStr(BPP);
if (TC<3) then  Label2.Caption:='Монохромный дисплей ' else
Label2.Caption:='Число цветов: '+IntToStr(TC);
OV.dwOSVersionInfoSize:=SizeOf(OV);
GetVersionEx(OV);
if OV.dwPlatformID=VER_PLATFORM_WIN32_NT then begin
VR:=GetDeviceCaps(Form1.Canvas.Handle,VREFRESH);
Label3.Caption:='Частота развертки: '+IntToStr(VR)+' Гц';
end else   Label3.Caption:='Частота развертки не определется в данной ОС';
end;
end.

Если запустить это приложение в операционной системе Windows NT, оно отобразит сведения о частоте развертки:

Рис. 5. Приложение для определения частоты развертки под управлением Windows NT

Рис. 6. То же приложение под управлением Windows 95