Проста консольна програма, Додатки та розповсюдження програм, Delphi, статті

На момент написання статті (1997р.), в Delphi не було можливості автоматично створювати консольні додатки (можливо на сьогоднішній день цей недолік усунуто), тому ми створимо порожній файл і помістимо в нього наступний код:

  program ConPrg;
{$APPTYPE CONSOLE}
begin
end.

Потім збережемо цей файл з розширенням. Dpr – в даному випадку conprg.dpr. Далі, його можна завантажити в Delphi (File | Open) і приступити до додавання коду.

Зверніть увагу: Якщо Ви запустите вищенаведену програму, то вона негайно завершиться, тому що в ній немає жодного робочого коду.

Для початку, в неї можна додати рядок readln:

  program ConPrg;
{$APPTYPE CONSOLE}
begin
readln
end.

Ви побачите пусте текстове віконце, яке закриється, якщо натиснути клавішу
Enter.

Йдемо далі

Як згадувалося раніше, Ви можете використовувати майже будь-яку функцію Win32 API з консольного додатку. Таке додаток дуже зручно ще й тим, що про інтерфейсі можна взагалі не думати, а для виведення інформації використовувати тільки пару функцій Write / Writeln. Прикладів застосування консольних додатків безліч: це і різного виду утиліти, і тестові програми для перевірки роботи функцій API і т.д. Ми не буде занурюватися в приклади того як використовувати певні API, а поговоримо лише про консольних
API (Console API).

Консольні API (Console API)


Microsoft надає певний набір функцій, які дуже навіть корисні при створенні консольних додатків. Для початку скажу, що існує по принаймні два дескриптора (handles), які пов’язані з консольним вікном. Один для введення, другий для виводу. Нижче наводяться дві невеликі функції, які показують, як отримати ці дескриптори.

//—————————————– / / Отримання дескриптора для консольного вводу
//—————————————–
function GetConInputHandle : THandle;
begin
Result := GetStdHandle(STD_INPUT_HANDLE)
end;
//—————————————– / / Отримання дескриптора для консольного виводу
//—————————————–
function GetConOutputHandle : THandle;
begin
Result := GetStdHandle(STD_OUTPUT_HANDLE)
end;

Так само, краще відразу створити свої функції для таких простих операцій як позиціонування курсора, очищення екрана і відображення / приховування курсора (так як в консольних API вони трошки Громозкая і заплутані). Ось як вони виглядають:

//—————————————– / / Установка курсора в координати X, Y
//—————————————–
procedure GotoXY(X, Y : Word);
begin
Coord.X := X; Coord.Y := Y;
SetConsoleCursorPosition(ConHandle, Coord);
end;
//—————————————– / / Очищення екрану – заповнення його пробілами
//—————————————–
procedure Cls;
begin
Coord.X := 0; Coord.Y := 0;
FillConsoleOutputCharacter(ConHandle, ” “, MaxX*MaxY, Coord, NOAW);
GotoXY(0, 0);
end;
//————————————– / / Показуємо / Приховуємо курсор
//————————————–
procedure ShowCursor(Show : Bool);
begin
CCI.bVisible := Show;
SetConsoleCursorInfo(ConHandle, CCI);
end;

Як Ви встигли помітити, ми скористалися чотирма функціями консольного
API: GetStdHandle, SetConsoleCursorPosition, FillConsoleOutputCharacter, SetConsoleCursorInfo. Іноді може виникнути завдання визначення розміру консольного вікна по вертикалі і по горизонталі. Для цього ми створимо дві змінні: MaxX і MaxY, типу WORD:

//————————————– / / Ініціалізація глобальних змінних
//————————————–
procedure Init;
begin / / Отримуємо дескриптор виводу (output)
ConHandle := GetConOutputHandle; / / Отримуємо максимальні розміри вікна
Coord := GetLargestConsoleWindowSize(ConHandle);
MaxX := Coord.X;
MaxY := Coord.Y;
end;

Ми навіть можемо зробити “цикл обробки повідомлень” (message loop) – для тих, хто тільки починає програмувати в Delphi – цикл обробки повідомлень необхідно робити, якщо додаток створюється в чистому API – при цьому необхідні як мінімум три складові: WinMain, message loop та window proc.

Нижче наведено код “циклу обробки повідомлень”:

SetConsoleCtrlHandler(@ConProc, False);
Cls;
// / / “Цикл обробки повідомлень”
//
Continue := True;
While Continue do
Begin
ReadConsoleInput(GetConInputHandle, IBuff, 1, IEvent);
Case IBuff.EventType of
KEY_EVENT : Begin / / Перевіряємо клавішу ESC і завершуємо програму
If ((IBuff.KeyEvent.bKeyDown = True) AND
(IBuff.KeyEvent.wVirtualKeyCode = VK_ESCAPE)) Then
Continue := False;
End;
_MOUSE_EVENT : Begin
With IBuff.MouseEvent.dwMousePosition do
StatusLine(Format(“%d, %d”, [X, Y]));
End;
end;
End {While}

Так само можна додати “обробник подій” і перехоплювати такі комбінації клавіш як Ctrl + C і Ctrl + Break:

//—————————————————– / / Оброблювач консольних подій
//—————————————————–
function ConProc(CtrlType : DWord) : Bool; stdcall; far;
var
S : String;
begin
case CtrlType of
CTRL_C_EVENT : S := “CTRL_C_EVENT”;
CTRL_BREAK_EVENT : S := “CTRL_BREAK_EVENT”;
CTRL_CLOSE_EVENT : S := “CTRL_CLOSE_EVENT”;
CTRL_LOGOFF_EVENT : S := “CTRL_LOGOFF_EVENT”;
CTRL_SHUTDOWN_EVENT : S := “CTRL_SHUTDOWN_EVENT”;
else
S := “UNKNOWN_EVENT”;
end;
MessageBox(0, PChar(S + ” detected”), “Win32 Console”, MB_OK);
Result := True;
end;

Щоб переглянути все це у дії, я зробив невелику демонстраційну програму, яка містить підпрограми, наведені вище, а так само деякі інші можливості. Далі наведено повний вихідний код цього додатка. Насолоджуйтесь!

{
[]———————————————————————–[]
CON001 – Show various Console API functions. Checked with Win95
version 1.01
by Alex G. Fedorov, May-July, 1997
alexfedorov@geocities.com
09-Jul-97 some minor corrections (shown in comments)
[]———————————————————————–[]
}
program Con001;
{$APPTYPE CONSOLE}
uses Windows, SysUtils;
const / / Деякі стандартні кольори
YellowOnBlue = FOREGROUND_GREEN OR FOREGROUND_RED OR
FOREGROUND_INTENSITY OR BACKGROUND_BLUE;
WhiteOnBlue = FOREGROUND_BLUE OR FOREGROUND_GREEN OR
FOREGROUND_RED OR FOREGROUND_INTENSITY OR
BACKGROUND_BLUE;
RedOnWhite = FOREGROUND_RED OR FOREGROUND_INTENSITY OR
BACKGROUND_RED OR BACKGROUND_GREEN OR BACKGROUND_BLUE
OR BACKGROUND_INTENSITY;
WhiteOnRed = BACKGROUND_RED OR BACKGROUND_INTENSITY OR
FOREGROUND_RED OR FOREGROUND_GREEN OR FOREGROUND_BLUE
OR FOREGROUND_INTENSITY;
var ConHandle: THandle; / / Дескриптор консольного вікна Coord: TCoord; / / Для зберігання / установки позиції екрану MaxX, MaxY: Word; / / Для зберігання максимальних розмірів вікна
CCI : TConsoleCursorInfo; NOAW: LongInt; / / Для зберігання результатів деяких функцій
//—————————————– / / Отримання дескриптора для консольного вводу
//—————————————–
function GetConInputHandle : THandle;
begin
Result := GetStdHandle(STD_INPUT_HANDLE)
end;
//—————————————– / / Отримання дескриптора для консольного виводу
//—————————————–
function GetConOutputHandle : THandle;
begin
Result := GetStdHandle(STD_OUTPUT_HANDLE)
end;
//—————————————– / / Установка курсора в координати X, Y
//—————————————–
procedure GotoXY(X, Y : Word);
begin
Coord.X := X; Coord.Y := Y;
SetConsoleCursorPosition(ConHandle, Coord);
end;
//—————————————– / / Очищення екрану – заповнення його пробілами
//—————————————–
procedure Cls;
begin
Coord.X := 0; Coord.Y := 0;
FillConsoleOutputCharacter(ConHandle, ” “, MaxX*MaxY, Coord, NOAW);
GotoXY(0, 0);
end;
//————————————– / / Показуємо / Приховуємо курсор
//————————————–
procedure ShowCursor(Show : Bool);
begin
CCI.bVisible := Show;
SetConsoleCursorInfo(ConHandle, CCI);
end;
//————————————– / / Ініціалізація глобальних змінних
//————————————–
procedure Init;
begin / / Отримуємо дескриптор виводу (output)
ConHandle := GetConOutputHandle; / / Отримуємо максимальні розміри вікна
Coord := GetLargestConsoleWindowSize(ConHandle);
MaxX := Coord.X;
MaxY := Coord.Y;
end;
//————————————— / / Малюємо рядок статусу (“status line”)
//—————————————
procedure StatusLine(S : String);
begin
Coord.X := 0; Coord.Y := 0;
WriteConsoleOutputCharacter(ConHandle, PChar(S), Length(S)+1, Coord, NOAW);
FillConsoleOutputAttribute (ConHandle, WhiteOnRed, Length(S), Coord, NOAW);
end;
//—————————————————– / / Консольний обробник подій
//—————————————————–
function ConProc(CtrlType : DWord) : Bool; stdcall; far;
var
S : String;
begin
case CtrlType of
CTRL_C_EVENT : S := “CTRL_C_EVENT”;
CTRL_BREAK_EVENT : S := “CTRL_BREAK_EVENT”;
CTRL_CLOSE_EVENT : S := “CTRL_CLOSE_EVENT”;
CTRL_LOGOFF_EVENT : S := “CTRL_LOGOFF_EVENT”;
CTRL_SHUTDOWN_EVENT : S := “CTRL_SHUTDOWN_EVENT”;
else
S := “UNKNOWN_EVENT”;
end;
MessageBox(0, PChar(S + ” detected”), “Win32 Console”, MB_OK);
Result := True;
end;
{
[]—————————————————————[] Основна програма – показує використання деяких підпрограм а так само деяких функцій консольного API
[]—————————————————————[]
}
var
R : TSmallRect;
Color : Word;
OSVer : TOSVersionInfo;
IBuff : TInputRecord;
IEvent : DWord;
Continue : Bool;
begin / / Ініціалізація глобальних змінних
Init; / / Розташування вікна на екрані
With R do
{!! 1.01 !!}
begin
Left := 10; Top := 10; Right := 40; Bottom := 40;
end
{!! 1.01 !!}
SetConsoleWindowInfo(ConHandle, False, R); / / Встановлюємо оброблювач подій
SetConsoleCtrlHandler(@ConProc, True); / / Перевіряємо обробник подій
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); / / Змінюємо заголовок вікна
SetConsoleTitle(“Console Demo”); / / Ховаємо курсор
ShowCursor(False);
Coord.X := 0; Coord.Y := 0; / / Встановлюємо білий текст на синьому фоні
Color := WhiteOnBlue;
FillConsoleOutputAttribute(ConHandle, Color, MaxX*MaxY, Coord, NOAW);
// Console Code Page API is not supported under Win95 – only GetConsoleCP
Writeln(“Console Code Page = “, GetConsoleCP);
Writeln(“MAX X=”, MaxX,” MAX Y=”, MaxY); Readln; / / очікуємо введення користувача Cls; / / очищаємо екран ShowCursor (True); / / показуємо курсор
//
// Use some Win32API stuff
//
OSVer.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
GetVersionEx(OSVer);
With OSVer do
Begin
Writeln(“dwMajorVersion = “, dwMajorVersion);
Writeln(“dwMinorVersion = “, dwMinorVersion);
Writeln(“dwBuildNumber = “, dwBuildNumber);
Writeln(“dwPlatformID = “, dwPlatformID);
End;
// Readln; / / очікуємо введення користувача / / Видаляємо обробник подій
SetConsoleCtrlHandler(@ConProc, False);
Cls;
// / / “Цикл обробки повідомлень”
//
Continue := True;
While Continue do
Begin
ReadConsoleInput(GetConInputHandle, IBuff, 1, IEvent);
Case IBuff.EventType of
KEY_EVENT : Begin / / Перевіряємо клавішу ESC і завершуємо програму
If ((IBuff.KeyEvent.bKeyDown = True) AND
(IBuff.KeyEvent.wVirtualKeyCode = VK_ESCAPE)) Then
Continue := False;
End;
_MOUSE_EVENT : Begin
With IBuff.MouseEvent.dwMousePosition do
StatusLine(Format(“%d, %d”, [X, Y]));
End;
end;
End {While}
end.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*