# Лабораторная работа № 12.

Тема: Определение конфигурации компьютера на языках высокого уровня.

Цель работы: научить студентов определять устройства PCI на программном уровне.

Теоретические сведения:

Иногда Delphi-приложениям может не хватать функциональной полноты стандартной библиотеки компонентов и тогда бывает необходимо обратиться к Microsoft Win32 API (Application Programming Interface - интерфейса взаимодействия прикладной программы с операционной системой). Почти все функции из Microsoft Win32 API описаны в модуле windows.pas (который по умолчанию включается в cекцию uses новых модулей). Cледует заметить, что часть из этих функции ведет себя по разному в зависимости от текущей операционной системы (Windows 95, 98, NT).

Разработаем программу, показывающую нам некоторую системную информацию о компьютере. В частности, хотелось бы получить информацию о версии ОС, ее директориях, свойствах экрана, ресурсах памяти, имени пользователя и компьютера, дате BIOS.

Рассмотрим текст программы. В список включаемых модулей uses добавим registry. Добавим описание процедур в раздел public описания TfmMain.

type

TfmMain = class(TForm)

...

procedure FormCreate(Sender: TObject);

procedure Change(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

KeyboardDelay,

KeyboardSpeed,

ScreenSaveTimeOut : integer;

procedure ParametersInfo;

procedure ShowSomeInfo;

procedure BIOSInfo(OS : string);

procedure HardwareInfo;

procedure MemoryInfo;

procedure VideoInfo;

procedure OSInfo;

end;

var fmMain: TfmMain;

implementation

uses Registry;

{$R *.DFM}

Сначала получим информацию о компьютере. Используем функцию GetComputerName для получения имени компьютера, функцию GetUserName для получения имени пользователя и функцию GetSystemInfo для получения информации о процессоре (наиболее полно данная функция реализована в Windows NT, где она возвращает и кол-во процессоров и их тип и т.д.).

// Информация о компьютере.

procedure TfmMain.HardwareInfo;

var Size : cardinal;

PRes : PChar;

BRes : boolean;

lpSystemInfo : TSystemInfo;

begin

// Имя компьютера

Size := MAX_COMPUTERNAME_LENGTH + 1;

PRes := StrAlloc(Size);

BRes := GetComputerName(PRes, Size);

if BRes then laCompName_.Caption := StrPas(PRes);

// Имя пользователя

Size := MAX_COMPUTERNAME_LENGTH + 1;

PRes := StrAlloc(Size);

BRes := GetUserName(PRes, Size);

if BRes then laUserName_.Caption := StrPas(PRes);

// Процессор

GetSystemInfo(lpSystemInfo);

laCPU_.Caption := 'класса x' + IntToStr(lpSystemInfo.dwProcessorType);

end;

Перейдем к параметрам экрану. Здесь мы будем использовать и Win32 API функции и стандартные объекты VCL. Так для получения разрешения экрана нам понадобится объект TScreen (его свойства Width и Height). Остальные параметры мы получим через контекст драйвера устройства DC используя функцию GetDeviceCaps.

// Информация о видеосистеме.

procedure TfmMain.VideoInfo;

var DC : hDC;

c : string;

begin

// Разрешение экрана

laWidth_.Caption := IntToStr(Screen.Height);

laHeight_.Caption := IntToStr(Screen.Width);

// Информация о глубине цвета.

DC := CreateDC('DISPLAY',nil,nil,nil);

laBitsPerPixel_.Caption := IntToStr(GetDeviceCaps(DC,BITSPIXEL));

laPlanes_.Caption := IntToStr(GetDeviceCaps(DC,PLANES));

case GetDeviceCaps(DC,BITSPIXEL) of

8 : c := '256 цветов';

15 : c := 'Hi-Color / 32768 цветов';

16 : c := 'Hi-Color / 65536 цветов';

24 : c := 'True-Color / 16 млн цветов';

32 : c := 'True-Color / 32 бит';

end;

laColors_.Caption := c;

DeleteDC(DC);

end;

Также будет интересна информация о памяти. Здесь нам поможет функция GlobalMemoryStatus, возвращающая информацию по объему физической и виртуальной памяти.

// Информация о памяти.

procedure TfmMain.MemoryInfo;

var lpMemoryStatus : TMemoryStatus;

begin

lpMemoryStatus.dwLength := SizeOf(lpMemoryStatus);

GlobalMemoryStatus(lpMemoryStatus);

with lpMemoryStatus do begin

laFreeMemory.Caption := laFreeMemory.Caption + IntToStr(dwMemoryLoad) + '%';

laRAM_.Caption := Format('%0.0f Мбайт',[dwTotalPhys div 1024 / 1024]);

laFreeRAM_.Caption := Format('%0.3f Мбайт',[dwAvailPhys div 1024 / 1024]);

laPF_.Caption := Format('%0.0f Мбайт',[dwTotalPageFile div 1024 / 1024]);

laPFFree_.Caption := Format('%0.0f Мбайт',[dwAvailPageFile div 1024 / 1024]);

end;

end;

Узнаем информацию о ОС. Функция GetWindowsDirectory вернет путь к каталогу, где установлена система, функция GetSystemDirectory - к системному каталогу. Для определения версии ОС воспользуемся функцией GetVersionEx.

// Информация о Windows.

procedure TfmMain.OSInfo;

var PRes : PChar;

Res : word;

BRes : boolean;

lpVersionInformation : TOSVersionInfo;

c : string;

begin

// Каталог, где установлена Windows

PRes := StrAlloc(255);

Res := GetWindowsDirectory(PRes, 255);

if Res > 0 then laWinDir_.Caption := StrPas(PRes);

// Системный каталог Windows

Res := GetSystemDirectory(PRes, 255);

if Res > 0 then laSysDir_.Caption := StrPas(PRes);

// Имя ОС

lpVersionInformation.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);

BRes := GetVersionEx(lpVersionInformation);

if BRes then

with lpVersionInformation do case dwPlatformId of

VER_PLATFORM_WIN32_WINDOWS :

if dwMinorVersion=0 then c := 'Windows 95' else c := 'Windows 98';

VER_PLATFORM_WIN32_NT : c := 'Windows XP или выше';

VER_PLATFORM_WIN32s : c := 'Win 3.1 with Win32s'

end;

laVersion_.Caption := c;

// Дата создания BIOS-а

if c='Windows NT' then BIOSInfo('NT') else BIOSInfo('95');

end;

В предыдущем отрывке программы внимательный читатель заметил вызов функции BIOSInfo с параметром, характеризующем текущую ОС. Опишем эту функцию. Важно отметить, что способ получения информации о дате BIOS различен. Для NT получим информацию из реестра, а для Windows 95/98 из соответствующего участка памяти. Эти два способа взаимоисключаемы, так как у Windows 95/98 нет соответствующего раздела реестра, а прямой доступ к памяти в NT невозможен.

// Информация о дате создания BIOS-а.

procedure TfmMain.BIOSInfo(OS : string);

var p : pointer;

s : string[255];

begin

if OS='NT' then begin with TRegistry.Create do

try RootKey := HKEY_LOCAL_MACHINE;

if OpenKeyReadOnly('HARDWARE\DESCRIPTION\System')

then laBIOSDate_.Caption := ReadString('SystemBiosDate')

finally Free;

end;

end

else try

s[0] := #8;

p := Pointer($0FFFF5);

Move(p^,s[1],8);

laBIOSDate_.Caption := copy(s,1,2) + '/' + copy(s,4,2) + '/' +copy (s,7,2);

except laBIOSDate_.Caption := 'XX.XX.XXXX';

end;

end;

И ,наконец, вызовем все эти процедуры при создании формы.

// Вызов информационных процедур при создании формы.

procedure TfmMain.FormCreate(Sender: TObject);

begin

HardwareInfo;

MemoryInfo;

VideoInfo;

ParametersInfo;

ShowSomeInfo;

OSInfo;

end;

Внешний вид запущенной программы приведен на рисунке.

Использование Delphi совместно c фунциями Microsoft Win32 API позволит программисту создать более функционально богатые и гибкие приложения.

Литература: 10, стр. 49-68; 17, стр. 35- 39.

Контрольные вопросы

1. Объясните понятие «конфигурационное пространство PCI».

2. Что выполняет в конфигурационного пространства Register Number?

3. Если прочитать что-то из конфигурационного пространства реально несуществующего устройства, то что получится?