Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to emulate a console on TForms Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
30-Jun-03
Category
Others
Language
Delphi 2.x
Views
152
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: DrMungkee XXL

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 
1   (please forgive the broken lines) 
2   
3   unit Console;
4   
5   interface
6   uses Forms, Graphics, SysUtils, ExtCtrls, Classes, Controls, ClipBrd;
7   
8   const
9     CONSOLE_WIDTH = 70;
10    CONSOLE_HEIGHT = 25;
11    CONSOLE_CARET_SPEED = 500;
12    CONSOLE_OFFSET_X = 5;
13    CONSOLE_OFFSET_Y = 5;
14    CONSOLE_FONT_HEIGHT = 14;
15    CONSOLE_FONT_WIDTH = 7;
16  
17  type
18    TConsoleContext = record
19      Name: string;
20      Lines: array[0..CONSOLE_HEIGHT - 1] of string[CONSOLE_WIDTH];
21      PosX, PosY, CaretPosX, CaretPosY: word;
22      LastKey: char;
23      ShiftKeys: TShiftState;
24      KeyPressed: boolean;
25      ShowCaret: boolean;
26    end;
27    PConsoleContext = ^TConsoleContext;
28  
29    TConsole = class
30      constructor Create(AForm: TForm);
31      destructor Destroy; override;
32    private
33      Context: PConsoleContext;
34      Caret: TTimer;
35      Canvas: TCanvas;
36      Form: TForm;
37      Background, Forground: TColor;
38      StartDragX, StartDragY: word;
39      PreviousOnPaint: TNotifyEvent;
40      PreviousOnKeyPress: TKeyPressEvent;
41      PreviousOnMouseDown, PreviousOnMouseUp: TMouseEvent;
42      PreviousWidth, PreviousHeight: word;
43      procedure PaintLine(y: byte);
44      procedure Refresh(Sender: TObject);
45      procedure EraseCaret;
46      procedure PaintCaret;
47      procedure ToggleCaret(Sender: TObject);
48      procedure KeyPress(Sender: TObject; var Key: char);
49      procedure OnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
50        x, y: Integer);
51      procedure OnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; 
52  x,
53        y: Integer);
54    public
55      procedure CopyContext(var AContext: TConsoleContext);
56      procedure SetContext(var AContext: TConsoleContext);
57      procedure Update;
58      procedure SetColors(FgColor, BgColor: TColor);
59      procedure GotoXY(x, y: byte);
60      procedure GotoEndOfLine(y: byte);
61      function GetX: byte;
62      function GetY: byte;
63      function GetLastLine: byte;
64      function GetChar(x, y: byte): char;
65      function GetText(y: byte): string;
66      procedure Clear;
67      procedure ClearLn(y: byte);
68      procedure LineFeed;
69      procedure write(Str: string);
70      procedure WriteLn(Str: string);
71      function ReadKey: char;
72      function ReadLength(Len: byte): string;
73      function read: string;
74      function ReadLn: string;
75      function ReadLnLength(Len: byte): string;
76    end;
77  
78  implementation
79  
80  constructor TConsole.Create(AForm: TForm);
81  begin
82    Form := AForm;
83    Canvas := Form.Canvas;
84    Canvas.Font.Name := 'Courier New';
85    Canvas.Font.Size := 8;
86    Canvas.Font.Height := -11;
87    Canvas.Brush.Color := Form.Color;
88    Canvas.Font.Color := Form.Font.Color;
89  
90    Background := Form.Color;
91    Forground := Form.Font.Color;
92    PreviousOnPaint := Form.OnPaint;
93    PreviousOnKeyPress := Form.OnKeyPress;
94    PreviousOnMouseDown := Form.OnMouseDown;
95    PreviousOnMouseUp := Form.OnMouseUp;
96    Form.OnMouseDown := OnMouseDown;
97    Form.OnMouseUp := OnMouseUp;
98  
99    GetMem(Context, Sizeof(TConsoleContext));
100 
101   PreviousWidth := AForm.ClientWidth;
102   PreviousHeight := AForm.ClientHeight;
103   Form.ClientWidth := (CONSOLE_OFFSET_X * 2) + (CONSOLE_WIDTH * CONSOLE_FONT_WIDTH);
104   Form.ClientHeight := (CONSOLE_OFFSET_Y * 2) + (CONSOLE_HEIGHT *
105     CONSOLE_FONT_HEIGHT);
106   Form.OnPaint := Refresh;
107 
108   Caret := TTimer.Create(nil);
109   with Caret do
110   begin
111     Enabled := false;
112     Interval := CONSOLE_CARET_SPEED;
113     OnTimer := ToggleCaret;
114   end;
115   Context^.ShowCaret := false;
116 
117   Clear;
118 end;
119 
120 destructor TConsole.Destroy;
121 begin
122   Caret.Free;
123   FreeMem(Context);
124   Form.OnPaint := PreviousOnPaint;
125   Form.OnKeyPress := PreviousOnKeyPress;
126   Form.OnMouseDown := PreviousOnMouseDown;
127   Form.OnMouseUp := PreviousOnMouseUp;
128   Form.ClientWidth := PreviousWidth;
129   Form.ClientHeight := PreviousHeight;
130   inherited;
131 end;
132 
133 procedure TConsole.PaintLine(y: byte);
134 begin
135   Canvas.FillRect(Rect(CONSOLE_OFFSET_X, CONSOLE_OFFSET_Y + (y *
136     (CONSOLE_FONT_HEIGHT)), CONSOLE_OFFSET_X + (CONSOLE_WIDTH) * 
137 (CONSOLE_FONT_WIDTH),
138     CONSOLE_OFFSET_Y + (y * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
139   Canvas.TextOut(CONSOLE_OFFSET_X, CONSOLE_OFFSET_Y + (y * (CONSOLE_FONT_HEIGHT)),
140     Context^.Lines[y]);
141 end;
142 
143 procedure TConsole.Refresh(Sender: TObject);
144 var
145   y: byte;
146 begin
147   if (CONSOLE_OFFSET_X <> 0) and (CONSOLE_OFFSET_Y <> 0) then
148   begin
149     Canvas.FillRect(Rect(0, 0, Canvas.ClipRect.Right, CONSOLE_OFFSET_Y));
150     Canvas.FillRect(Rect(0, CONSOLE_OFFSET_Y, CONSOLE_OFFSET_X, CONSOLE_OFFSET_Y +
151       ((CONSOLE_HEIGHT - 1) * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
152     Canvas.FillRect(Rect(0, CONSOLE_OFFSET_Y + ((CONSOLE_HEIGHT - 1) *
153       (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT, Canvas.ClipRect.Right,
154       Canvas.ClipRect.Bottom));
155     Canvas.FillRect(Rect(CONSOLE_OFFSET_X + (CONSOLE_WIDTH) * (CONSOLE_FONT_WIDTH),
156       CONSOLE_OFFSET_Y, Canvas.ClipRect.Right, CONSOLE_OFFSET_Y + ((CONSOLE_HEIGHT 
157 - 1)
158       * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
159   end;
160   with Context^ do
161     for y := 0 to CONSOLE_HEIGHT - 1 do
162       PaintLine(y);
163   PaintCaret;
164   if Assigned(PreviousOnPaint) then
165     PreviousOnPaint(Sender);
166 end;
167 
168 procedure TConsole.EraseCaret;
169 begin
170   with Context^ do
171     if Length(Lines[CaretPosY]) > CaretPosX then
172       Canvas.TextOut(CONSOLE_OFFSET_X + (CaretPosX * (CONSOLE_FONT_WIDTH)),
173         CONSOLE_OFFSET_Y + (CaretPosY * (CONSOLE_FONT_HEIGHT)), Lines[CaretPosY,
174         CaretPosX + 1])
175     else
176       Canvas.TextOut(CONSOLE_OFFSET_X + (CaretPosX * (CONSOLE_FONT_WIDTH)),
177         CONSOLE_OFFSET_Y + (CaretPosY * (CONSOLE_FONT_HEIGHT)), ' ');
178 end;
179 
180 procedure TConsole.PaintCaret;
181 begin
182   with Context^ do
183   begin
184     if Caret.Enabled = false then
185       Exit;
186     if ShowCaret = true then
187     begin
188       if (CaretPosX <> PosX) or (CaretPosY <> PosY) then
189         EraseCaret;
190       Canvas.Brush.Color := Forground;
191       Canvas.FillRect(Rect(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
192         CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)) + 10, CONSOLE_OFFSET_X + 
193 (PosX
194         * (CONSOLE_FONT_WIDTH)) + CONSOLE_FONT_WIDTH, CONSOLE_OFFSET_Y + (PosY *
195         (CONSOLE_FONT_HEIGHT)) + 13));
196       Canvas.Brush.Color := Background;
197       CaretPosX := PosX;
198       CaretPosY := PosY;
199     end
200     else
201       EraseCaret;
202   end;
203 end;
204 
205 procedure TConsole.ToggleCaret(Sender: TObject);
206 begin
207   with Context^ do
208     ShowCaret := not ShowCaret;
209   PaintCaret;
210 end;
211 
212 procedure TConsole.KeyPress(Sender: TObject; var Key: char);
213 begin
214   with Context^ do
215   begin
216     LastKey := Key;
217     KeyPressed := true;
218   end;
219   if Assigned(PreviousOnKeyPress) then
220     PreviousOnKeyPress(Form, Key);
221 end;
222 
223 procedure TConsole.OnMouseDown(Sender: TObject; Button: TMouseButton; Shift:
224   TShiftState; x, y: Integer);
225 begin
226   if Button <> mbLeft then
227     Exit;
228   StartDragX := (X - CONSOLE_OFFSET_X) div CONSOLE_FONT_WIDTH;
229   StartDragY := (Y - CONSOLE_OFFSET_Y) div CONSOLE_FONT_HEIGHT;
230   if StartDragX >= CONSOLE_WIDTH then
231     StartDragX := CONSOLE_WIDTH - 1;
232   if StartDragY >= CONSOLE_HEIGHT then
233     StartDragY := CONSOLE_HEIGHT - 1;
234   if Assigned(PreviousOnMouseDown) then
235     PreviousOnMouseDown(Sender, Button, Shift, x, y);
236 end;
237 
238 procedure TConsole.OnMouseUp(Sender: TObject; Button: TMouseButton; Shift:
239   TShiftState; x, y: Integer);
240 var
241   EndDragX, EndDragY, Temp: word;
242   Str: string;
243 begin
244   if Button <> mbLeft then
245     Exit;
246   EndDragX := (x - CONSOLE_OFFSET_X) div CONSOLE_FONT_WIDTH;
247   EndDragY := (y - CONSOLE_OFFSET_Y) div CONSOLE_FONT_HEIGHT;
248   if EndDragX >= CONSOLE_WIDTH then
249     EndDragX := CONSOLE_WIDTH - 1;
250   if EndDragY >= CONSOLE_HEIGHT then
251     EndDragY := CONSOLE_HEIGHT - 1;
252   if (StartDragX = EndDragX) and (StartDragY = EndDragY) then
253     Exit;
254   if EndDragY < StartDragY then
255   begin
256     Temp := EndDragX;
257     EndDragX := StartDragX;
258     StartDragX := Temp;
259     Temp := EndDragY;
260     EndDragY := StartDragY;
261     StartDragY := Temp;
262   end
263   else if (EndDragY = StartDragY) and (EndDragX < StartDragX) then
264   begin
265     Temp := EndDragX;
266     EndDragX := StartDragX;
267     StartDragX := Temp;
268   end;
269   Inc(StartDragX, 1);
270   Inc(EndDragX, 1);
271 
272   with Context^ do
273   begin
274     if StartDragY = EndDragY then
275       Str := Copy(Lines[StartDragY], StartDragX, EndDragX - StartDragX + 1)
276     else
277     begin
278       Str := Copy(Lines[StartDragY], StartDragX, CONSOLE_WIDTH - StartDragX);
279       if EndDragY - StartDragY > 1 then
280         for y := StartDragY + 1 to EndDragY - 1 do
281           Str := Str + Lines[y];
282       Str := Str + Copy(Lines[EndDragY], 1, EndDragX);
283     end;
284   end;
285   ClipBoard.SetTextBuf(PChar(Str));
286   if Assigned(PreviousOnMouseUp) then
287     PreviousOnMouseUp(Sender, Button, Shift, x, y);
288 end;
289 
290 procedure TConsole.CopyContext(var AContext: TConsoleContext);
291 begin
292   Move(Context^, AContext, Sizeof(TConsoleContext));
293 end;
294 
295 procedure TConsole.SetContext(var AContext: TConsoleContext);
296 begin
297   Move(AContext, Context^, Sizeof(TConsoleContext));
298   Update;
299 end;
300 
301 procedure TConsole.Update;
302 begin
303   Refresh(Form);
304 end;
305 
306 procedure TConsole.SetColors(FgColor, BgColor: TColor);
307 begin
308   Forground := FgColor;
309   Background := BgColor;
310   Canvas.Font.Color := FgColor;
311   Canvas.Brush.Color := BgColor;
312   Canvas.FillRect(Canvas.ClipRect);
313   Update;
314 end;
315 
316 procedure TConsole.GotoXY(x, y: byte);
317 begin
318   with Context^ do
319   begin
320     if x > CONSOLE_WIDTH then
321       x := CONSOLE_WIDTH
322     else if x = 0 then
323       Inc(x, 1);
324     if y > CONSOLE_HEIGHT then
325       y := CONSOLE_HEIGHT
326     else if y = 0 then
327       Inc(y, 1);
328     PosX := x - 1;
329     PosY := y - 1;
330   end;
331 end;
332 
333 procedure TConsole.GotoEndOfLine(y: byte);
334 begin
335   if y > CONSOLE_HEIGHT then
336     y := CONSOLE_HEIGHT
337   else if y = 0 then
338     Inc(y, 1);
339   with Context^ do
340   begin
341     PosY := y - 1;
342     PosX := Length(Lines[PosY]);
343   end;
344 end;
345 
346 function TConsole.GetX: byte;
347 begin
348   Result := Context^.PosX + 1;
349 end;
350 
351 function TConsole.GetY: byte;
352 begin
353   Result := Context^.PosY + 1;
354 end;
355 
356 function TConsole.GetLastLine: byte;
357 begin
358   Result := CONSOLE_HEIGHT;
359 end;
360 
361 function TConsole.GetChar(x, y: byte): char;
362 begin
363   with Context^ do
364   begin
365     if (x > CONSOLE_WIDTH) or (x = 0) or (y > CONSOLE_HEIGHT) or (y = 0) then
366       Result := #0
367     else
368     begin
369       Dec(y, 1);
370       if x > Length(Lines[y]) then
371         Result := ' '
372       else
373         Result := Lines[y - 1, x];
374     end;
375   end;
376 end;
377 
378 function TConsole.GetText(y: byte): string;
379 begin
380   if (y > CONSOLE_HEIGHT) or (y = 0) then
381     Result := ''
382   else
383     Result := Context^.Lines[y - 1];
384 end;
385 
386 procedure TConsole.Clear;
387 var
388   y: byte;
389 begin
390   with Context^ do
391   begin
392     for y := 0 to CONSOLE_HEIGHT - 1 do
393       Lines[y] := '';
394     PosX := 0;
395     PosY := 0;
396     KeyPressed := false;
397     LastKey := #0;
398     Canvas.FillRect(Rect(0, 0, (CONSOLE_OFFSET_X * 2) + (CONSOLE_FONT_WIDTH *
399       CONSOLE_WIDTH), (CONSOLE_OFFSET_Y * 2) + (CONSOLE_FONT_HEIGHT * 
400 CONSOLE_HEIGHT)));
401   end;
402 end;
403 
404 procedure TConsole.ClearLn(y: byte);
405 begin
406   if y > CONSOLE_HEIGHT then
407     y := CONSOLE_HEIGHT
408   else if y = 0 then
409     Inc(y, 1);
410   Dec(y, 1);
411   with Context^ do
412   begin
413     Canvas.FillRect(Rect(0, CONSOLE_OFFSET_Y + (y * (CONSOLE_FONT_HEIGHT)),
414       (CONSOLE_OFFSET_X * 2) + (CONSOLE_WIDTH - 1) * (CONSOLE_FONT_WIDTH + 1),
415       (CONSOLE_OFFSET_Y * 2) + (y * (CONSOLE_FONT_HEIGHT)) + CONSOLE_FONT_HEIGHT));
416     Lines[y] := '';
417     PosX := 0;
418     PosY := y;
419   end;
420 end;
421 
422 procedure TConsole.LineFeed;
423 var
424   y: byte;
425 begin
426   with Context^ do
427   begin
428     PosX := 0;
429     if PosY = CONSOLE_HEIGHT - 1 then
430     begin
431       for y := 0 to CONSOLE_HEIGHT - 2 do
432         Lines[y] := Lines[y + 1];
433       Lines[CONSOLE_HEIGHT - 1] := '';
434       Update;
435     end
436     else
437       Inc(PosY, 1);
438   end;
439 end;
440 
441 procedure TConsole.write(Str: string);
442 var
443   StrLen, SubPos, SubLen, y, StartPosY: word;
444 begin
445   with Context^ do
446   begin
447     StartPosY := PosY;
448     StrLen := Length(Str);
449     SubPos := 1;
450     if StrLen + PosX < CONSOLE_WIDTH then
451     begin
452       SetLength(Lines[PosY], PosX + StrLen);
453       Move(Str[1], Lines[PosY, PosX + 1], StrLen);
454       Inc(PosX, StrLen);
455     end
456     else if StrLen + PosX = CONSOLE_WIDTH then
457     begin
458       SetLength(Lines[PosY], CONSOLE_WIDTH);
459       Move(Str[1], Lines[PosY, PosX + 1], StrLen);
460       LineFeed;
461     end
462     else
463     begin
464       SubLen := CONSOLE_WIDTH - Length(Lines[PosY]);
465       repeat
466         if PosX + 1 + SubLen > Length(Lines[PosY]) then
467           SetLength(Lines[PosY], PosX + SubLen);
468         Move(Str[SubPos], Lines[PosY, PosX + 1], SubLen);
469         Inc(SubPos, SubLen);
470         if SubPos < StrLen then
471         begin
472           LineFeed;
473           if (StartPosY <> 0) and (PosY = CONSOLE_HEIGHT - 1) then
474             Dec(StartPosY, 1);
475         end
476         else
477           Inc(PosX, SubLen);
478         SubLen := StrLen - SubPos + 1;
479         if SubLen > CONSOLE_WIDTH then
480           SubLen := CONSOLE_WIDTH;
481       until ((SubLen + Length(Lines[PosY]) <= CONSOLE_WIDTH) and (SubPos >= StrLen))
482         or (SubLen = 0);
483       if SubPos < StrLen then
484       begin
485         SetLength(Lines[PosY], PosX + SubLen);
486         Move(Str[SubPos], Lines[PosY, PosX + 1], SubLen);
487         Inc(PosX, SubLen);
488       end;
489     end;
490     for y := StartPosY to PosY do
491       PaintLine(y);
492   end;
493 end;
494 
495 procedure TConsole.WriteLn(Str: string);
496 begin
497   write(Str);
498   LineFeed;
499 end;
500 
501 function TConsole.ReadKey: char;
502 begin
503   with Context^ do
504   begin
505     KeyPressed := false;
506     repeat
507       Application.HandleMessage;
508     until KeyPressed = true;
509     Result := LastKey;
510   end;
511 end;
512 
513 function TConsole.ReadLength(Len: byte): string;
514 var
515   StartPosX, StartPosY: byte;
516   ClipBoardStr: array[0..255] of char;
517   Key: char;
518 begin
519   with Context^ do
520   begin
521     Form.OnKeyPress := KeyPress;
522     Caret.Enabled := true;
523     StartPosX := PosX;
524     StartPosY := PosY;
525     Result := '';
526     repeat
527       Key := ReadKey;
528       if Key = #8 then
529       begin
530         if PosY > StartPosY then
531         begin
532           if PosX > 0 then
533           begin
534             Dec(PosX, 1);
535             SetLength(Lines[PosY], Length(Lines[PosY]) - 1);
536             SetLength(Result, Length(Result) - 1);
537             Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
538               CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), ' ');
539           end
540           else
541           begin
542             Lines[PosY] := '';
543             Dec(Posy, 1);
544             PosX := CONSOLE_WIDTH - 1;
545             SetLength(Lines[PosY], CONSOLE_WIDTH - 1);
546             SetLength(Result, Length(Result) - 1);
547             Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
548               CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), ' ');
549           end;
550         end
551         else if PosX > StartPosX then
552         begin
553           Dec(PosX, 1);
554           SetLength(Lines[PosY], Length(Lines[PosY]) - 1);
555           SetLength(Result, Length(Result) - 1);
556           Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
557             CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), ' ');
558         end;
559       end
560       else if Key = #22 then
561       begin
562         ClipBoard.GetTextBuf(@ClipBoardStr, Len - Length(Result));
563         Result := Result + StrPas(ClipBoardStr);
564         write(StrPas(ClipBoardStr));
565       end
566       else if (Key <> #13) and (Length(Result) <= Len) and (Key > #31) and (Key < 
567 #127)
568         then
569       begin
570         Result := Result + Key;
571         Lines[PosY] := Lines[PosY] + Key;
572         Canvas.TextOut(CONSOLE_OFFSET_X + (PosX * (CONSOLE_FONT_WIDTH)),
573           CONSOLE_OFFSET_Y + (PosY * (CONSOLE_FONT_HEIGHT)), Key);
574         Inc(PosX, 1);
575         if PosX = CONSOLE_WIDTH then
576         begin
577           if StartPosY <> 0 then
578             Dec(StartPosY, 1)
579           else
580             StartPosX := 0;
581           LineFeed;
582           Refresh(Canvas);
583         end;
584       end;
585       PaintCaret;
586     until Key = #13;
587     ShowCaret := false;
588     Caret.Enabled := false;
589     Form.OnKeyPress := PreviousOnKeyPress;
590   end;
591 end;
592 
593 function TConsole.read: string;
594 begin
595   Result := ReadLength(250);
596 end;
597 
598 function TConsole.ReadLn: string;
599 begin
600   Result := ReadLength(250);
601   LineFeed;
602 end;
603 
604 function TConsole.ReadLnLength(Len: byte): string;
605 begin
606   if Len > 250 then
607     Len := 250;
608   Result := ReadLength(Len);
609   LineFeed;
610 end;
611 
612 end. //UNIT CONSOLE.PAS FINISHED
613 
614 //*************************************************************************
615 //*************************** EXAMPLE ***************************************
616 //*************************************************************************
617 
618 //Call: AConsole:=TConsole.Create(Form1); before calling TForm1.CommandPrompt;
619 
620 procedure TForm1.CommandPrompt;
621 var
622   Command: string;
623   Parameters: array[0..9] of string;
624   ParameterCount: byte;
625 
626   procedure ParseLine(c: string);
627   var
628     i: byte;
629     Param: byte;
630     Brackets: boolean;
631   begin
632     try
633       Brackets := false;
634       Param := 0;
635       for i := 0 to 9 do
636         Parameters[i] := '';
637       for i := 1 to Length(c) do
638       begin
639         if c[i] = '"' then
640         begin
641           Brackets := not Brackets;
642           if Brackets = false then
643             Inc(Param, 1);
644         end
645         else if Brackets = true then
646           Parameters[Param] := Parameters[Param] + c[i]
647         else if (c[i] = ' ') and (c[i - 1] <> ' ') then
648         begin
649           Inc(Param, 1);
650           if Param = 10 then
651             Exit;
652         end
653         else
654           Parameters[Param] := Parameters[Param] + c[i];
655       end;
656     finally
657       ParameterCount := Param + 1;
658       Parameters[0] := LowerCase(Parameters[0]);
659     end;
660   end;
661 
662   procedure CommandRun;
663   begin
664     with AConsole do
665     begin
666       if ParameterCount < 2 then
667       begin
668         Writeln('Use: run <path>');
669         Writeln('   ex: run "c:\program files\myprogram.exe"');
670         Writeln('');
671         Exit;
672       end;
673       case WinExec(PChar(Parameters[1]), SW_SHOWNORMAL) of
674         0: Writeln('The system is out of memory or resources.');
675         ERROR_BAD_FORMAT:
676           Writeln('The .EXE file is invalid (non-Win32 .EXE or error in .EXE 
677 image).'
678         ERROR_FILE_NOT_FOUND: Writeln('The specified file was not found.');
679         ERROR_PATH_NOT_FOUND: Writeln('The specified path was not found.');
680       end;
681     end;
682   end;
683 
684   procedure CommandOpen;
685   begin
686     with AConsole do
687     begin
688       if ParameterCount < 2 then
689       begin
690         Writeln('Use: open <path>');
691         Writeln('   ex: open "c:\my documents\finance.doc"');
692         Writeln('');
693         Exit;
694       end;
695       case ShellExecute(Application.Handle, 'open', PChar(Parameters[1]), nil, nil,
696         SW_NORMAL) of
697         0: Writeln('The operating system is out of memory or resources.');
698         ERROR_FILE_NOT_FOUND: Writeln('The specified file was not found.');
699         ERROR_PATH_NOT_FOUND: Writeln('The specified path was not found.');
700         ERROR_BAD_FORMAT:
701           Writeln('The .EXE file is invalid (non-Win32 .EXE or error in .EXE 
702 image).'
703         SE_ERR_ACCESSDENIED:
704           Writeln('The operating system denied access to the specified file.');
705         SE_ERR_ASSOCINCOMPLETE:
706           Writeln('The filename association is incomplete or invalid.');
707         SE_ERR_DDEBUSY:
708           Writeln('The DDE transaction could not be completed because other DDE 
709 transactions were being processed.'
710         SE_ERR_DDEFAIL: Writeln('The DDE transaction failed.');
711         SE_ERR_DDETIMEOUT:
712           Writeln('The DDE transaction could not be completed because the request 
713 timed out.'
714         SE_ERR_DLLNOTFOUND:
715           Writeln('The specified dynamic-link library was not found.');
716         SE_ERR_NOASSOC:
717           Writeln('There is no application associated with the given filename 
718 extension.'
719         SE_ERR_OOM: Writeln('There was not enough memory to complete the 
720 operation.'
721         SE_ERR_SHARE: Writeln('A sharing violation occurred.');
722       end;
723     end;
724   end;
725 
726   procedure CommandHelp;
727   begin
728     with AConsole do
729     begin
730       Writeln('The following commands are available:');
731       Writeln('   run <path>     (starts an application)');
732       Writeln('   open <path>    (opens a file with the associated application)');
733       Writeln('   help           (displays this message)');
734       Writeln('   exit           (ends the console session)');
735       Writeln('');
736     end;
737   end;
738 
739 begin
740   with AConsole do
741   begin
742     GotoXY(0, GetLastLine);
743     WriteLn('Welcome to DrMungkee''s demo console.');
744     WriteLn('   Type ''help'' for a list of available commands.');
745     repeat
746       write('>');
747       Command := ReadLn;
748       ParseLine(Command);
749       if Parameters[0] = 'clear' then
750         Clear
751       else if Parameters[0] = 'run' then
752         CommandRun
753       else if Parameters[0] = 'open' then
754         CommandOpen
755       else if Parameters[0] = 'help' then
756         CommandHelp
757       else if Parameters[0] <> 'exit' then
758       begin
759         Writeln('Unknow Command (' + Parameters[0] + ')');
760       end;
761     until Parameters[0] = 'exit';
762     AConsole.Free;
763   end;
764 end;


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC