home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / TVGRAPH.ZIP / TVGDEMO1.PAS < prev    next >
Pascal/Delphi Source File  |  1994-01-04  |  57KB  |  1,684 lines

  1. {***************************************}
  2. {                                       }
  3. {     TVGraphic Library Demo1           }
  4. {                                       }
  5. {        COPYRIGHT (C) 1993,1994        }
  6. {        RICHARD P. ANDRESEN            }
  7. {                                       }
  8. {***************************************}
  9.  
  10. {This demo program provides source code that illustrates the
  11.  use of the TVGraphic library. It is part of the documentation
  12.  of TVGraphic.
  13.  Things to Study:
  14.    Both very simple and complex commented Draw methods.
  15.    TDemoApp.GetEvent to see how to generate evTimerTick events.
  16.      Also how to modify/respond
  17.      to events no matter what view is modal.
  18.    The process of initializing and shutting down a TVGraphic
  19.      application is completely shown.
  20.    Setting up Menu, StatusLine, MessageBar and DeskTop.
  21.    Saving the DeskTop
  22.      Note: The code used here to reload the DeskTop from disk is not
  23.      safe in Borland's Turbo Vision. View by View LowMemory checking
  24.      in TVGraphic's TGroup.Load makes it safe here.
  25.    DOS shell and critical error handling in graphic mode are illustrated.
  26.    Examples of setting the mouse cursor grid.
  27.    Examples of using evTimerTick event.
  28.    Setting up TScroller for text and/or graphics.
  29.    Loading a .BMP bitmap file.
  30.    Building a ToolBar.
  31.    The Help window now is non-modal (acts like a regular window) if called
  32.      while the Application is modal, otherwise Help is modal.
  33.    Examples of running Dialogs using both DeskTop^.ExecView() from TV1.0
  34.      and ExecuteDialog() as used in TV2.0 are shown.
  35.    Example of how to set up and use TVGraphic's TPanWindow with TSubWindows.
  36.  
  37. Users of TVGraphic may incorporate sections of this source code
  38. into their own programs.
  39.  
  40. ----------------------------------
  41. Significant changes in TVDemo1 (ver 1.5) from earlier TVGraphic versions.
  42. 1. TCircles.HandleEvent changed so it doesn't overwrite menus
  43.      and other modal views.
  44. 2. Help window
  45.      now both modal and non-modal
  46.      added menu redraw if Help is modal
  47. 3. TScroller
  48.      show how to change scroller step sizes
  49.      better description in complex TScroller.Draw
  50.      example of incremental background drawing
  51.      example of writing highlighted strings with WriteCStr
  52. 4. Bitmaps
  53.      load and draw .BMP file in TDemoApp.LoadBMP .
  54.      Bitmapped buttons and Toolbar - see InitToolBar.
  55. 5. note on forcing screen to color mode in TDemoApp.Init .
  56. 6. Mouse cursor
  57.    let you set speed. Restore settings after DOS shell.
  58. 7. TDemoApp.GetEvent
  59.    A. evTimerTick events are now generated and sent to all views
  60.       automatically in TProgram.GetEvent. The code that generated them
  61.       in earlier versions should be commented out.
  62.    B. the updating of the mouse cursor position has been moved to
  63.       TProgram.GetEvent. The call in earlier versions to
  64.       MCur.Move(Event.Where) should be deleted.
  65. }
  66.  
  67. program TVGDemo1;
  68.  
  69. {$F+,X+}    {+X - use Extended syntax so can call a function as if
  70.                   it were a procedure.}
  71.  
  72. uses CRT, DOS, Memory, MyGraph3, GObjects, GDrivers,
  73.      MCursor2, GMENU6,
  74.      GViews,  GDialogs, GMsgBox, GStdDlg,
  75.      GApp, GColors, GWindow,
  76.      BMPDrvr, GBut;
  77.  
  78. {causes compiler to link in Bitmap to this unit}
  79. procedure BAR1_BMP; external;
  80. {$L BAR1.OBJ}
  81. procedure BAR2_BMP; external;
  82. {$L BAR2.OBJ}
  83. procedure BAR3_BMP; external;
  84. {$L BAR3.OBJ}
  85. procedure BAR4_BMP; external;
  86. {$L BAR4.OBJ}
  87. procedure BAR7_BMP; external;
  88. {$L BAR7.OBJ}
  89. procedure BAR8_BMP; external;
  90. {$L BAR8.OBJ}
  91.  
  92.  
  93. const
  94.   ProgName = 'TVGDemo1';
  95.   Ver      = '1.50';
  96.  
  97. const
  98.   dpTV1Dialog = 3;
  99.   WinNum : integer = 0;
  100.   hcMouseGrid   = 1000;
  101.   hcColorSel    = 1001;
  102.   cmBMPlikebuttons   = 254;
  103.   cmTVlikeButtons    = 255;
  104.   cmSetColors        = 1100;
  105.   cmDosCriticalError = 1101;
  106.   cmCircleWindow     = 1102;
  107.   cmScrollerWindow   = 1103;
  108.   cmShowMessageBar   = 1104;
  109.   cmAbout            = 1105;
  110.   cmOptionsSave      = 1106;
  111.   cmOptionsLoad      = 1107;
  112.   cmTools            = 1108;
  113.   cmBMP              = 1109;
  114.   cmBitBut           = 1110;
  115.   cmTEdit            = 1111;
  116.   cmHourGlass        = 1112;
  117.   cmDeskTopStyle     = 1114;
  118.   cmDeskTopOptions   = 1115;
  119.   cmVersion          = 1116;
  120.   cmMouseGrids       = 1117;
  121.  
  122.   AString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  123.  
  124. var
  125.   OldExitProc : Pointer;  { Saves exit procedure address }
  126.   Graphic  : boolean;     { true if screen is in graphic mode }
  127.  
  128.  
  129. procedure GExitProc; far;     {must be Far}
  130.   {Exit procedure - restore screen to text mode if program halts}
  131. begin
  132.   ExitProc := OldExitProc; { Restore exit procedure address }
  133.   CloseGraph;              { Shut down the graphics system }
  134. end;
  135.  
  136.  
  137. function GSystemError(ErrorCode: integer; Drive: byte): Integer; far;
  138.                                                         {must be Far}
  139.   {GSystemError handles DOS Critical Errors while in graphics mode.
  140.        Not an example of drawing Views in TVGraphics
  141.        - see .Draw methods instead for that.
  142.    Note the saving and restoring of the Viewport (vital). Also of
  143.    TextSettings which may not be necessary in every program.}
  144.    {Caution - BOMBS unless you use FarSelectKey to get user input.}
  145. const
  146.   SRetryOrCancel:  string[30] = '~Enter~: Retry  ~Esc~: Cancel';
  147. var
  148.   P: Pointer;
  149.   S: string[63];
  150.   X,YOff : integer;
  151.   SS : string;
  152.   VPort : ViewPortType;
  153.   SaveText : TextSettingsType;
  154. begin
  155.   P := Pointer(Drive + Ord('A'));
  156.   FormatStr(S, GetCritErrorStr(ErrorCode), P);
  157.   SS := S + '      ' + SRetryOrCancel;
  158.   X := (GetMaxX - (Length(SS))*Charlen) div 2;
  159.  
  160.   GetViewSettings(VPort);                  {save current viewport}
  161.   SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn); {set to full screen}
  162.  
  163.   GetTextSettings(SaveText);                 {save current font, style}
  164.   SetTextStyle(font8x8,HorizDir,1);
  165.   YOff := CalcVertTextOffset(MenuBar^.Size.y);
  166.  
  167.   SetColor(lightcyan);
  168.   SetFillStyle(solidfill, red);
  169.       {draw over menu bar so can erase by calling MenuBar^.Draw}
  170.   Bar3d(0, 0, GetMaxX, MenuBar^.Size.y, 0, false);
  171.   WriteCStrXY(X, YOff, SS, white, yellow);
  172.   SetColor(white);
  173.   OutTextXY(Charlen,YOff, Chr($10));
  174.   OutTextXY(GetMaxX-2*Charlen,YOff, Chr($11));
  175.  
  176.   GSystemError := FarSelectKey;        {get retry/cancel user input}
  177.   MenuBar^.Draw;                        {erase error message}
  178.  
  179.   with SaveText do
  180.     SetTextStyle(Font, Direction, CharSize);
  181.   with VPort do
  182.     SetViewPort(X1, Y1, X2, Y2, Clip);
  183. end;
  184.  
  185.  
  186. {------ Heap View object ----------}
  187. {displays available heap space, updates using timer tick}
  188.  
  189. type
  190.   PHeapView = ^THeapView;
  191.   THeapView = object(TView)
  192.     OldMem : LongInt;
  193.     constructor Init(var Bounds: TRect);
  194.     procedure Draw; virtual;
  195.     procedure HandleEvent(var Event : TEvent); virtual;
  196.   end;
  197.  
  198. constructor THeapView.Init(var Bounds: TRect);
  199. begin
  200.   TView.Init(Bounds);
  201.   OldMem := 0;
  202.   EventMask := evTimerTick;
  203.   VFont := font8x8;
  204. end;
  205.  
  206. procedure THeapView.Draw;
  207.   {Because the HeapView is outside of the default viewport in this
  208.    program, the viewport is changed and restored in this Draw routine.}
  209. var
  210.   S: string;
  211.   C: word;
  212.   VPort : ViewPortType;
  213.   YOff : integer;
  214.   Glob : TRect;
  215. begin
  216.   MCur.Hide;                                       {hide mouse cursor}
  217.   GetViewSettings(VPort);                          {save current viewport}
  218.  
  219.   GetScreenCoords(Glob);      {set viewport to outline of this view}
  220.   SetViewPort(Glob.A.x, Glob.A.y, Glob.B.x, Glob.B.y,ClipOn);
  221.  
  222.   GetVPRelCoords(Glob);       {get view outline in viewport relative coords}
  223.  
  224.   OldMem := MemAvail;
  225.   Str(OldMem, S);
  226.   C := GetColor(2);           {get normal menu text color pair from palette}
  227.  
  228.   SetColor(ForeColor(C));                      {set text color}
  229.   SetFillStyle(solidfill,BackColor(C));        {set background color}
  230.   Bar(Glob.A.x, Glob.A.y, Glob.B.x, Glob.B.y); {draw background}
  231.  
  232.   S := 'HEAP: ' + S;
  233.   SetTextStyle(VFont,HorizDir,1);                  {set text font}
  234.     {must set font Before calling CalcVertTextOffset}
  235.   YOff := CalcVertTextOffset(Size.y); {center text vertically in view}
  236.  
  237.   OutTextXY(Glob.A.x+BXOffset,Glob.A.y+YOff,S);    {write text}
  238.  
  239.   with VPort do                                    {restore viewport}
  240.     SetViewPort(X1, Y1, X2, Y2, Clip);
  241.   MCur.Show;                                       {show mouse cursor}
  242. end;
  243.  
  244. procedure THeapView.HandleEvent(var Event : TEvent);
  245. begin
  246.   if (Event.What = evTimerTick) and (OldMem <> MemAvail) then DrawView;
  247. end;
  248.  
  249. {-----------------------------------}
  250. const
  251.   SArraySize = 34;
  252.   SArray : array[0..SArraySize] of Str80 = (
  253.     '',
  254.     '         TVGraphic is a compiled library',
  255.     'written in Borland''s Turbo Vision and extending it',
  256.     'into DOS graphic mode by using the EGA/VGA driver.',
  257.     'TVGraphic requires Turbo Vision and the Graph unit.',
  258.     '',
  259.     'Currently based on TV 1.0, it includes fixes and',
  260.     'many upgrades from TV 2.0 plus other enhancements',
  261.     'aimed at pure graphics applications.',
  262.     '',
  263.     'A new partial screen redraw mechanism provides',
  264.     'automatic sizing of the viewport and the Clip variable.',
  265.     '',
  266.     'TView methods are included that calculate the',
  267.     'global coordinates needed for graphic drawing calls.',
  268.     '',
  269.     'Two FAST, clippable bit mapped fonts are included.',
  270.     'Optional user settable grid for mouse cursor.',
  271.     'Hooks are present for user modifications.',
  272.     '',
  273.     'A Window (or any TGroup descendent) may have an',
  274.     'interior larger than the screen which contains',
  275.     'SubWindows and TView descendants.',
  276.     '',
  277.     'Units are available for Pascal versions 6 and 7.',
  278.     'Full TV2.0 functionality, more links to the visual',
  279.     'design tool, Protected mode and VESA 800x600 are',
  280.     'likely for 1994.',
  281.     '',
  282.     'For information, comments, wish items, bugs, etc.',
  283.     '       or software consulting/development',
  284.     '',
  285.     '   Richard P Andresen     CompuServe# 71222,1200',
  286.     '   RR2 Box 900',
  287.     '   Hinesburg,Vermont 05461');
  288.  
  289.  
  290. const
  291.   TestStr : string =
  292.     'A GOOD LONG PIECE OF LENGTHY, MONOTONOUS, BORING, REPETITIVE TEXT.';
  293.  
  294. type
  295.   {A basic text oriented scrolling view with graphics too}
  296.  
  297.   PMyScroller = ^TMyScroller;
  298.   TMyScroller = object (TScroller)
  299.     constructor Init(var Bounds: TRect;
  300.                          AHScrollBar,AVScrollBar: PScrollBar);
  301.     procedure Draw; virtual;
  302.     procedure PartOfSetLimit(X, Y: Integer); virtual; {new with version 1.5}
  303.   end;
  304.  
  305. const     {change constants here to set TMyScroller step sizes}
  306.           {also see discussion of changing vertical text offset in .Draw}
  307.   HSpacing = Charlen;
  308.   VSpacing = Boxheight;
  309.  
  310. constructor TMyScroller.Init(var Bounds: TRect;
  311.                                  AHScrollBar, AVScrollBar: PScrollBar);
  312. begin
  313.   TScroller.Init(Bounds, AHScrollBar, AVScrollBar);
  314.   GrowMode := gfGrowHiX + gfGrowHiY;
  315.   SetLimit((3*Size.x div 2) div HSpacing, 2*Size.y div VSpacing);
  316. end;
  317.  
  318. procedure TMyScroller.Draw;
  319. const
  320.   Triangle: array[1..4] of TPoint = ((X: 200; Y: 70), (X: 400; Y:70),
  321.    (X: 300; Y: 170), (X:  200; Y: 70));
  322. var
  323.   VPort : ViewPortType;
  324.   R,C : TRect;
  325.   HColor,Color,I,Err : integer;
  326.   Glob : TRect;
  327. begin
  328.   MCur.Hide;                       {hide mouse cursor}
  329.   GetViewSettings(VPort);          {save current viewport settings}
  330.   Move(VPort,C, Sizeof(C));        {copy viewport outline to C}
  331.   GetScreenCoords(R);              {get outline of this view in screen coords}
  332.   R.Intersect(C);        {find outline of view contained within the viewport}
  333.                          {reset viewport to clip at this outline}
  334.      {Note that the viewport's size is set automatically by TVGraphic
  335.       whenever it redraws only a portion of the screen (a common occurance).
  336.       Thus the viewport may be larger than, smaller than
  337.       or cover only a part of this view when this Draw is called.
  338.  
  339.       General discussion:
  340.       BECAUSE SCROLLERS HAVE A DRAWABLE INTERIOR LARGER THEN
  341.       THEIR SIZE, we must prevent drawing outside the View. If we drew
  342.       only text, we could alter the text strings that show to just fit
  343.       in the size of the window and not draw the rest. This is how
  344.       Turbo Vision works.
  345.       But since we are also drawing diagonal lines, not just text, and the
  346.       view and the viewport can be any size, we will limit drawing by
  347.       resetting the viewport for the duration of this Draw method.
  348.       To do this, we re-size (shrink) the viewport to match the rectangle
  349.       of this View that falls within the current viewport (as shown above).
  350.  
  351.       VITAL - Because there may be other views to redraw, ALWAYS restore
  352.       a re-sized viewport to the values saved in VPort at the end of
  353.       a .Draw !! }
  354.  
  355.       {Debugging note: When calling a view's Draw via it's DrawView method,
  356.        DrawView first checks the view's Exposed function. Exposed will
  357.        prevent Draw from being called if no part of the view overlaps
  358.        the Clip variable.
  359.        At the start of a partial redraw, the viewport is set to match
  360.        (cover) the Clip area.}
  361.  
  362.   SetViewPort(R.A.x,R.A.y,R.B.x,R.B.y,ClipOn);
  363.  
  364.   GetVPRelCoords(Glob);   {get view's outline in Viewport Relative coords}
  365.                           {Must call after setting viewport!}
  366.  
  367.   Color := GetColor(1);   {call palette for normal text color}
  368.                           {note that GetColor returns both foreground
  369.                            and background colors in single word}
  370.               {color for text       - use ForeColor for foreground color}
  371.               {color for background - use BackColor}
  372.   HColor := GetColor(2);  {call palette for Highlight text color}
  373.  
  374.   SetFillStyle(solidfill,BackColor(Color));
  375.   Bar(Glob.A.x,Glob.A.y,Glob.B.x,Glob.B.y);   {draw background}
  376.  
  377.   SetColor(ForeColor(Color));
  378.   SetTextStyle(font8x14,HorizDir,1);
  379.  
  380.      {draw scrolling text using scroller offset "Delta"}
  381.    {Note: we are assuming text is HSpacing wide by VSpacing tall.
  382.     These are the scroll step sizes this scroller was set to with
  383.     these constants in TMyScroller.PartOfSetLimit.}
  384.  
  385.   {kludge for demo program - text varies with window title}
  386. if PWindow(Owner)^.Title^[1] <> 'A' then begin
  387.   SetTextStyle(font8x14,HorizDir,1);
  388.   OutTextXY(Glob.A.x+HSpacing - (Delta.x*HSpacing),
  389.             Glob.A.y + (10-Delta.y)*VSpacing, TestStr);
  390.  
  391.    {Draw some text that doesn't move as view scrolls}
  392.   SetTextStyle(font8x8,HorizDir,1);
  393.      {Can write text the usual way}
  394. (*  OutTextXY(Glob.A.x,Glob.A.y+200,'This line doesn''t scroll.');*)
  395.      {or write strings with imbedded highlights using the ~ delimiter.}
  396.   WriteCStrXY(Glob.A.x, Glob.A.y+200, 'This line ~doesn''t~ scroll.',
  397.                  ForeColor(Color), ForeColor(HColor));
  398.  
  399.   {Now for something Graphic:
  400.    Note that since we have set TScroller up as a text scroller, we
  401.    have to multiply Delta.x by HSpacing and Delta.y by VSpacing to
  402.    get graphic coords.
  403.    By changing the constants used in PartOfSetLimits and in the SetLimit
  404.    call in Init, and using these same constants in this Draw method,
  405.    you can get any scroll step size you want.
  406.  
  407.    For a scroller of your own that is single pixel oriented
  408.    (rather than text spacing), you don't need to override
  409.    TScroller.PartOfSetLimit. You will probably want to set
  410.    GrowMode the same as in TMyScroller.Init.
  411.  
  412.    Related subject:
  413.    TVGraphic's TView.VOffset field can be used in any view similarly
  414.    to how Delta is used by TScroller to offset/scroll the interior.
  415.    GetVPRelCoords automatically includes all VOffset's in its calculation.
  416.    TVGraphic expects VOffset to be maintained in pixel units.
  417.    TVGraphic's TPanWindow is an example of this. It does not have a
  418.    separate scroller view. This allows drawing to go all the way
  419.    to window edges.}
  420.  
  421.   SetColor(red);
  422.   for I := 1 to 3 do    {lines scroll since using Delta}
  423.     Line(Glob.A.x+Triangle[I].x-(Delta.x*HSpacing),Glob.A.y+Triangle[I].y-(Delta.y*VSpacing),
  424.       Glob.A.x+Triangle[I+1].x-(Delta.x*HSpacing),Glob.A.y+Triangle[I+1].y-(Delta.y*VSpacing));
  425.   SetColor(Yellow);
  426.   Circle(Glob.A.x+300 -(Delta.x*HSpacing),
  427.          Glob.A.y+120 -(Delta.y*VSpacing),
  428.          100);
  429. end
  430. else         {normal scroller code}
  431.     {Optional - for speed improvement on large files, call OutTextXY
  432.                   only when it is within the current viewport.}
  433.     {Remember - GetVPRelCoords(Glob) is viewport relative.}
  434.     {ByOffset
  435.       is automatically set in TVGraphic. It is a font dependent
  436.       value used to center text vertically in the standard Boxheight.
  437.       If you make VSpacing other than Boxheight, don't use ByOffset.
  438.       Use function CalcVertTextOffset -
  439.         YOffset := CalcVertTextOffset(VSpacing) to find the offset to
  440.       center text in arbitrary vertical spacing.}
  441.  
  442.       {TVGraphic Version 1.0 code, works but I should now start at 0.}
  443. (*  for I := 1 to SArraySize do
  444.     if ((Glob.A.y + (I+1-Delta.y)*VSpacing) > 0)
  445.      and ((Glob.A.y + (I-2-Delta.y)*VSpacing) < Glob.B.y) then
  446.        OutTextXY(Glob.A.x+HSpacing - (Delta.x*HSpacing) +1,
  447.            Glob.A.y + (I-Delta.y)*VSpacing + BYOffset, SArray[I]);*)
  448.  
  449.    for I := 0 to (Size.y+1) div VSpacing +1 do begin
  450.      {If you want to draw the background incrementally, use the
  451.      following line instead of the earlier call to Bar.}
  452.      (* Bar(Glob.A.x, Glob.A.y + (I)*VSpacing,
  453.             Glob.B.x, Glob.A.y + (I+1)*VSpacing-1); *)
  454.     if (I+Delta.y <= SArraySize) then
  455.     OutTextXY(Glob.A.x+HSpacing - (Delta.x*HSpacing) +1,
  456.            Glob.A.y + I*VSpacing + BYOffset, SArray[I+Delta.y]);
  457.   end;
  458.  
  459.   with VPort do       {restore viewport}
  460.     SetViewPort(X1,Y1,X2,Y2,Clip);
  461.  
  462.   MCur.Show;          {show mouse cursor}
  463. end;
  464.  
  465.    {ADDED Version 1.5}
  466. procedure TMyScroller.PartOfSetLimit(X, Y : integer);
  467. var
  468.   YSize,XSize : integer;
  469. begin
  470.   XSize := (Size.x+1) div HSpacing;
  471.   YSize := (Size.y+1) div VSpacing;
  472.   Limit.X := X;
  473.   Limit.Y := Y;
  474.   if HScrollBar <> nil then
  475.     HScrollBar^.SetParams(HScrollBar^.Value, 0, X - XSize, XSize - 1,
  476.       HScrollBar^.ArStep);
  477.   if VScrollBar <> nil then
  478.     VScrollBar^.SetParams(VScrollBar^.Value, 0, Y - YSize, YSize - 1,
  479.       VScrollBar^.ArStep);
  480. end;
  481.  
  482.  
  483. type
  484.  
  485.   {demonstrates very simple Draw method and using TimerTick events}
  486.  
  487.   PCircles = ^TCircles;
  488.   TCircles = object(TWinBackground)
  489.     Count : integer;
  490.     Speed : integer;
  491.     constructor Init(var Bounds: TRect);
  492.     procedure Draw; virtual;
  493.     procedure DrawCircle;
  494.     procedure HandleEvent(var Event : TEvent); virtual;
  495.   end;
  496.  
  497.   constructor TCircles.Init(var Bounds: TRect);
  498.   begin
  499.     TWinBackground.Init(Bounds);
  500.     EventMask := evTimerTick;
  501.     VColor := black;               {store drawing color}
  502.   end;
  503.  
  504.   procedure TCircles.Draw;
  505.   var   Glob : TRect;
  506.   begin
  507.     MCur.Hide;              {hide cursor}
  508.     GetVPRelCoords(Glob);   {get view's outline in viewport relative coords}
  509.  
  510.     SetFillStyle(solidfill,VColor);            {set background color}
  511.     Bar(Glob.A.x,Glob.A.y,Glob.B.x,Glob.B.y);  {draw background}
  512.  
  513.     DrawCircle;
  514.  
  515.     MCur.Show;
  516.   end;
  517.  
  518.   procedure TCircles.DrawCircle;
  519.   var
  520.     Radius : word;
  521.     Glob : TRect;
  522.     Color : integer;
  523.   begin
  524.     MCur.Hide;              {hide cursor}
  525.     GetVPRelCoords(Glob);   {get view's outline in viewport relative coords}
  526.  
  527.     if (Count = 0) or (Count =8) then Color := 14
  528.       else Color := Count;
  529.     SetColor(Color);               {set circle Color based on Count}
  530.  
  531.                                    {compute radius based on view's size}
  532.     if Size.x < Size.y then Radius := Size.x
  533.     else Radius := Size.y;
  534.     Radius := Radius div 3;
  535.                                    {draw circle}
  536.     Circle(Glob.A.x+Size.x div 2, Glob.A.y+Size.y div 2, Radius);
  537.     MCur.Show;               {show the mouse cursor}
  538.   end;
  539.  
  540.   procedure TCircles.HandleEvent(var Event : TEvent);
  541.   begin
  542.     if Event.What = evTimerTick then begin
  543.          { if you want to avoid overwriting menus and modal dialog boxes,
  544.            must exit if the Application (Desktop's Owner) is not the
  545.            modal view.}
  546.       if TopView <> PView(DeskTop^.Owner) then Exit;
  547.  
  548.       Inc(Speed);
  549.       if Speed > 1023 then Speed := 0;
  550.       if (Speed mod 8 = 0) then begin
  551.         Inc(Count);
  552.         if Count > 15 then Count := 0;   {limit to highest color}
  553.         if GetState(sfActive) then DrawCircle;
  554.       end;
  555.     end;
  556.   end;
  557.  
  558. {RegisterTypes}
  559. const
  560.   RMyScroller: TStreamRec = (
  561.      ObjType: 3000;
  562.      VmtLink: Ofs(TypeOf(TMyScroller)^);
  563.      Load:    @TMyScroller.Load;
  564.      Store:   @TMyScroller.Store
  565.   );
  566.   RCircles: TStreamRec = (
  567.      ObjType: 3001;
  568.      VmtLink: Ofs(TypeOf(TCircles)^);
  569.      Load:    @TCircles.Load;
  570.      Store:   @TCircles.Store
  571.   );
  572.  
  573.   procedure RegisterLocals;
  574.   begin
  575.     RegisterType(RMyScroller);
  576.     RegisterType(RCircles);
  577.   end;
  578. {--------------------------------}
  579. type
  580.   TDemoApp = object(TProgram)
  581.     DeskTopStyle : word;            {style currently in use}
  582.     ThePanWindow : PPanWindow;      {pointer to panning window if it exists}
  583.     constructor Init;
  584.     procedure GetEvent(var Event : TEvent); virtual;
  585.     procedure DoAboutBox;
  586.     procedure DosShell;
  587.     procedure HandleEvent(var Event: TEvent); virtual;
  588.     procedure InsertCircleWin;
  589.     procedure InsertScrollerWin(ATitle : string);
  590.     procedure InitHeapViewer;
  591.     procedure InitMenuBar; virtual;
  592.     procedure InitShiftView;
  593.     procedure InitMessageBar;       {message that covers over the MenuBar}
  594.     procedure InitStatusLine; virtual;
  595.     procedure InitToolBar;
  596.     procedure IntroScreen;
  597.     procedure LoadBMP;
  598.     procedure NewWindow;
  599.     procedure SaveDeskTop;
  600.     procedure SelectDeskTopStyle;
  601.     procedure LoadDeskTop;
  602.     procedure ShowHelp;
  603.     procedure ShowMouseBox;
  604.     destructor Done; virtual;
  605.     destructor HaltDone;
  606.   end;
  607.  
  608. destructor TDemoApp.Done;
  609.   {called for normal program termination}
  610. begin
  611.   TProgram.Done;
  612.   MCur.Done;            {releases mouse cursor memory}
  613.   CloseGraph;
  614.   Graphic := false;
  615.  
  616.   {DoneHistory;}
  617.   DoneSysError;
  618.   DoneEvents;
  619.   DoneVideo;
  620.   DoneMemory;
  621. end;
  622.  
  623. destructor TDemoApp.HaltDone;
  624.   {used if program halts while trying to initilize graphic mode}
  625. begin
  626.   {DoneHistory;}
  627.   DoneSysError;
  628.   DoneEvents;
  629.   DoneVideo;
  630.   DoneMemory;
  631. end;
  632.  
  633. constructor TDemoApp.Init;
  634.   procedure DoStreamRegistration;
  635.     {register objects and views for stream I/O}
  636.     {vary contents to match your program}
  637.   begin
  638.     RegisterObjects;
  639.     RegisterViews;
  640.     RegisterDialogs;
  641.     RegisterMenus;
  642.     RegisterApp;
  643.     RegisterStdDlg;
  644.     RegisterWindows;
  645.     RegisterLocals;
  646.     RegisterBitMaps;
  647.   end;
  648. var
  649.   GraphDriver,GraphMode,ErrorCode : integer;
  650. begin
  651.   Graphic := false;
  652.  
  653.   InitMemory;
  654.   InitVideo;
  655.   InitEvents;
  656.   InitSysError;
  657.   {InitHistory;}
  658.  
  659.      {register screen driver}
  660.   if RegisterBGIdriver(@EGAVGADriverProc) < 0 then begin
  661.     HaltDone;
  662.     Writeln('Internal EGA/VGA driver not linked.');
  663.     Halt(1);
  664.   end;
  665.      {verify graphics mode}
  666.   DetectGraph(GraphDriver, GraphMode);
  667.   if not ((GraphDriver = VGA) or (GraphDriver = EGA)) then begin
  668.     HaltDone;
  669.     Writeln('Error - system does not support EGA or VGA graphics.');
  670.     Halt(1);
  671.   end;
  672.  
  673. (*  {Optional -forces color display mode if in B&W mode. This can
  674.                cause a problem with B&W LCD laptops which can
  675.                drive an external VGA color monitor. They end up in
  676.                color mode and so Turbo Vision selects the color
  677.                palette instead of B&W palette.}
  678.   SetVideoMode(smCO80);*)
  679.  
  680.     {enter graphics mode}
  681.   if GraphDriver = VGA then GraphMode := VGAHi
  682.     else GraphMode := EGAHi;
  683.   InitGraph(GraphDriver,GraphMode,'');
  684.   ErrorCode := GraphResult;
  685.   if ErrorCode <> grOK then begin
  686.     HaltDone;
  687.     Writeln('Graphics Error: ',GraphErrorMsg(ErrorCode));
  688.     Halt(1);
  689.   end
  690.   else begin
  691.           {install exit proc to Close graphics}
  692.     OldExitProc := ExitProc;                { save previous exit proc }
  693.     ExitProc := @GExitProc;                { insert our exit proc in chain }
  694.     Graphic := true;
  695.           {install graphic mode DOS critical error handler}
  696.     SysErrorFunc := GSystemError;
  697.           {improves look of dark gray and brown on VGA monitors,
  698.            no effect in EGA}
  699.     ImprovePaletteColors;
  700.   end;
  701.  
  702.   MCur.Init;             {mouse cursor object}
  703.   MCur.SetSpeed(12,12);  {how fast cursor moves, "normal" is 8,8}
  704.  
  705.   InitShiftView;     {must do before TProgram.Init if calling
  706.                       ShiftView.HandleEvent from TDemoApp.HandleEvent.
  707.                       ShiftView is needed for Panning windows only.}
  708.   TProgram.Init;
  709.  
  710.  
  711.       {following items may be different for your program}
  712.   DoStreamRegistration;
  713.  
  714.   InitMessageBar;
  715.  
  716.   DoubleDelay := 6;   {time between mouse button presses for double press}
  717.                       {TV uses 8 - very slow}
  718.  
  719.     {set default Viewport to just cover the DeskTop. The MainMenu,MessageBar
  720.        and StatusLine temporarily reset viewport when they draw themselves.}
  721.   with DeskTop^ do
  722.     SetViewPort(Origin.x, Origin.y,
  723.            Origin.x + Size.x, Origin.y + Size.y, ClipOn);
  724.  
  725.     {set mouse grids to off}
  726.   MCur.SetGrid(1,1,0,0);
  727.   MouseSnapToMenuGrid := false;
  728.   MouseSnapToDialogGrid := false;
  729.  
  730.   InitHeapViewer;
  731.  
  732.   InitToolBar;
  733.  
  734.   IntroScreen;      {optional}
  735.  
  736.   DisableCommands([cmTVlikeButtons]);  { for demo program only! }
  737. end;
  738.  
  739. procedure TDemoApp.DosShell;
  740.   {Must override method TApplication.DosShell for graphics.}
  741. begin
  742.    {USE TurboVision 2.0 MEMORY Unit if compiling with TP 7.0,
  743.       use MEMORY ver 1.0 with TP.6.0}
  744.   RestoreCrtMode;          {back to text mode}
  745.  
  746.   DoneSysError;
  747.   DoneEvents;
  748.   DoneVideo;
  749.  
  750.   {$IFDEF VER60}
  751.     SetMemTop(HeapPtr);      {reduce reserved memory size}
  752.   {$ELSE}
  753.     DoneDosMem;
  754.   {$ENDIF}
  755.   Writeln('Type EXIT to return to '+ ProgName + '...');
  756.   SwapVectors;
  757.   Exec(GetEnv('COMSPEC'), '');
  758.   SwapVectors;
  759.   {$IFDEF VER60}
  760.     SetMemTop(HeapEnd);      {reserve all of memory}
  761.   {$ELSE}
  762.     InitDosMem;
  763.   {$ENDIF}
  764.  
  765.   InitVideo;
  766.   InitEvents;
  767.   InitSysError;
  768.  
  769.   SetGraphMode(GetGraphMode);
  770.   ImprovePaletteColors;
  771.  
  772.         {Other programs can change mouse settings. Restore here.}
  773.   MCur.RestoreSettings;
  774.  
  775.   Redraw;                          {Use Redraw here, not Draw.}
  776.   if DosError <> 0 then DOSErrorMessageBox(DosError, 'Running DOS shell');
  777. end;
  778.  
  779.  
  780. procedure TDemoApp.GetEvent(var Event : TEvent);
  781. const
  782.   HelpInUse : boolean = false;
  783.   LastPressDouble : boolean = false;
  784. begin
  785.   TProgram.GetEvent(Event);    {usual call}
  786.  
  787.    {Timer Tick events for v1.5 and above
  788.      are now handled automatically in TProgram.GetEvent}
  789.  
  790.      {Optional - Mouse button behavior}
  791.   if (Event.What and evMouse <> 0) and (Graphic = true) then begin
  792.   (* next line moved to TProgram.GetEvent
  793.       MCur.Move(Event.Where);    {move cursor to mouse location}*)
  794.     if (Event.What = evMouseDown) then begin
  795.           {OPTIONAL - remap middle button of 3 button mouse}
  796.       if (Event.Buttons > mbRightButton) then Event.Buttons := mbLeftButton;
  797.          {eliminate sequential double press events}
  798.       if (Event.Double) then
  799.         if not LastPressDouble then LastPressDouble := true  {remember this double press}
  800.         else begin
  801.           Event.Double := false;         {reset the double flag}
  802.           LastPressDouble := false;
  803.         end
  804.       else LastPressDouble := false;     {clear flag if non-double press}
  805.     end;
  806.   end;
  807.  
  808.     {Hook in HELP screens here in GetEvent to cover
  809.      situation when another view is Modal}
  810.   if (Event.What = evCommand) and (Event.Command = cmHelp)
  811.    and not HelpInUse then begin
  812.     HelpInUse := true;
  813.     ShowHelp;
  814.     ClearEvent(Event);
  815.     HelpInUse := false;
  816.   end;
  817.  
  818. end;
  819.  
  820. procedure TDemoApp.ShowHelp;
  821.   var
  822.     HWin : PDialog;
  823.     S : string;
  824.     Control : integer;
  825.     HCtx : word;
  826.     PS : PGStaticText;
  827.     B : PButton;
  828.     R : TRect;
  829.     Event : TEvent;
  830.     P : PMenuView;
  831.   begin
  832.     HCtx := GetHelpCtx;
  833.     Str(HCtx,S);
  834.     case HCtx of
  835.       hcMouseGrid:
  836.         S := 'TVGraphic allows the mouse cursor to be snapped to any user specified grid for the screen in general.'+
  837.          ' Grid Off (uses every pixel) and two other choices are provided here.';
  838.       hcColorSel:
  839.         S := ^C'Use Background color selector for all items listed after a "/".'+^M^M+
  840.              ^C'Only Items showing "bkgnd" have a changable background.';
  841.       else
  842.         S := ^C'THIS IS NO HELP AT ALL'^M^M^M+
  843.          ^C+ 'Help Context = ' + S;
  844.     end;
  845.     R.A.x := 0;  R.B.x := R.A.x + 49*Charlen;
  846.     R.A.Y := 0;  R.B.y := R.A.y + (11+3)*Boxheight;
  847.  
  848.     HWin := New(PDialog,Init(R,'HELP'));
  849.     HWin^.Options := HWin^.Options or OfCentered;  {autocenter}
  850.  
  851.     Inc(R.A.x, 4*Charlen);
  852.     Dec(R.B.x, 4*Charlen);
  853.     Inc(R.A.y, 4*Boxheight);
  854.     R.B.y := R.A.y + 5*Boxheight;
  855.     PS := New(PGStaticText, Init(R,S,DefaultOpts));
  856.     HWin^.Insert(PS);
  857.  
  858.     if TopView = @Self then
  859.              {if no other view is modal, insert dialog
  860.               as non-modal (persistant) view}
  861.       if ThePanWindow <> nil then ThePanWindow^.Insert(HWin)
  862.       else DeskTop^.Insert(HWin)
  863.     else begin         {some other view is already modal, make dialog modal}
  864.       R.A.x := HWin^.Size.x - 11*Charlen;
  865.       R.A.y := HWin^.Size.y - 2*Boxheight;
  866.       B := New(PCancelButton, Init(R.A));
  867.       HWin^.Insert(B);                      {add Cancel button}
  868.  
  869.       Control := DeskTop^.ExecView(HWin);
  870.       Dispose(HWin,Done);
  871.                    {TVGraphics partial redraw scheme isn't aware of open
  872.                    submenu(s) extending over the DeskTop. If you create a
  873.                    overlapping modal view while these menus are open,
  874.                    you must manually call the menu chain to redraw
  875.                    themselves as shown here.}
  876.         P := MenuBar^.Target;     {first submenu in the chain}
  877.         while P <> nil do begin   {redraw all open submenus}
  878.           P^.DrawView;
  879.           P := P^.Target;
  880.         end;
  881.     end;
  882.   end;
  883.  
  884. procedure TDemoApp.DoAboutBox;
  885. begin
  886.   InsertScrollerWin('ABOUT TVGRAPHIC');
  887. end;
  888.  
  889.  
  890. procedure TDemoApp.HandleEvent(var Event: TEvent);
  891.  
  892.   procedure Colors;
  893.   var
  894.     D: PColorDialog;
  895.   begin
  896.     D := New(PColorDialog, Init('',
  897.       ColorGroup('Desktop',       DesktopColorItems(nil),
  898.       ColorGroup('Menus',         MenuColorItems(nil),
  899.       ColorGroup('Dialogs',  DialogColorItems(dpTV1Dialog, nil),
  900.       ColorGroup('Windows',  WindowColorItems(wpBlueWindow, nil),
  901.       {ColorGroup('Help',     WindowColorItems(wpCyanWindow, nil),}
  902.         nil)))))){)};
  903.     D^.HelpCtx := hcColorSel;
  904.  
  905.     if ExecuteDialog(D, Application^.GetPalette) <> cmCancel then
  906.     begin
  907.       ReDraw;        { Redraw application with new palette }
  908.     end;
  909.   end;
  910.  
  911.   procedure DosErr;
  912.   var
  913.     F: Text;
  914.     Cmd : integer;
  915.   begin
  916.     Cmd := MessageBox(^C'Testing DOS Critical Error'+
  917.           ^M^M^C'Remove any disk in drive A:',nil,mfWarning+mfOKCancel);
  918.     if Cmd <> cmOK then exit;
  919.  
  920.     Assign(F, 'a:\8anyfile.7Z3');
  921.   {$I-}
  922.     Reset(F);
  923.     Close(F);
  924.     Cmd := IOResult;   {added 5/17/93}
  925.   {$I+}
  926.   end;
  927.  
  928.   procedure ShowVersion;
  929.   var Cmd : integer;
  930.   begin
  931.     Cmd := MessageBox(^C'TVGraphic Demo1 ver '+Ver,
  932.       nil, mfInformation+mfOKButton);
  933.   end;
  934.   procedure ShowHourGlass;
  935.   begin
  936.     Mcur.SelectHourGlass;
  937.     Delay(500);
  938.     MCur.SelectStdCursor;
  939.   end;
  940.  
  941.   procedure DeskTopOptionsInfo;
  942.   begin
  943.     MessageBox(^C'The heights and fonts of the Menubar and the '
  944.                      +'StatusLine are adjustable in the code.',
  945.       nil, mfInformation+mfOKButton);
  946.   end;
  947.   procedure ToolsInfo;
  948.   begin
  949.     MessageBox(^C'TVGraphic now works with David Baldwin''s visual '+
  950.                         'design tool, Dialog Design v4.0.',
  951.       nil, mfInformation+mfOKButton);
  952.   end;
  953.   procedure TEditInfo;
  954.   begin
  955.     MessageBox(^C'The Editors unit for TVGraphic is in progress.',
  956.       nil, mfInformation+mfOKButton);
  957.   end;
  958.   procedure ToolBarInfo;
  959.   begin
  960.     MessageBox(^C'Bitmapped buttons may be used in Dialogs or in'+
  961.                         ' a ToolBar.',
  962.       nil, mfInformation+mfOKButton);
  963.   end;
  964.   procedure MakeSound;
  965.   begin
  966.     Sound(1000);
  967.     Delay(10);
  968.     NoSound;
  969.   end;
  970.  
  971. var
  972.   R: TRect;
  973.   PDir,FInputBox : PView;
  974.   Cmd : integer;
  975. begin
  976.   if (ShiftViewPtr <> Nil) then ShiftViewPtr^.HandleEvent(Event);
  977.       {ShiftViewPtr will be nil unless InitShiftView has been
  978.       called. A ShiftView is needed if using TPanWindow type. Call to
  979.       ShiftViewPtr^.HandleEvent must come before call to
  980.       TProgram.HandleEvent.}
  981.  
  982.   TProgram.HandleEvent(Event);    {usual call to ancestor method}
  983.  
  984.   if Event.What = evCommand then
  985.   begin
  986.     case Event.Command of
  987.       cmNew: NewWindow;
  988.       cmShowMessageBar:
  989.         begin
  990.           MessageBar^.ShowText('~T~HIS IS THE MESSAGE BAR.');
  991.           Delay(1000);
  992.           MessageBar^.Hide;
  993.         end;
  994.       cmAbout: DoAboutBox;
  995.       cmOpen:
  996.         begin
  997.           FInputBox := New(PFileDialog, Init('*.*', 'OPEN A FILE', '~N~ame', fdOpenButton,0));
  998.           Cmd := DeskTop^.ExecView(FInputBox);
  999.           Dispose(FInputBox, Done);
  1000.         end;
  1001.       cmChangeDir:
  1002.         begin
  1003.           PDir := New(PChDirDialog, Init(cdNormal {+ cdHelpButton},0));
  1004.           Cmd := DeskTop^.ExecView(PDir);
  1005.           Dispose(PDir, Done);
  1006.         end;
  1007.       cmSetColors: Colors;
  1008.       cmDOSshell : DOSShell;
  1009.       cmDosCriticalError : DosErr;
  1010.       cmOptionsSave : SaveDeskTop;
  1011.       cmOptionsLoad : LoadDeskTop;
  1012.       cmCircleWindow : InsertCircleWin;
  1013.       cmScrollerWindow : InsertScrollerWin('WINDOW WITH SCROLLER');
  1014.       cmMouseGrids   : ShowMouseBox;
  1015.       cmDeskTopStyle : SelectDeskTopStyle;
  1016.       cmDeskTopOptions : DeskTopOptionsInfo;
  1017.       cmVersion       : ShowVersion;
  1018.       cmTools        : ToolsInfo;
  1019.       cmTEdit        : TEditInfo;
  1020.       cmBMP          : LoadBMP;
  1021.       cmBitBut       : ToolBarInfo;
  1022.       cmHourGlass    : ShowHourGlass;
  1023.       cmTVlikeButtons : begin
  1024.             TextButtonsMatchBitMapButtons := false;
  1025.             DisableCommands([cmTVlikeButtons]);
  1026.             EnableCommands([cmBMPlikeButtons]);
  1027.                         end;
  1028.       cmBMPlikeButtons :begin
  1029.             TextButtonsMatchBitMapButtons := true;
  1030.             DisableCommands([cmBMPlikeButtons]);
  1031.             EnableCommands([cmTVlikeButtons]);
  1032.                         end;
  1033.     end;
  1034.   end;
  1035. end;
  1036.  
  1037. procedure TDemoApp.InsertCircleWin;
  1038. var
  1039.   P : PView;
  1040.   W : PWindow;
  1041.   R : TRect;
  1042. begin
  1043.   R.Assign((WinNum+20)*Grid, (WinNum+20)*Grid,
  1044.            (WinNum+40)*Grid, (WinNum+40)*Grid);
  1045.  
  1046.    {use a TSubWindow here rather than TWindow since window may be
  1047.    inserted into another window instead of the DeskTop}
  1048.   W := New(PSubWindow, Init(R,'CIRCLES',wnNoNumber));
  1049.  
  1050.   W^.GetMaxSubViewSize(R);
  1051.   P := New(PCircles, Init(R));
  1052.   W^.Insert(P);
  1053.   if ThePanWindow <> nil then ThePanWindow^.Insert(W)
  1054.    else DeskTop^.Insert(W);
  1055. end;
  1056.  
  1057. procedure TDemoApp.InsertScrollerWin(Atitle : string);
  1058. var
  1059.   WinTitle : string;
  1060.   TheWindow : PSubWindow;
  1061.   PScrollH,PScrollV : PScrollBar;
  1062.   PS : PView;
  1063.   R : TRect;
  1064. begin
  1065.   Inc(WinNum);
  1066.   R.Assign((WinNum+4)*Charlen, (WinNum+4)*Boxheight,
  1067.            (WinNum+64)*Charlen,(WinNum+24)*Boxheight);
  1068.   WinTitle := ATitle;
  1069.   TheWindow := New(PSubWindow, Init(R, WinTitle, WinNum{wnNoNumber}));
  1070.  
  1071.   PScrollH := TheWindow^.StandardScrollBar(sbHorizontal + sbHandleKeyboard);
  1072.   PScrollV := TheWindow^.StandardScrollBar(sbVertical + sbHandleKeyboard);
  1073.  
  1074.   TheWindow^.GetMaxSubViewSize(R);
  1075.      {GetMaxSubViewSize returns the rectangle that needs to be filled
  1076.      with views - here fill it with the scroller}
  1077.   PS := New(PMyScroller, Init(R,PScrollH,PScrollV));
  1078.   TheWindow^.Insert(PS);
  1079.  
  1080.   if ThePanWindow <> nil then ThePanWindow^.Insert(TheWindow)
  1081.   else DeskTop^.Insert(TheWindow);
  1082. end;
  1083.  
  1084. procedure TDemoApp.InitHeapViewer;
  1085. var
  1086.   P : PView;
  1087.   R : TRect;
  1088. begin
  1089.   R.Assign(Size.x - 14*Charlen, StatusLine^.Origin.y, Size.x, Size.y);
  1090.   P := New(PHeapView, Init(R));
  1091.   Insert(P);
  1092. end;
  1093.  
  1094. procedure TDemoApp.InitMessageBar;  {message that covers over the MenuBar}
  1095. begin
  1096.   MessageBar := New(PGMessageBar,Init);
  1097.   Insert(MessageBar);
  1098. end;
  1099.  
  1100. procedure TDemoApp.InitShiftView;
  1101.  {Used with full desktop panning window(s).
  1102.   Zero or One ShiftView per application.
  1103.   The shape of ShiftView is the top row of pixels on the screen.}
  1104. var
  1105.   R : TRect;
  1106. begin
  1107.   R.A.x := 0;  R.B.x := GetMaxX;
  1108.   R.A.y := 0;  R.B.y := 0{1};           {shape = slit above menubar}
  1109.   ShiftViewPtr := New(PShiftView,Init(R));
  1110. end;
  1111.  
  1112. procedure TDemoApp.InitMenuBar;
  1113. var
  1114.   R: TRect;
  1115. begin
  1116.   MenuBarHeight := {15}20;   {user choice}
  1117.   GetExtent(R);
  1118.   MenuBar := New(PGMenuBar, Init(R, NewMenu(
  1119.     NewSubMenu('~F~ile', hcNoContext, NewMenu(
  1120.       NewItem('~N~ew', '', kbNoKey, cmNew, hcNew,
  1121.       NewItem('~O~pen...', 'F3', kbF3, cmOpen, hcOpen,
  1122.       NewLine(
  1123.       NewItem('~C~hange dir...', '', kbNoKey, cmChangeDir, hcChangeDir,
  1124.       NewItem('~D~OS shell', '', kbNoKey, cmDosShell, hcDosShell,
  1125.       NewItem('E~x~it', 'Alt+X', kbAltX, cmQuit, hcExit,
  1126.       nil))))))),
  1127.     NewSubMenu('~D~eskTop', hcNoContext, NewMenu(
  1128.       NewItem('~S~et Style...', '', kbNoKey, cmDeskTopStyle, hcNoContext,
  1129.       NewItem('~O~ptions...', '', kbNoKey, cmDeskTopOptions, hcNoContext,
  1130.       NewLine(
  1131.       NewItem('S~a~ve desktop', '', kbNoKey, cmOptionsSave, hcNoContext,
  1132.       NewItem('~L~oad desktop', '', kbNoKey, cmOptionsLoad, hcNoContext,
  1133.       nil)))))),
  1134.     NewSubMenu('~W~indows', hcNoContext, NewMenu(
  1135.       NewItem('~C~ircleWindow', '', kbNoKey, cmCircleWindow , hcNoContext,
  1136.       NewItem('~S~crollerWindow1', '', kbNoKey, cmScrollerWindow , hcNoContext,
  1137.       NewItem('~S~crollerWindow2', '', kbNoKey, cmAbout, hcNoContext,
  1138.       NewLine(
  1139.       NewItem('~S~ize/Move','Ctrl+F5', kbCtrlF5, cmResize, hcResize,
  1140.       NewItem('~Z~oom', 'F5', kbF5, cmZoom, hcZoom,
  1141.       NewItem('~N~ext', 'F6', kbF6, cmNext, hcNext,
  1142.       NewItem('~P~revious', 'Shift+F6', kbShiftF6, cmPrev, hcPrev,
  1143.       NewItem('~C~lose', 'Alt+F3', kbAltF3, cmClose, hcClose,
  1144.       nil)))))))))),
  1145.     NewSubMenu('~M~ouse', hcNoContext, NewMenu(
  1146.       NewItem('~S~et Cursor grids...', '', kbNoKey, cmMouseGrids, hcNoContext,
  1147.       NewItem('~H~ourglass Cursor', '', kbNoKey, cmHourGlass, hcNoContext,
  1148.       nil))),
  1149.     NewSubMenu('O~p~tions', hcNoContext, NewMenu(
  1150.       NewItem('~S~how MessageBar', '', kbNoKey, cmShowMessageBar, hcNoContext,
  1151.       NewItem('~D~os Crit Error', '', kbNoKey, cmDosCriticalError, hcNoContext,
  1152.       NewItem('Set ~C~olors...', '', kbNoKey, cmSetColors, hcNoContext,
  1153.       NewLine(
  1154.       NewItem('~T~V style text buttons', '', kbNoKey, cmTVlikeButtons, hcNoContext,
  1155.       NewItem('~B~MP like text buttons', '', kbNoKey, cmBMPlikeButtons, hcNoContext,
  1156.       nil))))))),
  1157.     NewSubMenu('~I~nfo', hcNoContext, NewMenu(
  1158.       NewItem('~A~bout...', '', kbNoKey, cmAbout, hcNoContext,
  1159.       NewItem('~V~ersion #', '', kbNoKey, cmVersion, hcNoContext,
  1160.       nil))),
  1161.     NewSubMenu('The Future', hcNoContext, NewMenu(
  1162.       NewSubMenu('~H~ere now', hcNoContext, NewMenu(
  1163.         NewItem('~T~ools', '', kbNoKey, cmTools, hcNoContext,
  1164.         NewItem('~B~itMaps', '', kbNoKey, cmBMP, hcNoContext,
  1165.         nil))),
  1166.       NewItem('~E~ditors Unit', '', kbNoKey, cmTEdit, hcNoContext,
  1167.       nil))),
  1168.     nil)))))))
  1169.   )));
  1170. end;
  1171.  
  1172. procedure TDemoApp.InitStatusLine;
  1173.   function  HiddenStatusKeys(Next : PStatusItem) : PStatusItem;
  1174.   begin
  1175.     HiddenStatusKeys :=
  1176.         NewStatusKey('', kbF10, cmMenu,
  1177.         NewStatusKey('', kbAltF3, cmClose,
  1178.         NewStatusKey('', kbF5, cmZoom,
  1179.         NewStatusKey('', kbCtrlF5, cmResize,
  1180.         NewStatusKey('', kbF6, cmNext,
  1181.         Next)))));
  1182.   end;
  1183. var
  1184.   R: TRect;
  1185. begin
  1186.   GetExtent(R);
  1187.   R.B.x := R.B.x - 14*Charlen;           {leave space for heap viewer}
  1188.   R.A.Y := R.B.Y - 9 {Boxheight};    {this gives a 10 pixel tall StatusLine}
  1189. StatusLine :=   New(PGStatusLine, Init(R,
  1190.     NewStatusDef(0, $FFFF,
  1191.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  1192.       NewStatusKey('~F6~ Next', kbF6, cmNext,
  1193.       NewStatusKey('~Shift+F6~ Prev', kbShiftF6, cmPrev,
  1194.       NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
  1195.       HiddenStatusKeys(nil))))),
  1196.        nil)));
  1197.  
  1198. StatusLine^.VFont := font8x8;
  1199.    {use for 10 pixel tall StatusLine - default font is Font8x14}
  1200. end;
  1201.  
  1202. procedure TDemoApp.InitToolBar;
  1203.   {NOTE: this is a toolbar that is inserted into the DeskTop,
  1204.    just like a window. It can be any size. Windows can cover it.
  1205.    As an alternative, you could make a toolbar which is inserted into
  1206.    the application like a menu and reduces the size of the DeskTop.
  1207.    See Bitmap documentation.}
  1208. const
  1209.   BWidth = 28;
  1210.   BHeight = 28;
  1211. var
  1212.   PBar : PToolBar;
  1213.   PBut : PIconButton;
  1214.   R : TRect;
  1215. begin
  1216.   R.Assign(0, 0, 5 +BWidth, 2+Boxheight +6*BHeight);
  1217.   PBar := New(PToolBar, Init(R, ''));
  1218.  
  1219. { Buttons have ofSelectable set by default.  If so, the Selected
  1220.   button will have a dotted line drawn around it. Setting bfGrabFocus
  1221.   in the Opts field of the constructor will cause a button to Select
  1222.   itself when clicked with mouse. So the dotted line will be on the last
  1223.   clicked button.
  1224.     If you don't want the dotted line , clear the ofSelectable flag
  1225.   in the button's Options field after construction. bfGrabFocus is
  1226.   not needed in this case but doesn't hurt.
  1227.     Note that buttons will respond to HotKeys, if you have set them,
  1228.   but Turbo Vision does not cause such a button to select itself.}
  1229.  
  1230.   R.A.x := 3;  R.A.y := 14;        {HotKey = "N"}
  1231.   PBut := New(PIconButton, Init(R, '~N~',cmNext,
  1232.       tbDrawDisabled+bfGrabFocus+tbDrawFrame+tbAutoSize, @Bar8_BMP));
  1233. PBut^.Options := PBut^.Options and not ofSelectable;
  1234.   PBar^.Insert(PBut);
  1235.   Inc(R.A.y, BHeight);
  1236.   PBut := New(PIconButton, Init(R, '',cmBitBut,
  1237.               bfGrabFocus+tbDrawFrame+tbAutoSize, @Bar2_BMP));
  1238. PBut^.Options := PBut^.Options and not ofSelectable;
  1239.   PBar^.Insert(PBut);
  1240.   Inc(R.A.y, BHeight);
  1241.   PBut := New(PIconButton, Init(R, '',cmBitBut,
  1242.               bfGrabFocus+tbDrawFrame+tbAutoSize, @Bar3_BMP));
  1243. PBut^.Options := PBut^.Options and not ofSelectable;
  1244.   PBar^.Insert(PBut);
  1245.   Inc(R.A.y, BHeight);
  1246.   PBut := New(PIconButton, Init(R, '',cmBitBut,
  1247.               bfGrabFocus+tbDrawFrame+tbAutoSize, @Bar4_BMP));
  1248. PBut^.Options := PBut^.Options and not ofSelectable;
  1249.   PBar^.Insert(PBut);
  1250.   Inc(R.A.y, BHeight);
  1251.   PBut := New(PIconButton, Init(R, '',cmBitBut,
  1252.               bfGrabFocus+tbDrawFrame+tbAutoSize, @Bar7_BMP));
  1253. PBut^.Options := PBut^.Options and not ofSelectable;
  1254.   PBar^.Insert(PBut);
  1255.   Inc(R.A.y, BHeight);
  1256.   PBut := New(PIconButton, Init(R, '',cmBitBut,
  1257.               bfGrabFocus+tbDrawFrame+tbAutoSize, @Bar1_BMP));
  1258. PBut^.Options := PBut^.Options and not ofSelectable;
  1259.   PBar^.Insert(PBut);
  1260.  
  1261.   PBar^.SelectNext(false);
  1262.  
  1263.   DeskTop^.Insert(PBar);
  1264. end;
  1265.  
  1266. procedure TDemoApp.IntroScreen;
  1267. var
  1268.   R : TRect;
  1269.   I,J : integer;
  1270.   Msg : string;
  1271.   XPt,YPt : integer;
  1272. begin
  1273.   DeskTop^.GetExtent(R);
  1274.   SetTextStyle(defaultfont,HorizDir,2);
  1275.   SetColor(white);
  1276.   for I := 1 to 22 do begin
  1277.     if I > 10 then SetTextStyle(font8x14,HorizDir,1);
  1278.     if I > 18 then SetTextStyle(font8x8,HorizDir,1);
  1279.     OutTextXY(I*20,I*20{R.A.y}, 'TVGraphic');
  1280.   end;
  1281.   Delay(500);
  1282.   R.B.x := 52*Charlen;
  1283.   R.B.y := 14*Boxheight;
  1284.   Msg := ^C'WELCOME TO TVGraphic Demo1'^M^M^C+
  1285.           'TVGraphic is written in Borland Turbo Vision.'+
  1286.           ^M^M^C'Make your TV application look like this one with TVGraphic(tm).'
  1287.           +^M^M^C+
  1288.           'CopyRight 1993,1994 Richard P Andresen';
  1289.  
  1290.   MessageBoxRect(R, Msg, nil, mfInformation+mfOKButton);
  1291.   DeskTop^.Draw;
  1292. end;
  1293.  
  1294. procedure TDemoApp.LoadBMP;
  1295. var
  1296.   R : TRect;
  1297.   BitPtr : PBitMap;
  1298.   Cmd : integer;
  1299.   FInputBox : PFileDialog;
  1300.   FName : PathStr;
  1301.   InFile : file;
  1302.   Result : word;
  1303.   Buf : array[0..Sizeof(TBitMapInfoHeader)-1] of byte;
  1304.   TotalBytes : LONGint; {!!!}
  1305.   ErrStr : string;
  1306. begin
  1307.   BitPtr := nil;
  1308.   Inc(WinNum);
  1309.   R.A.x := 100; R.A.y := 100;
  1310.   FInputBox := New(PFileDialog, Init('*.BMP', 'LOAD AND DRAW A BITMAP', '~N~ame', fdOpenButton,0));
  1311.   Cmd := DeskTop^.ExecView(FInputBox);
  1312.  
  1313.   if (Cmd = cmFileOpen) or (Cmd = cmOK) then FInputBox^.GetFileName(FName)
  1314.       else FName := '';
  1315.   Dispose(FInputBox, Done);
  1316.   if FName <> '' then begin
  1317.     Assign(InFile, FName);
  1318.     Reset(InFile,1);   {reads 1 byte blocks}
  1319.  
  1320.       {read just the InfoHeader}
  1321.     BlockRead(InFile, Buf, Sizeof(TBitMapInfoHeader), Result);
  1322.  
  1323.         {remember - the Infoheader is in Buf, not yet in BitPtr^.}
  1324.     ErrStr := BMPFormatOKStr(PBitMap(@Buf), FName);
  1325.     If ErrStr = '' then begin
  1326.       BitPtr := AllocateBMPmem(PBitMap(@Buf)); {allocate mem,use special call}
  1327.       if BitPtr <> nil then begin
  1328.         TotalBytes := GetBitImageSize(PBitMap(@Buf));
  1329.  
  1330.         Reset(InFile,1);   {start again at beginning of file, read all}
  1331.         BlockRead(InFile, BitPtr^, TotalBytes, Result);
  1332.  
  1333.         WinToTVColor(BitPtr);
  1334.         MCur.Hide;
  1335.         PutBitMap(100,100, BitPtr, 0, NormalPut);
  1336.         MCur.Show;
  1337.       end;
  1338.     end
  1339.     else
  1340.       Cmd := MessageBox(ErrStr, nil, mfError+mfOKButton);
  1341.  
  1342.     System.Close(InFile);
  1343.  
  1344.   {! WARNING ! - following line disposes of memory used by this bitmap -
  1345.     fine here since just want to draw bitmap once on screen but disaster
  1346.     if you assign BitPtr to a View or Button in your own code!}
  1347.  
  1348.     if BitPtr <> nil then FreeMem(BitPtr, TotalBytes); {do here for demo}
  1349.   end;
  1350. end;
  1351.  
  1352.  
  1353. procedure TDemoApp.SaveDeskTop;
  1354. const
  1355.   FName = 'TVGDEMO.DSK';
  1356. var
  1357.   SaveFile : TBufStream;
  1358.   FStatus,Cmd : integer;
  1359.   Pal : PString;
  1360. begin
  1361.     SaveFile.Init(FName, stCreate, 1048);          {create a save file}
  1362.     Pal := PString(GetPalette);   {get pointer to palette}
  1363.     SaveFile.WriteStr(Pal);          {save palette}
  1364.     SaveFile.Put(DeskTop);           {save DeskTop}
  1365.     SaveFile.Flush;
  1366.     FStatus := SaveFile.Status;
  1367.     SaveFile.Done;          {flushes buffer}
  1368.     if FStatus <> stOK then
  1369.       if FStatus = stPutError then
  1370.         Cmd := MessageBox('Put of unregistered object.',nil, mfError + mfOkButton)
  1371.       else if SaveFile.ErrorInfo <> 0 then
  1372.            DOSErrorMessageBox(SaveFile.ErrorInfo, FName)
  1373.            else
  1374.              Cmd := MessageBox('Error saving file.',nil, mfError + mfOkButton);
  1375. end;
  1376.  
  1377. procedure TDemoApp.LoadDeskTop;
  1378.   procedure CloseView(P: PView); far;
  1379.   begin
  1380.     Message(P, evCommand, cmClose, nil);
  1381.   end;
  1382.   procedure ReadFile(var S : TBufStream);
  1383.   var
  1384.     Pal : PString;
  1385.   begin
  1386.     if Desktop^.Valid(cmClose) then
  1387.     begin
  1388.       Pal := S.ReadStr;
  1389.       if Pal <> nil then
  1390.       begin
  1391.         GetPalette^ := Pal^;
  1392.         DisposeStr(Pal);
  1393.       end;
  1394.       Delete(DeskTop);
  1395.       Dispose(DeskTop,Done);
  1396.       DeskTop := PDeskTop(ValidView(PDeskTop(S.Get)));
  1397.                    {May overflow memory in TV, safe in TVGraphic}
  1398.                    {note pointer type conversion to PDeskTop}
  1399.  
  1400.       Insert(DeskTop);
  1401.     end;
  1402.   end;
  1403. const
  1404.   FName = 'TVGDEMO.DSK';
  1405. var
  1406.   SaveFile : TBufStream;
  1407.   FStatus,Cmd : integer;
  1408. begin
  1409.   SaveFile.Init(FName, stOpenRead, 1048);
  1410.   if (SaveFile.Status = stOK) then begin      {found file}
  1411.     ReadFile(SaveFile);
  1412.     FStatus := SaveFile.Status;
  1413.     SaveFile.Done;          {flushes buffer}
  1414.     if FStatus <> stOK then
  1415.       if FStatus = stGetError then
  1416.         Cmd := MessageBox('Get of unregistered object.',nil, mfError + mfOkButton)
  1417.       else if SaveFile.ErrorInfo <> 0 then
  1418.            DOSErrorMessageBox(SaveFile.ErrorInfo, FName)
  1419.            else
  1420.              Cmd := MessageBox('Error reading file.',nil, mfError + mfOkButton);
  1421.   end;
  1422. end;
  1423.  
  1424. procedure TDemoApp.NewWindow;
  1425. var
  1426.   Cmd : integer;
  1427. begin
  1428.   Cmd := MessageBox(^C'Use the Windows Menu to open Windows',nil,
  1429.                        mfInformation+mfOKButton);
  1430. end;
  1431.  
  1432. procedure TDemoApp.ShowMouseBox;
  1433. type
  1434.   Temptype = record
  1435.     RW : word;
  1436.     CW : word;
  1437.   end;
  1438. var
  1439.   Win : PDialog;
  1440.   WinTitle : PGStaticText;
  1441.   OKButton,CancelButton : PButton;
  1442.   StyleStr  : string;
  1443.   Control,SaveStyle : integer;
  1444.   R     : TRect;
  1445.   Org   : TPoint;
  1446.   Lab   : PGLabel;
  1447.   Radio : PRadioButtons;
  1448.   Check : PCheckBoxes;
  1449.   Temp : Temptype;
  1450.   MGridSize : MGridRec;
  1451. begin
  1452.         R.A.x := 0;  R.B.x := R.A.x + 42 * Charlen;
  1453.         R.A.y := 0;  R.B.y := R.A.y + 19 * Boxheight;
  1454.         Win := New(PDialog,Init(R,'MOUSE GRIDS'));
  1455.         Win^.Options := Win^.Options or ofCentered;
  1456.         {Win^.HelpCtx := hcMouseGrid;}
  1457.  
  1458.         {add note}
  1459.         StyleStr:= ^C'The mouse Cursor can be continuous or snapped to an invisible grid.'+
  1460.         ^M^M^C'BoxMenus and Dialogs use the desktop grid if their own grid is not enabled.';
  1461.         R.Assign(Charlen{0},2*Boxheight, Win^.Size.x-Charlen, 7*Boxheight);
  1462.         WinTitle := New(PGStaticText,Init(R,StyleStr,DefaultOpts));
  1463.         Win^.Insert(WinTitle);
  1464.  
  1465.         {create buttons}
  1466.         Org.x := 3{2}*Charlen; Org.y := Win^.Size.y - 2*Boxheight;
  1467.         OkButton := New(POKButton,Init(Org, true));
  1468.         Win^.Insert(OKButton);
  1469.  
  1470.         Org.x := Win^.Size.x - 13{10}{9} * Charlen;
  1471.         Org.y := Win^.Size.y - 2*Boxheight;
  1472.         CancelButton := New(PCancelButton,Init(Org));
  1473.         Win^.Insert(CancelButton);
  1474.  
  1475.         {create RadioButtons}
  1476.         R.A.x := 4*Charlen;
  1477.         R.B.x := Win^.Size.x - 4*Charlen;
  1478.         R.A.y := R.B.y + 2*Boxheight;
  1479.         R.B.y := R.A.y + 3*Boxheight;
  1480.         Radio := New(PRadioButtons, Init(R,
  1481.           NewSItem('Desktop Grid off',
  1482.           NewSItem('10x10 grid for desktop',
  1483.           NewSItem('8x14 Text grid for desktop',
  1484.           nil)))));
  1485.         Radio^.HelpCtx := hcMouseGrid;
  1486.         Win^.Insert(Radio);
  1487.  
  1488.         Dec(R.A.y, Boxheight);
  1489.           {note use of txAdjustSize to avoid specifying exact size}
  1490.         Lab := New(PGLabel, Init(R,'~D~esktop',Radio,txAdjustSize));
  1491.         Win^.Insert(Lab);
  1492.         Inc(R.A.y, Boxheight);
  1493.  
  1494.         {create CheckBoxes}
  1495.         R.A.y := R.B.y + 2*Boxheight;
  1496.         R.B.y := R.A.y + 2*Boxheight;
  1497.         Check := New(PCheckBoxes, Init(R,
  1498.           NewSItem('8x14 Grid for Box Menus',
  1499.           NewSItem('8x14 Grid for Dialog Boxes',
  1500.           nil))));
  1501.         Win^.Insert(Check);
  1502.  
  1503.         Dec(R.A.y, Boxheight);
  1504.           {note use of txAdjustSize to avoid specifying exact size}
  1505.         Lab := New(PGLabel, Init(R,'Use ~S~pecialty grids',Check,txAdjustSize));
  1506.         Win^.Insert(Lab);
  1507.         Inc(R.A.y, Boxheight);
  1508.  
  1509.         {set Temp variable}
  1510.           {Desktop mouse grid: 0 = 1x1, 1=10x10, 2=8x14}
  1511.         MCur.GetGrid(MGridSize);   {added 11/11/93}
  1512.         case MGridSize.X of
  1513.           1  : Temp.RW := 0;
  1514.           10 : Temp.RW := 1;
  1515.           8  : Temp.RW := 2;
  1516.         end;
  1517.  
  1518.         Temp.CW := 0;
  1519.         if MouseSnapToMenuGrid then Temp.CW := Temp.CW or $01;
  1520.         if MouseSnapToDialogGrid then Temp.CW := Temp.CW or $02;
  1521.  
  1522.         Radio^.Select;
  1523.         Win^.SetData(Temp);
  1524.         Control := DeskTop^.ExecView(Win);   {MODAL, owner is DeskTop}
  1525.         Win^.GetData(Temp);
  1526.  
  1527.         if (Control <> cmCancel) then begin
  1528.          {Setting the mouse grid with MCur.SetGrid .
  1529.           The third and fourth parameters are an Xoffset and
  1530.           YOffset of the grid from the screen's upper left corner.
  1531.           Note that MCur.SetGrid(1,1,0,0) causes the mouse coords to
  1532.           be used as they come from the mouse driver.
  1533.           Unit MCursor also provides functions to limit the area
  1534.           of the screen the mouse cursor can move in.}
  1535.  
  1536.           case byte(Temp.RW) of
  1537.             0 : MCur.SetGrid(1,1,0,0);
  1538.             1 : MCur.SetGrid(10,10,0,0);
  1539.             2 : MCur.SetGrid(Charlen,Boxheight,0,0);
  1540.           end;
  1541.  
  1542.           if (Temp.CW and $01 <> 0) then MouseSnapToMenuGrid := true
  1543.             else MouseSnapToMenuGrid := false;
  1544.           if (Temp.CW and $02 <> 0) then MouseSnapToDialogGrid := true
  1545.             else MouseSnapToDialogGrid := false;
  1546.         end;
  1547.  
  1548.         Dispose(Win,Done);
  1549. end;
  1550.  
  1551. procedure TDemoApp.SelectDeskTopStyle;
  1552.   {While you probably won't switch Desktop styles in a real application,
  1553.    it does show two different ways you can set up a program.
  1554.    You could also change the heights and fonts of the MenuBar
  1555.    and the StatusLine. Or eliminate the StatusLine if you wish.}
  1556.  
  1557.    {Example of changing entire Application palette and also
  1558.     color pairs within the palette.}
  1559.  
  1560.   procedure SetDeskTopStyle;
  1561.   var
  1562.     R : TRect;
  1563.     PanStep,IntSize : TPoint;
  1564.     TheWindow: PWindow;
  1565.     PScrollH,PSCrollV : PScrollbar;
  1566.     PS : PScroller;
  1567.     P,PBak : PView;
  1568.     WinTitle,TestStr : string;
  1569.     Pal : PPalette;
  1570.   begin
  1571.     Delete(DeskTop);
  1572.     Dispose(DeskTop, Done);      {dispose old desktop and everything in it}
  1573.     InitDeskTop;
  1574.     Insert(DeskTop);             {insert the new one}
  1575.     ThePanWindow := nil;          {tested for nil elsewhere in program}
  1576.     Dispose(ShiftViewPtr, Done);    {dispose to reset Shiftview}
  1577.     InitShiftView;
  1578.  
  1579.     if DeskTopStyle = 1 then begin       {Panning window}
  1580.       Inc(WinNum);
  1581.       R.Assign(0, 0, 60*Charlen, 20*Boxheight);
  1582.       WinNum := 1;
  1583.       DeskTop^.GetExtent(R);
  1584.       IntSize.x := GetMaxX+200;
  1585.       IntSize.y := GetMaxY+100;
  1586.       PanStep.x := ScrnShiftX;
  1587.       PanStep.y := ScrnShiftY;
  1588.         {The pan window should be a even multiple of the mouse grid size}
  1589.       ThePanWindow := New(PPanWindow, Init(R,
  1590.         'Larger Than Screen Panning Window', wnNoNumber, IntSize, PanStep));
  1591.  
  1592.       with ThePanWindow^ do begin
  1593.         Flags := 0;        {prevent from closing}
  1594.         VOffset.y := 50;   {shift the window's Interior by 50 pixels so
  1595.                             it starts above the top of the window.}
  1596.         R.Assign(Charlen,200,InteriorSize.x-Charlen,200+4*Boxheight);
  1597.         P := New(PGStaticText, Init(R,AString+AString+AString,txAuto+font8x14));
  1598.         P^.VOptions := P^.VOptions or txDrawBackground;
  1599.         Insert(P);
  1600.       end;
  1601.       DeskTop^.Insert(ThePanWindow);
  1602.       Pal := GetPalette;
  1603.       Pal^[2] := Chr($30);    {change menu background color to cyan}
  1604.     end
  1605.     else begin
  1606.       Pal := GetPalette;
  1607.       Pal^[2] := Chr($70);    {change menu background color to light gray}
  1608.     end;
  1609.     MenuBar^.Draw;            {since changed color}
  1610.     StatusLine^.Draw;
  1611.   end;
  1612.  
  1613. type
  1614.   Temptype = record
  1615.     W : word;
  1616.   end;
  1617. var
  1618.   Win : PDialog;
  1619.   WinTitle : PGStaticText;
  1620.   OKButton,CancelButton : PButton;
  1621.   StyleStr  : Str80;
  1622.   Control : integer;
  1623.   R     : TRect;
  1624.   Org   : TPoint;
  1625.   Radio : PRadioButtons;
  1626.   Temp : Temptype;
  1627. begin
  1628.         R.A.x := 0;  R.B.x := R.A.x + 42 * Charlen;
  1629.         R.A.y := 0;  R.B.y := R.A.y + 10 * Boxheight;
  1630.         Win := New(PDialog,Init(R,'SELECT STYLE'));
  1631.         Win^.Options := Win^.Options or ofCentered;
  1632.         {SizeWin^.HelpCtx := hcSizeWin;}
  1633.  
  1634.                       {add note}
  1635.         StyleStr:= ^C'Changing Style clears the DeskTop.';
  1636.         R.Assign(0,2*Boxheight, Win^.Size.x, 3*Boxheight);
  1637.         WinTitle := New(PGStaticText,Init(R,StyleStr,DefaultOpts));
  1638.         Win^.Insert(WinTitle);
  1639.  
  1640.         {create buttons}
  1641.         Org.x := 3{2}*Charlen; Org.y := Win^.Size.y - 2*Boxheight;
  1642.         OkButton := New(POKButton,Init(Org, true));
  1643.         Win^.Insert(OKButton);
  1644.  
  1645.         Org.x := Win^.Size.x - 13{10}{9} * Charlen;
  1646.         Org.y := Win^.Size.y - 2*Boxheight;
  1647.         CancelButton := New(PCancelButton,Init(Org));
  1648.         Win^.Insert(CancelButton);
  1649.  
  1650.         {create RadioButtons}
  1651.         R.A.x := 4*Charlen;
  1652.         R.B.x := Win^.Size.x - 4*Charlen;
  1653.         Inc(R.A.y, 2*Boxheight);
  1654.         R.B.y := R.A.y + 2*Boxheight;
  1655.         Radio := New(PRadioButtons, Init(R,
  1656.           NewSItem('Multiple Non-Panning Windows',
  1657.           NewSItem('Full Screen Panning Window',
  1658.           nil))));
  1659.         Win^.Insert(Radio);
  1660.  
  1661.           {DeskTopStyle: 0 = non-panning, 1=panning}
  1662.         Temp.W := DeskTopStyle;
  1663.  
  1664.         Win^.SetData(Temp.W);
  1665.         Control := DeskTop^.ExecView(Win);   {MODAL, owner is DeskTop}
  1666.         Win^.GetData(Temp.W);
  1667.  
  1668.         if (Control <> cmCancel) and (Temp.W <> DeskTopStyle) then begin
  1669.           DeskTopStyle := Temp.W;
  1670.           SetDeskTopStyle;
  1671.         end;
  1672.  
  1673.         Dispose(Win,Done);
  1674. end;
  1675.  
  1676.  
  1677. var
  1678.   DemoApp: TDemoApp;
  1679. begin
  1680.   DemoApp.Init;
  1681.   DemoApp.Run;
  1682.   DemoApp.Done;
  1683. end.
  1684.