Тема: Индикатор использования ЦП и ОЗУ(пример Frame + ProgressBar)
Пример показывает уровень загрузки процессора и использования оперативной памяти.
Для получения значения тактовой частоты процессора используется системная функция GetCPUClock.
Однако, эта функция может возвращать значения только в пределах до 4 ГГц.
В примере используется системная функция SetWindowZOrder для установки положения окна поверх всех окон, это удобно — окно всегда наверху.
program CPUMemUsageIndicator;
uses
KolibriOS;
const
WINDOW_BORDER_SIZE = 5;
// Константы положения окна относительно других окон:
ZPOS_DESKTOP = -2; // на самом заднем плане
ZPOS_ALWAYS_BACK = -1; // позади всех окон
ZPOS_NORMAL = 0; // обычное
ZPOS_ALWAYS_TOP = 1; // поверх всех окон
// 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;
type
TProgressBar = packed record
Value: LongWord;
Left: LongInt;
Top: LongInt;
Width: LongWord;
Height: LongWord;
Style: LongWord;
Min: LongWord;
Max: LongWord;
BackColor: LongWord;
ProgressColor: LongWord;
FrameColor: 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;
var
CPUFrame: TFrame = (
Style: 0;
Width: 271;
Left: 8;
Height: 57;
Top: 13;
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;
);
MemFrame: TFrame = (
Style: 0;
Width: 271;
Left: 8;
Height: 57;
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;
);
CPUProgressBar: TProgressBar = (
Value: 0;
Left: 56;
Top: 37;
Width: 215;
Height: 17;
Style: 0;
Min: 0;
Max: 100;
BackColor: $00FFFFFF;
ProgressColor: $0000007F;
FrameColor: $007F7F7F;
);
MemProgressBar: TProgressBar = (
Value: 0;
Left: 56;
Top: 108;
Width: 215;
Height: 17;
Style: 0;
Min: 0;
Max: 100;
BackColor: $00FFFFFF;
ProgressColor: $0000007F;
FrameColor: $007F7F7F;
);
BoxLib: Pointer;
progressbar_draw: procedure(var ProgressBar: TProgressBar); stdcall;
frame_draw: procedure(var Frame: TFrame); stdcall;
WndLeft, WndTop: LongInt;
WndWidth, WndHeight: LongWord;
// беззнаковое число Number в строку Buffer, размер буфера > 10
procedure UIntToStr(Number: LongInt; Buffer: PAnsiChar);
asm
push edi
push esi
mov eax, Number
mov ecx, 10
mov esi, Buffer
mov edi, esi
add esi, ecx
mov byte ptr [esi], 0
@next:
xor edx, edx
div ecx
dec esi
add dl, 48
mov [esi], dl
test eax, eax
jnz @next
mov ecx, esi
sub ecx, edi
rep movsb
pop esi
pop edi
end;
procedure DrawIndicators;
var
ValueBuffer: array [0..10] of AnsiChar;
begin
// если тактовая частота больше 4 ГГц(что уже не редкость), то
// системная функция GetCPUClock вернёт неверное значение
// "shr 8" чтобы не было переполнения при умножении на 100
// определяем значения в процентах
CPUProgressBar.Value := 100 - (GetIdleTime shr 8) * 100 div (GetCPUClock shr 8);
MemProgressBar.Value := 100 - (GetFreeMemory shr 8) * 100 div (GetAvailableMemory shr 8);
progressbar_draw(CPUProgressBar);
progressbar_draw(MemProgressBar);
DrawText(16, CPUProgressBar.Top, ' %', CPUFrame.ForeColor, CPUFrame.BackColor, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
UIntToStr(CPUProgressBar.Value, ValueBuffer);
DrawText(16, CPUProgressBar.Top, ValueBuffer, CPUFrame.ForeColor, CPUFrame.BackColor, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
DrawText(16, MemProgressBar.Top, ' %', MemFrame.ForeColor, MemFrame.BackColor, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
UIntToStr(MemProgressBar.Value, ValueBuffer);
DrawText(16, MemProgressBar.Top, ValueBuffer, MemFrame.ForeColor, MemFrame.BackColor, DT_ZSTRING + DT_CP866_8x16 + DT_FILL_OPAQUE, 0);
end;
begin
WndHeight := 149 + GetSkinHeight + WINDOW_BORDER_SIZE;
WndWidth := 286 + WINDOW_BORDER_SIZE * 2;
BoxLib := LoadLibrary('/sys/lib/box_lib.obj');
frame_draw := GetProcAddress(BoxLib, 'frame_draw');
progressbar_draw := GetProcAddress(BoxLib, 'progressbar_draw');
with GetScreenSize do
begin
WndLeft := (Width - WndWidth) div 2;
WndTop := (Height - WndHeight) div 2;
end;
SetEventMask(EM_REDRAW or EM_BUTTON);
SetWindowZOrder($FFFFFFFF, ZPOS_ALWAYS_TOP);
while True do
case WaitEventByTime(25) of
REDRAW_EVENT:
begin
BeginDraw;
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Индикатор использования', $00CFCFCF,
WS_SKINNED_FIXED + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
frame_draw(CPUFrame);
frame_draw(MemFrame);
DrawIndicators;
EndDraw;
end;
BUTTON_EVENT:
Break;
else
DrawIndicators;
end;
end.
Также прикладываю уже скомпилированный пример CPUMemUsageIndicator.kex