скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Использовать модуль CRT в Delphi



Оформил: DeeCo

{$IfDef VER130}
   {$Define NEW_STYLES}
 {$EndIf}
 {$IfDef VER140}
   {$Define NEW_STYLES}
 {$EndIf}

 {..$Define HARD_CRT}      {Redirect STD_...}
 {..$Define CRT_EVENT}     {CTRL-C,...}
 {$Define MOUSE_IS_USED}   {Handle mouse or not}
 {..$Define OneByOne}      {Block or byte style write}
 unit CRT32;

 Interface
   {$IfDef Win32}
   Const
     { CRT modes of original CRT unit }
     BW40 = 0;     { 40x25 B/W on Color Adapter }
     CO40 = 1;     { 40x25 Color on Color Adapter }
     BW80 = 2;     { 80x25 B/W on Color Adapter }
     CO80 = 3;     { 80x25 Color on Color Adapter }
     Mono = 7;     { 80x25 on Monochrome Adapter }
     Font8x8 = 256;{ Add-in for ROM font }
     { Mode constants for 3.0 compatibility of original CRT unit }
     C40 = CO40;
     C80 = CO80;
     { Foreground and background color constants of original CRT unit }
     Black = 0;
     Blue = 1;
     Green = 2;
     Cyan = 3;
     Red = 4;
     Magenta = 5;
     Brown  6;
     LightGray = 7;
     { Foreground color constants of original CRT unit }
     DarkGray = 8;
     LightBlue = 9;
     LightGreen = 10;
     LightCyan = 11;
     LightRed = 12;
     LightMagenta = 13;
     Yellow = 14;
     White = 15;
     { Add-in for blinking of original CRT unit }
     Blink = 128;
     {  }
     {  New constans there are not in original CRT unit }
     {  }
     MouseLeftButton = 1;
     MouseRightButton = 2;
     MouseCenterButton = 4;

 var
   { Interface variables of original CRT unit }
   CheckBreak: Boolean;    { Enable Ctrl-Break }
   CheckEOF: Boolean;      { Enable Ctrl-Z }
   DirectVideo: Boolean;   { Enable direct video addressing }
   CheckSnow: Boolean;     { Enable snow filtering }
   LastMode: Word;         { Current text mode }
   TextAttr: Byte;         { Current text attribute }
   WindMin: Word;          { Window upper left coordinates }
   WindMax: Word;          { Window lower right coordinates }
   {  }
   {  New variables there are not in original CRT unit }
   {  }
   MouseInstalled: boolean;
   MousePressedButtons: word;

 { Interface functions & procedures of original CRT unit }
 procedure AssignCrt(var F: Text);
 function KeyPressed: Boolean;
 function ReadKey: char;
 procedure TextMode(Mode: Integer);
 procedure Window(X1, Y1, X2, Y2: Byte);
 procedure GotoXY(X, Y: Byte);
 function WhereX: Byte;
 function WhereY: Byte;
 procedure ClrScr;
 procedure ClrEol;
 procedure InsLine;
 procedure DelLine;
 procedure TextColor(Color: Byte);
 procedure TextBackground(Color: Byte);
 procedure LowVideo;
 procedure HighVideo;
 procedure NormVideo;
 procedure Delay(MS: Word);
 procedure Sound(Hz: Word);
 procedure NoSound;
 { New functions & procedures there are not in original CRT unit }
 procedure FillerScreen(FillChar: Char);
 procedure FlushInputBuffer;
 function GetCursor: Word;
 procedure SetCursor(NewCursor: Word);
 function MouseKeyPressed: Boolean;
 procedure MouseGotoXY(X, Y: Integer);
 function MouseWhereY: Integer;
 function MouseWhereX: Integer;
 procedure MouseShowCursor;
 procedure MouseHideCursor;
 { These functions & procedures are for inside use only }
 function MouseReset: Boolean;
 procedure WriteChrXY(X, Y: Byte; Chr: char);
 procedure WriteStrXY(X, Y: Byte; Str: PChar; dwSize: Integer);
 procedure OverwriteChrXY(X, Y: Byte; Chr: char);
 {$EndIf Win32}

 implementation
 {$IfDef Win32}

 uses Windows, SysUtils;

 type
   POpenText = ^TOpenText;
   TOpenText = function(var F: Text; Mode: Word): Integer; far;

 var
   IsWinNT: boolean;
   PtrOpenText: POpenText;
   hConsoleInput: THandle;
   hConsoleOutput: THandle;
   ConsoleScreenRect: TSmallRect;
   StartAttr: word;
   LastX, LastY: byte;
   SoundDuration: integer;
   SoundFrequency: integer;
   OldCP: integer;
   MouseRowWidth, MouseColWidth: word;
   MousePosX, MousePosY: smallInt;
   MouseButtonPressed: boolean;
   MouseEventTime: TDateTime;
 {  }
 {  This function handles the Write and WriteLn commands }
 {  }

 function TextOut(var F: Text): Integer; far;
   {$IfDef OneByOne}
 var
   dwSize: DWORD;
   {$EndIf}
 begin
   with TTExtRec(F) do
   begin
     if BufPos > 0 then
     begin
       LastX := WhereX;
       LastY := WhereY;
       {$IfDef OneByOne}
       dwSize := 0;
       while (dwSize < BufPos) do
       begin
         WriteChrXY(LastX, LastY, BufPtr[dwSize]);
         Inc(dwSize);
       end;
       {$Else}
       WriteStrXY(LastX, LastY, BufPtr, BufPos);
       FillChar(BufPtr^, BufPos + 1, #0);
       {$EndIf}
       BufPos := 0;
     end;
   end;
   Result := 0;
 end;
 {  }
 {  This function handles the exchanging of Input or Output }
 {  }

 function OpenText(var F: Text; Mode: Word): Integer; far;
 var
   OpenResult: integer;
 begin
   OpenResult := 102; { Text not assigned }
   if Assigned(PtrOpenText) then
   begin
     TTextRec(F).OpenFunc := PtrOpenText;
     OpenResult := PtrOpenText^(F, Mode);
     if OpenResult = 0 then
     begin
       if Mode = fmInput then
         hConsoleInput := TTextRec(F).Handle
       else
       begin
         hConsoleOutput := TTextRec(F).Handle;
         TTextRec(Output).InOutFunc := @TextOut;
         TTextRec(Output).FlushFunc := @TextOut;
       end;
     end;
   end;
   Result := OpenResult;
 end;
 {  }
 {  Fills the current window with special character }
 {  }

 procedure FillerScreen(FillChar: Char);
 var
   Coord: TCoord;
   dwSize, dwCount: DWORD;
   Y: integer;
 begin
   Coord.X := ConsoleScreenRect.Left;
   dwSize := ConsoleScreenRect.Right - ConsoleScreenRect.Left + 1;
   for Y := ConsoleScreenRect.Top to ConsoleScreenRect.Bottom do
   begin
     Coord.Y := Y;
     FillConsoleOutputAttribute(hConsoleOutput, TextAttr, dwSize, Coord, dwCount);
     FillConsoleOutputCharacter(hConsoleOutput, FillChar, dwSize, Coord, dwCount);
   end;
   GotoXY(1,1);
 end;
 {  }
 {  Write one character at the X,Y position }
 {  }

 procedure WriteChrXY(X, Y: Byte; Chr: char);
 var
   Coord: TCoord;
   dwSize, dwCount: DWORD;
 begin
   LastX := X;
   LastY := Y;
   case Chr of
     #13: LastX := 1;
     #10:
       begin
         LastX := 1;
         Inc(LastY);
       end;
     else
       begin
         Coord.X := LastX - 1 + ConsoleScreenRect.Left;
         Coord.Y := LastY - 1 + ConsoleScreenRect.Top;
         dwSize := 1;
         FillConsoleOutputAttribute(hConsoleOutput, TextAttr, dwSize, Coord, dwCount);
         FillConsoleOutputCharacter(hConsoleOutput, Chr, dwSize, Coord, dwCount);
         Inc(LastX);
       end;
   end;
   if (LastX + ConsoleScreenRect.Left) > (ConsoleScreenRect.Right + 1) then
   begin
     LastX := 1;
     Inc(LastY);
   end;
   if (LastY + ConsoleScreenRect.Top) > (ConsoleScreenRect.Bottom + 1) then
   begin
     Dec(LastY);
     GotoXY(1,1);
     DelLine;
   end;
   GotoXY(LastX, LastY);
 end;
 {  }
 {  Write string into the X,Y position }
 {  }
 (* !!! The WriteConsoleOutput does not write into the last line !!!
   Procedure WriteStrXY(X,Y: byte; Str: PChar; dwSize: integer );
   {$IfDef OneByOne}
     Var
       dwCount: integer;
   {$Else}
     Type
       PBuffer= ^TBuffer;
       TBUffer= packed array [0..16384] of TCharInfo;
     Var
       I: integer;
       dwCount: DWORD;
       WidthHeight,Coord: TCoord;
       hTempConsoleOutput: THandle;
       SecurityAttributes: TSecurityAttributes;
       Buffer: PBuffer;
       DestinationScreenRect,SourceScreenRect: TSmallRect;
   {$EndIf}
   Begin
     If dwSize>0 Then Begin
       {$IfDef OneByOne}
         LastX:=X;
         LastY:=Y;
         dwCount:=0;
         While dwCount < dwSize Do Begin
           WriteChrXY(LastX,LastY,Str[dwCount]);
           Inc(dwCount);
         End;
       {$Else}
         SecurityAttributes.nLength:=SizeOf(SecurityAttributes)-SizeOf(DWORD);
         SecurityAttributes.lpSecurityDescriptor:=NIL;
         SecurityAttributes.bInheritHandle:=TRUE;
         hTempConsoleOutput:=CreateConsoleScreenBuffer(
          GENERIC_READ OR GENERIC_WRITE,
          FILE_SHARE_READ OR FILE_SHARE_WRITE,
          @SecurityAttributes,
          CONSOLE_TEXTMODE_BUFFER,
          NIL
         );
         If dwSize<=(ConsoleScreenRect.Right-ConsoleScreenRect.Left+1) Then Begin
           WidthHeight.X:=dwSize;
           WidthHeight.Y:=1;
         End Else Begin
           WidthHeight.X:=ConsoleScreenRect.Right-ConsoleScreenRect.Left+1;
           WidthHeight.Y:=dwSize DIV WidthHeight.X;
           If (dwSize MOD WidthHeight.X) > 0 Then Inc(WidthHeight.Y);
         End;
         SetConsoleScreenBufferSize(hTempConsoleOutput,WidthHeight);
         DestinationScreenRect.Left:=0;
         DestinationScreenRect.Top:=0;
         DestinationScreenRect.Right:=WidthHeight.X-1;
         DestinationScreenRect.Bottom:=WidthHeight.Y-1;
         SetConsoleWindowInfo(hTempConsoleOutput,FALSE,DestinationScreenRect);
         Coord.X:=0;
         For I:=1 To WidthHeight.Y Do Begin
           Coord.Y:=I-0;
           FillConsoleOutputAttribute(hTempConsoleOutput,TextAttr,WidthHeight.X,Coord,dwCount);
           FillConsoleOutputCharacter(hTempConsoleOutput,' '     ,WidthHeight.X,Coord,dwCount);
         End;
         WriteConsole(hTempConsoleOutput,Str,dwSize,dwCount,NIL);
         {  }
         New(Buffer);
         Coord.X:= 0;
         Coord.Y:= 0;
         SourceScreenRect.Left:=0;
         SourceScreenRect.Top:=0;
         SourceScreenRect.Right:=WidthHeight.X-1;
         SourceScreenRect.Bottom:=WidthHeight.Y-1;
         ReadConsoleOutputA(hTempConsoleOutput,Buffer,WidthHeight,Coord,SourceScreenRect);
         Coord.X:=X-1;
         Coord.Y:=Y-1;
         DestinationScreenRect:=ConsoleScreenRect;
         WriteConsoleOutputA(hConsoleOutput,Buffer,WidthHeight,Coord,DestinationScreenRect);
         GotoXY((dwSize MOD WidthHeight.X)-1,WidthHeight.Y+1);
         Dispose(Buffer);
         {  }
         CloseHandle(hTempConsoleOutput);
       {$EndIf}
     End;
   End;
 *)

 procedure WriteStrXY(X, Y: Byte; Str: PChar; dwSize: Integer);
   {$IfDef OneByOne}
 var
   dwCount: integer;
   {$Else}
 var
   I: integer;
   LineSize, dwCharCount, dwCount, dwWait: DWORD;
   WidthHeight: TCoord;
   OneLine: packed array [0..131] of char;
   Line, TempStr: PChar;

   procedure NewLine;
   begin
     LastX := 1;
     Inc(LastY);
     if (LastY + ConsoleScreenRect.Top) > (ConsoleScreenRect.Bottom + 1) then
     begin
       Dec(LastY);
       GotoXY(1,1);
       DelLine;
     end;
     GotoXY(LastX, LastY);
   end;

   {$EndIf}
 begin
   if dwSize > 0 then
   begin
     {$IfDef OneByOne}
     LastX := X;
     LastY := Y;
     dwCount := 0;
     while dwCount < dwSize do
     begin
       WriteChrXY(LastX, LastY, Str[dwCount]);
       Inc(dwCount);
     end;
     {$Else}
     LastX := X;
     LastY := Y;
     GotoXY(LastX, LastY);
     dwWait  := dwSize;
     TempStr := Str;
     while (dwWait > 0) and (Pos(#13#10,StrPas(TempStr))= 1) do
     begin
       Dec(dwWait, 2);
       Inc(TempStr, 2);
       NewLine;
     end;
     while (dwWait > 0) and (Pos(#10, StrPas(TempStr)) = 1) do
     begin
       Dec(dwWait);
       Inc(TempStr);
       NewLine;
     end;
     if dwWait > 0 then
     begin
       if dwSize <= (ConsoleScreenRect.Right - ConsoleScreenRect.Left - LastX + 1) then
       begin
         WidthHeight.X := dwSize + LastX - 1;
         WidthHeight.Y := 1;
       end
       else
       begin
         WidthHeight.X := ConsoleScreenRect.Right - ConsoleScreenRect.Left + 1;
         WidthHeight.Y := dwSize div WidthHeight.X;
         if (dwSize mod WidthHeight.X) > 0 then Inc(WidthHeight.Y);
       end;
       for I := 1 to WidthHeight.Y do
       begin
         FillChar(OneLine, SizeOf(OneLine), #0);
         Line := @OneLine;
         LineSize := WidthHeight.X - LastX + 1;
         if LineSize > dwWait then LineSize := dwWait;
         Dec(dwWait, LineSize);
         StrLCopy(Line, TempStr, LineSize);
         Inc(TempStr, LineSize);
         dwCharCount := Pos(#13#10,StrPas(Line));
        if dwCharCount > 0 then
         begin
           OneLine[dwCharCount - 1] := #0;
           OneLine[dwCharCount]     := #0;
           WriteConsole(hConsoleOutput, Line, dwCharCount - 1,dwCount, nil);
           Inc(Line, dwCharCount + 1);
           NewLine;
           LineSize := LineSize - (dwCharCount + 1);
         end
         else
         begin
           dwCharCount := Pos(#10, StrPas(Line));
           if dwCharCount > 0 then
           begin
             OneLine[dwCharCount - 1] := #0;
             WriteConsole(hConsoleOutput, Line, dwCharCount - 1,dwCount, nil);
             Inc(Line, dwCharCount);
             NewLine;
             LineSize := LineSize - dwCharCount;
           end;
         end;
         if LineSize <> 0 then
         begin
           WriteConsole(hConsoleOutput, Line, LineSize, dwCount, nil);
         end;
         if dwWait > 0 then
         begin
           NewLine;
         end;
       end;
     end;
     {$EndIf}
   end;
 end;
 {  }
 {  Empty the buffer }
 {  }

 procedure FlushInputBuffer;
 begin
   FlushConsoleInputBuffer(hConsoleInput);
 end;
 {  }
 {  Get size of current cursor }
 {  }

 function GetCursor: Word;
 var
   CCI: TConsoleCursorInfo;
 begin
   GetConsoleCursorInfo(hConsoleOutput, CCI);
   GetCursor := CCI.dwSize;
 end;
 {  }
 {  Set size of current cursor }
 {  }

 procedure SetCursor(NewCursor: Word);
 var
   CCI: TConsoleCursorInfo;
 begin
   if NewCursor = $0000 then
   begin
     CCI.dwSize := GetCursor;
     CCI.bVisible := False;
   end
   else
   begin
     CCI.dwSize := NewCursor;
     CCI.bVisible := True;
   end;
   SetConsoleCursorInfo(hConsoleOutput, CCI);
 end;
 {  }
 { --- Begin of Interface functions & procedures of original CRT unit --- }

 procedure AssignCrt(var F: Text);
 begin
   Assign(F, '');
   TTextRec(F).OpenFunc := @OpenText;
 end;

 function KeyPressed: Boolean;
 var
   NumberOfEvents: DWORD;
   NumRead: DWORD;
   InputRec: TInputRecord;
   Pressed: boolean;
 begin
   Pressed := False;
   GetNumberOfConsoleInputEvents(hConsoleInput, NumberOfEvents);
   if NumberOfEvents > 0 then
   begin
     if PeekConsoleInput(hConsoleInput, InputRec, 1,NumRead) then
     begin
       if (InputRec.EventType = KEY_EVENT) and
         (InputRec{$IfDef NEW_STYLES}.Event{$EndIf}.KeyEvent.bKeyDown) then
       begin
         Pressed := True;
         {$IfDef MOUSE_IS_USED}
         MouseButtonPressed := False;
         {$EndIf}
       end
       else
       begin
         {$IfDef MOUSE_IS_USED}
         if (InputRec.EventType = _MOUSE_EVENT) then
         begin
           with InputRec{$IfDef NEW_STYLES}.Event{$EndIf}.MouseEvent do
           begin
             MousePosX := dwMousePosition.X;
             MousePosY := dwMousePosition.Y;
             if dwButtonState = FROM_LEFT_1ST_BUTTON_PRESSED then
             begin
               MouseEventTime := Now;
               MouseButtonPressed := True;
               {If (dwEventFlags AND DOUBLE_CLICK)<>0 Then Begin}
               {End;}
             end;
           end;
         end;
         ReadConsoleInput(hConsoleInput, InputRec, 1,NumRead);
         {$Else}
         ReadConsoleInput(hConsoleInput, InputRec, 1,NumRead);
         {$EndIf}
       end;
     end;
   end;
   Result := Pressed;
 end;

 function ReadKey: char;
 var
   NumRead: DWORD;
   InputRec: TInputRecord;
 begin
   repeat
     repeat
     until KeyPressed;
     ReadConsoleInput(hConsoleInput, InputRec, 1,NumRead);
   until InputRec{$IfDef NEW_STYLES}.Event{$EndIf}.KeyEvent.AsciiChar > #0;
   Result := InputRec{$IfDef NEW_STYLES}.Event{$EndIf}.KeyEvent.AsciiChar;
 end;

 procedure TextMode(Mode: Integer);
 begin
 end;

 procedure Window(X1, Y1, X2, Y2: Byte);
 begin
   ConsoleScreenRect.Left := X1 - 1;
   ConsoleScreenRect.Top := Y1 - 1;
   ConsoleScreenRect.Right := X2 - 1;
   ConsoleScreenRect.Bottom := Y2 - 1;
   WindMin := (ConsoleScreenRect.Top shl 8) or ConsoleScreenRect.Left;
   WindMax := (ConsoleScreenRect.Bottom shl 8) or ConsoleScreenRect.Right;
   {$IfDef WindowFrameToo}
   SetConsoleWindowInfo(hConsoleOutput, True, ConsoleScreenRect);
   {$EndIf}
   GotoXY(1,1);
 end;

 procedure GotoXY(X, Y: Byte);
 var
   Coord: TCoord;
 begin
   Coord.X := X - 1 + ConsoleScreenRect.Left;
   Coord.Y := Y - 1 + ConsoleScreenRect.Top;
   if not SetConsoleCursorPosition(hConsoleOutput, Coord) then
   begin
     GotoXY(1, 1);
     DelLine;
   end;
 end;

 function WhereX: Byte;
 var
   CBI: TConsoleScreenBufferInfo;
 begin
   GetConsoleScreenBufferInfo(hConsoleOutput, CBI);
   Result := TCoord(CBI.dwCursorPosition).X + 1 - ConsoleScreenRect.Left;
 end;

 function WhereY: Byte;
 var
   CBI: TConsoleScreenBufferInfo;
 begin
   GetConsoleScreenBufferInfo(hConsoleOutput, CBI);
   Result := TCoord(CBI.dwCursorPosition).Y + 1 - ConsoleScreenRect.Top;
 end;

 procedure ClrScr;
 begin
   FillerScreen(' ');
 end;

 procedure ClrEol;
 var
   Coord: TCoord;
   dwSize, dwCount: DWORD;
 begin
   Coord.X := WhereX - 1 + ConsoleScreenRect.Left;
   Coord.Y := WhereY - 1 + ConsoleScreenRect.Top;
   dwSize  := ConsoleScreenRect.Right - Coord.X + 1;
   FillConsoleOutputAttribute(hConsoleOutput, TextAttr, dwSize, Coord, dwCount);
   FillConsoleOutputCharacter(hConsoleOutput, ' ', dwSize, Coord, dwCount);
 end;

 procedure InsLine;
 var
   SourceScreenRect: TSmallRect;
   Coord: TCoord;
   CI: TCharInfo;
   dwSize, dwCount: DWORD;
 begin
   SourceScreenRect := ConsoleScreenRect;
   SourceScreenRect.Top := WhereY - 1 + ConsoleScreenRect.Top;
   SourceScreenRect.Bottom := ConsoleScreenRect.Bottom - 1;
   CI.AsciiChar := ' ';
   CI.Attributes := TextAttr;
   Coord.X := SourceScreenRect.Left;
   Coord.Y := SourceScreenRect.Top + 1;
   dwSize := SourceScreenRect.Right - SourceScreenRect.Left + 1;
   ScrollConsoleScreenBuffer(hConsoleOutput, SourceScreenRect, nil, Coord, CI);
   Dec(Coord.Y);
   FillConsoleOutputAttribute(hConsoleOutput, TextAttr, dwSize, Coord, dwCount);
 end;

 procedure DelLine;
 var
   SourceScreenRect: TSmallRect;
   Coord: TCoord;
   CI: TCharinfo;
   dwSize, dwCount: DWORD;
 begin
   SourceScreenRect := ConsoleScreenRect;
   SourceScreenRect.Top := WhereY + ConsoleScreenRect.Top;
   CI.AsciiChar := ' ';
   CI.Attributes := TextAttr;
   Coord.X := SourceScreenRect.Left;
   Coord.Y := SourceScreenRect.Top - 1;
   dwSize := SourceScreenRect.Right - SourceScreenRect.Left + 1;
   ScrollConsoleScreenBuffer(hConsoleOutput, SourceScreenRect, nil, Coord, CI);
   FillConsoleOutputAttribute(hConsoleOutput, TextAttr, dwSize, Coord, dwCount);
 end;

 procedure TextColor(Color: Byte);
 begin
   LastMode := TextAttr;
   TextAttr := (Color and $0F) or (TextAttr and $F0);
   SetConsoleTextAttribute(hConsoleOutput, TextAttr);
 end;

 procedure TextBackground(Color: Byte);
 begin
   LastMode := TextAttr;
   TextAttr := (Color shl 4) or (TextAttr and $0F);
   SetConsoleTextAttribute(hConsoleOutput, TextAttr);
 end;

 procedure LowVideo;
 begin
   LastMode := TextAttr;
   TextAttr := TextAttr and $F7;
   SetConsoleTextAttribute(hConsoleOutput, TextAttr);
 end;

 procedure HighVideo;
 begin
   LastMode := TextAttr;
   TextAttr := TextAttr or $08;
   SetConsoleTextAttribute(hConsoleOutput, TextAttr);
 end;

 procedure NormVideo;
 begin
   LastMode := TextAttr;
   TextAttr := StartAttr;
   SetConsoleTextAttribute(hConsoleOutput, TextAttr);
 end;

 procedure Delay(MS: Word);
   { 
  Const 
    Magic= $80000000; 
  var 
   StartMS,CurMS,DeltaMS: DWORD; 
   }
 begin
   Windows.SleepEx(MS, False);  // Windows.Sleep(MS); 
    { 
    StartMS:= GetTickCount; 
    Repeat 
      CurMS:= GetTickCount; 
      If CurMS >= StartMS Then 
         DeltaMS:= CurMS - StartMS 
      Else DeltaMS := (CurMS + Magic) - (StartMS - Magic); 
    Until MS<DeltaMS; 
    }
 end;

 procedure Sound(Hz: Word);
 begin
   {SetSoundIOPermissionMap(LocalIOPermission_ON);}
   SoundFrequency := Hz;
   if IsWinNT then
   begin
     Windows.Beep(SoundFrequency, SoundDuration)
   end
   else
   begin
     asm
         mov  BX,Hz
         cmp  BX,0
         jz   @2
         mov  AX,$34DD
         mov  DX,$0012
         cmp  DX,BX
         jnb  @2
         div  BX
         mov  BX,AX
         { Sound is On ? }
         in   Al,$61
         test Al,$03
         jnz  @1
         { Set Sound On }
         or   Al,03
         out  $61,Al
         { Timer Command }
         mov  Al,$B6
         out  $43,Al
         { Set Frequency }
     @1: mov  Al,Bl
         out  $42,Al
         mov  Al,Bh
         out  $42,Al
     @2:
     end;
   end;
 end;

 procedure NoSound;
 begin
   if IsWinNT then
   begin
     Windows.Beep(SoundFrequency, 0);
   end
   else
   begin
       asm
         { Set Sound On }
         in   Al,$61
         and  Al,$FC
         out  $61,Al
       end;
   end;
   {SetSoundIOPermissionMap(LocalIOPermission_OFF);}
 end;
 { --- End of Interface functions & procedures of original CRT unit --- }
 {  }

 procedure OverwriteChrXY(X, Y: Byte; Chr: char);
 var
   Coord: TCoord;
   dwSize, dwCount: DWORD;
 begin
   LastX := X;
   LastY := Y;
   Coord.X := LastX - 1 + ConsoleScreenRect.Left;
   Coord.Y := LastY - 1 + ConsoleScreenRect.Top;
   dwSize := 1;
   FillConsoleOutputAttribute(hConsoleOutput, TextAttr, dwSize, Coord, dwCount);
   FillConsoleOutputCharacter(hConsoleOutput, Chr, dwSize, Coord, dwCount);
   GotoXY(LastX, LastY);
 end;

 {  --------------------------------------------------  }
 {  Console Event Handler }
 {  }
 {$IfDef CRT_EVENT}
 function ConsoleEventProc(CtrlType: DWORD): Bool; stdcall; far;
 var
   S: {$IfDef Win32}ShortString{$Else}String{$EndIf};
   Message: PChar;
 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;
   S := S + ' detected, but not handled.';
   Message := @S;
   Inc(Message);
   MessageBox(0, Message, 'Win32 Console', MB_OK);
   Result := True;
 end;
   {$EndIf}

 function MouseReset: Boolean;
 begin
   MouseColWidth := 1;
   MouseRowWidth := 1;
   Result := True;
 end;

 procedure MouseShowCursor;
 const
   ShowMouseConsoleMode = ENABLE_MOUSE_INPUT;
 var
   cMode: DWORD;
 begin
   GetConsoleMode(hConsoleInput, cMode);
   if (cMode and ShowMouseConsoleMode) <> ShowMouseConsoleMode then
   begin
     cMode := cMode or ShowMouseConsoleMode;
     SetConsoleMode(hConsoleInput, cMode);
   end;
 end;

 procedure MouseHideCursor;
 const
   ShowMouseConsoleMode = ENABLE_MOUSE_INPUT;
 var
   cMode: DWORD;
 begin
   GetConsoleMode(hConsoleInput, cMode);
   if (cMode and ShowMouseConsoleMode) = ShowMouseConsoleMode then
   begin
     cMode := cMode and ($FFFFFFFF xor ShowMouseConsoleMode);
     SetConsoleMode(hConsoleInput, cMode);
   end;
 end;

 function MouseKeyPressed: Boolean;
   {$IfDef MOUSE_IS_USED}
 const
   MouseDeltaTime = 200;
 var
   ActualTime: TDateTime;
   HourA, HourM, MinA, MinM, SecA, SecM, MSecA, MSecM: word;
   MSecTimeA, MSecTimeM: longInt;
   MSecDelta: longInt;
   {$EndIf}
 begin
   MousePressedButtons := 0;
   {$IfDef MOUSE_IS_USED}
   Result := False;
   if MouseButtonPressed then
   begin
     ActualTime := NOW;
     DecodeTime(ActualTime, HourA, MinA, SecA, MSecA);
     DecodeTime(MouseEventTime, HourM, MinM, SecM, MSecM);
     MSecTimeA := (3600 * HourA + 60 * MinA + SecA) * 100 + MSecA;
     MSecTimeM := (3600 * HourM + 60 * MinM + SecM) * 100 + MSecM;
     MSecDelta := Abs(MSecTimeM - MSecTimeA);
     if (MSecDelta < MouseDeltaTime) or (MSecDelta > (8784000 - MouseDeltaTime)) then
     begin
       MousePressedButtons := MouseLeftButton;
       MouseButtonPressed := False;
       Result := True;
     end;
   end;
   {$Else}
   Result := False;
   {$EndIf}
 end;

 procedure MouseGotoXY(X, Y: Integer);
 begin
   {$IfDef MOUSE_IS_USED}
   mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE,
     X - 1,Y - 1,WHEEL_DELTA, GetMessageExtraInfo());
   MousePosY := (Y - 1) * MouseRowWidth;
   MousePosX := (X - 1) * MouseColWidth;
   {$EndIf}
 end;

 function MouseWhereY: Integer;
   {$IfDef MOUSE_IS_USED}
     {Var 
      lppt, lpptBuf: TMouseMovePoint;}
   {$EndIf}
 begin
   {$IfDef MOUSE_IS_USED}
       {GetMouseMovePoints( 
        SizeOf(TMouseMovePoint), lppt, lpptBuf, 
        7,GMMP_USE_DRIVER_POINTS 
      ); 
      Result:=lpptBuf.Y DIV MouseRowWidth;}
   Result := (MousePosY div MouseRowWidth) + 1;
   {$Else}
   Result := -1;
   {$EndIf}
 end;

 function MouseWhereX: Integer;
   {$IfDef MOUSE_IS_USED}
     {Var 
      lppt, lpptBuf: TMouseMovePoint;}
   {$EndIf}
 begin
   {$IfDef MOUSE_IS_USED}
       {GetMouseMovePoints( 
        SizeOf(TMouseMovePoint), lppt, lpptBuf, 
        7,GMMP_USE_DRIVER_POINTS 
      ); 
      Result:=lpptBuf.X DIV MouseColWidth;}
   Result := (MousePosX div MouseColWidth) + 1;
   {$Else}
   Result := -1;
   {$EndIf}
 end;
   {  }

 procedure Init;
 const
   ExtInpConsoleMode = ENABLE_WINDOW_INPUT or ENABLE_PROCESSED_INPUT or ENABLE_MOUSE_INPUT;
   ExtOutConsoleMode = ENABLE_PROCESSED_OUTPUT or ENABLE_WRAP_AT_EOL_OUTPUT;
 var
   cMode: DWORD;
   Coord: TCoord;
   OSVersion: TOSVersionInfo;
   CBI: TConsoleScreenBufferInfo;
 begin
   OSVersion.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
   GetVersionEx(OSVersion);
   if OSVersion.dwPlatformId = VER_PLATFORM_WIN32_NT then
     IsWinNT := True
   else
     IsWinNT := False;
   PtrOpenText := TTextRec(Output).OpenFunc;
   {$IfDef HARD_CRT}
   AllocConsole;
   Reset(Input);
   hConsoleInput := GetStdHandle(STD_INPUT_HANDLE);
   TTextRec(Input).Handle := hConsoleInput;
   ReWrite(Output);
   hConsoleOutput := GetStdHandle(STD_OUTPUT_HANDLE);
   TTextRec(Output).Handle := hConsoleOutput;
   {$Else}
   Reset(Input);
   hConsoleInput := TTextRec(Input).Handle;
   ReWrite(Output);
   hConsoleOutput := TTextRec(Output).Handle;
   {$EndIf}
   GetConsoleMode(hConsoleInput, cMode);
   if (cMode and ExtInpConsoleMode) <> ExtInpConsoleMode then
   begin
     cMode := cMode or ExtInpConsoleMode;
     SetConsoleMode(hConsoleInput, cMode);
   end;

   TTextRec(Output).InOutFunc := @TextOut;
   TTextRec(Output).FlushFunc := @TextOut;
   GetConsoleScreenBufferInfo(hConsoleOutput, CBI);
   GetConsoleMode(hConsoleOutput, cMode);
   if (cMode and ExtOutConsoleMode) <> ExtOutConsoleMode then
   begin
     cMode := cMode or ExtOutConsoleMode;
     SetConsoleMode(hConsoleOutput, cMode);
   end;
   TextAttr  := CBI.wAttributes;
   StartAttr := CBI.wAttributes;
   LastMode  := CBI.wAttributes;

   Coord.X := CBI.srWindow.Left;
   Coord.Y := CBI.srWindow.Top;
   WindMin := (Coord.Y shl 8) or Coord.X;
   Coord.X := CBI.srWindow.Right;
   Coord.Y := CBI.srWindow.Bottom;
   WindMax := (Coord.Y shl 8) or Coord.X;
   ConsoleScreenRect := CBI.srWindow;

   SoundDuration := -1;
   OldCp := GetConsoleOutputCP;
   SetConsoleOutputCP(1250);
   {$IfDef CRT_EVENT}
   SetConsoleCtrlHandler(@ConsoleEventProc, True);
   {$EndIf}
   {$IfDef MOUSE_IS_USED}
   SetCapture(hConsoleInput);
   KeyPressed;
   {$EndIf}
   MouseInstalled := MouseReset;
   Window(1,1,80,25);
   ClrScr;
 end;

 {  }

 procedure Done;
 begin
   {$IfDef CRT_EVENT}
   SetConsoleCtrlHandler(@ConsoleEventProc, False);
   {$EndIf}
   SetConsoleOutputCP(OldCP);
   TextAttr := StartAttr;
   SetConsoleTextAttribute(hConsoleOutput, TextAttr);
   ClrScr;
   FlushInputBuffer;
   {$IfDef HARD_CRT}
   TTextRec(Input).Mode := fmClosed;
   TTextRec(Output).Mode := fmClosed;
   FreeConsole;
   {$Else}
   Close(Input);
   Close(Output);
   {$EndIf}
 end;

 initialization
   Init;

 finalization
   Done;
   {$Endif win32}
 end.





Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook