Тема: FileInfo(получение информации о файлах\папках)
Данный пример показывает получение информации о файлах\папках, например, такой как дата и время создания, размер.
Путь к файлу задаётся в командной строке, например:
FileInfo.kex /sys/example.asm
Если путь не задан, то по умолчанию показывается информация о файле "/sys/kernel.mnt"
В примере используются элементы управления CheckBox и Frame из библиотеки BoxLib.
Но с CheckBox-ами есть проблемы(в которых удалось разобраться):
Вот полностью исходный код:
program FileInfo;
uses
KolibriOS;
const
WINDOW_BORDER_SIZE = 5;
// Frame flags
FR_CAPTION = 1;
FR_DOUBLE = 0;
FR_RAISED = 2;
FR_SUNKEN = 4;
FR_ETCHED = 6;
FR_RIDGED = 8;
FR_FILLED = 16;
// Frame text position
FR_TEXT_POS_BOTTOM = 1;
FR_TEXT_POS_TOP = 0;
// CheckBox flags
CH_FLAG_EN = 2; // флаг установленного чек бокса.
CH_FLAG_TOP = 8; // флаг расположения текста вверху т.е. 3-й бит
CH_FLAG_MIDDLE = 16; // флаг расположения текста в центре т.е. 4-й бит.
CH_FLAG_BOTTOM = 0; // флаг расположения текста в низу т.е. по умолчанию
type
TCheckBox = packed record
width: Word; // ширина прямоугольника
left: SmallInt; // положение по х
height: Word; // высота прямоугольника
top: SmallInt; // положение по у
ch_text_margin: LongWord; // расстояние от прямоугольника чекбокса до надписи
color: LongWord; // цвет внутри чекбокса
border_color: LongWord; // цвет рамки
text_color: LongWord; // цвет надписи
text: PAnsiChar; // адрес в коде программы, где расположен текст
flags: LongWord; // флаги
ch_text_length: LongWord; // длина строки с символами
end;
TFrame = packed record
Style: LongWord;
Width: Word;
Left: SmallInt;
Height: Word;
Top: SmallInt;
OuterColor: LongWord;
InnerColor: LongWord;
Flags: LongWord;
Text: PAnsiChar;
TextPosition: LongWord;
Font: LongWord;
FontHeight: LongWord;
ForeColor: LongWord;
BackColor: LongWord;
end;
TFileAttr = set of (faReadOnly, faHidden, faSystem, faVolumeLabel, faDirectory, faArchive);
var
BoxLib: Pointer;
check_box_draw: procedure(var CheckBox: TCheckBox); stdcall;
init_checkbox: procedure(var CheckBox: TCheckBox); stdcall;
frame_draw: procedure(var Frame: TFrame); stdcall;
CheckBox1: TCheckBox = (
width: 16;
left: 24;
height: 16;
top: 212;
ch_text_margin: 8;
color: $00FFFFFF;
border_color: $0000FF00;
text: 'Только чтение';
flags: CH_FLAG_MIDDLE;
ch_text_length: Length('Только чтение'));
CheckBox2: TCheckBox = (
width: 16;
left: 24;
height: 16;
top: 236;
ch_text_margin: 8;
color: $00FFFFFF;
border_color: $0000FF00;
text: 'Архивный';
flags: CH_FLAG_MIDDLE);
CheckBox3: TCheckBox = (
width: 16;
left: 24;
height: 16;
top: 260;
ch_text_margin: 8;
color: $00FFFFFF;
border_color: $0000FF00;
text: 'Скрытый';
flags: CH_FLAG_MIDDLE);
CheckBox4: TCheckBox = (
width: 16;
left: 24;
height: 16;
top: 284;
ch_text_margin: 8;
color: $00FFFFFF;
border_color: $0000FF00;
text: 'Системный';
flags: CH_FLAG_MIDDLE);
DateTimeFrame: TFrame = (
Style: 0;
Width: 297;
Left: 8;
Height: 97;
Top: 84;
OuterColor: $00FFFFFF;
InnerColor: $00808080;
Flags: FR_ETCHED + FR_CAPTION + FR_FILLED;
Text: 'Дата\время:';
TextPosition: FR_TEXT_POS_TOP;
Font: 1;
FontHeight: 16;
ForeColor: $00000070;
BackColor: $00D0D0D0;
);
AttrFrame: TFrame = (
Style: 0;
Width: 297;
Left: 8;
Height: 121;
Top: 196;
OuterColor: $00FFFFFF;
InnerColor: $00808080;
Flags: FR_ETCHED + FR_CAPTION + FR_FILLED;
Text: 'Атрибуты:';
TextPosition: FR_TEXT_POS_TOP;
Font: 1;
FontHeight: 16;
ForeColor: $00000070;
BackColor: $00D0D0D0;
);
WndLeft, WndTop: LongInt;
WndWidth: LongWord;
WndHeight: LongWord;
SC: TStandardColors;
FilePath: PAnsiChar = '/sys/kernel.mnt'; // по умолчанию, если запущена без параметров
FileAttributes: TFileAttributes;
IsError: Boolean = False;
function IntToStr(Number: LongInt; Buffer: PAnsiChar): LongWord;
asm
push edi
push ebx
xor ebx, ebx
mov edi, Buffer
test eax, eax
jns @L1
mov ebx, '-'
neg eax
@L1:
push 0
mov ecx, 10
@L0:
xor edx, edx
div ecx
add edx, 48
push edx
test eax, eax
jnz @L0
or edx, -1
test ebx, ebx
jz @L2
mov al, bl
stosb
inc edx
@L2:
inc edx
pop eax
stosb
test eax, eax
jnz @L2
mov eax, edx // return count
pop ebx
pop edi
end;
procedure FillChar(var Dest; Count: LongInt; Value: AnsiChar);
var
i: LongInt;
begin
if Count > 0 then
for i := 0 to Count - 1 do
PAnsiChar(@Dest)[i] := Value;
end;
procedure FileSize2ReadableString(FileSize: Int64; Buffer: PAnsiChar); stdcall;
asm
push ebx
push edi
mov ecx, 10
xor ebx, ebx
lea eax, FileSize
mov edx, [eax + 4] // hi part
mov eax, [eax + 0] // lo part
// convert size to readable ;
@next:
cmp eax, 1024
jnb @calc
test edx, edx
jz @done
@calc:
add eax, 512 // to avoid
adc edx, 0 // rounding errors
shrd eax, edx, cl
shr edx, cl
inc ebx
jmp @next
@units: // size of units = 4 bytes include end of string
db ' b',0 // byte
db ' Kb',0 // Kilobyte
db ' Mb',0 // Megabyte
db ' Gb',0 // Gigabyte
db ' Tb',0 // Terabyte
db ' Pb',0 // Petabyte
db ' Eb',0 // Exabyte
@done:
// in eax -- size, in ebx -- index of units ;
mov edi, Buffer
mov [edi], dword ptr $20202020 // " " // 4 spaces
add edi, 4
// out units ;
mov edx, [ebx * 4 + @units]
mov [edi], edx
dec edi // step back one space
// convert size to string ;
@next_divide:
xor edx, edx
div ecx // in ecx still 10
add edx, 48 // edx = (eax MOD ecx) + 48
mov [edi], dl
dec edi
test eax, eax
jne @next_divide
pop edi
pop ebx
end;
procedure DrawInfo;
var
InfoBuffer: array [0..20] of AnsiChar;
FileAttr: TFileAttr;
FileName: PAnsiChar;
i: LongInt;
procedure FileDateTimeToStr(FileDateTime: TFileDateTime; Buffer: PAnsiChar);
var
k: LongInt;
begin
FillChar(Buffer^, Length('00.00.0000 00:00:00'), '0');
k := 0;
// пояснение по поводу кода ниже "Inc(k, IntToStr(..." — функция IntToStr возвращает длину строки
with FileDateTime.Date do
begin
if Day < 10 then Inc(k);
Inc(k, IntToStr(Day, PAnsiChar(@Buffer[k]))); Buffer[k] := '.'; Inc(k);
if Month < 10 then Inc(k);
Inc(k, IntToStr(Month, PAnsiChar(@Buffer[k]))); Buffer[k] := '.'; Inc(k);
if Year = 0 then Inc(k, 3); // обычно год — четырёхзначное число, но если даты обнулены, то год будет равен нулю, в этом случае получим "0000"
Inc(k, IntToStr(Year, PAnsiChar(@Buffer[k]))); Buffer[k] := ' '; Inc(k);
end;
with FileDateTime.Time do
begin
if Hours < 10 then Inc(k);
Inc(k, IntToStr(Hours, PAnsiChar(@Buffer[k]))); Buffer[k] := ':'; Inc(k);
if Minutes < 10 then Inc(k);
Inc(k, IntToStr(Minutes, PAnsiChar(@Buffer[k]))); Buffer[k] := ':'; Inc(k);
if Seconds < 10 then Inc(k);
Inc(k, IntToStr(Seconds, PAnsiChar(@Buffer[k]))); Buffer[k] := #0{конец строки};
end;
end;
begin
InfoBuffer[SizeOf(InfoBuffer) - 1] := #0;
// если путь не абсолютный
if FilePath[0] <> '/' then
FileName := FilePath
else
begin
i := 0;
while FilePath[i] <> #0 do Inc(i);
while FilePath[i] <> '/' do Dec(i);
FileName := PAnsiChar(@FilePath[i + 1]);
end;
DrawText(8, 8, 'Имя: ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(8 + Length('Имя: ') * 8, 8, FileName, SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(8, 30, 'Тип: ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
if not (faDirectory in TFileAttr(Byte(FileAttributes.Attributes))) then
DrawText(8 + Length('Тип: ') * 8, 30, 'Файл ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0)
else
DrawText(8 + Length('Тип: ') * 8, 30, 'Папка', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(8, 52, 'Размер: ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
FileSize2ReadableString(FileAttributes.Size, InfoBuffer);
DrawText(8 + Length('Размер: ') * 8, 52, InfoBuffer, SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(24, 100, 'Создания: ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
FileDateTimeToStr(FileAttributes.Creation, InfoBuffer);
DrawText(24 + Length('Создания: ') * 8, 100, InfoBuffer, SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(24, 124, 'Изменения: ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
FileDateTimeToStr(FileAttributes.Modify, InfoBuffer);
DrawText(24 + Length('Изменения: ') * 8, 124, InfoBuffer, SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(24, 148, 'Доступа: ', SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
FileDateTimeToStr(FileAttributes.Access, InfoBuffer);
DrawText(24 + Length('Доступа: ') * 8, 148, InfoBuffer, SC.WorkText, SC.Work, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
FileAttr := TFileAttr(Byte(FileAttributes.Attributes));
if faReadOnly in FileAttr then
CheckBox1.Flags := CheckBox1.Flags or CH_FLAG_EN
else
CheckBox1.Flags := CheckBox1.Flags and not CH_FLAG_EN;
if faArchive in FileAttr then
CheckBox2.Flags := CheckBox2.Flags or CH_FLAG_EN
else
CheckBox2.Flags := CheckBox2.Flags and not CH_FLAG_EN;
if faHidden in FileAttr then
CheckBox3.Flags := CheckBox3.Flags or CH_FLAG_EN
else
CheckBox3.Flags := CheckBox3.Flags and not CH_FLAG_EN;
if faSystem in FileAttr then
CheckBox4.Flags := CheckBox4.Flags or CH_FLAG_EN
else
CheckBox4.Flags := CheckBox4.Flags and not CH_FLAG_EN;
end;
procedure On_Redraw;
begin
BeginDraw;
GetStandardColors(SC, SizeOf(TStandardColors));
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'FileInfo', SC.Work,
WS_SKINNED_FIXED + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
CheckBox1.text_color := SC.WorkText + DT_CP866_8x16;
CheckBox2.text_color := SC.WorkText + DT_CP866_8x16;
CheckBox3.text_color := SC.WorkText + DT_CP866_8x16;
CheckBox4.text_color := SC.WorkText + DT_CP866_8x16;
CheckBox1.border_color := SC.WorkGraph;
CheckBox2.border_color := SC.WorkGraph;
CheckBox3.border_color := SC.WorkGraph;
CheckBox4.border_color := SC.WorkGraph;
DateTimeFrame.BackColor := SC.Work;
AttrFrame.BackColor := SC.Work;
DateTimeFrame.ForeColor := SC.WorkText;
AttrFrame.ForeColor := SC.WorkText;
DateTimeFrame.OuterColor := SC.Work3DLight;
AttrFrame.OuterColor := SC.Work3DLight;
DateTimeFrame.InnerColor := SC.Work3DDark;
AttrFrame.InnerColor := SC.Work3DDark;
frame_draw(DateTimeFrame);
frame_draw(AttrFrame);
if not IsError then
DrawInfo;
init_checkbox(CheckBox1);
init_checkbox(CheckBox2);
init_checkbox(CheckBox3);
init_checkbox(CheckBox4);
check_box_draw(CheckBox1);
check_box_draw(CheckBox2);
check_box_draw(CheckBox3);
check_box_draw(CheckBox4);
EndDraw;
end;
begin
BoxLib := LoadLibrary('/sys/lib/box_lib.obj');
check_box_draw := GetProcAddress(BoxLib, 'check_box_draw2');
init_checkbox := GetProcAddress(BoxLib, 'init_checkbox2');
frame_draw := GetProcAddress(BoxLib, 'frame_draw');
with GetScreenSize do
begin
WndWidth := 312 + WINDOW_BORDER_SIZE * 2;
WndHeight := 325 + WINDOW_BORDER_SIZE + GetSkinHeight;
WndLeft := (Width - WndWidth) div 2;
WndTop := (Height - WndHeight) div 2;
end;
SetEventMask(EM_REDRAW + EM_BUTTON);
// если в командной строке есть парметры
if CmdLine[0] <> #0 then
FilePath := CmdLine;
// если информация об атрибутах файла доступна
if GetFileAttributes(FilePath, FileAttributes) <> 0 then
IsError := True;
while True do
case WaitEvent of
REDRAW_EVENT:
On_Redraw;
BUTTON_EVENT:
Exit;
end;
end.
Прикладываю скомпилированный пример FileInfo.kex