FPC 2.6.4 / Windows 7 x64 /
Задача: с экрана (консоль) считать символ и его атрибут.
На BorlandPascal делалось примерно так...
type
TEkr= array[1..2000,1..2] of byte;
var
Ekran : TEkr absolute $B800:$0000;
begin
{ читаем с массива что хотим }
end.
На такую конструкцию идет ошибка: 2.pas(4,29) Fatal: Syntax error, ";" expected but ":" found
как это можно сделать в FPC ? если можно с примером.
Работа с консолью
Модератор: Модераторы
Для начала рекомендую попробовать модуль video:
Технически он подходит под задачу, но на практике имеет странности (в частности, в винде предварительно очищает экран после запуска).
Код: Выделить всё
uses
video;
var
Cell: TVideoCell;
begin
InitVideo;
Cell := VideoBuf^[ScreenWidth * (ScreenHeight - 1)];
Writeln('Char: $', HexStr(Cell and $FF, 2), ', ',
'Color: ', (Cell shr 8) and $F, ', ',
'Background: ', (Cell shr 8) and $70, ', ',
'Blinking: ', (Cell shr 8) and $A0 > 0);
DoneVideo;
end.
Технически он подходит под задачу, но на практике имеет странности (в частности, в винде предварительно очищает экран после запуска).
Спасибо. Давно в руки паскаль не брал. Как все усложнилось, главное что понятно, то что написано. 
Добавлено спустя 21 час 39 минут 16 секунд:
получаем:
1
Char kod:32 (тут не правильно)
----------------------------------------------
а если
получаем:
1
Char kod:49 (тут правильно)
На экран выводит то что надо в обоих вариантах. Определяет символ неправильно. Почему?
Добавлено спустя 21 час 39 минут 16 секунд:
Код: Выделить всё
InitVideo;
gotoxy(1,1);
writeln('1');
Writeln('Char kod:', (VideoBuf^[0] and $FF) );
DoneVideo;
получаем:
1
Char kod:32 (тут не правильно)
----------------------------------------------
а если
Код: Выделить всё
InitVideo;
// символ цвет фон
VideoBuf^[0]:=byte('1') + ((7 + (0 shl 4)) shl 8);
UpdateScreen(false);
Writeln('Char kod:', (VideoBuf^[0] and $FF) );
DoneVideo;
получаем:
1
Char kod:49 (тут правильно)
На экран выводит то что надо в обоих вариантах. Определяет символ неправильно. Почему?
На экран выводит то что надо в обоих вариантах. Определяет символ неправильно. Почему?
Во-первых, модуль video не делает чуда и то, что выведено каким-то другим способом, само в VideoBuf не попадёт. Поэтому выводить нужно через video. Если же требуется прочитать что напечатал другой код или уже есть много кода со всякими Writeln, который нет возможности переписать, то придётся использовать чистый WinApi, никуда не деться:
Код: Выделить всё
uses
windows;
var
Stdout, ScreenBuffer: HANDLE;
Buf: array[0..24] of array[0..79] of TCharInfo;
BufPos, BufSize: TCoord;
ReadRect: TSmallRect;
Security: TSecurityAttributes;
Info: TConsoleScreenBufferInfo;
begin
Writeln(Char(49));
FillChar(Security, SizeOf(Security), 0);
Stdout := GetStdHandle(STD_OUTPUT_HANDLE);
ScreenBuffer := CreateConsoleScreenBuffer(
GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE,
Security, CONSOLE_TEXTMODE_BUFFER, nil);
GetConsoleScreenBufferInfo(Stdout, @Info);
ReadRect.Top := Info.srWindow.Bottom - Length(Buf);
ReadRect.Left := 0;
ReadRect.Bottom := Info.srWindow.Bottom;
ReadRect.Right := Length(Buf[0]);
BufPos.X := 0;
BufPos.Y := 0;
BufSize.X := Length(Buf[0]);
BufSize.Y := Length(Buf);
if (Stdout = INVALID_HANDLE_VALUE) or
(ScreenBuffer = INVALID_HANDLE_VALUE) or
(not SetConsoleActiveScreenBuffer(ScreenBuffer)) or
(not ReadConsoleOutput(Stdout, @Buf[0][0], BufSize, BufPos, ReadRect)) then
Halt(5);
Writeln('Char code: ', Ord(Buf[High(Buf)][0].AsciiChar));
end.
Во-вторых, по той ссылке, которую я дал, прямым текстом написано:
Remark: The video unit should not be used together with the crt unit. Doing so will result in very strange behaviour, possibly program crashes.
