2008. február 4., hétfő
Emulating a console on TForms
Problem/Question/Abstract:
Implementing a console within a windows application without resorting to an external console application.
Answer:
Consoles are usefull for giving a user access to an application's more complex features without cluttering the interface. If you've ever coded a windowed console, you realise the "messiness" of the code involved. This class allows you to forget about all input/output routines with a few lines of code. The console supports most of the input/output routines available in console (dos) applications such as WriteLn, ReadLn, ReadKey, GotoXY and many, many more.
Using it is simple, Create a TConsole variable and pass it the form on witch you want to display the console. The console's default colors will be the same as the form's color and font.color.
Simply place a "with Console do begin end;" block and put all your console application code in it. I've placed an example with a string parser at the end of the article.
There are also some great features:
cutomizable width/height(in characters), borders
easily load and copy displays with CopyContext and SetContext
user can copy text by dragging the mouse over it like mIRC
user can paste into a read or readln input with CTRL+V
form's properties are adjusted on Create and restored on Free
form's event handler are still processed
and there are some quirks:
you cannot create a TConsole on it's form's OnCreate event
if the form has visible components they will hide the console
you cannot close the form while a read/readln is in progress
read/readln only allow up to 250 chars to avoid glitches
extended characters are not supported for input
text copying with the mouse provides no visual feedback
NOTES
GotoXY,GotoEndOfLine,GetX,GetY,GetLastLine,GetChar,GetText(y:byte), and ClearLn all refer to x,y coordinates starting at position 1,1 (like in console applications)
TConsole has not been tested with other fonts. If you want to tinker with different fonts you should set all properties of Canvas.Font (in the Create procedure) and constants CONSOLE_FONT_HEIGHT, CONSOLE_FONT_WIDTH accordingly.
I was unable to code a suitable visual feedback such as highlighting for the auto-text-copying feature. The main problem is the TForm.OnMouseMove event is only called once. Running a loop through the OnMouseDown even did not work either. I could have implemented the loop in a seperate thread but that seems like overkill. Besides, I want all TConsole functions suspended until the mouse is released so the user isn't fumbled by the application changing the displayed text. If anyone knows how mIRC did it, please email me and I'll add it in.
Here is unit Console.pas
(please forgive the broken lines)
unit Console;
interface
uses Forms, Graphics, SysUtils, ExtCtrls, Classes, Controls, ClipBrd;
const
CONSOLE_WIDTH = 70;
CONSOLE_HEIGHT = 25;
CONSOLE_CARET_SPEED = 500;
CONSOLE_OFFSET_X = 5;
CONSOLE_OFFSET_Y = 5;
CONSOLE_FONT_HEIGHT = 14;
CONSOLE_FONT_WIDTH = 7;
type
TConsoleContext = record
Name: string;
Lines: array[0..CONSOLE_HEIGHT - 1] of string[CONSOLE_WIDTH];
PosX, PosY, CaretPosX, CaretPosY: word;
LastKey: char;
ShiftKeys: TShiftState;
KeyPressed: boolean;
ShowCaret: boolean;
end;
PConsoleContext = ^TConsoleContext;
TConsole = class
constructor Create(AForm: TForm);
destructor Destroy; override;
private
Context: PConsoleContext;
Caret: TTimer;
Canvas: TCanvas;
Form: TForm;
Background, Forground: TColor;
StartDragX, StartDragY: word;
PreviousOnPaint: TNotifyEvent;
PreviousOnKeyPress: TKeyPressEvent;
PreviousOnMouseDown, PreviousOnMouseUp: TMouseEvent;
PreviousWidth, PreviousHeight: word;
procedure PaintLine(y: byte);
procedure Refresh(Sender: TObject);
procedure EraseCaret;
procedure PaintCaret;
procedure ToggleCaret(Sender: TObject);
procedure KeyPress(Sender: TObject; var Key: char);
procedure OnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
x, y: Integer);
procedure OnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; x,
y: Integer);
public
procedure CopyContext(var AContext: TConsoleContext);
procedure SetContext(var AContext: TConsoleContext);
procedure Update;
procedure SetColors(FgColor, BgColor: TColor);
procedure GotoXY(x, y: byte);
procedure GotoEndOfLine(y: byte);
function GetX: byte;
function GetY: byte;
function GetLastLine: byte;
function GetChar(x, y: byte): char;
function GetText(y: byte): string;
procedure Clear;
procedure ClearLn(y: byte);
procedure LineFeed;
procedure Write(Str: string);
procedure WriteLn(Str: string);
function ReadKey: char;
function ReadLength(Len: byte): string;
function Read: string;
function ReadLn: string;
function ReadLnLength(Len: byte): string;
end;
implementation
constructor TConsole.Create(AForm: TForm);
begin
Form := AForm;
Canvas := Form.Canvas;
Canvas.Font.Name := 'Courier New';
Canvas.Font.Size := 8;
Canvas.Font.Height := -11;
Canvas.Brush.Color := Form.Color;
Canvas.Font.Color := Form.Font.Color;
Background := Form.Color;
Forground := Form.Font.Color;
PreviousOnPaint := Form.OnPaint;
PreviousOnKeyPress := Form.OnKeyPress;
PreviousOnMouseDown := Form.OnMouseDown;
PreviousOnMouseUp := Form.OnMouseUp;
Form.OnMouseDown := OnMouseDown;
Form.OnMouseUp := OnMouseUp;
GetMem(Context, Sizeof(TConsoleContext));
PreviousWidth := AForm.ClientWidth;
PreviousHeight := AForm.ClientHeight;
Form.ClientWidth := (CONSOLE_OFFSET_X * 2) + (CONSOLE_WIDTH * CONSOLE_FONT_WIDTH);
Form.ClientHeight := (CONSOLE_OFFSET_Y * 2) + (CONSOLE_HEIGHT *
CONSOLE_FONT_HEIGHT);
Form.OnPaint := Refresh;
Caret := TTimer.Create(nil);
with Caret do
begin
Enabled := false;
Interval := CONSOLE_CARET_SPEED;
OnTimer := ToggleCaret;
end;
Context^.ShowCaret := false;
Clear;
end;
destructor TConsole.Destroy;
begin
Caret.Free;
FreeMem(Context);
Form.OnPaint := PreviousOnPaint;
Form.OnKeyPress := PreviousOnKeyPress;
Form.OnMouseDown := PreviousOnMouseDown;
Form.OnMouseUp := PreviousOnMouseUp;
Form.ClientWidth := PreviousWidth;
Form.ClientHeight := PreviousHeight;
inherited;
end;
procedure TConsole.PaintLine(y: byte);
begin
Canvas.FillRect(Rect(CONSOLE_OFFSET_X, CONSOLE_OFFSET_Y + (y *
(CONSOLE_FONT_HEIGHT)), CONSOLE_OFFSET_X + (CONSOLE_WIDTH) * (CONSOLE_FONT_WIDTH),
CONSOLE_OFFSET_Y + (y * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
Canvas.TextOut(CONSOLE_OFFSET_X, CONSOLE_OFFSET_Y + (y * (CONSOLE_FONT_HEIGHT)),
Context^.Lines[y]);
end;
procedure TConsole.Refresh(Sender: TObject);
var
y: byte;
begin
if (CONSOLE_OFFSET_X <> 0) and (CONSOLE_OFFSET_Y <> 0) then
begin
Canvas.FillRect(Rect(0, 0, Canvas.ClipRect.Right, CONSOLE_OFFSET_Y));
Canvas.FillRect(Rect(0, CONSOLE_OFFSET_Y, CONSOLE_OFFSET_X, CONSOLE_OFFSET_Y +
((CONSOLE_HEIGHT - 1) * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
Canvas.FillRect(Rect(0, CONSOLE_OFFSET_Y + ((CONSOLE_HEIGHT - 1) *
(CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT, Canvas.ClipRect.Right,
Canvas.ClipRect.Bottom));
Canvas.FillRect(Rect(CONSOLE_OFFSET_X + (CONSOLE_WIDTH) * (CONSOLE_FONT_WIDTH),
CONSOLE_OFFSET_Y, Canvas.ClipRect.Right, CONSOLE_OFFSET_Y + ((CONSOLE_HEIGHT - 1)
* (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
end;
with Context^ do
for y := 0 to CONSOLE_HEIGHT - 1 do
PaintLine(y);
PaintCaret;
if Assigned(PreviousOnPaint) then
PreviousOnPaint(Sender);
end;
procedure TConsole.EraseCaret;
begin
with Context^ do
if Length(Lines[CaretPosY]) > CaretPosX then
Canvas.TextOut(CONSOLE_OFFSET_X + (CaretPosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (CaretPosY * (CONSOLE_FONT_HEIGHT)), Lines[CaretPosY,
CaretPosX + 1])
else
Canvas.TextOut(CONSOLE_OFFSET_X + (CaretPosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (CaretPosY * (CONSOLE_FONT_HEIGHT)), ' ');
end;
procedure TConsole.PaintCaret;
begin
with Context^ do
begin
if Caret.Enabled = false then
Exit;
if ShowCaret = true then
begin
if (CaretPosX <> PosX) or (CaretPosY <> PosY) then
EraseCaret;
Canvas.Brush.Color := Forground;
Canvas.FillRect(Rect(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)) + 10, CONSOLE_OFFSET_X + (PosX
* (CONSOLE_FONT_WIDTH)) + CONSOLE_FONT_WIDTH, CONSOLE_OFFSET_Y + (PosY *
(CONSOLE_FONT_HEIGHT)) + 13));
Canvas.Brush.Color := Background;
CaretPosX := PosX;
CaretPosY := PosY;
end
else
EraseCaret;
end;
end;
procedure TConsole.ToggleCaret(Sender: TObject);
begin
with Context^ do
ShowCaret := not ShowCaret;
PaintCaret;
end;
procedure TConsole.KeyPress(Sender: TObject; var Key: char);
begin
with Context^ do
begin
LastKey := Key;
KeyPressed := true;
end;
if Assigned(PreviousOnKeyPress) then
PreviousOnKeyPress(Form, Key);
end;
procedure TConsole.OnMouseDown(Sender: TObject; Button: TMouseButton; Shift:
TShiftState; x, y: Integer);
begin
if Button <> mbLeft then
Exit;
StartDragX := (X - CONSOLE_OFFSET_X) div CONSOLE_FONT_WIDTH;
StartDragY := (Y - CONSOLE_OFFSET_Y) div CONSOLE_FONT_HEIGHT;
if StartDragX >= CONSOLE_WIDTH then
StartDragX := CONSOLE_WIDTH - 1;
if StartDragY >= CONSOLE_HEIGHT then
StartDragY := CONSOLE_HEIGHT - 1;
if Assigned(PreviousOnMouseDown) then
PreviousOnMouseDown(Sender, Button, Shift, x, y);
end;
procedure TConsole.OnMouseUp(Sender: TObject; Button: TMouseButton; Shift:
TShiftState; x, y: Integer);
var
EndDragX, EndDragY, Temp: word;
Str: string;
begin
if Button <> mbLeft then
Exit;
EndDragX := (x - CONSOLE_OFFSET_X) div CONSOLE_FONT_WIDTH;
EndDragY := (y - CONSOLE_OFFSET_Y) div CONSOLE_FONT_HEIGHT;
if EndDragX >= CONSOLE_WIDTH then
EndDragX := CONSOLE_WIDTH - 1;
if EndDragY >= CONSOLE_HEIGHT then
EndDragY := CONSOLE_HEIGHT - 1;
if (StartDragX = EndDragX) and (StartDragY = EndDragY) then
Exit;
if EndDragY < StartDragY then
begin
Temp := EndDragX;
EndDragX := StartDragX;
StartDragX := Temp;
Temp := EndDragY;
EndDragY := StartDragY;
StartDragY := Temp;
end
else if (EndDragY = StartDragY) and (EndDragX < StartDragX) then
begin
Temp := EndDragX;
EndDragX := StartDragX;
StartDragX := Temp;
end;
Inc(StartDragX, 1);
Inc(EndDragX, 1);
with Context^ do
begin
if StartDragY = EndDragY then
Str := Copy(Lines[StartDragY], StartDragX, EndDragX - StartDragX + 1)
else
begin
Str := Copy(Lines[StartDragY], StartDragX, CONSOLE_WIDTH - StartDragX);
if EndDragY - StartDragY > 1 then
for y := StartDragY + 1 to EndDragY - 1 do
Str := Str + Lines[y];
Str := Str + Copy(Lines[EndDragY], 1, EndDragX);
end;
end;
ClipBoard.SetTextBuf(PChar(Str));
if Assigned(PreviousOnMouseUp) then
PreviousOnMouseUp(Sender, Button, Shift, x, y);
end;
procedure TConsole.CopyContext(var AContext: TConsoleContext);
begin
Move(Context^, AContext, Sizeof(TConsoleContext));
end;
procedure TConsole.SetContext(var AContext: TConsoleContext);
begin
Move(AContext, Context^, Sizeof(TConsoleContext));
Update;
end;
procedure TConsole.Update;
begin
Refresh(Form);
end;
procedure TConsole.SetColors(FgColor, BgColor: TColor);
begin
Forground := FgColor;
Background := BgColor;
Canvas.Font.Color := FgColor;
Canvas.Brush.Color := BgColor;
Canvas.FillRect(Canvas.ClipRect);
Update;
end;
procedure TConsole.GotoXY(x, y: byte);
begin
with Context^ do
begin
if x > CONSOLE_WIDTH then
x := CONSOLE_WIDTH
else if x = 0 then
Inc(x, 1);
if y > CONSOLE_HEIGHT then
y := CONSOLE_HEIGHT
else if y = 0 then
Inc(y, 1);
PosX := x - 1;
PosY := y - 1;
end;
end;
procedure TConsole.GotoEndOfLine(y: byte);
begin
if y > CONSOLE_HEIGHT then
y := CONSOLE_HEIGHT
else if y = 0 then
Inc(y, 1);
with Context^ do
begin
PosY := y - 1;
PosX := Length(Lines[PosY]);
end;
end;
function TConsole.GetX: byte;
begin
Result := Context^.PosX + 1;
end;
function TConsole.GetY: byte;
begin
Result := Context^.PosY + 1;
end;
function TConsole.GetLastLine: byte;
begin
Result := CONSOLE_HEIGHT;
end;
function TConsole.GetChar(x, y: byte): char;
begin
with Context^ do
begin
if (x > CONSOLE_WIDTH) or (x = 0) or (y > CONSOLE_HEIGHT) or (y = 0) then
Result := #0
else
begin
Dec(y, 1);
if x > Length(Lines[y]) then
Result := ' '
else
Result := Lines[y - 1, x];
end;
end;
end;
function TConsole.GetText(y: byte): string;
begin
if (y > CONSOLE_HEIGHT) or (y = 0) then
Result := ''
else
Result := Context^.Lines[y - 1];
end;
procedure TConsole.Clear;
var
y: byte;
begin
with Context^ do
begin
for y := 0 to CONSOLE_HEIGHT - 1 do
Lines[y] := '';
PosX := 0;
PosY := 0;
KeyPressed := false;
LastKey := #0;
Canvas.FillRect(Rect(0, 0, (CONSOLE_OFFSET_X * 2) + (CONSOLE_FONT_WIDTH *
CONSOLE_WIDTH), (CONSOLE_OFFSET_Y * 2) + (CONSOLE_FONT_HEIGHT * CONSOLE_HEIGHT)));
end;
end;
procedure TConsole.ClearLn(y: byte);
begin
if y > CONSOLE_HEIGHT then
y := CONSOLE_HEIGHT
else if y = 0 then
Inc(y, 1);
Dec(y, 1);
with Context^ do
begin
Canvas.FillRect(Rect(0, CONSOLE_OFFSET_Y + (y * (CONSOLE_FONT_HEIGHT)),
(CONSOLE_OFFSET_X * 2) + (CONSOLE_WIDTH - 1) * (CONSOLE_FONT_WIDTH + 1),
(CONSOLE_OFFSET_Y * 2) + (y * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
Lines[y] := '';
PosX := 0;
PosY := y;
end;
end;
procedure TConsole.LineFeed;
var
y: byte;
begin
with Context^ do
begin
PosX := 0;
if PosY = CONSOLE_HEIGHT - 1 then
begin
for y := 0 to CONSOLE_HEIGHT - 2 do
Lines[y] := Lines[y + 1];
Lines[CONSOLE_HEIGHT - 1] := '';
Update;
end
else
Inc(PosY, 1);
end;
end;
procedure TConsole.Write(Str: string);
var
StrLen, SubPos, SubLen, y, StartPosY: word;
begin
with Context^ do
begin
StartPosY := PosY;
StrLen := Length(Str);
SubPos := 1;
if StrLen + PosX < CONSOLE_WIDTH then
begin
SetLength(Lines[PosY], PosX + StrLen);
Move(Str[1], Lines[PosY, PosX + 1], StrLen);
Inc(PosX, StrLen);
end
else if StrLen + PosX = CONSOLE_WIDTH then
begin
SetLength(Lines[PosY], CONSOLE_WIDTH);
Move(Str[1], Lines[PosY, PosX + 1], StrLen);
LineFeed;
end
else
begin
SubLen := CONSOLE_WIDTH - Length(Lines[PosY]);
repeat
if PosX + 1 + SubLen > Length(Lines[PosY]) then
SetLength(Lines[PosY], PosX + SubLen);
Move(Str[SubPos], Lines[PosY, PosX + 1], SubLen);
Inc(SubPos, SubLen);
if SubPos < StrLen then
begin
LineFeed;
if (StartPosY <> 0) and (PosY = CONSOLE_HEIGHT - 1) then
Dec(StartPosY, 1);
end
else
Inc(PosX, SubLen);
SubLen := StrLen - SubPos + 1;
if SubLen > CONSOLE_WIDTH then
SubLen := CONSOLE_WIDTH;
until ((SubLen + Length(Lines[PosY]) <= CONSOLE_WIDTH) and (SubPos >= StrLen))
or (SubLen = 0);
if SubPos < StrLen then
begin
SetLength(Lines[PosY], PosX + SubLen);
Move(Str[SubPos], Lines[PosY, PosX + 1], SubLen);
Inc(PosX, SubLen);
end;
end;
for y := StartPosY to PosY do
PaintLine(y);
end;
end;
procedure TConsole.WriteLn(Str: string);
begin
Write(Str);
LineFeed;
end;
function TConsole.ReadKey: char;
begin
with Context^ do
begin
KeyPressed := false;
repeat
Application.HandleMessage;
until KeyPressed = true;
Result := LastKey;
end;
end;
function TConsole.ReadLength(Len: byte): string;
var
StartPosX, StartPosY: byte;
ClipBoardStr: array[0..255] of char;
Key: char;
begin
with Context^ do
begin
Form.OnKeyPress := KeyPress;
Caret.Enabled := true;
StartPosX := PosX;
StartPosY := PosY;
Result := '';
repeat
Key := ReadKey;
if Key = #8 then
begin
if PosY > StartPosY then
begin
if PosX > 0 then
begin
Dec(PosX, 1);
SetLength(Lines[PosY], Length(Lines[PosY]) - 1);
SetLength(Result, Length(Result) - 1);
Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), ' ');
end
else
begin
Lines[PosY] := '';
Dec(Posy, 1);
PosX := CONSOLE_WIDTH - 1;
SetLength(Lines[PosY], CONSOLE_WIDTH - 1);
SetLength(Result, Length(Result) - 1);
Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), ' ');
end;
end
else if PosX > StartPosX then
begin
Dec(PosX, 1);
SetLength(Lines[PosY], Length(Lines[PosY]) - 1);
SetLength(Result, Length(Result) - 1);
Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), ' ');
end;
end
else if Key = #22 then
begin
ClipBoard.GetTextBuf(@ClipBoardStr, Len - Length(Result));
Result := Result + StrPas(ClipBoardStr);
Write(StrPas(ClipBoardStr));
end
else if (Key <> #13) and (Length(Result) <= Len) and (Key > #31) and (Key < #127)
then
begin
Result := Result + Key;
Lines[PosY] := Lines[PosY] + Key;
Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), Key);
Inc(PosX, 1);
if PosX = CONSOLE_WIDTH then
begin
if StartPosY <> 0 then
Dec(StartPosY, 1)
else
StartPosX := 0;
LineFeed;
Refresh(Canvas);
end;
end;
PaintCaret;
until Key = #13;
ShowCaret := false;
Caret.Enabled := false;
Form.OnKeyPress := PreviousOnKeyPress;
end;
end;
function TConsole.Read: string;
begin
Result := ReadLength(250);
end;
function TConsole.ReadLn: string;
begin
Result := ReadLength(250);
LineFeed;
end;
function TConsole.ReadLnLength(Len: byte): string;
begin
if Len > 250 then
Len := 250;
Result := ReadLength(Len);
LineFeed;
end;
end. //UNIT CONSOLE.PAS FINISHED
//*************************************************************************
//*************************** EXAMPLE ***************************************
//*************************************************************************
//Call: AConsole:=TConsole.Create(Form1); before calling TForm1.CommandPrompt;
procedure TForm1.CommandPrompt;
var
Command: string;
Parameters: array[0..9] of string;
ParameterCount: byte;
procedure ParseLine(c: string);
var
i: byte;
Param: byte;
Brackets: boolean;
begin
try
Brackets := false;
Param := 0;
for i := 0 to 9 do
Parameters[i] := '';
for i := 1 to Length(c) do
begin
if c[i] = '"' then
begin
Brackets := not Brackets;
if Brackets = false then
Inc(Param, 1);
end
else if Brackets = true then
Parameters[Param] := Parameters[Param] + c[i]
else if (c[i] = ' ') and (c[i - 1] <> ' ') then
begin
Inc(Param, 1);
if Param = 10 then
Exit;
end
else
Parameters[Param] := Parameters[Param] + c[i];
end;
finally
ParameterCount := Param + 1;
Parameters[0] := LowerCase(Parameters[0]);
end;
end;
procedure CommandRun;
begin
with AConsole do
begin
if ParameterCount < 2 then
begin
Writeln('Use: run <path>');
Writeln(' ex: run "c:\program files\myprogram.exe"');
Writeln('');
Exit;
end;
case WinExec(PChar(Parameters[1]), SW_SHOWNORMAL) of
0: Writeln('The system is out of memory or resources.');
ERROR_BAD_FORMAT:
Writeln('The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).');
ERROR_FILE_NOT_FOUND: Writeln('The specified file was not found.');
ERROR_PATH_NOT_FOUND: Writeln('The specified path was not found.');
end;
end;
end;
procedure CommandOpen;
begin
with AConsole do
begin
if ParameterCount < 2 then
begin
Writeln('Use: open <path>');
Writeln(' ex: open "c:\my documents\finance.doc"');
Writeln('');
Exit;
end;
case ShellExecute(Application.Handle, 'open', PChar(Parameters[1]), nil, nil,
SW_NORMAL) of
0: Writeln('The operating system is out of memory or resources.');
ERROR_FILE_NOT_FOUND: Writeln('The specified file was not found.');
ERROR_PATH_NOT_FOUND: Writeln('The specified path was not found.');
ERROR_BAD_FORMAT:
Writeln('The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).');
SE_ERR_ACCESSDENIED:
Writeln('The operating system denied access to the specified file.');
SE_ERR_ASSOCINCOMPLETE:
Writeln('The filename association is incomplete or invalid.');
SE_ERR_DDEBUSY:
Writeln('The DDE transaction could not be completed because other DDE transactions were being processed.');
SE_ERR_DDEFAIL: Writeln('The DDE transaction failed.');
SE_ERR_DDETIMEOUT:
Writeln('The DDE transaction could not be completed because the request timed out.');
SE_ERR_DLLNOTFOUND:
Writeln('The specified dynamic-link library was not found.');
SE_ERR_NOASSOC:
Writeln('There is no application associated with the given filename extension.');
SE_ERR_OOM: Writeln('There was not enough memory to complete the operation.');
SE_ERR_SHARE: Writeln('A sharing violation occurred.');
end;
end;
end;
procedure CommandHelp;
begin
with AConsole do
begin
Writeln('The following commands are available:');
Writeln(' run <path> (starts an application)');
Writeln(' open <path> (opens a file with the associated application)');
Writeln(' help (displays this message)');
Writeln(' exit (ends the console session)');
Writeln('');
end;
end;
begin
with AConsole do
begin
GotoXY(0, GetLastLine);
WriteLn('Welcome to DrMungkee''s demo console.');
WriteLn(' Type ''help'' for a list of available commands.');
repeat
Write('>');
Command := ReadLn;
ParseLine(Command);
if Parameters[0] = 'clear' then
Clear
else if Parameters[0] = 'run' then
CommandRun
else if Parameters[0] = 'open' then
CommandOpen
else if Parameters[0] = 'help' then
CommandHelp
else if Parameters[0] <> 'exit' then
begin
Writeln('Unknow Command (' + Parameters[0] + ')');
end;
until Parameters[0] = 'exit';
AConsole.Free;
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése