Board index » delphi » Novice need help doing user interface

Novice need help doing user interface

Hi, I want to do something similar to turbo pascal's editor where you
can use Alt-F and other key combinations to activate the function
menu.
What I can't figure out is how to get back the underlying portion of
screen after the menu closes.
Any help will be greatly appreaciated!

ps: I've heard of turbo vision but i'm not sure how to use it because
i don't know object oriented programming...
All i could find from the net is function reference, but no tutorials
on Turbo vision.

 

Re:Novice need help doing user interface


Quote
Jack wrote:

> Hi, I want to do something similar to turbo pascal's editor where you
> can use Alt-F and other key combinations to activate the function
> menu.
> What I can't figure out is how to get back the underlying portion of
> screen after the menu closes.
> Any help will be greatly appreaciated!

> ps: I've heard of turbo vision but i'm not sure how to use it because
> i don't know object oriented programming...
> All i could find from the net is function reference, but no tutorials
> on Turbo vision.

http://bsn.ch/tp-links
chapter "turbo vision", "manuals", "FAQ"
--
Franz Glaser, Glasau 3, A-4191 Vorderweissenbach Austria +43-7219-7035-0
Muehlviertler Elektronik Glaser.  Industrial control and instrumentation
http://members.eunet.at/meg-glaser/    http://members.xoom.com/f_glaser/
http://www.geocities.com/~franzglaser/            http://start.at/bedarf

Re:Novice need help doing user interface


Hi,

on Sun, 19 Mar 2000 at 02:03:42 o'clock, Jack wrote:

Quote
> What I can't figure out is how to get back the underlying portion of
> screen after the menu closes.

You should write a 'redraw' routine that redraws the entire screen or
portions of it, relying on some internal representation of the windows
or whatever screen elements you use. In other words, you shouldn't draw
to the screen and then forget about it, but instead make all changes
to internal data structures and then call 'redraw'. For better
performance, you might want to include the option to pass rectangle
coordinates to this procedure, so that only a portion of the screen is
redrawn.

Another possibility - rather lowlevel and hardware-dependant - would
be to write directly to the video memory. In this case, you could make
use of double-buffering (this is, however, quite unusual for text-mode
applications).

 - Sebastian

Re:Novice need help doing user interface


Quote
Jack wrote:
> Hi, I want to do something similar to turbo pascal's editor where you
> can use Alt-F and other key combinations to activate the function
> menu.
> What I can't figure out is how to get back the underlying portion of
> screen after the menu closes.

Save the entire screen to a buffer and restore it afterwards:

type
  TScreen = array[0..1999] of word;
var
  screen : TScreen absolute $B800:0;
  scr : TScreen;

Saving the screen is done with move(screen, scr, 4000). Restore it using
move (scr, screen, 4000).

Re:Novice need help doing user interface


JRS:  In article <38D4B8B5.E9311...@mail.dotcom.fr> of Sun, 19 Mar 2000
12:23:33 seen in news:comp.lang.pascal.borland, Frederic Bonroy

Quote
<fbon...@mail.dotcom.fr> wrote:
>Jack wrote:

>> Hi, I want to do something similar to turbo pascal's editor where you
>> can use Alt-F and other key combinations to activate the function
>> menu.
>> What I can't figure out is how to get back the underlying portion of
>> screen after the menu closes.

>Save the entire screen to a buffer and restore it afterwards:

>type
>  TScreen = array[0..1999] of word;
>var
>  screen : TScreen absolute $B800:0;
>  scr : TScreen;

>Saving the screen is done with move(screen, scr, 4000). Restore it using
>move (scr, screen, 4000).

That's simple, and not too slow (I expect) on almost any CPU.  But it is
better not to make unnecessary assumptions.

The screen may not be Page 0, colour, 80*25 characters.

The location of the screen, and its size, can be obtained from Seg0400;
see Ralf Brown's List, and/or TSFAQP #117.

It may be better to save the screen on the heap, especially if nested
saves of larger screens are needed.

On my Win98 machine, I do BP, etc., in a DOS box of size 80*50 - it's
easy to see when a programmer has assumed 80*25.  And my oldest machine
runs in monochrome.

--
? John Stockton, Surrey, UK.  j...@merlyn.demon.co.uk   Turnpike v4.00   MIME. ?
 <URL: http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
 <URL: ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ;
 <URL: http://www.merlyn.demon.co.uk/clpb-faq.txt> Pedt Scragg: c.l.p.b. mFAQ.

Re:Novice need help doing user interface


In article <38D4B8B5.E9311...@mail.dotcom.fr>,
Frederic Bonroy  <fbon...@mail.dotcom.fr> wrote:

Quote

>Save the entire screen to a buffer and restore it afterwards:

>type
>  TScreen = array[0..1999] of word;
>var
>  screen : TScreen absolute $B800:0;
>  scr : TScreen;

>Saving the screen is done with move(screen, scr, 4000). Restore it using
>move (scr, screen, 4000).

That solution works only with 80x25 color screen and in real mode. But
why not use simply scr:=Screen; and Screen:=Scr?

Osmo

Re:Novice need help doing user interface


In article <otc2b8.aa...@bastisoft.de>,

Quote
Sebastian Koppehel <un0...@bastisoft.de> wrote:
>Hi,

>on Sun, 19 Mar 2000 at 02:03:42 o'clock, Jack wrote:

>> What I can't figure out is how to get back the underlying portion of
>> screen after the menu closes.

>You should write a 'redraw' routine that redraws the entire screen or
>portions of it, relying on some internal representation of the windows
>or whatever screen elements you use. In other words, you shouldn't draw
>to the screen and then forget about it, but instead make all changes
>to internal data structures and then call 'redraw'. For better
>performance, you might want to include the option to pass rectangle
>coordinates to this procedure, so that only a portion of the screen is
>redrawn.

It is much simpler to copy the background into a safe place when one
opens the window and restore it when the window closes.

Here is such a unit (use for example MakeWindow, and then RemoveWindow).
This kind of a system works when the windows are operated in a stack
like manner like with menus.

Unit Windows;

Interface

uses Crt,dos;

type Linetype=boolean; { false= single, true=double }

type Tborder=(Top,Bottom,Left,Right);
     Tborderset=set of Tborder;

Procedure MakeWindow(x1,y1,x2,y2:integer);
Procedure RemoveWindow;
Procedure MakeBWindow(x1,y1,x2,y2:integer;b:Tborderset;attr:byte);
Procedure SetTitle(st:string;pos:integer);
Procedure MoveWindow(x,y:integer);
Procedure Window(x1,y1,x2,y2:integer);
Procedure BWindow(x1,y1,x2,y2:integer;b:Tborderset);
Procedure SwapWindows;

Const WindError:boolean=false;

{Const doubleborders:Tborderset=[Top,Bottom,Left,Right];}

type TPage40=record
                 fill1:array[0..$48] of byte;
               Videomode:byte;
               Cols:word;
                 fill2:array[$4c..$83] of byte;
               Rows:byte;
             End;

var Page40:^Tpage40;

Function Rows:word;

Implementation

{$R-}

{$ifdef msdos}
const Seg0040=$40;
      SegB000=$b000;
      segB800=$b800;
{$endif}

Const UL:Array[LineType,LineType] of Char=('?','?');
      UR:Array[LineType,LineType] of Char=('??','?');
      LL:Array[LineType,LineType] of Char=('?','');
      LR:Array[LineType,LineType] of Char=('?','??');
      Hz:Array[LineType] of Char='?';
      Vr:Array[LineType] of Char='3o';

Type ByteArray=Array[1..16000] of byte;
     WindowPtr=^WindRec;
     nextrec=record
                ptr:Windowptr;
                Xcoord,YCoord:byte;     { saved cursor position }
                WinMin,WinMax:word;     { saved windmin and windmax }
                Cursorsize:word;
                attr:word;
             End;

     Windrec=record
               xx1,yy1,xx2,yy2:byte;   { coordinates of this window }
               Next:NextRec;
               Data:ByteArray;
             end;
     screenarr=array[1..8000] of word;

{$f+}
Function HeapFunc(x:word):integer;
Begin
  HeapFunc:=1;
  if x>0 then WindError:=true;
End;
{$f-}

function alloc(x:word):pointer;
var p,heapsave:pointer;
Begin
  heapsave:=heaperror;
  Heaperror:=@heapfunc;
  getmem(p,x);
  heaperror:=heapsave;
  Alloc:=p;
End;

Function Rows:word;
var r:word;
begin
  r:=Page40^.rows;
  if r=0 then r:=25;
  rows:=r+1;
End;

Function GetCursorSize:word;
var regs:registers;
begin
 regs.ah:=3;
 regs.bx:=0;
 intr($10,regs);
 GetCursorSize:=regs.cx;
end;

Procedure SetCursorSize(x:word);
var regs:registers;
begin
 regs.ah:=1;
 regs.bx:=0;
 regs.cx:=x;
 intr($10,regs);
end;

procedure adjust(var x1,y1,x2,y2:integer);
var r,c:integer;
begin
  r:=rows;
  c:=page40^.cols;
  if x1<1 then begin
     inc(x2,1-x1);
     x1:=1;
  End;
  if y1<1 then begin
     inc(y2,1-y1);
     y1:=1;
  End;
  if x2>c then begin
     dec(x1,x2-c);
     x2:=c;
  End;
  if y2>r then begin
     dec(y1,y2-r);
     y2:=r;
  End;
  if x1<1 then x1:=1;
  if y1<1 then y1:=1;
  if x2>c then x2:=c;
  if y2>r then y2:=r;
End;

Procedure Window(x1,y1,x2,y2:integer);
Begin
  if (y2<y2) or (x2<x1) then exit;
  adjust(x1,y1,x2,y2);
  if y2>rows then y2:=rows;
  if x2>page40^.cols then x2:=page40^.cols;
  windmax:=(y2-1)*256+(x2-1);
  windmin:=(y1-1)*256+(x1-1);
  gotoxy(1,1);
End;

Var WindStack:windowptr;

Procedure MakeWindow(x1,y1,x2,y2:integer);
var koko:word;
    screen:^screenarr;
    p:windowptr;
    maara,ind,i:word;
    leveys:word;
    s:word;
Begin
  WindError:=false;
  adjust(x1,y1,x2,y2);
  leveys:=page40^.cols;
  koko:=word(x2-x1+1)*word(y2-y1+1)*2;
  s:=koko+(Sizeof(p^)-sizeof(p^.Data));
  p:=Alloc(s);
  if p=nil then exit;

  with p^ do begin
    xx1:=x1;
    xx2:=x2
    yy1:=y1;
    yy2:=y2;
    next.Xcoord:=Wherex;
    next.Ycoord:=Wherey;
    next.winmin:=Windmin;
    next.winmax:=Windmax;
    next.ptr:=windstack;
    next.attr:=textattr;
    next.cursorsize:=getcursorsize;
  End;
  windstack:=p;
  if page40^.videomode=7 then screen:=ptr(SegB000,0)
                         else screen:=ptr(SegB800,0);
  ind:=1;
  maara:=word(x2-x1+1)*2;
  for i:=y1 to y2 do begin
    Move(screen^[(i-1)*leveys+x1],p^.data[ind],Maara);
    Inc(Ind,Maara);
  End;
  window(x1,y1,x2,y2);
End;

Procedure RemoveWindow;
var koko:word;
    screen:^screenarr;
    p:windowptr;
    maara,ind,i:word;
    leveys:word;
Begin
  leveys:=page40^.cols;
  p:=windstack;
  if p=nil then exit;
  with p^ do begin
    crt.windmin:=next.Winmin;
    crt.windmax:=next.Winmax;
    if page40^.videomode=7 then screen:=ptr(SegB000,0)
                           else screen:=ptr(SegB800,0);
    ind:=1;
    maara:=(xx2-xx1+1)*2;
    for i:=yy1 to yy2 do begin
      Move(data[ind],screen^[(i-1)*Leveys+p^.xx1],Maara);
      Inc(Ind,Maara);
    End;
    gotoxy(next.xcoord,next.ycoord);
    textattr:=next.attr;
    SetCursorsize(next.cursorsize);
    windstack:=next.ptr;
    koko:=word(xx2-xx1+1)*word(yy2-yy1+1)*2;
  end;
  Freemem(p,koko+(Sizeof(p^)-sizeof(p^.Data)));
End;

{$ifdef ver70} {$define new} {$endif}
{$ifdef ver60} {$define new} {$endif}

Procedure MoveWindow(x,y:integer);
var screen:^screenarr;
    leveys,cx,cy,wx1,wy1,wx2,wy2:integer;
    p1,p2:pointer;
    p3:word;
    wwidth,wheight:word;
    dir:integer;
Begin
  if x<1 then x:=1;
  if y<1 then y:=1;

  with page40^ do begin
    leveys:=cols;
    if videomode=7 then screen:=ptr(SegB000,0)
                   else screen:=ptr(SegB800,0);
  End;
  cx:=wherex;
  cy:=wherey;
  with windstack^ do begin
     if x+(xx2-xx1)>leveys then x:=leveys-(xx2-xx1);
     if y+(yy2-yy1)>rows then y:=rows-(yy2-yy1);
     wwidth:=xx2-xx1+1;
     wheight:=yy2-yy1+1;
     wx1:=lo(crt.windmin)-xx1+1;
     wy1:=hi(crt.windmin)-yy1+1;
     wx2:=lo(crt.windmax)-xx1+1;
     wy2:=hi(crt.windmax)-yy1+1;
     if (xx1=x) and (yy1=y) then exit;
     if (y<yy1) or (y=yy1) and (x<xx1)
        then begin
                p1:=@data;
                p2:=@screen^[(y-1)*leveys+x];
                p3:=ofs(screen^[(yy1-1)*leveys+xx1]);
                dir:=2;
             End
             else begin
                p1:=@data[wwidth*wheight*2-1];
                p2:=@screen^[(y+wheight-2)*leveys+x+wwidth-1];
                p3:=ofs(screen^[(yy2-1)*leveys+xx2]);
                leveys:=-leveys;
                dir:=-2;
             End;
      {$ifdef new}
      asm
      push ds
      les di,p1
      lds bx,p2
      mov si,p3
      sub si,bx
      mov cx,wheight

@row:
      push cx
      mov cx,wwidth
      push bx
      push bp
      mov bp,dir
@col:
      mov dx,es:[di]
      mov ax,[bx]
      mov es:[di],ax
      mov ax,[bx+si]
      mov [bx],ax
      mov [bx+si],dx
      add bx,bp
      add di,bp
      dec cx
      jnz @col

      pop bp
      pop bx
      mov ax,leveys
      add ax,ax
      add bx,ax
      pop cx
      dec cx
      jnz @row
      pop ds
      end;
      {$else}
      Inline($1E/$C4/$BE/P1/$C5/$9E/P2/$8B/$B6/P3/$29/$DE/
             $8B/$8E/WHEIGHT/$51/$8B/$8E/WWIDTH/$53/$55/$8B/$AE/DIR/
             $26/$8B/$15/$8B/$07/$26/$89/$05/$8B/$00/$89/$07/$89/$10/
             $01/$EB/$01/$EF/$49/$75/$EB/$5D/$5B/$8B/$86/LEVEYS/$01/$C0/
             $01/$C3/$59/$49/$75/$D2/$1F);
      {$endif}

    dec(xx2,xx1-x);
    dec(yy2,yy1-y);
    xx1:=x;
    yy1:=y;
  End;

  window(x+wx1,y+wy1,x+wx2,y+wy2);
  gotoxy(cx,cy);
End;

Procedure SwapWindows;
var w,ww:word;
    pscr,p1,p2:pointer;  {p1 topwindow, p2: bottomwindow}
    isx1,isx2,isy1,isy2,isw:word;
    screen:^screenarr;
    leveys:word;
    win1,win2:windowptr;
    nr1:nextrec;
    tmp:word;
    nextscr,next1,next2:word;
    t86:byte;

Begin
  {$ifdef new}
  if (windstack=nil) or (windstack^.next.ptr=nil) then exit;

  win1:=windstack;
  win2:=win1^.next.ptr;
  nr1:=win1^.next;

  windstack:=win2;
  win1^.next:=win2^.next;

  with win2^.next do begin
     winmin:=windmin;
     winmax:=windmax;
     xcoord:=wherex;
     ycoord:=wherey;
     ptr:=win1;
  End;

  with windstack^ do begin

    windmin:=nr1.winmin;
    windmax:=nr1.winmax;
    gotoxy(nr1.xcoord,nr1.ycoord);

    if xx2<next.ptr^.xx1 then exit;
    if yy2<next.ptr^.yy1 then exit;
    if xx1>next.ptr^.xx2 then exit;
    if yy1>next.ptr^.yy2  then exit;

    ww:=xx2-xx1+1;
    with next.ptr^ do w:=xx2-xx1+1;

    isx1:=xx1;
    isx2:=xx2;
    isy1:=yy1;
    isy2:=yy2;
    with next.ptr^ do begin
      if xx1>isx1 then isx1:=xx1;
      if xx2<isx2 then isx2:=xx2;
      if yy1>isy1 then isy1:=yy1;
      if yy2<isy2 then isy2:=yy2;
    End;
    isw:=isx2-isx1+1;

    with page40^ do begin
      leveys:=cols;
      if videomode=7 then screen:=ptr(SegB000,0)
                     else screen:=ptr(SegB800,0);
    End;
    pscr:=@screen^[leveys*(isy1-1)+isx1];
    p2:=@data[2*ww*(isy1-yy1)+(isx1-xx1)*2+1];
    with next.ptr^ do p1:=@data[2*w*(isy1-yy1)+(isx1-xx1)*2+1];
    nextscr:=2*(leveys-isw);
    next1:=2*(w-isw);
    next2:=2*(ww-isw);
  End;

  {$ifdef ver70}
   if test8086>=2 then
       asm
       push ds
       les di,pscr
       lds si,p1
       db $0f,$b4,$9e; dw p2   { lfs bx,p2 }
       mov cx,isy2
       sub cx,isy1
       inc cx

@row:  push cx
       mov cx,isw

@col: ...

read more »

Re:Novice need help doing user interface


Quote

>It may be better to save the screen on the heap, especially if nested
>saves of larger screens are needed.

>On my Win98 machine, I do BP, etc., in a DOS box of size 80*50 - it's
>easy to see when a programmer has assumed 80*25.  And my oldest machine
>runs in monochrome.

To the original poster:

My ewindow unit (which is for BP btw) did work with BP before I added
some exception handling unit.
This is a window stack based unit(like in Modula2), not simply something that
saves the screen temporarily.

You could check it out on

www.stack.nl/~marcov/xtdfpc.htm

it is in the xtdfpc archive.

Other Threads