Open navigation menu
Close suggestions
Search
Search
en
Change Language
Upload
Sign in
Sign in
Download free for days
0 ratings
0% found this document useful (0 votes)
495 views
Turbo Pascal 6.0 Turbo Vision Guide
Borland Turbo Pascal 6.0 Turbo Vision Guide
Uploaded by
sirjole7584
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content,
claim it here
.
Available Formats
Download as PDF or read online on Scribd
Download now
Download
Save Turbo Pascal 6.0 Turbo Vision Guide For Later
Download
Save
Save Turbo Pascal 6.0 Turbo Vision Guide For Later
0%
0% found this document useful, undefined
0%
, undefined
Embed
Share
Print
Report
0 ratings
0% found this document useful (0 votes)
495 views
Turbo Pascal 6.0 Turbo Vision Guide
Borland Turbo Pascal 6.0 Turbo Vision Guide
Uploaded by
sirjole7584
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content,
claim it here
.
Available Formats
Download as PDF or read online on Scribd
Download now
Download
Save Turbo Pascal 6.0 Turbo Vision Guide For Later
Carousel Previous
Carousel Next
Save
Save Turbo Pascal 6.0 Turbo Vision Guide For Later
0%
0% found this document useful, undefined
0%
, undefined
Embed
Share
Print
Report
Download now
Download
You are on page 1
/ 215
Search
Fullscreen
TURBO PASCALTurbo Pascal? Version 6.0 Turbo Vision Guide SORIANO ATERYATONAL NC. 1890 GREEN HLS ROAD PLO. BOX 600001, SCOMSVALLEY. GA 8067-00 RRRRBB seseen SSSSBIReeCopyright © 1990 by Borland Intemational, Allrights reserved. Al Borland products are frademaris or registered frademarics of 'Boniand international. nc. Other brand and product names are frademarks or registered trademarks of thei respective holders. PRINTED INTHE USA. 10987654321 Introduction Why Turbo Vision? ‘What is Turbo Vision? ‘What you need to know ‘What’ in this book? ing T Chapter 1 Inheriting the wheel 7 ‘The framework ofa windowing application ......-.+++. ; Anew Vision of application development .8 ‘The elements of a Turbo Vision application ...... Naming of parts... Views -- Events... Mute objects A-common “look and feel”... “ello, World!” Turbo Vision style... Running HELLO.PAS : Pulling down a menu A.dialog box Buttons . : Getting out =... Inside HELLO.PAS ‘The application object The dialog box object 5 Flow of execution and debugging =... 19 HELLO$ main program... ‘The Init method. ‘The Run method « ‘The Done method Summary... ion Chapter 2 Writing Turbo Vision applications ‘Your first Turbo Vision application . ‘The desktop, menu bar, and status line The desktop ‘The status line «.....+. Creating new commands . ‘The menu bar ‘Anote on structure Opening a window Standard window equipment Window initialization The Insert method Closing a window ..- Window behavior 220.22... Look through any window « What do you see? ....-.. Abetter way to Write A simple file viewer . Reading a text file Buffered drawing « The draw butfer Moving text into a buffer - Writing buffer contents Knowing how much to write Scrolling up and down .. Multiple views in a window ‘Where to put the functionality Making a dialog box... Executing a modal dialog box ‘Taking control Button, bution... Normal and default buttons Ea Focused controls ..... ‘Take your pick BESSSESVSLRLLSSSVSBRRRRBBCreating a cluster Check box values ‘One more cluster Labeling the controls ‘The input line object Setting and getting data Shortcut keys and conflicts Ending the dialog box : Other dialog box controls <2. .....22. 61 Static text. mo List viewer .. List box, History... Standard dialog boxes Part 2 Programming Turbo Vision hepter 9 The object hierarchy Object typology ‘Abstract objects « “Abstract methods Object instantiations and derivations. Tnstantiation Derivation ‘Turbo Vision methods “Abstract methods Pseudo-abstract methods Virtual methods . Static methods . Turbo Vision fields - Primitive object types - SRARL SS Groups. ‘The abstract group - Desktops Programs ... Applications Windows .. Dialog boxes Terminal views Frames Buttons Clusters Menus . Histories Input lines List viewers Scrolling objects Text devices Statictext.. Status lines Non-visible elements . Streams. DOS streams Buffered streams - EMS streams Resources . Collections Sorted collections String collections . Resource collections String lists Chapter 4 Views ‘We have taken contol of your TV.. Simple view objects Setting your sights Getting the TPoint - Getting into a TRect -- ‘Turbo Vision coordinates. - ‘Making an appearance Territoriality Drawing on demand Putting on your best behavior Complex views .....-.++ Groups and subviews Getting into a group ‘Another angle on Z-order «..-.-. Group portraits ..... fees 88 Relationships between views: 90 ‘The object hierarchy : (Ownership Subviews and view trees . aaaa 76 76 76 76 RN PEEEEE EE] Selected and focused views . Finding the focused view How does a view get the focus? . ‘The focus chain . : Modal views ..... Modifying default behavior»... ‘The Options flag word . ofSelectable ‘ofTopSelect ofFirstClick offramed ofPreProcess ofPostProcess .-..-. ofBuffered 100 ofTileable ofCenterX ofCenterY ofCentered . The GrowMode fag byte. gfGrowLoX gfGrowLoY giGrowHix, gfGrowHiY giGrowAll . gfGrowRel . fa) ‘The DragMode flag byte 102 dmDragMove dmDragGrow dmLimitLox dmLimitLoY BSSEESSELLEEE State flag and SetState - ‘Acting on a state change . What colorie your view? . Color paleties . Inside color palettes - The GetColor method - : Overriding the default colors ....... 107 Adding new colors 108 Chapter 5 Event-driven programming 108 Bringing Turbo Vision to life . Reading the user's input. ‘The nature of events Kinds of events .... Mouse events... Keyboard events «... Message events “Nothing” events Events and commands . Routing of events " ‘Where do events come from? «++... 113 Where do events go? .. Positional events Focused events « Broadcast events User-defined events . ‘Masking events . Phase... The Phase field Commands ......+. Defining commands . Binding commands Enabling and disabling commands Handling events ‘The event record Clearing events «... Abandoned events = ‘Modifying the event mechanism Centralized event gathering Overriding GetBvent Using idle time .... Inter-view communication Intermediaries .. Messages among views ‘Who handled the broadcast? Isanyone out there? .. Who's on top? .. Calling HandleEvent « Help contextChapter 6 Writing safe programs 131 Allornothing programming . 131 ‘The safety pool ...... ‘The ValidView method Non-memory errors .. Reporting errors “Major consumers : Chapter 7 Collections 137 Collection objects ...... S Collections are dynamically sized... 138 Collections are polymorphic 138 ‘Type checking and collections 138 Collecting non-objects Creating a collection Iterator methods ... ‘The Forkach iterator : ‘The FirstThat and LastThat iterators | 142 Sorted collections String collections Tterators revisited Finding an item a 16 Polymorphic collections 146 Collections and memory management . 149 Chapter 8 Streams ‘The question: Object I/O ‘The answer: Streams ‘Streams are polymorphic Streams handle objects Essential stream usage Setting up a stream Reading and writing a stream. Putting it on Getting it back Incase of errors... Shutting down the streaan » Making objects streamable Load and Store methods ‘Stream registration . ‘Object ID numbers... ‘The automatic fields Register here .. Registering standard objects - ‘The stream mechanism . ‘The Put process ‘The Get process Handling nil object pointers - Collections on seams: A complete example ..... 160 ‘Adding Store methods .....1-.+. 161 Registration records 162 Registering ...... 163 ‘Writing to the stream . 2168 Who gets to store things? -- Subview instances... Peer view instances Storing and loading the desktop Copying a stream ...... Random-access streams [Non-objects on streams Designing your own streams Stream error handling .. Chapter 9 Resources 168 Why use resources? wee What’ ina resource? - 170 Creating a resource v7 Reading a resource . 12 String lists : 173 Making string lists - : 174 Chapter 10 Hints and tips 175 Debugging Turbo Vision applications . 175 Itdoesn’t get there ........ Hiding behind a mask Stolen events ..... Blame your parents Itdoesn’t do what I expect Ithangs....... Ponting applications io Turbo Vision »-. 178 Scavenge your old code . 22 18 Rethink your organization 2179 Using bitmapped fields . 180 Flag values Bit masks . Bitwise operations - Setting a bit Clearing a bit 181 Checking bits |. 182 Using masks 182 ‘Summary : 182 Part3 Turbo Vision Reference Chapter 11 How to use the reference 185 How to find what you want ........-. 185 Objects in general 186 Naming conventions .- 186 ‘Chapter 12 Unit cross reference 189 The Objects unit ..... Objects unit types «oe. ssss see, 190 Constants... : Stream access modes 190 Stream error codes «= ....sss.000. 190 Maximum collection size .-..s-.. 191 Collection error codes, rer Variables... : 191 Procedures and functions 191 The Views units... Types - Constants TWiew State masks - Views unit constants ‘View Option masks TView GrowMode masics TView DragMode masks Scroll bar part codes, Window flag masks Window palette entries Standard view commande Variables Function . ‘The Dialogs unit Types... Constants Button fags Procedures and functions ‘The App unit Types ...- Variables ‘The Menus unit - Types Procedures and functions ‘TMenultem functions ‘TMenu routines ...... ‘TStatusL.ine functions ‘The Drivers unit Types Constants “Mouse bution state masks Event codes «.....-.+. Event masks. Keyboard state and shift masks .-. 199 Standard command codes ........ 199 ‘TDialog standard commands « Screen modes... 5 Variables Initialized variables... Uninitialized variables 02.0... System error handler variables -. Procedures and functions ........ Event manager procedures Screen manager procedures Default system error handler function . . System error handler procedures .. 201 Keyboard support functions 201 String formatting procedure ..... Buffer move procedures . String length function Driver initialization . The TextView unit The Memory unit . — Variables ......2.2.+4 + 203 Procedures and functions 203 ‘The HistList unit 203 Variables ...... 203 Procedures and functions 208Chapter 13 Object reference ‘TSample object Fields ...... Methods ‘TApplication vw Fields Methods THistory .. Fields Methods - Palette THistoryViewer - ‘TParamText -. ‘TotrListMaker .. Chapter 14 Global reference a7 ‘Sample procedure : Abstract procedure ‘Application variable . ‘AppPalette variable 328 apXXXX constants 329 ‘AssignDevice procedure 329 DEXXXX constants... 329 ButtonCount variable -. CCheckSnow variable . ClearHistory procedure - 330 ClearSereen procedure . 331 emXXXX constants 331 coXXXX constants 334 (CStrLen function... (CtrlBreakHit variable CtrlToArrow function - + 335 CursorLines variable + 336 DeskTop variable 336 DisposeMenu procedure + 336 DisposeStr procedure + 336 ‘dmXXXX constants 37 DoneBvents procedure + 337 DoneHistory procedure . + 338 DoneMemory procedure + 338 DoneSysError procedure . + 338DoneVideo procedure DoubleDelay variable EmsCurFlandle variable EmsCurPage variable . evXXXX constants « FNameSt type 4 FocusedEvents variable . FormatStr procedure . FreeBufMem procedure . GetAltChar function GetAltCode function. GetBufMem procedure GetKeyEvent procedure. GetMouseBvent procedure - SXXXX constants. ReXXXX constants HideMouse procedure . HiResScreen variable HistoryAdd procedure HistoryBlock variable HistoryCount fanetion HistorySize variable . HistorySt function HistoryUsed variable InitEvents procedure InitHistory procedure InitMemory procedure. InitSyslind procedure InitVideo procedure KbXXXX constants - LongDiv function LongMul function LongRec type LowMemory function LowMemSize variable 353, ‘MaxBufem vanable 354 MaxCollectionSize variable... 1... + 354 MaxViewWidth constant ......s0000. 354 mbXXXX constants ‘MemAlloc function «2... MemAllocSeg function. MenuBar variable ». Message function MinWinSize variable MouseButtons variable... MouseEvents variable MouselntFlag variable MouseWhere variable MoveBuf procedure .. MoveChar procedure MoveCStr procedure - MoveStr procedure Newltem function Newline function NewMenu function NewSItem function NewStatusDef function . NewStatusKey function . NewStr function ...... NewSubMenu function . OfKXXX constants. PChar type .. PositionalEvents variable... PrintStr procedure . PString type PtrRec type .- RegisterDialogs procedure. Registertype procedure . RepeatDelay variable SaveCtriBreak variable... sbXXXX constants « ScreenBuffer variable . ScreenHeight variable ScreenMode variable . ScreenWidth variable . SelectMode type . ‘SetMemTop procedure . SetVideoMode procedure S{XXXX constants ShadowAttr variable ShadowSize variable . ShowMarkers variable ShowMouse procedure . smXXXX constants. SpecialChars variable .. stXXXX constants StartupMode variable StatusLine variable StreamError variable 7 SysColorAttr variable ...... : SysErrActive variable .....0......0+++ SysErrorFunc variable SysMonoAttr variable. SystemError function . ‘TByteArray type ‘TTerminalBuffer type. ‘TCommandSet type ‘Thitlestr type . ‘TDrawButfer type ‘TVideoBut type ‘TEvent type . ‘TWordArray type. TitemList type - wOQOXX constants... ‘TMenu type ..- wnNoNumber constant ‘TMenultem type WordRec type .... ‘TMenuStr type wpXXXX constants teat! Index 3872: Data for dialog box controls 38 34: Inheritance of view fields LT 1: Turbo Vision command ranges... ..120 1: Turbo Vision constant prefixes... .187 1: Turbo Vision units ...............189 Stream error codes - 295 ‘Application palette constants 142: Button flags . : 143: Standard command codes 144: Dialog box standard commands ...332 145: Standard view commands 146: Collection error codes «....- 147: Control-key mappings 148: Drag mode constants .. 149: Standard event flags . 1410: Standard event masks | 1411: Format specifiers and their results 342 1412: Grow mode flag definitions 346 1413; Help context constants ... 346 14.14: Keyboard state and shift masks 50 1415: Altetter key codes .. 1416: Special key codes ..... 1417: Alt-number key codes » 1418: Function key codes 1419: Shift-function key codes 14.20: Ctrlfunction key codes 14.21: Alt-function key codes 14.22: Mouse button constants ‘Option flags Scroll bar part constants 14.25: StandardScrollBar constants 14.26: State flag constants. 14.27: Screen mode constants 1428: Stream access modes, 14.29; Stream error codes . 14.30: System error function codes . . 2374 1431: System error function return values 37 1d: Systemes fonction messages «57 ream record fields 381 1434 Window flag constants ... 384 14.35: Standard window palettes, 385 11: Turbo Vision objects onscreen . 1.2: The HELLO.PAS startup screen 21: Default TApplication screen . 2.2: TVGUIDOS with multiple windows open - 23: TVGUIDOS with open window 214: Multiple file views ile viewer with scroling interior fndow with multiple panes - Simple dialog box - jalog box with buttons «.....- ialog box with labeled chusters sput line added - 211: Dialog box with initial values set. 34: Turbo Vision object hierarchy 44: Turbo Vision coordinate system - 42: TApplication screen layout 43: Side view of a text viewer window 4: Side view of the desktop .. 45: A simple dialog box ...-.-. 46: Turbo Vision object hierarchy . simple dialog box’s view tree eeeezeraznn Basic Turbo Vision view tree «.......92 49: Desktop with file viewer added... ..93 4.10: View tree with file viewer added. -.93 411: Desktop with file viewer added .....94 4.12: View tree with two file viewers added .......2.. 94 4.13: The focus chain . 96 414: Options bit flags «..-.-. 9 415: GrowMode bit flags -.- :101 416: DragMode bit flags "102 417: State flag bit mapping - 2103 4.16: TScroller® default color palette’... .105 449: Mapping a scroller’s palette onto a window .. 5.1: TEvent. What field bit mapping. ---112 184: GrowMode bit mapping, 132: DragMode bit mapping 18.3: Options bit flags - dd: Drag mode bit flags 142: Bvent mask bit mapping - 143: Grow mode bit mapping 1444: Options bit flags 145: Scroll bar parts 146: State flag bit mapping - sprue‘This volume contains complete documentation for Turbo Vision, a ‘whole new way of looking at application development. We describe not only what Turbo Vision can do and how, but also why. fyou take the time to understand the underlying principles of ‘Turbo Vision, you will find ita rewarding, time-saving, and productive tool: You can build sophisticated, consistent interactive applications in less time than you thought possible. Why Turbo Vision? ‘After creating a number of programs with windows, dialogs, ‘menus, and mouse support at Borland, we decided to package all, that functionality into a reusable set of tools. Object-oriented ‘programming gave us the vehicle, and Turbo Vision is the result. Does it work? You bet! We used Turbo Vision to write the new integrated development environment for Turbo Pascal in a fraction of the time it would have taken to write it from scratch. Now you can use these same tools to write your own applications. With Turbo Vision and object-oriented programming, you don't have to reinvent the wheel—you can inherit ours! If you write character-based applications that need a high: performance, flexible, and consistent interactive user interface, ‘Turbo Vision is for yor What is Turbo Vision? Introduction ‘Turbo Vision is an object-oriented application framework for windowing programs. We created Turbo Vision to save you fromendlessly recreating the basic platform on which you build your application programs, ‘Turbo Vision is a complete object-oriented library, including: = Multiple, resizeable, overlapping windows = Pull-down menus = Mouse support mDialog boxes ‘Built-in color installation Buttons, scroll bars, input boxes, check boxes and radio buttons Standard handling of keystrokes and mouse clicks mAnd more! Using Turbo Vision, all your applications can have this state-of- the-art look and feel, with very little effort on your part. What you need to know ‘You need to be pretty comfortable with object-oriented programming in order to use Turbo Vision. Applications written in Turbo Vision make extensive use of object-oriented techniques, including inheritance and polymorphism. These topics are covered in Chapter 4, “Object-oriented programming,” in the User's Guide. Inaddition to object-oriented techniques, you also need to be familiar with the use of pointers and dynamic variables, because nearly all of Turbo Vision’s object instances are dynamically allocated on the heap. You may want to review the extended syntax of the New function, which allows the inclusion of a ‘constructor as a parameter. Most instances of Turbo Vision objects are created that way. What's in this book? Because Turbo Vision is new, and because it uses some techniques that might be unfamiliar to many programmers, we have included a lot of explanatory material and a complete reference section. Tutbo Vision Guide Introduction ‘This manual is divided into three parts: =Part 1 introduces you to the basic principles behind Turbo Vision and provides a tutorial that walks you through the ‘process of writing Turbo Vision applications. Part 2 gives greater detail on all the essential elements of Turbo ‘Vision, including explanations of the members of the Turbo Vision object hierarchy and suggestions for how to write better applications. Part 3is a complete reference lookup for all the objects and. other elements included in the Turbo Vision units.| Learning Turbo Vision Turbo Vision Guide | .Inheriting the wheel How much of your last application was meat, and how much was, bones? ‘The meat of an application is the part that solves the problem the application was written to address: Calculations, database ‘manipulations, and so on. The bones, on the other hand, are the parts that hold the whole thing together: Menus, editable fields, error reporting, mouse handlers, and so on. If your applications are like most, you spend as much or more time writing the bones as you do the meat. And while this sort of program infrastructure can in general be applied to any application, out of habit most programmers just keep writing new field editors, menu ‘managers, event handlers, and so on, with only minor differences, for each new project they begin. ‘You've been wamed often enough to avoid reinventing the same old wheel, So here's your chance to stop reinventing the wheel— and start inheriting it. The framework of a windowing application ‘Turbo Vision is the framework of an event-driven, windowing application. There's no meat as delivered—just a strong, flexible skeleton. You flesh the skeleton out by using the extensibility feature of Turbo Pascal object-oriented programming. Turbo Vision provides you with a skeleton application object, Tutbo Vision Guide Chapter 1, nhenting the wheel 7‘Application, and you create a descendant object of TApplication— call it MyApplication, perhaps—to act as your application. Then you add to My Application what it needs to get your job done. ‘At the very highest level, that’s all there isto it. The entire begin..end block of your application program looks like this: begin pppphication.tnit; (Set the application op... pappicat ion. Runs Cescran ity mytepLication.Done; ( ...and then put it avay when you're done! | nd. Anew Vision of application development A You've probably used procedure/function libraries before, and at first glance Turbo Vision sounds a lot like traditional libraries, Alter all, libraries can be purchased to provide menus, windows, mouse bindings, and so on. But beneath that superficial resemblance is a radical difference, one that is worth, understanding to avoid running up against some very high and very hard conceptual walls. ‘The first thing to do is remind yourself that you're now in object country. In traditional structured programming, when a tool such as a menu manager doesn’t quite suit your needs, you modify the tool's source code until it does. Going in and changing the tool’s source code isa bold step that is difficult to reverse, unless you somehow take note of exactly what the code originally looked like. Furthermore, changing proven source code (especially source code written by somebody else) is a fine way to introduce ‘obnoxious new bugs into a proven subsystem, bugs that could propagate far beyond your area of original concern. With Turbo Vision, you never have to modify the actual source code. You “change” Turbo Vision by extending it. The TApplication application skeleton remaine unchanged inside APP.TPU. You add to it by deriving new object types, and change what you need to by overriding the inherited methods with new methods that ‘you write for your new objects. Also, Turbo Vision isa hierarchy, not just a disjoint box full of tools. Ifyou use any of it at all, you should use all of it. There isa single architectural vision behind every component of Turbo Vision, and they all work together in many subtle, interlocking ways. You Turbo Vision Guide shouldn't try to just “pull out” mouse support and use it—the “pulling out” would be more work than writing your own mouse bindings from scratch. ‘These two recommendations are the foundation of the Turbo Vision development philosophy: Use object-oriented techniques fully, and embrace the entirety of Turbo Vision on its own terms. This ‘means playing by Turbo Vision’ “rules” and using its component ‘object types as they were intended to be used. We created Turbo ‘Vision to save you an enormous amount of unnecessary, repetitive ‘work, and to provide you with a proven application framework ‘you can trust. To get the most benefit from it, et Turbo Vision do the work. The elements of a Turbo Vision application Naming of parts Views Views ore coveredin detail in Chapier4 Events Chapter 1, Inheriting the wheel Before we look at how a Turbo Vision application works, lets take a look at “what's in the box”—what tools Turbo Vision gives you to build your applications with. 'A Turbo Vision application is a cooperating society of views, events, and mute objects. A piew is any program element that is visible on the screen—and all such elements are objects. In a Turbo Visfon context, if you can see it, its a view. Fields, field captions, window borders, scroll bars, menu bars, and dialog boxes are all views. Views can be combined to form more complex elements like windows and dialog boxes. These collective views are called groups, and they operate together as though they were a single view. Conceptually, groups may be considered views. Views are always rectangular. This includes rectangles that contain a single character, or lines which are only one character high or one character wide. An event is some sort of occurrence to which your application ‘ust respond. Events come from the keyboard, from the mouse, ‘or from other parts of Turbo Vision. For example, a keystroke is an event, as isa click of a mouse button. Events are queued up byEvents ore exeionedin deta’ Turbo Vision's application skeleton as they occur, then they are in Chapters. Mute objects Acommon “look and feel” processed in order by an event handler. The TApplication object, which is the body of your application, contains an event handler. ‘Through a mechanism that will be explained later on, events that are not serviced by TApplication are passed along to other views ‘owned by the program until either a view is found to handle the event, or an “abandoned event” error occurs. For example, an 1 keystroke invokes the help system. Unless each view has its own entry to the help system (as might happen ina context-sensitive help system) the Ff keystroke is handled by ‘the main program’ event handler. Ordinary alphanumeric keys or the line-editing keys, by contrast, need to be handlled by the view ‘that currently has the focus; that is, the view that is currently interacting with the user, Mute objects are any other objects in the program that are not views. They are “mute” because they do not speak to the screen themselves. They perform calculations, communicate with peripherals, and generally do the work of the application. When a :mute object needs to display some output to the screen, it must do 0 through the cooperation of a view. This concept is very important to keeping order in a Turbo Vision application: Only views may access the display Nothing will stop your mute objects from writing to the display with Turbo Pascal's Write or Writeln statements. However, if you write to the display “on your own,” the text you write will disrupt the text that Turbo Vision writes, and the text that Turbo Vision writes (by moving or sizing windows, for example) will obliterate this “renegade” text. Because Turbo Vision was designed to take a standardized, rational approach to screen design, your applications acquire a familiar look and feel. That look artd feel is identical tu that of the ‘Turbo languages themselves, and is based on years of experience and usability testing, Having a common and well-understood look to an application is a distinct advantage to your users and to yourself: No matter how arcane your application isin terms of ‘what it does, the way to use it will always be familiar ground, and the learning curve will be easier to ascend. Turbo Vision Guide As hese tems ore descitbed "h Chapford, Views” Turbo Vion abject Figure 11 shows a collection of common objects that might appear as part of a Turbo Vision application. The desktop is the shaded background against which the rest of the application appears. Like everything else in Turbo Vision, the desktop is an object. So are the menu bar at the top of the display and the status line at the bottom. Words in the menu bar represent menus, which are “pulled down” by clicking on the words with the mouse pointer cor by pressing hotkeys. ‘The text that appears in the status line is up to you, but typically it displays messages about the current state of your application, shows available hot keys, or prompts for commands that are currently available to the user. When a menu is pulled down, a highlight bar slides up and down ‘the men’s list of selections in response to movements of the ‘mouse or cursor keys. When you press Ener or click the left mouse button, the item highlighted at the time of the button press is selected. Selecting a menu item transmits a command to some ppart of the application. Your application typically communicates with the user through a - é£é + i~- on the desktop in response to commands from the mouse oF the keyboard. Turbo Vision provides a great assortment of window machinery for entering and displaying information. Window interiors can be made scrollable, which enbles windows to act a8 portals into larger data displays such as document ies. Sroling the window across the data is done by moving a sera br along Chapter 1. nherting the whee! uthe bottom of the window, the right side of the window, or both. ‘The scroll bar indicates the window's position relative to the entirety of the data being displayed. Dialog boxes often contain buttons, which are highlighted words that can be selected by clicking on them (or by Tabbing to the button and pressing Spacebar) The displayed words appear to ‘move “downward” in response to the click (as a physical push- button would) and can be set to transmit a command to the application. “Hello, World!” Turbo Vision style The “Holo, Wed” code ts ‘glen the fle HELLO.PAS.on 12 your dsibution dks. ‘The traditional way to demonstrate how to use any new language ‘or user interface toolkit is to present a “Fello, world” program ‘written with the tools in question. This program usually consists of only enough code to display the string “Hello, World” on the screen, and to return control to DOS. ‘Turbo Vision gives us a different way to say “Hello, World!” ‘The classic “Hello, World” program is not interactive (it “talks but it doesn't “listen”) and Turbo Vision is above all to! for producing interactive programs. ‘The simplest Turbo Vision application is much more involved than a Writeln sandwiched between begin and end. Compared to the classic “Hello, World” program, Turbo Vision's HELLO.PAS does a fair number of things, including clearing the desktop to a halftone pattern ‘displaying a menu bar and a status line at the top and bottom of, the screen establishing a handler for keystrokes and mouse events building a menu object “behind the scenes” and connecting it to the menu bar building a dialog box, also “behind the scenes” connecting the dialog box to the menu sm waiting for you to take some action, through the mouse or Keyboard Nowhere in this list is there anything about displaying text to the sereen. Some text has been prepared, but it’ all in the background, waiting to be called up on command. That’s Turbo Vision Guide Running HELLO.PAS Fgue 12 The HELLOPAS storup screen ‘something to keep in mind while you're learning Turbo Vision: ‘The essence of programming with Turbo Vision is designing a ‘custom view and teaching it what to do when it receives ‘commands. Turbo Vision--the framework—worries about getting your view the proper commands. You only have to worry about ‘what to do when the keystroke, mouse click, or menu command finds its way to your view’s code, ‘The meat of your program is the code that performs some ‘meaningful work in response to commands entered by the user— and this “meaty” cotle is contained in the view objects you create. Before we dissect HELLO-PAS in detail, it would be a good idea to load the program, compile it, and follow through its execution. ‘When run, Hello clears the screen, and creates a desktop like that shown in Figure 1.2. No windows are open, and only one item appears in the menu bar at the top of the screen: the command Hello. Notice that the “H” in Hello is set off in a different color from the “ello”, and that the status bar contains a message: Alt-X Beit. This isa good time to point out two general rules for program- ‘ing in any user environment: Never put the user at a loss as to what todo next, and always give the user away forward and a woay back. Before doing anything at all, the user of Hello has two clear choices: Either select the menu item Hello or press AitX o leave the program entirely, Chapter 1. Inheriting ihe wheel 13Pulling down a menu Fque 13 The HELLOPAS Hi menu ‘With that in mind, select Hello in the menu bar. There are actually three ways to do this: Move the mouse pointer over Hello and click the left button. Press F10 to take the cursor to the menu bar, where Hello becomes highlighted. Then press Enterto select Hello. Press AltH, where H is the highlighted character in the menu. command Hello. Mall three cases, a pull-down menu appears beneath the item Hello. This should feel familiar to you, a8 a Turbo Pascal programmer. I's the same way the Turbo Pascal IDE operates. ‘You'll find that Turbo Vision uses all of the conventions of the ‘Turbo Pascal integrated environment. Afterall, the IDE is a Turbo Vision application! ‘The menu that appears is shown in Figure 1.3. There are only two items in the menu, separated by a single line into two separate panes. Hell is so simple that there is only one menu iter in each ppane, but in fact there may be any number of items in a pane, subject to the limitations of the screen. =a ‘You can select a menu item either from the keyboard or with the mouse. The arrow keys move the kighlight bar up and down the ‘menu, Selecting a highlighted item from the keyboard is done by pressing Enter when the desired item is under the highlight bar. More interesting is selection by mouse: You “grasp” the highlight bar by pressing the left mouse button down while the mouse pointer is on the highlight bar and holding the button down. As long as you hold the button down, you can move the bar up and down the list of menu items within the menu, You select one of the menu items by Tetting go of the mouse button when the highlight bar is over the menu item that you wish to select. Turbo Vision Guide: A dialog box An oo.) fra moni som usedio mekoote at ‘he fem inccker @ GaI60 ‘oe Figue 14 The Hello World dolog box Buttons However you select it, the Greeting item in the menu brings up a rectangular window called a dialog box, as shown in Figure 1.4. ‘The dialog box appears in the center of the screen, but you can move it around the screen by moving the mouse pointer to the top line of the dialog box, pressing the left mouse button, and moving the mouse while you hold the button dewon. As soon as you let the button up, the dialog box will stop where itis and remain there, ()— tet, writ Taniteg tow are yout mall ee om ‘The dialog box has a title, “Hello, World!”, and a close icon at its upper left comer. The close icon, when clicked by the mouse, closes the dialog box and make it disappear. Inside the dialog box isa short text string: “How are you?” This is an example of static text, which is text that can be read but which contains no interactive power. In other words, static text is used to label things, but nothing happens if you click on it. ‘The four rectangles on the right side of the box are the most interesting parts of the “Hiello, World!” dialog box. These are called buttons, and are examples of controls. They are called controls because they resemble the controls on electronic instruments. Each button has a label, which indicates what happens when that button is pushed. ‘You push a button by clicking on it with the mouse, or by making the button the default (described later in this section) and then. pressing Ene. Try pressing one of the buttons with the mouse (holding down the mouse button while the pointer is on the button) and see what happens: The body of the button moves one position to the right, and its shadow vanishes. The illusion is that of a rectangular bution being pressed “downward” toward the Chapter 1, Inheriting ine wheel 6Monochrome systems Inefcate ne detour button wih" character. Getting out screen. When you release the mouse button, the action specified by the button takes place. ‘Notice that the title inside the Cancel button is colored differently than the others. The difference in color indicates that the Cancel Dutton is currently the default control within the dialog box. If you press Enter while Cancel is the default, you are in effect pressing the Cancel button. ‘The default control within a dialog box can be changed by pressing the Tab key. Try Tating around in the “Hello, World!” dialog box. The distinctive default colors move from one button to the next with each press of the Tab key. This allows the user to press a button without using a mouse, by moving the default to the chosen button with the Tab key, and then pressing Enferor ‘Spacebarto perform the actual “press of the button.” Pressing any of the buttons in Hello “puts away” the dialog box and leaves you with an empty desktop. You can pull down the Hello menui again, and bring up the dialog box again, any number of times. To exit the program, you can either select the Exit item in the Hello menu, or simply press the Exit shortcut, AIbX. Note that this shortcut is presented both inside the Hello menu and in the status line at the bottom of the screen. ‘This is good practice: Altoays make it easy for the user to exit the program. Frustrated users who can’t find the door are quite likely to reboot the system, preventing your application from closing files or otherwise cleaning house before shutting down, Inside HELLO.PAS 16 ‘That's what Hello does if you run it. Now, how does it make all this happen? Much—in fact, most—of the code comprising Hello is inherited from predetined objects provided in Turbo Vision. 50 ‘much is inherited that when the program runs, haw it works may first seem a bit of a mystery. Tracing execution with the integrated debugger will not show you the whole picture, since Turbo Vision is provided as compiled units. Fortunately, if you take the time to understand what is going on, the exact how won't be necesssary. Turbo Vision Guide The application object To.understand a Turbo Vision application, start by reminding yourself that a Turbo Vision application is a society of objects working ‘ogether Find the major objects and understand how they work together. Then see how the lesser objects support the major objects. Be sure you read and understand the object definitions before you read the method implementations. Its important that you first understand what an object contains and how it relates tothe other ‘objects inthe system, ‘The cornerstone object of any application is the TApplication object. Actually, you never create an instance of object type ‘Application. TApplication is an abstract object type—just bones, no ‘meat. It doesn’t do anything. You use TApplication by creating a descendant object type of TApplication that contains the meat of the program you're writing. In Hello, that descendant object type is THelleApp: LL = “tel Lapp: Telicdyy = ebject (apy ication) precedare See! nor: Procedare Sandletvest (vas Event: Evert) vista; Peecedre Inictensbar; viral; procedure Inestatosine; virtual ws: As shown here its a good idea to define a pointer type to every, object type that you define, since most serious work with objects ‘operates through pointer references. Polymorphism works primarily through pointer references. THelloApp contains much more than just these four methods, of course; a descendant object inherits cverything from its ancestor. In defining THelloApp, you define how the new object difers from its ancestor, TApplication. Everything that you do not redefine is anherited unchanged trom Applicaton Ifyou think about it, the four method definitions in THelloApp down the “big picture” of your entire application: ‘How the application functions is dictated by what events it responds to, and how it responds to them, You must define a HandleEvent method to fulfill this all-important requirement. A HandleEvent method is defined in TApplication to deal with Chapter I. inheriting the wheel vThe dialog box object ‘generic events that occur within any application, but you must provide one that handles events specific to your own application. ss The InitMenuBar method sets up the menus behind the menu bar for your application. TApplication has a menu bar but no menus; if you want menus (and it would be a poor application indeed without them!) you simply define a method to define ‘the menus. You might wonder why InitMenuBar's code isn’t part of THelloApp’s constructor. It could be, but a more ‘advanced application might wish to choose among several ‘possible menus for its initial menu display. Best to leave that ‘outside of the constructor, and allow the constructor to set up ‘only those things that are always done the same way every time the application is run. The initStatusLine method sets up the status line text at the bottom of the screen. This text typically displays messages about the current state of the application, shows the available hot keys, or notifies the user of some action to be taken. The GreetingBox method brings up the dialog box in response to the menu item Greeting. GreetingBox is called from within the HandleEvent method, in response to the event triggered by the selection of the Greeting menu item. In more advanced applications, you would have separate methods to respond to ‘each of the menu items defined in the initial menu, In short, THelloApp’s methods provide what all main-program objects must provide: a means to set the application up, an “engine” (the event handler) to respond to events, and methods to embody the responses to particular events. These three things are, by and large, what you must add to TApplication when you create descendant object types of TApplication. The only other major object used in Hello is a dialog box object. Because the dialog box doesn’t have to do anything special, Hello "uses an instance of the TDialog object. There is no need to derive a special object from TDialog. ‘TDialog itself contains no interactive elements. It is nothing more than a frame (albeit a clever frame); you provide whatever fields or controls are to interact with the user. Turbo Vision Guide Flow of execution and debugging Formore hints and tis on ‘debugging Turbo Vision eppiicatons,se6 Chaprer 10, HELLO’s main ‘THelloApp.GreetingBox builds on TDialog by inserting four buttons ‘which are also Turbo Vision views (Remember that ail program elements that display anything to the screen must be Turbo Vision views!) This is typical when using dialog boxes. Usually you just insert the controls you want to have in the dialog box. Everything, else that a dialog box must have (including an event handler) i built into TDiaiog. Because Turbo Vision applications are event-driven, the code is, structured somewhat differently than conventional programs. Specifically, event-driven programs separate the control structures that read and evaluate user input (and other events) from the procedures and functions that act on that input. ‘Conventional programs typically contain many blocks of code, each of which involves getting some input, deciding which code gets that input, calling the appropriate routine(s) to process the Input, then doing the same thing again. In addition, the code that finishes processing the input must then know where to give control for the next round of input. Event-
Nev", KOE, cmlevtn, {bind new comand } Neustatsey|/=Alt-F3+ Close’, ROAIEES, enClose, ni))), aul ni ‘The status lines initialization syntax is a good introduction to ‘menu initialization, which is somewhat more complex. ‘The Turbo Vision menu bar variable MenuBar is initialized with nested calls to the standard Turbo Vision functions NewMen, ‘NewSubMenu, Newltem, and NewLine. Once you've initialized a menu, your work is finished. The menu bar knows how to handle the user’s input without your help. Initialize a simple memu bar, one menu containing one selection, ike this: caPiledpen = 200; (define a new comand } procedure Myhpp.InitéensBar; epi Get Bxtent 1 {get ares of the application ) RBY i RAY +1) [se bottom 1 Line below tep ) enubar := vou(PMenuBar, Tale (Ry Wewieny( { eveate Bir vith nen Nevsuilena(/~Foile’, helcontert, eaten (define mens } Mewitenl’ Orpen’, 7F3", W823, caPLledpen, heloContert, | Sten | ail), {30 more Sten} il) (no mote submenus } ” (ond of the har } es: ‘The single menu produced by this code is called ‘File’ and the single menu selaction is called ‘Open.’ The tildes (~) make F the shortcut leter in Tile’ and Othe shortcut letter in ‘Open,’ and the Fikey is bound asa hot key for ‘Open’ All Turbo Vision views can have a help context number associat- ed with them. The number makes it easy for you to implement context-sensitive help throughout your application. By default, views have a context of hcNoContext, which isa special context that doesn’t change the current context. Help context numbers Turbo Vision Guide 1 te I bie AER Ths TVGUDOS.PAS (Chapter 2, Witing Turbo Vision applications appear in the initialization of the menu bar because the nested structure of this object makes it difficult to add numbers later. When you're ready to add help context to the menu bar, you can substitute your own values for heNoContext in the Init code. ‘To add a second item to the File’ menu, you simply nest another Newlltem function, like this: Menutar i= Wew(EHensBas, Tit (Ry Netana( exaubtenn("-F-ile", Heocontext, Heen( eviten(/-O-pen’,'"93", HOPS, caFiledpen, hetecoatext, Noviten(/-¥eew, "F%", "1804, cmowin, betoContert, 3)), all) vn ‘Todd a second menu, you nest another NewSubMenu function call like this: Monobar := Mau(PMenaBax, Init, Mowers ewsubtens ( hetotontert, vewtonn( 3", WOES, cabLLedpen, betoContext, Rae, "catia, Nevocontext, sil))), {closing parens for mens selections} Wevsubtenu(‘-Wrindow", etocontext, ewer ( Wevlten "tert, "26", WOF6, caext, hotocontext, Yoviten("-t-oon", 'P5", KBPS, cutecn, hetotontext, ail)), ‘il})) "(closing pareae for mens) ms ‘You just bound two more standard Turbo Vision commands, cemNext and emZoom, to ment items and hot keys. ‘To add a horizontal line between menu selections, insert a call to ‘NewLine between the Newltem calls, like tis: MenuBar := Nov(pMonuBar, Tait, Newent Neveublens(/“Foile’, hetocontext, Nedena( ewiten(' Orpen’, 7F3", H283, caPlledpen, hetoContext, ewiten(" lov", 724", KBPS, callertin, newocontext, newtine( Marten Bake, "ALLAK!, ALEX, caguit, helocontext, a), Nevsuttena('-Wrindow’, nelocontext, Newent Mewiten(" text’, "P6!, WOES, callext, hoXocontext, Hevtten("-t-con!, "PS", KBPS, caloon, ho¥otontext, iN)1), aun) meAnote on structure You may notice that the version of TVGUID03.PAS supplied on ‘your disk also adds a status key to the status line, binding the F10 key to the cm Menu command. cmMenu isa standard Turbo Vision ‘command that helps non-mouse users make use of the menu bar. In this case, the F10 keystroke causes the menu bar to be activated, allowing menus and menu items to be selected using cursor keys. ‘You may also notice that the status item has a mull string as its text, so nothing appears on the screen for it. Although it might be nice to alert users that F10 will activate the menus, itis rather pointless to have an item to click on that performs that action. Clicking directly on the menu bar makes much more sense. At this point, a number of commands are available, but most of them are disabled, and the cmNewWin and emFileOpen commands don't yet perform any actions, If your initial reaction is one of disappointment, it shouldn't be— you've accomplished a lot! In fact, what you've just discovered is ‘one ofthe big advantages of event-driven programming: You separate the function of geting your input from the function of responding to that input. With traditional programming techniques, you would need to go back into the code you've just written and start adding code to ‘open windows and such. But you don’t have to do that: You've gota solid engine that knows how to generate commands. All you need to do is write a few routines that respond to those commands. And that’ just what you'll do in the next section. ‘The Turbo Vision application framework takes you one step ‘beyond traditional modular programming. Not only do you break your code up into functional, reusable blocks, but those blocks ‘can be smaller, more independent, and more interchangeable. Your program now has several different ways to generate a command (emNeoWin) to opan a window: a statue line item, a menu item, and a hot key. In a moment, you'll sce how easy itis to tell your application to open a window when that command ‘shows up. The most important thing is that the application doesn’t care how the command was generated, and neither will, ‘the window. All that functionality is independent. If later on, you decide you want to change the binding of the ‘command—move the menu selection, remap the hot keys, Turbo Vision Guide whatever—you don’t have to worry or even think about how it ‘will affect your other code. That's what event-driven program- ‘ming buys you: It separates your user interface design from your program workings, and as you'll see, it also allows different parts of your program to function just as independently. Opening a window Objects used: ‘Rect TMiew Standard window equipment If you're a typical programmer, you may have jumped directly to this section as soon as you opened the book. After all, what's more central to writing a windowed application than making a window? It’s true that if Turbo Vision were a collection of traditional library routines, then jumping right to this section and trying to get right to work might be a good idea. You could very well get a good sense of the library's overall quality and organization. But Turbo Vision isn'ta traditional library. If you've read the preceding chapters, you already know that. In order to program {in Turbo Vision, there are some things you need to do before it ‘makes sense to create a window. You need to understand just what a Tubo Vision window is (its an object), and how itis different from windows you might have used before. When you've done this, you will be further along in your first Application than you'd ever imagine. So, if you've jumped into the cookbook at this point, you need to 0 back to the preceding sections and lay a little groundwork. It ‘will be well worth it. A Turbo Vision window is an object, and built into it is the ability to respond to much of the user's input without you having to ‘write a line of code. A Turbo Vision window already knows how to open, resize, move, and close. But you don’t write on a Turbo Vision window. A Turbo Vision window is a container that holds and manages other objects: Its these objects that represent themselves on the screen, not the window itself. The window ‘manages the views, and your application's unique functionality is in the views that the window owns and manages. The views you create retain great flexibility about where and how they will appear Chapter 2, Witing Turbo Vision appications aThs 1veuDo4PAS [Note that we always dectare ‘@poinier ype for each new 2 object Ne. So how do you combine the standard window tools with the things you want to put in the window? Over and over again, remind yourself that you've got a strong framework to build on— and use it! Start with a standard window, then add the features you want. As you go through the next few examples you'll see how easy itis to flesh out the skeleton Turbo Vision provides. ‘The following code initializes a window and attaches it to the desktop. Remember to add the new methods to the declaration of ‘your TMyApp type. Note that again you are defining a new type (rDemoWindow) without adding any fields or methods to its ancestor type. As before, you're doing that just to provide a simple platform you can build on easily. You'll add new methods as you go. raat Wincount: tatege | initlalize window counter } encode Denoindow ent: *tDenakindows sbject (Tindow) (define a new window type J procedure Tyhrp.Newindows Te(Wincount) + R.dssign(, 0, 26, 7): .tve andon(S2), Randam(16)); Window := Wew(PbemcRindow, Tait &, ‘Deno Window", WinCount)}: (set initial aize and position ) (randomly aove around sereen } Desktop". Insert indo (poe window into desktop } ends procedure Tyhyp.RandleBvent (var Event: TBvent) begin ‘application Mandlebvent (Bvt); ( basically, act Like ancestor } Af Brent. Wat = evConmand then ein ‘ase BvestCommand ef _{ Yat respond to additional comands } caedlin: Hewindow; {define action for ca¥ewtin comand } as Exits ots Cleaztvent(event}: {clear event after banding Turbo Vision Guide Window initialization Ihe TRect abject s described ih detain Chapter 4, eee The Insert method, ‘To use this window in your program, you frst need to bind the command cmiNew Win toa menu option or status line hot key, as ‘you did earlier When the user invokes cmNew Win, Turbo Vision dispatches the command to TMyApp.HandleEvent, which responds by calling TMyAyp NewWindow. You need to give a Turbo Vision window three parameters fort to initialize itself its size and position onthe screen, a ttle, and a window number ‘The frst parameter, determining the window's size and position, isa TRect, Turbo Visions rectangle object. TRect isa very simple object. Its Assign method gives it a size and position, based on its top-left comer and its bottom-right corner. There are several other ‘ways to assign or change the values of a TRect object. Consult Chapter 14, “Global reference,” for complete descriptions. In TVGUID04, Ris created at the origin of DeskTop, then moved a random distance into the desktop. “Normal” programs probably ‘won't do that kind of random movement, but for this exercise you ‘want to be able to open a lot of windows and not have them all be in the same place. ‘The second initialization parameter is a string, which is displayed as the window's title. ‘The last initialization parameter is stored in the window's Number field. If Number is between 1 and 9, it will be displayed on the window frame, and the user can select a numbered window by pressing Alt through Alto If you don’t need to assign.a number to a window, just pass it the ‘Turbo Vision constant wnNoNumber, Inserting a window into DeskTop automatically makes the ‘window appear. The Insert method is used to give a view control over another view. When you execute the instruction Desktop Tnaest (indo) ¢ you are inserting Window into the desktop. You may insert any ‘number of views into a group object like the desktop. The group you insert a view into is called the owner view, and the view you insert into it is called a subview. Note that a subview may itself be a group, and may have its own subviews. For instance, when you insert a window into the desktop, the window isa subview, but (Chapter 2, Witing Turbo Vision applications 8Ab nese retatonstips among ‘ious are explained in ‘Chapter 4 Closing a window Window behavior the window may itself own a frame, scroll bars, or other subviews. ‘This process of establishing links between view objects creates a view tree, 90 named because the multiple linkages of views and subviews branch out from the central view, the application, much as limbs branch out from the trunk ofa tree. Clicking the close icon on a window generates the same cmClose command you bound to the A-F3 keystroke and a status line item, By default, opening a window (with Fé or the File|Open menu choice) automatically enables the cmClose command and the views that generate it (as well as other window-related com- ‘mands like cmZoom and omNext). ‘You don’t have to write any new code to close the window. When the user clicks on the window's close icon, Turbo Vision does the rest. By default, a window responds to the cmClose command by calling its Done destructor: Dispose tyRindow, Done) As part of the window's Done method, it calls the Done methods of all its subviews. If you've allocated any additional memory your- self in the window's constructor, you need to make sure that you deallocate it in the window’s Dorie method. ‘Take some time to play with the program you've written. Ithas a great deal of capability already. It knows how to open, close, select, move, resize, and zoom multiple windows on the desktop. Not bad for fewer than 100 lines of code! After TMyApp initializes the window, it inserts it into the desktop. ‘As you recall, DeskTop is a group, which means that its purpose is to own and manage subviews, like your window. If you compile and run the code, you'll notice that you can resize, move, and close the new window. Your mouse input is being turned into @ series of events and routed from the desktop to the new window, ‘which knows how to handle them, Ifyou keep invoking emNewWin, more windows will appear on the desktop, each with a unique mumber. These windows can be resized, selected, and moved over one another. Figure 2.2 shows the desktop as it appears with several windows open. Tutbo Vision Guide Foe 22 Tv@U004 wth muffle ‘windows open Look through any window A TWindow is a group that initially owns one view, a TFrame. The user clicks on the frame's icons to move, resize, or close the window. The frame displays the tite that it receives during the window's initialization, and it draws the window's background, just as TBackGround does for the desktop. All this happens, as you've seen, without you writing any code. you were dealing with traditional window here, the next step ‘would be to write something in Buta TWindow ont blank Slate to be wnten on: Its a Turbo Vision group, a TGroup objet, writ no scoon representation atl beyond ts fame view. To put Something in’ a window, you need fo ake an adil step, a step that pus tremendous power in your hands ‘Tomake something appear in the window, you create a view that knows how to draw itself and insert it into the window. This view is called an interior. ‘This first interior will entirely fill the window, but you'll find it easy later to reduce its size and make room for other views. A window can own multiple interiors, and any number of other useful views—input lines, labels, buttons, or check boxes. You'll also see how easy itis to place scroll bar views on a window's frame. Chapter 2, Witing Turbo Vision applications 35Th mokes TVGUIDOS.PAS ‘You can tile or overlap the subviews within a group—how the views interact is up to you. TDeskTop has a method, Tile, that can tile subviews after they are initialized, but that method is for the desktop alone to use. ‘The interior you'll create next is a simple descendant of TView. ‘Any TView can have a frame that operates like a traditional static window frame. A TViews frame, which can’t be clicked on, outside the clipping region of any writing that takes place inside the view. Its just a line around the view. If your TView interior fills its entire owner window, it doesn’t ‘matter if it has a frame—the window's frame covers the interior’s frame. Ifthe interior is smaller than the window, the interior ‘frame is visible. Multiple interiors within a window ean then be delineated by frames, as you'll see in a later example. ‘The following code writes “Hello, World!” in the demonstration ‘window, and the results are shown in Figure 2.3. Pinterior = “Tinterions "interior * object (Tview constructor Init (var Bounds: Tect); procedure Dray; virtual; ent; ‘constructor Tinterior. Init (var Bounds: TRect} ogi ‘TWiew. Int Bounds) Growlode 1= gfGrowiix + grout; end; [ake efte follow wiodon's 1 procedure Tisterior.oran: begin Weiteser(¢, 2, "Mello, Morld!’, 11; ot constructor toescindow. Init Bounds: Rect; Wintitle: BStrlags Windowie: Integer): Se string]; begin SteQindowto, )5 {put window nunber sno tftze | ‘Window.tnit Bounds, Wintitle +" + 8, wmotumber); atcLiptect Bounds): Bounds.Grow(-Ly-1); | make interior fit inside window frame 1 Interior :~ Wer(PInterior, Init (ound); Turbo Vision Guide Figure 23 {TVGUIOS with open window What do you see? Insert (Interion)? {ed interior to window } eat: All Turbo Vision views know how to draw themselves. A view’s drawing takes place within the method Draw. If you create a descendant view with a new screen representation, you need to ‘override its ancestor's Draw method and teach the new object how to represent itself on the screen. Tinterior is a descendant of TView, and itneeds a new Draw method. Notice that the new TInterior.Draw first calls the Draw of its ancestor, TView, which in this case just clears the rectangle of the ‘view. Normally you would not do this: Your interior view’s Draw method should take care of its entire region, making the ‘TView. Draw call redundant. If you really have something to put into a windows interior, you ‘won't want to cal the inherited Draw method anyway. Calling ‘TView.Draw wil tend to cause flickering, because parts of the interior are being drawn more than once. ‘Asan exercise, you might try recompiling TVGUID0S.PAS with the call to TView.Draw commented out. Then move and resize the window. This should make quite clear why a view needs to take responsibility for covering its entire region! Turbo Vision calls a views Draw method whenever the user ‘opens, closes, moves, or resizes views. If you need to ask a view Chapter 2, Witing Turbo Vision applications 7Abetter way to Write Asimple file viewer Weming! This 1VGUID06 PAS, to redraw itself, call DrawvView instead of Draw. DrawView draws the view only ifit is exposed. This is important: You override Draw, but never call it directly; you call DrmView, but you never override it! While you can make Turbo Pascal's Write procedure work in ‘Turbo Vision, itis the wrong tool for the job. First, if you simply write something, there's no way you can keep a window or other view from eventually coming along and obliterating it. Second, you need to write to the current view’s local coordinates, and clip to the view’s boundary. Third, there is the question of what color touse when writing, ‘Turbo Vision’s WriteStr not only knows how to write with local coordinates and how to be clipped by the view’s boundaries, but also how to use the view’s color palette. The WriteStr procedure takes x-and y-coordinates, the string to be written, and a color index as parameters. ‘Similar to WriteStr is WriteChar, defined as Wieltechar tt, 1, ch, Colo, count) Like WriteStr, WriteChar positions its output atx- and y- ‘coordinates within the view, and writes Count copies of the character Ch in the color indicated by the Color'th entry in the view’ palette. Each of these Write methods should only be called from within a view’s Draw method. That's the only place you need to write anything in Turbo Vision. In this section you'll add some new functionality to your window and put something real in the interior. You'll add methods to read. a text file from disk and display it in the interior. This program will display some “garbage” characters, Don’t ‘worry—we did that on purpose! const WaxLines = 100; isecount: rntegers ines: aezay[0. MaxLines ~ 1) of String: Pinterlor = “tInteriors {This is an axaiteary number of Lines } Turbo Vision Guide ‘i Reading a text fle ‘interior = ebject(rVLee) constructor Init var Sounds: Tact); procedure Draw; vistoal; ond procedure interior. Ort Ys dntegerr (Chie wink Look wsiyt ) for ¥ i= 0 to Sine. = 1 o begin Titeste(0, Yy Linest YI", $015 simple 2ine co ) each Line 1 Tinecount 2 0: assign(f, FiloTotoad); esot iF); walle not Bof(@) and (LineCount < waxbines) do esta eaain(, §) ines{Linecount) := Newste(S); Tne (Dinecouat end: hosel): nt procedure Doneelie; Te tategers ogi for Z :~ D to Lizecount ~ 1 do ‘Sf Lines(1) © all then ent: este (Lines(iD) Your application needs to call Reade to load the text file into the array Lines, and DoneFile after executing to deallocate the space used by Lines. In ReadFile, the Turbo Vision global type PString isa string. pointer, Turbo Vision also supplies a function called NewStr that stores a string on the heap and returns a pointer to it. Even though NewSir returns a pointer, don’t use Dispose to get rid of it. Chapter 2, Wing Turbo Vision applications 29Always use the companion procedure DisposeStr to deallocate the string. Buffered drawing ‘You will notice that when you run this program, there are “garbage” characters dispiayed on the screen where there should, be empty lines. That's a result of the incomplete Draw method. It violates the principle that a view’s Draw method needs to cover, the entire area for which the view is responsible. Also, the text array Lines is not really in the proper form to be displayed in a view. Text typically consists of variable length strings, many of which will be of zero length. Because the Draw method needs to cover the entire area ofthe interior, the text lines need to be padded to the width of the view. The draw buffer To take care of this, create anew Drmw that assembles each line in a butfer before writing it in the window. TDrawBufer is a global ‘ype: Mexttowitin is 132 charactors oravbutfer = array[0..Waxiewtidth-1] of Word: ‘TDrawBuffer holds alternating attribute and character bytes. ‘The new TinteriorDraw looks like this: TnBISTVGUDO7PAS ——prooadare Tinterior.028¥; Color := Getcotor(t}: for = to Size. ~ 1 do begin Novechar 8,’ ', color, size.x) AE (YC Linecount) and’ (Linestt] © nit) Moweste(B, Copy(Lines|Y]*, 1, Size.x), eiveLine(, %, $130-%, 3, 3 ond ent; eected Draw method | (£011 Line with spaces 1 ee Color); { copy in text} wrice ene 2ine } Figure 24 shows TVGUIDO7 with several windows open. Tutbo Vision Guide Figue24 Mutipie fe views Moving text info a buffer Whiting buffer contents Terie Pascal 6.0 ESS repran ft the tars vison xe Draw first uses a MoveChar call to move Size X number of spaces (he width of your interior) of the proper color into a TDraiwBufer. Now every line it writes will be padded with spaces to the width of the interior. Next, Draw uses MoveStr to copy a text line into the TDrawBufer, then displays the entire buffer with a WhiteLine call. ‘Turbo Vision supplies four global procedures for moving text into a TDrawBuffer: MoveStr, which you just looked at, and MoveChar, ‘MoveCStr, and MoveBuf, which move characters, control strings (ctrings with tildes for menus and status items), and other buffers, respectively, into a buffer. Al these procedures are explained in detail in Chapter 14, “Global reference.” ‘Turbo Vision provides two different procedures for writing the contents of a buffer to a view. One, WriteLine(X, Y, W, H, Buf), was shown in TVGUIDO7. In TlhterionDraw, WriteLine writes TDrawBuffer on one line. Ifthe fourth parameter, H (for height), is greater than 1, WriteLine repeats the buffer on subsequent lines. Thus, if Bufholds “Hello, World!”, weitetine(0,0,13,4,8uf) will write Bello, Wortét AeLio, Worle! ello, ello, Chapter 2, Witting Turbo Vision applications a1Knowing how much to 42 wate Scrolling up and down Ths TVeUD08 PAS ‘The other procedure, WriteBuf(X, Y, W, H, Buf, will also write a rectangular area of the screen. W and H refer to the width and height of the buffer. If Buf holds “ABCDEFGHIKLMNOP", WriteBufi0,0,44,Bup) will write 0 ix Unlike their non-buffered counterparts, Writestr and WriteChar, ‘you'll notice that you don’t specify the color palette entry to use ‘when writing a draw buffer. This is because colors are specified when the text is moved into the buffer, meaning that text with liffering attributes may appear in the same bulfer. Both WriteLine and WriteBuf are explained in detail in Chapter 14, “Global reference.” Note that TInterior.Draw draws just enough of the file to fill the interior. Otherwise, Draw would spend much of its time writing parts ofthe file that would just end up being clipped by the boundaries of Tinterior. Ifa view requires a lot of time to draw itself, you can first call GetClipRect. GetClipRect returns the rectangle that is exposed ‘within the owner, so you only need to draw the part of the view that is exposed. For example, if you have a complex dialog box with a number of controls in it, and you move it most of the way off the screen so you can look at something behind it, calling GetClipRect before drawing would save having to redraw the parts of the dialog box that are temporarily off the screen. Obviously, file viewer isn’t much use if you can only look at the first few lines ofthe file. So next you'll change the interior to a scrolling view, and give it scroll bars, so that Interior becomes a scrollable window on the textfle. You'll also change ‘TDemoWindow, giving it a Makelnterior method to separate that function from the mechanics of opening the window. tape Pinterior = “TIateriors Tutbo Vision Guide = Note that you have changed ihe ancestor of Tinto! imterloe ~ abject (sezoller] constructor Init (war Sounds: Tect; MiScxollOas, AVS SezollBar) procedure Draws virtvaly a DenoWindow = “TDenctindor; TenoWindow = object (Window) constructor Init (Bounde: Ted ora procedte NakeTnterior (Bounde: TRact): ond; constructor THaterlor.tnit (var Sounds: TRect; iScroNIBar, ‘SerolBar: PSero}iBaz); begin Tscroller. Init Bounds, ABSerollBar, AVScrol1Ban); lode i= gfGrOWEiX + gfGroe; SetLinit (128, LineCout); ( horizontal, vertical scroll Linits ents Tote: strings wadowto procedure Prnterlor. rau Color: yey Y, fr Integer Bt srawbuttor: setcolor 01) for Y i= 0 to Siae.t ~ 1 do Degin Movethar(, * *, Color, sire.t); {11 buffer with spaces | Delta.y 4 t { belta is sexoller offset } SE (1 Linecoont) and (Lines(1} © nil) then MoveStri8, Copy(Lines{I]*, Delta.X + 1, Size.X), Color}: Ueivenine 0, Y, Size.%y 1, Bz (use normal text color } ( stiL) need to count Lines | end end ‘procedure rDenohindow.vaketnterior (sounds: Tet): serollBar, VScrollBar: 2Serol1B4r Degin Werolisar := StandardSerol lar (sbVertical}; seroL\bar ‘= StandardserobAbar [eboeszontal): Interior := ter(@interior, Init Bounds, HScrollBar, VSerol18ar)); Inseet (Interior ed; constructor Tenclindow.tnit (Bounds: Tract; Wintitle: string: Chapter 2, Witting Turbo Vision applications “aFigure 25 Fle viewor with serting Interior indowo: Tnteges): steing(3); Degin Str(Mindosto, 8); ‘Mindov.Init Bounds, Wiatitle + * 4 +S, wnounber)z GotBxtont (Bounds); Bounds.crou(-1,-1): akeTaterior (Bonds): oat eacceeaeeeeeersve)| eS papa file the Trt Visten 6 Conyroht () 1980 by Borland Iteration re See Peccid =F aes tite: rome cata Sei: gee oat re Titarto ‘The horizontal and vertical scroll bars are initialized and inserted in the group, and then are passed to TScroller in its initialization A scroller is a view designed to display part of a larger virtual ‘view. A scroller and its scroll bars cooperate to produce a scrollable view with remarkably little work by you. All you have to dois provide a Draw method for the scroller s0 it displays the proper part ofthe virtual view. The scroll bars automaticaly control the scroller values Della X (the column to begin displaying) and Delia (the first line to begin displaying). ‘You must override a TScrole’s Draw method in order to make a ‘useful scroller. The Delta values will change in response to the scroll bas, but it won't display anything by itsell. The Drew method will be called whenever Delta changes, so that is where you need to put the response to Delt Turbo Vision Guide Multiple views in a window w= Be sure to change the ‘declaration of Mokeinterior! Thsis TVEUDORPAS. Next, you duplicate the interior and create a window with two scrolling views of the text file. The mouse or the tab key automatically selects one of the two interior views. Fach view scrolls independently and has its own cursor position. Todo this, you add a bit to the Maketnterior method so it knows ‘which side of the window the interior is on (since the different sides behave a bit differently), and you make two cals to ‘Makelnterior in TDemoWindow Init. procedure roeno¥indov.vakeTnterior Bounds: TRectr Tatts Boolean)? Taterior begin Interior := tew(@tnterior, Init (Bounds, StandardSerollar(abfor‘zontal}, StandardScroliRar(ebVerticai))); Af Lae then Znterior*,Growode := gfGuowily flee Interior” Grose i= gEGrowiik + Gronks Insert (interior): Ser Window, 8) ‘Windov Iai Bounds, Wlnzitle + ' 7 + 5, water): Gotzatont Bounds): R.Aseign (Sounds AK, Bounde.AWY, Sounds.B.X div 2 + 1, Sounds.8.X) akelmterior(Ry Te); R.Assign(Sounds.5.X dl 2, ounds.A.Y, Bounds.8.X, Bourds.B.2) kelmerior(Ry False) nd; Chapter 2, Witing Turbo Vision applications 45Figure 26 ‘Window with mutiple panes = Remember to add SeLinis to ToemoWindow. i vitual) ‘hie ie IVSUIDIOPAS. Where to put the functionality eves} ot ts Note that you've changed Makelnterior both in style and in substance. Instead of declaring two static scroll bars and then passing them to the Init method, you simply included the ‘StandardScrollBar calls as parameters to Init. The earlier style is somewhat clearer; the latter isa bit more efficient. If you shrink down the windows in TVGUIDO9.PAS, you'll notice that the vertical scroll bar gets overwritten by the left interior vview if you move the right side of the window too close to the left. To get around this, you can seta limit on how small you're allowed to make the window. You do this by overriding the ‘TWindow method SizeLimits. ‘procedure "Desciindoy SizeLinits(vae Min, Max: TRoint): var B: TRoct; begin ‘Window SizeLinits Win, Max) Gexetent (8s Nin.x = RBA div 2; ext: Note that you do not have to call SizeLimits, You just override it, and it will be called at the appropriate times. This is the same thing you did with the Draw method: You told the view how to draw itself, but not when. Turbo Vision already knew when to call, Draw. The same applies to SizeLimits: You set the limits, and the view knows the appropriate times ta check them. ‘You've now created a window with a number of views: a frame and two scrolling interiors, each with two scroll bars. You're on your way to creating a window that can carry out specific ‘functions in an application, Turbo Vision Guide Making a dialog box Theis VGUDTIPAS How do you proceed? Suppose you want to turn your window into a full-fledged text editor. Since the window has two views, you may be tempted to put some of the text-editing functionality into the group, and then have the group communicate with the two views. Alter all, a group's job is to manage views. Isn't natural for it to be involved in all the work? While a group is as capable of being extended as any view, and you can put any functionality in it that you wish, your Turbo Vision applications will be more robust and flexible if you follow these two pointers: keep objects as autonomous as possible, and keep _groups (such as windows) as dumb and devoid of additional functionality as possible. ‘Thus, you'd build the text editor by putting all the functionality into the interior view: Create a text editor view type. Views can be ‘easily reusable if you design them properly, and moving your text ‘editor into a different environment wouldn't be very easy if its editing functionality were divided between a group and a view. A dialog box is just a special kind of window. In fact, TDialag is a descendant of TWindow, and though you can treat it as just another window, you will usually do some things differently. Building on your demonstration program, you'll add a new menu. item that generates a command to open a dialog box, add a method to your application that knows how to do that, and add a line to the application's HandleEvent method to link the command to the action. Note that you do not need to derive a new object type from ‘TDialog as you did with TWindow (to produce TDemoWindow). Rather than creating a special dialog box type, you'll add the intelligence to the application: Instead of instantiating a dialog box object that knows what you want itt do, you'l instantiate a generic dialog box and tell it what you want it to do. You will rarely find it necessary to ereate a descendant of TDialog, since the only difference between any two dialog boxes is what they contain, not how the dialog boxes themselves work. const ‘atievaog = 200 Chapter 2, Witing Turbo Vision applications aprocedure mytpp.raituenstar sar A Tects begin Geteatent RAY #1 NevlMemer, Init (Ry Mewieny| Nevsibtena("“F-ile", heodontert, Vewtens( Meuiten(' Orpen’, 773", HBE3, ea LLedpen, hotocentext, Dowrten "8", 1284, ements, aecontext, Neuiten(/Borkt', “ALK, ALEX, catuit, haiocontext, aun, Nevsublena|"“Roindow', neotontoxt, Nowtins( Yevten(/srert", "76", IEE, calext, hotocontext, YevTeent’-t-o00", “F5', ES, eatoon, Hedecontext, Novrten(/-D-ialog’, "22", KAZ, calewDialog, hofeCent au), il) me ed procedure Mihpp.Nexdialog: Dialog: PDialog: Rs Rect Degin R.assign(0, 0) 40, 13): Nove andon(38), Pandan 00); Dialog = New(POialog, Tait, “Demo Dialos")}7 Desktop". Insert (Dialog); end procedure Tyhpp.Randlebvent (var Broct: Event); Dogia “TappLicet ion tandleBvent (vent); Af Event inet = evCammand then begin ame Byent.Comand of ‘lenin: Nendo eubialos; Cleacbvent (event); nd; Turbo Vision Guide Figue 27 ‘Sinple cioiog box ‘Modal views ore dscussedin ‘Chapter 4, "Views." Executing a modal dialog box Ths TVSUDI2PAS ‘There are really very few differences between this dialog box and your earliest windows, except for the following: The default color of the dialog box is gray instead of blue. The dialog box is not resizable or zoomable. = The dialog box has no window number. Note that you can close the dialog box either by clicking on its close icon, clicking the AIFS-status line item, or pressing the ES key. By default, the Esc key eancels the dialog box. This is an example of what is called a non-modal (or “modeless”) dialog box. Dialog boxes are usually modal, which means that they define a mode of operation. Usually when you open a dialog box, the dialog box isthe only thing active: it is the modal view. Clicking on other windows or the menus will have no effect as Tong as you are in the dialog box’s mode. There may be occasions ‘when you want to use non-modal dialog boxes, but in the vast majority of cases, you will want to make your dialog boxes modal. So how do you make your dialog box modal? It’ really very easy. Instead of inserting the dialog box object into the desktop, you execute it, by calling the DeskTop” ExecView function: procedure miyhpp.Nexbialog: Dialogs Pialog; Control: Word: begin Radssign(9, 0, 40, 13); move anden(38), Rando (10)17 Dialog := Ner(2Dialog, Init (2, "Deno Dialog’)}; Control := DeskTop” BxecViex iaiog); od; (Chapter 2, Witing Turbo Vision applications “Taking control (Command handling s expleined mare in Chapter 6, “Event-ctiven programming.” Button, button, A TDialog already knows how to respond to an Esckey event (wich i turns into a enCancel command) and an Enforkey event (which will be handied by the dialog box’ default TButton). A dialog box always closes in response to aemCancel command Calling ExecView both inserts the dialog box into the group and makes the dialog box modal. Execution remains in ExecView until the dialog box is closed or canceled. ExecView then removes the dialog box from the group and exits, For the moment, you'll ignore the value returned by the ExecView function and stored in Control. You'll make use of this value in TVGUIDI6. Of course, a dialog box with nothing in itis not much of a dialog ‘box! To make this interesting, you need to add controls. Controls are various elements within a dialog box that allow you to manipulate information. The important thing to remember about controls is that they only affect things within the dialog box. ‘The only exception to this rule is the case of a button in a maodeless dialog bex. Because buttons generate commands, those commands will spread downward from the current modal view. If the dialog box is not the modal view, those commands will go to places outside the dialog box, which may have unintended effects. In general, when setting up controls in a dialog box, you can separate the visual presentation from the handling of data. This means you can easily design an entire dialog box without having to create the code that sets up or uses the data provided in the dialog box, just as you were able to set up menus and status items ‘without having code that acted on the commands generated. One of the simplest control objects is the TButton. It works very much like a fancy status line item: It’s a colored region with a text label on it, and if you click on it, it generates a command. There is also a shadow “behind” the button, so that when you click on the ‘button it gives a sort of three-dimensional movement effect Most dialog boxes have at least one or two buttons, The most common are buttons for “OK" (meaning “'m done. You may close the dialog box and accept the results”) and “Cancel” (meaning “I want to close the dialog box and ignore any changes Turbo Vision Guide made in it”). A Cancel button will usually generate the same ‘emCancel command that the close icon produces. ‘The Dialogs unit defines five standard dialog commands that can bbe bound to a TButton: cmOK, cmCancel, emYes, emNo, and ‘emDefault. The first four commands also close the dialog box by having TDilog call its EndModal method, which restores the previous modal view to modal status. You can also use buttons to generate commands specific to your application. Theis TVGUDISPAS procedure THyRgpHevOLalogr ReAssign(20, 6 60, 18) Dislog :» Naw(PDiaiog, Init, "Deno Dlalo ssign{l5, 10, 25, 12); lee(PButton, Tait Ry *=0°K", WK, bfDefault) 1; R.Assign!28, 10) 38, 12); Insert OlewPButton, Init (Ry ‘Cancel’, caCancel, bE¥ernal))} ond; Control := Desktop*.xecVieutDialog): end: Creating a button requires four parameters for the Init constructor: 1. the region the button will cover (Remember to leave room for the shadow!) 2, the text that will appear on the button 3. the command to be bound to the button 4, a flag indicating the type of button (normal or default) Figure 28 pil te oie fe Dialog box with Buttons (Chapter 2, Wing Turbo Vision appiications 51Normal and default Focused controls Labet are cecussed jatern Tab orders important! Notice that you didn’t highlight the “C” in “Cancel” because ‘there is already a hot key (Ese) for canceling the dialog box. This eaves Cavailable as a shortcut for some other control. ‘Whenever you create a button, you give it flag, either bfNormal or bDefeult. Most buttons will be ffNormal. A button flagged with ‘Default will be the default button, meaning that it will be “pressed” when you press the Enter key. Turbo Vision does not, check to ensure that you have only one default button—that is your responsibility. Ifyou designate more than one default control, the results will be unpredictable. Usually, the “OK"” button in a dialog box is the default button, and users become accustomed to pressing Enterto close a dialog box and accept changes made in it. Notice that when a dialog box is open, one of the controls in always highlighted. That is the active, or focused, control. Focus of controls is most useful for directing keyboard input and for activating controls without a mouse. For example, ifa button has the focus, the user can “press” the button by pressing Spacabar. Characters can only be typed into an input line ifthe input line has the focus. ‘The user can press the Tab key to move the focus from control to control within the dialog box. Labels won't accept the focus, 50, the Tab key skips over them, ‘You will want the user to be able to Tab around the dialog box in some logical order. The Tab order is the order in which the objects. ‘were inserted into the dialog box. Internally, the objects owned by the dialog box are maintained in a circular linked list, with the last object inserted linked to the first object. By default, the focus ends up at the last object inserted. You can ‘move the focus to another control either by using the dialog box’s SelectNext method or by calling the control's Select method directly. SelectNex allows you to mave either forward or backward through thelist of controls, SlectNext(False) moves you forward through the circular lst (in Tab order); SelectNext(True) ‘moves you backward. Take your pick Creating a cluster (Often, the choices you want to offer your users in a dialog box are rot simple ones that can be handled by individual buttons. Turbo Vision provides several useful standard controls for allowing the ‘user to choose among options. Two of the most useful are check boxes and radio buttons. ‘Check boxes and radio buttons function almost identically, with the exception that you ean pick as many (or as few) of the check boxes ina set as you want, but you can pick only one (and exztly ‘one) radio button. The reason the two sets appear and behave so similarly is that they both derive from a single Turbo Vision object, the TCluster. If you're not familiar with the concept of check boxes and radio buttons, you might look at the Options menu in the Turbo Pascal integrated environment. Many of the dialog boxes brought up by ‘that menu feature cluster controls. ‘Theres probably no reason you would ever want to create an instance ofa plain TClustr. Since the process for seting up a check box cluster isthe same as that for setting up a cluster of radio buttons, you only need to look at the process in detail once. ‘Add the following code to the TMyApp.NewDialog method, after the dialog box is created but before the buttons are added. Keep the buttons as the last items inserted so they will also be last in Tab order. Bs view: Raassign(3, 3, 18, 61; B s= Wow(@CheckSoxes, Init evstten Werstten’ stent ain) nse); ‘The initialization is quite simple. You designate a rectangle to hold the items (remembering to allow room for the check boxes, themselves), and then create a linked list of pointers to strings that will show up next to the check boxes, terminated by a nil i 2 Turbo Vision Guice | Chapter 2, Wing Turbo Vision applications 83 I‘Check box values The preceding code creates a set of check boxes with three ‘One more cluster 8 we erst choices. You may have noticed that you gave no indication of the settings for each of the items in the list. By default, they will all be unchecked. But often you will want to set up boxes where some or al of the entries are already checked. Rather than assigning values when you set up the list, Turbo Vision provides a way to set and store values easily, outside the visual portion of the control. ‘Asset of check boxes may have as many as 16 entries. Since you have up to 16 items that may be checked either on or off, you can represent the information as a single 16-bit word, with each bit corresponding to one item to be checked. ‘After you finish constructing the dialog box as a whole, you will Took at how to set and read the values of all the controls. For now, ‘concentrate on getting the proper controls in place. Before moving on, however, add a set of radio buttons to the dialog box so you can compare them with check boxes. The following code sets up a set of three radio buttons next to your check boxes: Rassignl ys 4 17 B sm tev PRadlosuttons, alt Meysiten(/ Solid", TexsTtea("-Reanny"y eysiten(/-elted, aun) Incest 0); ‘The main differences you will note between the check boxes and the radio buttons are that you can only select one radio button in the group, and the first item in the list of radio buttons is selected by default, Since you don't need to know the state of every radio button (only ‘one can be on, $0 you only need to know which one itis), radio ‘button data ie not hitmapped. This means you can have more than just 16 radio buttons, if you choose, but since the data is still stored, you are limited io 65,536 radio buttons per cluster. This should not bea serious impediment to your design. A value of zero indicates the first radio button is selected, a one indicates the second button, a two the third, and so on. Turbo Vision Guide Labeling the controls Ingle TVGUDI4PAS owe 29 Dialog box wih labeled ‘custors added The input line object Of course, setting up controls may not be sufficient. Simply offering a set of choices may not tell the user just what he is choosing! Turbo Vision provides a handy method for labeling controls in the form of another control, the TLabel ‘There's more to the TLabel than appears at first glance. A TLabel not only displays tex, itis also bound to another view. Clicking ona label will move the focus to the bound view. You can also define a shortcut leter for a label by surrounding the letter with tildes (-). ‘To label your check boxes, add the following code right after you insert the check boxes into the dialog box: Raassign(2, 2, 10, 3); ‘Insert (Newel, Init (Ry 'Cheeses', 3}: ‘You can now activate the set of check boxes by clicking on the ‘word “Cheeses.” This also lets the uninformed know that the items in the box are, in fact, cheeses. Similarly, you can add a label to your radio buttons with the following code: Raslgn 2, 2 38, 312 Taser fovEtabel, TALE, “Consistency, BIN17 {8— tr aos x ely a ‘There ie one other fairly simple kind of control that you can add to your dialog box: an item for editing string input, called an input tine. Actually, the workings of the input line are fairly complex, but from your perspective as a programmer, TInputLine is a very simple object to use. Chapter 2, Wilting Turbo Vision applications 55Theis VGUDISPAS Figure 210 Dialog box with input fine ‘added Setting and getting data Add the following code after the code for labeling the radio buttons and before you execute the dialog box: Rassignl3, 8 37, 9 B se ew(PinputLine, init, 128) Insert; Reassign(2, 7, 24, 8 Insert (lew\@label, Init ’Delivery instructions", 3)))1 Setting up an input line is simplicity itself: You assign a rectangle ‘that determines the length of the input line within the screen. The only other parameter required is one defining the maximum length of the string to be edited. That length may exceed the displayed length because the TinputLine object knows how to seroll the string forward and backward. By default, the input line can handle keystrokes, editing commands, and mouse clicks and drags. pil ws 0 esses Pare Seen atl ‘The input line also has a label for clarity, since unlabeled input lines can be even more confusing to users than unlabeled clusters. ‘Now that you have constructed a fairly complex dialog box, you need to figure out how to use it. You have set up the user interface end; now you need to set up the program interface. Having. controls isn’t much help if you don’t know how to get information from them! ‘There are basically two things you need to be able to do: Set the initial values of the controls when the dialog box is opened, and read the values back when the dialog box is closed. Note that you don’t want to modify any data outside the dialog box until you successfully close the box. If the user decides to cancel the dialog, ox, you have to be able to ignore any changes made while the dialog box was open. Turbo Vision Guide Luckily, Turbo Vision facilitates doing just that. Your program. sands a record of information to a dialog box when itis opened. When the user ends the dialog box, your program needs to check to see if the dialog box was canceled or closed normally. Ifit was canceled, you can simply proceed, without modifying the record, If the dialog box closed successfully, you can read back a record. from the dialog box in the same form as the one given toit. ‘The methods SetData and GetData are used to copy data to and from a view. Every view has both a SetDaia and GetData method. When a group (such as Dialog) is initialized through a SetData call, it passes the data along by calling each of its subviews’ SetData methods. When you calla group’ SetDala, you pass ita data record that contains the data for each view in the group. You need to arrange each view’s data in the same order as the group's views were inserted. You also need to make the data the proper size for each view. Every view has a method called DataSize which returns the size of the view’s data space. Each view copies DataSize amount of data from the data record, then advances a pointer to tell the next view ‘where to begin. Ifa subview’s data is the wrong size, each subsequent subview will also copy invalid data. If you create a new view and add data fields to it, don’t forget to override DataSize, SetData, and GetData so that they handle the proper values. The order and sizes of the data in the data structure is entirely up to you. The compiler will return no errors. if you makea mistake. ‘After the dialog box executes, your program should first make ssure the dialog box wasn’t canceled, then call GetData to import the dialog’box’s information back into your application. So, in your example program, you initialize in tur a cluster of ‘check boxes, a label, a cluster of radio buttons, a label, an input ine of up to 128 charactors, a label, and two buttons (Ok and Cancel). Table 21 summarizes the data requirements for each of these. (Chapter 2, Wing Turbo Vision applications a7Table 21 Data for diiog box controls The 1VeUDI6 PAS Controt Data required ‘check boxes Word label none radiobuttons Wind label none input ine string{1281 label one Dutton one Dutton none ‘Views that have no data (such as labels and buttons) use the GetData method they inherit from TViaw, which does nothing at all, so you don’t need to concern yourself with them here. This, ‘means that when getting and setting data, you can skip over labels and buttons. ‘Thus, you are only concerned with three of the views in the dialog box: the check boxes, the radio buttons, and the input line. As noted earlier, each of the cluster items stores its data ina Word- type field. The input line's data is stored in a string. You can set up a data record for this dialog box in a global type declaration: Dialogbeta = record CheekBowata: Nord Hadiobutcontata: Word: Inpokbineeea: etetng(128]+ ont: Now all you have to do is initialize the record when you start up tie program (MyApp Jnitis a good place), set the data when you enter the dialog box, and read it back when the dialog box closes successfully. Ité almost easier to say that in Pascal than it was in English! Once you've declared the type as we did here, you declare a global variable: Denobislogbate: Dislogoats7 then add one line before executing the dialog box and one after: Dialog*.setoata (bemebialogoata): Control © DeskZop".£1edVier(DLalog): Af Control © entancel then Dialog” CstData Dembialogbstal and add six lines to the TMyApp.nit method to set the initial values for the dialog box: with panooLalognata do Turbo Vision Guide Figure 211 Dialog box with infil values set Shortcut keys and conflicts begin Checkboxbate i= 1: adioButtoabata := 2: nputLinadata := "Phone bone." ond; [1] tes 04019 tok ny esses we a Now any changes you make to the dialog box should be there ‘when you reopen it, as long as you didn’t cancel the dialog. ‘One of the things we learned as we wrote the Turbo Pascal integrated environment was that itis a good idea to have your [program store information that gets altered by a dialog box in the form of a record that can be used for setting or getting data from the dialog box. This Keeps you from having to construct lots of data records from discrete variables every time you want fo open ‘dialog bex, and from having to disperse the information returned from a dialog box to various variables when it's done. By default, labels, check boxes and radio buttons can respond to shortcut keys even when the focus is elsewhere within the dialog. For example, when your example dialog box first opens, the focus, is in the check boxes, and the cursor is on the first check box. Pressing an M for “Melted” will immediately move the focus to the Melted radio button and turn it on. While you obviously want shortcut keys to be as mnemonic as, possible, there are only 26 letters and 10 digits available. This may cause come conflict, For example, in your little dialog bow it ‘would make sense to have Cas the shortcut for “Cheeses,” “Consistency,” and maybe a cheese called “Cheddar.” There are a couple of ways to deal with such situations. First, while itis nice to have the first letter of a word be the shorteut, itis not always possible. You can resolve the conilict between “Cheeses” and “Consistency,” for example, by making 0 the shortcut for “Consistency,” but the result is not as easy to Chapter 2, Wiiting Turbo Vision applications 9The Options feld and the ofPostProcess bit are both ‘explained in Chapter 4 ‘See the “Phaso” section in ‘Chapter § for more ‘explanation. remember. Another way, of course, is to relabel something. Instead of the label “Cheeses,” you could label that cluster “Kind of Cheese,” with Kas the shortcut. This sort of manipulation is the only way around conflicts of shortcut keys at the same level. However, there is another approach you can take ifthe conflict is between, say, a label and a ‘member of a cluster: Shortcut keys can be made local within a dialog box item. In the previous example, for example, if you localize the shortcuts within each cluster, pressing Mwhen the ‘check boxes are focused will not activate the “Consistency” buttons or the “Melted” button. Mwould only function as a shortcut if you clicked or Tabbed into the “Consistency” cluster first. By default ll shortcut keys are active over the entire dialog box. If ‘you want to localize shortcuts, change the default Options field for the object you are about to insert into the dialog box. For example, if you want to make the shortcuts in your check boxes local, you. ‘would add another line before inserting into the dialog box: Rassign!3, 3, 18) 61s ow (neck Mexsiten("evart YerdTten(?-T-ilset’, estten(!~Jrarlaberg' ait) options and not ofPostPzocess; ower Now the H, T, and Jshortcut keys only operate if you click or Tab into the “Cheeses” cluster first. Alt, AILT, and Alt will continue to function as before, however. Xeep in mind that a label never gets the focus. Therefore, a label aust have its ofPastProcess bit on for its shortcut to operate. Having ofPostProces set means that the user can enter information in a dialog box quickly. However, there are come pooaible drawbacks. A user may press a shortcut key expecting it to go to one place, but because of a conflict it goes somewhere else. ‘Similarly, ifthe user expects shortcut keys to be active, but they're only active locally, it could be confusing to have a shortcut key do nothing when itis pressed outside the area where itis active. ‘The best advice we can give you is to test your dialog boxes carefully for conflicts. Avoid having duplicate shortcut keys when Turbo Vision Guide ' | | { i i t Ending the dialog box possible, and always make it clear to the user which options are available. When you are through with the dialog box, you call Dispose(D, Done). Calling Done also removes the dialog box from the desktop. Other dialog box controls Static text List viewer List box ‘The Dialogs unit has some additional ready-made parts that ‘weren’t used in this example, They are used in the same way as the items you did use: You create a new instance, insert it into the dialog box, and include any appropriate data in the data record. ‘This section will just describe briefly the functions and usage of each one. Much more detail is contained in Chapter 13, “Object reference.” TStaticText is a view that simply displays the string passed to it. ‘The string is word wrapped within the view’s rectangle. The text will be centered if the string begins with a Cir-Cand line breaks ‘can be forced with CttM, By default, the text can’t get the focus, and of course, the object gets no data from the data record. A TListViewer will display a single or multiple columa list, from which the user can select items. A ListViewer can also communicate with two seroll bars. ‘ListViewer is meant to be a building block, and is not usable by itself It has the ability to handle alist, but does not itself contain a list. Its abstract method GetText loads the list members for its Draw method. A working descendant of TListVicwer needs to override GetTet to load actual data. ‘ListBox is a working descendant of TListViewer. It owns a ‘Collection that is assumed to be pointers to strings. TListBox only ‘supports one scroll bar. An example of alist box is the file (Chapter 2, Witing Turbo Vision applications 6History selection list in the Turbo Pascal integrated environment, or the file list used by TFileDizlog in STDDLG.PAS. Getting and setting data with list boxes is greatly facilitated by the use of the TListBoxRec record type, which holds a pointer to a collection containing the list of strings to be displayed and a word indicating which item is currently selected in the lst. ‘THistory implements an object that works together with an input line and a related list box. By clicking on the arrow icon next to ‘the input line, the user brings up a list of previous values given {or the input line, any of which may then be selected. This saves ‘on repetitive typing. ‘THistory objects are used in many places in the Turbo Pascal integrated environment, such as the File | Open dialog box and in the Search| Find dialog box. Standard dialog boxes 2 ‘The StdDig unit contains a pre-built dialog called TFileDialog. You ‘use this dialog box in the integrated environment when you open, afile. TFileDialog uses a number of further objects, also in the StdDig unit, which you may find useful: ‘lletotlecticn » abject (sSortedcollection) ‘WortedListBex = ebject(1ListBox) IelleList = object (SortedtistBox) ‘ilelntozene + abject (Tviee) Because the source for the entire standard Dialogs unit is included, ‘we will not describe the objects in detail here. Turbo Vision Guide Programming Turbo Vision\ The object hierarchy : ‘This chapter assumes that you have a good working knowledge ' of Turbo Pascal, especially the object-oriented extensions, although we do recap some relevant facts about object types. It also assumes that you have read Part I of this book to get an overview of Turbo Vision’ philosophy, capabilities, and | terminology. | ‘After some general comments on OOP and hierarchies, this | chapter takes you quickly through the Turbo Vision object ' hierarchy, stressing how the objects are related through the | inheritance mechanism. By learning the main properties of each standard objec type (many of which are related to the objects : name in an obvious way), you will gain an insight into how the : inherited and new fields and methods of each object combine to i provide the objects functionality. i ‘The complete hierarchy tree is shown in Figure 3.1. You'll find i} that this picture repays careful study. To know that TDialog, for { example, is derived from TWindow, which isa descendant of ' ‘TGroup, which ia descendant of TView, reduces the learning, curve considerably. Each new derived object type you encounter already has familia inherited properties; you simply study ‘whatever additional fields and properties it as over its parent. Tuba Vision Guicte ; Chapter 3, The object hierarchy 6Fgue3.1 Turbo Vsion object hierarchy Tobject—-TVie ‘Teackground Button TCluste ‘TheckBoxes TRadioBut tons TFrane Térou} TheskTop Ererogran———tapptication THindor————-TDialog THistoryWindow THistory TInputLine TListViever TListdox Litistoryviener MenuVier Hera _ TMerBox crol er ——Textevice 1 TScrol Bar full TStaticText- TLabel Ciparantext TStatusLine ‘Tol lection——TSortedCol lection—TStringCol lect ion—TResourceCol lection TStreat TResourceFile TStringList TStrListNaker ‘TDosStrean—————TBufStrean TEnsStrean ‘As you develop your own Turbo Vision applications, you will find that a general familiarity with the standard object types and their mutual relationships is an enormous help. Mastering the minute details will come later, but as with all OOP projects, the initial overall planning of your new objects is the key to success. ‘There is no “perfect” hierarchy for any application. Every object hierarchy is something of a compromise obtained by careful experiment and ir amount of intton acquired with practice). You can benefit from our experience in developing {bjt ype herarchies Naturally, you can create your own base ‘object types to achieve special eects beyond the standard objects provided. Chapter 13, “Object reference,” describes the methods and fields of each standard object type in depth, but until you acquire an ‘overall fee for how the hierarchy is structured, you can easily become overwhelmed by the mass of detail This chapter presents an informal brovrse through the hierarchy before you tackle the Turbo Vision Guide detail. The remainder of this part will give explanations of the components of Turbo Vision and how to use them. Part 3 provides alphabetical reference material. Object typology Abstract objects Not all object types are created equal in Turbo Vision. You can separate their functions into three distinct groups: primitive objects, view objects, and mute objects. Each of these is described in a separate section of this chapter. Within each of these groups there are also different sorts of objects, some of which are useful objects that you can instantiate and use, and others of which are abstract objects that serve as the basis for deriving related, useful objects. Before we look at the objects in the Turbo Vision hierarchy, it will be helpful to understand a little about these abstract objects. ‘Many object types exist as “abstract” bases from which more specialized and immediately useful object types can be derived. ‘The reason for having abstract types is partly conceptual but largely serves the practical aim of reducing coding effort. “Take the TRadioButons and TCheckBoxes types, for example. They could each be derived directly from TView without difficulty. However, they share a great deal in common: They both represent sels of controls with similar responses. A set of radio buttons is a lot like a set of check boxes within which only one box can be checked, although there are a few other technical differences. This commonality warrants an abstract class called TCtustr. ‘TRadioButtons and TCheckBoxes are then derived from TClustr with the addition of few specialized methods to provide their individual functionalities. Abstract types are never usefully instantiated. An instance of TCluster, MyCluser, for example, would not have a useful Draw method: It inherits TView Draw without overriding, s0 MyCluster Draw would simply display an empty rectangle ofthe default color. If you want a fancy cluster of controls with [properties different from radio buttons or check boxes, you might {ay deriving a TMyCluster from TClustr, or it might be easier to derive your special cluster from TRadioButtons or TCheckBoxes, Chapter 8, he object hierarchy oAbstract methods depending on which is closer to your needs. In all cases, you would add fields, and add or override methods, with the least possible effort. If your plans include a whole family of fancy clusters, you might find it convenient to create an intermediate abstract object type. ‘Whether you can usefully instantiate an object type depends entirely on the circumstances. Many of Turbo Vision's standard types have abstract methods that must be defined in descendant types. Standard types may also have pseudo-abstract methods offering minimal default actions that may suit your purposes—if not, a derived type will be needed. AA general rule is that as you travel down the Turbo Vision hierarchy, the standard types become more specialized and less “abstract.” Their names reveal the functionality encapsulated in their fields and methods. For most applications there will be ‘obvious base types from which you can create a “standard” interface: a desktop, menu bar, status line, dialog boxes, and so Object instantiations and derivations instantiation Given any object type there are two basic operations available: You can create an instance of that type (“instantiate” it), or you can derive a descendant object type. In the latter case, you have a new object type on which the previous two operations can again be applied. Let’s examine these operations in more detail. Creating an instance of an object is usually accomplished by a variable declaration, either static or dynamic: ySeroLlBar: tSerot2Bars Semebutton: 2Bvttor; ‘MyScrollBar would be initialized by TScrollBar.init with certain default field values. These can be found by consulting the ‘TScrollBar init entry in Chapter 13, “Object reference.” Since TScroliBar is a descendant of TView, TScrollBar.Init calls TView Init to set the fields inherited from TView. Similarly, TView.Jnit is a Turbo Vision Guide: Derivation descendant of TObject, soit calls the TObject constructor to allocate memory. TOtject has no parent, so the buck stops there. ‘The MyScrollBar object now has default field values which you may need to change. It also has all the methods of TScrollBar plus the methods (possibly overridden) of TView and TObject. To make use of MyScrollBar, you need to know what its methods do, especially HandleEvent and Draw. Ifthe required functionality is, not defined in TScrollBar, you need to derive a new descendant type ‘You can easily derive a new object type from an existing one: PeSerollBar = “PowSorollBar ‘TiewSeroL1Bor = abject (TSorol}B2r) end; You do not yet have any instances of this new object type. Before declaring any TNewScrollBar objects, you need to define new methods or override some of TScrollar’s methods and possibly add some new fields; otherwise there would be no reason to create a new scroll bar object type. The new or revised methods and fields you define constitute the process of adding, functionality to TScrollBar. Your new Init method would determine the default values for your new scroll bar objects. Turbo Vision methods Abstract methods Chapter 3, he object hierarchy ‘Turbo Vision methods can be characterized in four (possibly overlapping) ways, each described here. In the base object type, an abstract method has no defining body (ora body containing the statement Abstract set to trap illegal calls). Abstract methods must be defined by a descendant before they can be used. Abstract methods are always virtual methods. ‘An example of this is TStream Read. &Pseudo-abstract methods Virtual methods Static methods In the base object type, a pseudo-abstract method has a minimal action defined. It will almost always be overridden by a descendant to be useful, but the method provides a reasonable default forall objects in the inheritance chain. An example is TSortedCollection.Compare. Virtual methods use the virtual directive in their prototype declarations. A virtual method can be redefined (overridden) in descendants but the redefined method must itself be virtual and match the original method's header exactly. Virtual methods need not be overridden, but the usual intention is that they will be overridden sooner or later. An example of this is TView.DataSize. A static method cannot be overridden per se. A descendant type ray definea method with the same name using entirely different arguments and return types, if necessary, but static methods do xnot operate polymorphically. This is most critical when you call methods of dynamic objects. For example, if PGeneric is a pointer variable of type PView, you can assign pointers of any type from the hierarchy to it However, when you dereference the variable and calla static method, the method called will always be TView’s, since tha is the type ofthe pointer as determined at compile time. Inother words, PGeneric SaticMethod is aluays equivalent to View StaticMethod, even if you have assigned a pointer of some ‘other type to PGeneric. An example is TView Jn. Turbo Vision fields Ifyou take an important trio of objects: TView, TGroup, and Tivindow, a glance at thelr felds reveals inheritance at work, and, also tells you quite abit about the growing functionality as you move down the hierarchy (recall that object tres grow downward from the root. Turbo Vision Guide Table 33 Inheritance of view fields TGroup fields ——TWindow fields ‘Owner ‘Owner Now Next Origin Origin Sie Sue Catsor Cirsor GrowMode GrowMode DragMode DragMode Help Helpot State State Options Options BventMask EventMask Batter Batter Phase Phase Carrent Carrent ast Last gs Tile Number Zoom Palette Frame [Notice that TGroup inherits all the fields of TViaw and adds several more that are pertinent to group operation, such as pointers to the current and last views inthe group. TWindow in fur inherits all of TGroup's fields and adds yet more which are needed for window operation, such as the title and number of the window. In order to fully understand TWindow, you need to keep in mind that a window isa group and also a view. Primitive object types ‘Turbo Vision provides three simple object types that exist primarily to be used by other objects or to act as the basis of a hierarchy of more complex objects. TPoint and TRect are used by all the visible objects in the Turbo Vision hierarchy. TObject is the basis of the hierarchy. Note that objects of these types are not directly displayable. ‘TPoint is simply a screen-position object (X, Y coordinates). TRect sounds like a view object, but it just supplies upper-left, ower- right rectangle bounds and several non-display utility methods, Chapter 3, The object hierarchy nTPoint TRect TObject This object represents a point. Its fields, X and Y, define the cartesian (X,Y) coordinates of a screen position. The point (0,0) is the topmost, leftmost point on the screen. X increases horizontally to the right; Y increases vertically downwards. TPoint has no ‘methods, but other types have methods that convert between global (whole screen) and local (relative to a view’s origin) coordinates. ‘This object represents a rectangle. Its fields, A and B, are TPoint objects defining the rectangle's upper-left and lower right points. TRect has methods Assign, Copy, Move, Grow, Intersect, Union, Contains, Equals, and Emply. TRect objects are not visible views and cannot draw themselves. However, all views are rectangular: ‘Their Init constructors all take a Bounds parameter of type TRect to determine the region they will cover. Object is an abstract base type with no fields. Itis the ancestor of all Turbo Vision objects except TPoint and TRect. TObject provides three methods: Int, Free, and Done. The constructor, Init, forms the base for all Turbo Vision constructors by providing memory. allocation. Free disposes of this allocation. Done is an abstract destructor that must be overriden by descendants. Any objects ‘that you intend to use with Turbo Vision's streams must be derived ultimately from TObject. ‘TObject’s descendants fall into one of two families: views or non- views. Views are descendants of TView, which gives them special properties not shared by non-views. Views can draw themselves and handle events sent to them. The non-view objects provide a host of utilities for handling streams and collections of other objects, including views, but they are not directly “viewable.” ‘The displayable descendants of TObject are known as views, and. are derived from TView, an immediate descendant of TObject. You Tutbo Vision Guide Views overview Groups The abstract group should distinguish “visible” from “displayable,” since there may bbe times when a view is wholly or partly hidden by other views. ‘A view is any object that can be drawn (displayed) in a rectangular portion of the screen. The type of a view object must bea descendant of TView. TView itself is an abstract object representing an empty rectangular screen area. Having TView as, an ancestor, though, ensures that each derived view has atleast a rectangular portion ofthe screen and a minimal virtual Draw ‘method (forcing all immediate descendants to supply a specific Draw method) Most of your Turbo Vision programming will use the more specialized descendants of TView, but the functionality of TView permeates the whole of Turbo Vision, so you'll need to understand what it offers. ‘The importance of TView is literally apparent from the hierarchy chart shown in Figure 31. Everything you can see in a Turbo ‘Vision application derives in some way from TView. But some of ‘hose visible objects are also important for another reason: They allow several objects to actin concert. ‘Troup lets you handle dynamically chained lists of related, interacting subviews via a designated view called the owner of the group. Each view has an Owner field of type PView that points to the owning TGroup object. A nil pointer means that the view has no owner. A field called Next provides a link to the next view in the view chain. Since a group is a view, there can be subviews that are groups owning their own subviews, and so on. “The state of the chain is constantly changing as the user clicks and types during an application. New groups can be eroated and. subviews can be added to (inserted) and deleted from a group. During its lifespan, a subview can be hidden or exposed by actions performed on other subviews, so the group needs to coordinate many activities. Chapter 3, The object hierarchy iy4 Desktops Programs Applications Windows Dialog boxes "TDesktop is the normal startup background view, providing the familar users desktop, usually surrounded by a menu bar and status line. Typically, TApplication will be the owner of a group containing TDesktop, TMenuBar and TStatusL.ine objects. Other views (such as windows and dialog boxes) are created, displayed, and manipulated in the desktop in response to user actions (mouse and keyboard events). Most of the actual work in an application goes on inside the desktop. ‘TProgram provides a set of virtual methods for its descendant, ‘TApplication. ‘TApplication provides a program template object for your Turbo Vision application. Its a descendant of TGroup (via TProgram). ‘Typically, it will own TMenuBar, TDesktop and TStatusLine subviews. TApplication has methods for creating and inserting these three subviews. The key method of TApplication is ‘Application Run which executes the application's code. ‘TWindow objects, with help from associated TFrame objects, are ‘the popular bordered rectanglar displays that you can drag, resize, and hide using methods inherited from TView. A Geld called Frame points tothe window's TFrame object. A TWindow object can also zoom and close itself using its own methods. TWindow handles the Tab and Shi. Tab key method for selecting the next and previous selectable subviews in a window. TWindows event handler takes care of close, zoom, and resize commands. Numbered windows can be selected with Alta hot eys. ‘TDialog is a descendant of TWindow used to create dialog boxes to handle a variety of user interactions. Dialog boxes typically contain controls such as buttons and check boxes. The parent's ExecView method is used to save the previous context, insert a ‘TDiklog object into the group, and then make the dialog bux ‘modal. The TDialog object then handles user-generated events such as button clicks and keystrokes. The Esc key is treated specially as an exit (omCancl). The Enter key is specially treated as a broadcast omDefault event (usually meaning that the default button has been selected). Finally, ExeeView restores the previously saved context. Turbo Vision Guide Terminal views Frames Buttons Clusters Menus Terminal views are all views that are not groups. That is, they cannot own other views. They are therefore the endpoints of any chains of views. ‘TFrame provides the displayable frame (border) for a TWindow object together with icons for moving and closing the window. ‘TFrame objects are never used on their own, but always in conjunction with a TWindow object. ‘A TButton object is a titled box used to generate a specific ‘command event when “pushed.” They are usually placed inside (owned by) dialog boxes, offering such choices as "OK" or “Cancel.” The dialog box is usually the modal view when it appears, soit traps and handles all events, including its button events, The event handler offers several ways of pushing a button: ‘mouse-clicking in the button’s rectangle, typing the shortcut letter, ‘or selecting the default button with the Enlerkey. ‘Cluster is an abstract type used to implement check boxes and radio buttons. A cluster is a group of controls that all respond in ‘the same way. Cluster controls are often associated with TLabel objects, letting you select the control by selecting on the adjacent explanatory label. Additional fields are Value, giving a user- defined value, and Sel, indexing the selected control of the cluster. ‘Methods for drawing text-based icons and mark characters are provided. The cursor keys or mouse clicks can be used to mark controls in the cluster. Radio buttons are special clusters in which only one control can be selected. Each subsequent selection deselects the current one (as with a car radio station selector), Check boxes are clusters in Which any number of controls can be marked (selected). "TMenView and ite two descendants, TMenuBar and TMenuBex, provide the basic objects for creating pull-down menus and submenus nested to any level. You supply text strings for the ‘menu selections (with optional highlighted shortcut leters) together with the commands associated with each selection. The HandleEvent methods take care of the mechanics of mouse and /or keyboard (including shortcut and hot key) menu selection. Chapter 3, he object hierarchy 8% Histories Input lines Ust viewers ‘Menu selections are displayed using a TMenuBar object, usually ‘owned by a TApplication object. Menu selections are displayed in objects of type TMenuBox. For most applications, you will not be involved directly with menu objects. By overriding TApplication InitMenuBar with a suitable set of nested New, NewSubMenu, Newltem and NewLine «alls, Turbo Vision builds, displays, and interacts with the required menus. ‘The abstract type THistory implements a generic picklist mechanism. Its two additional fields, Link and History, give each ‘THistory object an associated TInputLine and the ID of alist of previous entries in the input line. THistory works in conjunction ‘with THistoryWindow and THistoryViewer. ‘TinputLine isa specialized view that provides a basic input line string editor. It handles all the usual keyboard entries and cursor ‘movements (including Home and End. It offers deletes and inserts with selectable insert and overwrite modes and automatic cursor shape control. The mouse can be used to block mark text. ‘The TListViewer object type is an abstract base type from which to derive list viewers of various kinds, such as TListBor. TListViewer's fields and methods let you display linked lists of strings with control over one or two scroll bars. The event handler permits ‘mouse or key selection (with highlight) of items on the list. The Draw method copes with resizing and scrolling. TListViewer has an abstract GetText method, so you need to supply the mechanism for creating and manipulating the text ofthe items to be displayed. ‘ListBox, derived from TListViewer, implements the most commonly used list boxes, namely those displaying lists of strings such as file names. TListBox objects represent displayed lists of such items in one or more columns with an optional vertical scroll bat. The horizontal scroll bars of TListViewer are not supported. The inherited TListViewer methods let you select (and highlight) items by mouse and keyboard cursor actions. TListBox has an additional field called List, pointing to a Collection object. This provides the items to be listed and selected. The contents of the collection are your responsibility, as are the actions to be performed when an item is selected. Turbo Vision Guide Scroling objects Text devices Static text A TScroller object isa scrollable view that serves as a portal onto another larger “background” view. Scrolling occurs in response to keyboard input or actions in the associated TScrollBar objects. Scrollers have two fields, HScrollid and VScrollid, identifying their controlling horizontal and vertical scroll-bars. The Delta field in TScroller determines the unit amount of X and Y scrolling in conjunction with fields in the associated scroll bars. TerollBar objects provide either vertical or horizontal control. The key fields are Value (the position of the scrollbar indicator), Step (the amount of scrolling needed in response to mouse clicks and PoUp, Pal keys) and ArStep (the amount of scrolling needed in response to mouse clicks and arrow keys). ‘A scroller and its scroll bars are usually owned by a TWindow ‘object leading to a complex set of events to be handled. For example, resizing the window must trigger appropriate redraws by the scroller. The values of the scroll bar must also be changed. and redrawn, ‘TTextDevice isa scrollable TTY-type text viewer/ device driver. Apart from the fields and methods inherited from TScroler, THextDevice defines virtual methods for reading and writing strings from and to the device. TTextDevice exists solely as a base type for deriving real terminal drivers. TTextDevice uses TScroller’s constructor and destructor. TTerminal implements a “dumb” terminal with buffered string reads and writes. The size of the buffer is determined at initialization. TStaticText objects are simple views used to display fixed strings provided by the field Text. They ignore any events sent to them. ‘The TLabel type adds the property that the view holding the text, Known asa label, can be selected (highlighted) by mouse-click, cursor key, or shortcut Altletter keys, The additional field Link associates the abel with another view, usually a control view that handles all label events. Selecting the label selects the linked control and selecting the linked control highlights the label as, ‘well as the control. Chapter 3, The object hierarchy nStatus lines A TStatusLine object is intended for various status and hint (help) displays, usually at the bottom line of the screen. A status line isa cone-character high strip of any length up to the screen width. The object offers dynamic displays reacting with events in the unfolding application, Items on the status line can be mouse or hot key selected rather like TLabel objects. Most application objects will start life owning a TMenuBar object, a TDesktop object, and a TStatusLine object. The added fields for TStatusLine provide an Items pointer and a Defs pointer. ‘The Items field points to the current linked lst of TStatusltem records. These hold the strings to be displayed, the hot key ‘mappings, and the associated Command word. The Defs field points toa linked list of PStatusDef records used to determine the current help context so you can display short “hints.” TStatusLine can be instantiated and initialized using Application nitStatusLine. Non-visible elements 8 Streams ‘The non-view families derived from TObject provide streams, resource file, collections, and string lists. ‘A stream isa generalized object for handling input and output. In traditional device and file I/O, separate sets of functions must be devised to handle the extraction andl conversion of different data, types. With Turbo Vision streams, you can create polymorphic 1/O methods such as Rexd and Write that know how to process their own particular stream contents. Stream is the base abstract object providing polymorphic I/O to and from a storage device. TStream provides a Status fold indicating the access mode (read only, write only, read/write) and an Lrrorinfo field to report I/O failures. There are acven virtual methods: Flush, GetPos, GetSize, Read, Seek, Truncate, and Write. ‘These must be overridden to derive specialized stream types. You'll see that Turbo Vision adopts this strategy to derive ‘TDosStream, TEmsStream, and TBufStream. Other methods include CopyFrom, Error, Get, ReadStr, Reset, and WriteStr. Turbo Vision Guide DOS streams Buffered streams EMS streams Resources Collections ‘Object types must be registered using RegisterType before they can bbe used with streams. Turbo Vision’s standard object types are preregistered (see “RegisterType procedure” in Chapter 14, “Global reference"). ‘TDosStream is a specialized TStream derivative implementing unbuffered DOS file streams. A Hanile field is provided, ‘corresponding to the familiar DOS file handle. The Init constructor creates a DOS stream with a given file name and access mode. TDosStream defines all the abstract methods of Stream except for Flush, which is needed only for buffered streams. ‘TBufStream implements a buffered version of TDasStream. The Bufer and Bufsize fields are added to specify the location and size of the buffer: The fields BufPtr and BufEnd define a current position and final position within the buffer. The abstract Stream Flush method is defined to flush the buffer. Flushing means writing out and clearing any residual buffer data before a stream is closed. ‘A further specialized stream, TEmsStream implements streams in EMS memory. New fields provide an EMS handle, the number of pages, the stream size, and the current position within the stream. A resource file is a special kind of stream where generic objects (“items”) can be indexed via string keys. Rather than derive resource files from Stream, TResouceFile has afield, Stream, associating a stream with the resource file. Resource items are accessed with Get(Key) calls where Key is the string index. Other ‘methods provided are Put (store an item with a given key), KeyAt (Get the index to a given item), Flush (write all changes to the stream), Delete (erase the item at a given key), and Count (return the number of items on file) ‘Collection implements a general set of items, inchuding arbitrary objects of different types. Unlike the arrays, sets, and lists of non- OOP languages, a Turbo Vision collection allows for dynamic sizing. TCollecion is an abstract base for more specialized. Chapter 3, The object hierarchy nSorted collections String collections Resource collections String lists collections, such as TSortedCollection. The chief field is Items, a pointer to an array of items. Apart fom the indexing, insertion, and deletion methods, TCollection offers several iterator routines, A collection can be scanned for the first or last item that meets a condition specified in a user-supplied test function. With the ForEack method you can also trigger user-supplied actions on each item in the collection. ‘TSortedCollection implements collections that are sorted by keys. Sorting is defined via a virtual, abstract Compare method. Your derived types can therefore specify particular ordering for collections of objects of any type. The Insert method adds items to ‘maintain this ordering, and keys can be located quickly with a binary Search method. ‘TStringCollecton is a simple extension of TSortedCollection for handling sorted collections of Turbo Pascal strings. The secret ingredient is the overriding of the Compare method to provide alphabetical ordering. A Freeltem method removes a given string, item from the collection. For writing and reading string collections on streams, the virtual Putltem and Getltem methods are provided. ‘TResourceCollection implements a collection of sorted resource indexes used by resource files. The TStringCollection methods, Freeltem, Getltem, KeyOf, and Putltem are all overriden to handle TstringList implements a special kind of string resource in which strings can be accessed via a numerical index using the Get method. A Count field holds the number of strings in the object. ‘TStringList simplifies internationalization and multilingual text applications. String lists can be read from a stream using the Load constructor. To create and add to string lists, you use ‘TStrListMaker. ‘TStringList offers access only to existing numerically indexed string lists, T'StrListMaker supplies the Put method for adding a string to a string list, and a Store method for saving string lists on a stream. Tutbo Vision Guide | | | I Views By now, you should have a sense, from reading Chapters 1 and 2 and front looking at the integrated environment, of what a Turbo Vision application looks like from the outside. But what's behind the scenes? That’ the subject of the next two chapters. “We have taken control of your TV...” Chapter 4, Views (One of the adjustments you make when you use Turbo Vision is that you give up writing directly to the screen. Instead of using Write and Writeln to convey information to the user, you give the information to Turbo Vision, which makes sure the information appears in the right places atthe right time. ‘The basic building block of a Turbo Vision application is the view. ‘A view is a Turbo Pascal object that manages a rectangular area of the screen. For example, the menu bar atthe top of the screen is a view. Any program action in that area of the screen (for example, clicking the mouse on the men bar) will be dealt with by the ‘view that controls that area. ‘Menus are views, as are windows, the status line, buttons, scroll bars, dialog boxes, and usually even a simple line of text. In general, anything that shows up on the screen of a Turbo Vision. Program must be a view, and the most important property of a ‘view is that it knows how to represent itself on the screen. So, for example, when you want to make a menu system, you simply tell 81‘Turbo Vision that you want to create a menu bar containing, certain menus, and Turbo Vision handles the rest. ‘The most visible example of a view, but one you probably would not think of as a view, is the program itself. It controls the entire screen, but you don’t notice that because the program sets up other views (called its subviews) to handle its interactions with the user. As you will see, what appears to the user as a single object ike a window) is often a group of related views. Simple view objects Setting your sights ‘As you can see from the hierarchy chart in Figure 46, all Turbo Vision views have TObject as an ancestor. TObject is little more than a common ancestor for all the objects. Turbo Vision itself really starts at TView. ‘A.TView itself just appears on the screen as a blank rectangle. ‘There is little reason to instantiate a TView itself unless you want to create a blank rectangle on the screen for prototyping purposes. But even though TView is visually simple, it contains all of Turbo Vision's basic screen management methods and fields. ‘There are two things any TView-derived object must be able to do: ‘The frst is draw itself at any time. TView defines a virtual method called Draw, and each object derived from TView must also have a Draw method. This is important, because often a view will be covered or overlapped by another view, and when that other ‘view goes away or moves, the view must be able to show the part of itself that was hidden. ‘The second is handle any events that come its way. As noted in Chapter 1, Turbo Vision programs are event-driven. This means that Turbo Vision gathers input from the user and parcels it out to ‘the appropriate objects in the application. Views need to know. ‘what to do when events affect them. Event handling is covered in detail in Chapter 5. Before discussing what view objects do, you need to learn a bit about what they are—how they represent themselves on the Turbo Vision Guide Points described inthe next section. Getting the TPoint Getting into a TRect ‘Te Window and PinsideView ‘fe just made up for his example, Chapter 4, Views ‘The location of a view is determined by two points: its top left corner (called its origin) and its bottom right corner. Each of these points is represented in the object by a field of the type TPoint. ‘The Origin field is a TPoint indicating the origin of the view, and the Size field represents the lower right corner. Note that Origin is a point in the coordinate system of the owner view: If you open a window on the desktop, its Origin field indicates the x-and y-coordinates of the window relative to the origin of the desktop. The Size field, on the other hand, is a point relative to the origin of its own object. It tells you how far the lower right comer is from the origin point, but unless you know ‘where the view’s origin is located within another view, you can’t tell where that corner realy is. ‘The TPoint type is extremely simple. It has only two fields, called X and ¥, which are its coordinates. It has no methods. Turbo Vision, uses the TPoint object to allow views to specify their coordinates asa single field. For convenience, TPoints are rarely dealt with directly in Turbo ‘Vision. Since each view object has both an origin and a size, they are usually handled together in an object called TRect. TRect has two fields, A and B, each of which is a TPoint. When specifying the boundaries of a view object, those boundaries are passed to the constructor in a TRect. ‘TRect and TView both provide useful methods for manipulating the size of a view. For example, if you want to create a view that fits just inside a window, you can get the window to tell you how big iti, then shrink that size and assign it to the new inside view. procedare Thishndoy.sakereLde: Inside: PInsidaview begin eteneene 1; (sets R to size of Taishindow J R.srov(-1, I} shrinks the rectangle by 1, both ways } Inside :+ vee(@tnsideviey, lt (B))2 ates inside view } Insert (Taste) (insert the nev view into the window J ent: GetExtent is a TView method that sets the argument TRect to the coordinates of a rectangle covering the entire view. Grow is aTurbo Vision, coordinates Figure 41 Turbo Vision coordinate system Making an appearance ‘Rect method that increases (or with negative parameters, decreases) the horizontal and vertical sizes ofa rectangle. ‘Turbo Vision's method of assigning coordinates may be different from what you're used to. The difference is that, unlike most coordinate systems that designate the character spaces on the screen, Turbo Vision coordinates specify the grid between the characters. For example, if Ris a TRect object, X-Assign(0, 00,0) designates a rectangle with no size—it is only a point. The smallest rectangle that can actually contain anything would be created with Reassign (0,0, 1/3) Figure 411 shows a TRect created by R.Assign (2,2,4,5)- ‘Thus, 2.Assign(2,2, 4,5) produces a rectangle that contains six character spaces. Although this coordinate system is slightly ‘unconventional, it makes it much easier to calculate the sizes of, rectangles, the coordinates of adjacent rectangles, and some other things as well. ‘The appearance of a view object is determined by its Draw method. Nearly every new type of view will need to have its own Draw, since it is, generally, the appearance of a view that distinguishes it from other views. ‘There are a couple of rules that apply to all views with respect to appearance. A view must cover the entire area for which itis responsible, and. tube able to draw itself at any time. Both of these properties are very important and deserve some discussion. Turbo Vision Guide Teritoriality Drawing on demand Putting on your best behavior event nanaing s covered n ‘defallin Chapter 5. "Event ‘ven programming.” Chapter 4, Views ‘There are good reasons for each view to take responsibility for its ‘own territory. A view is assigned a rectangular region of the screen. IF it does not fill in that whole area, the contents of the unfilled area are undefined: Just about anything could show up there, and you would have no control over it. The program ‘TVDEMO05.PAS demonstrates what happens if view leaves some of its appearance to chance. Inaddition, a view must aluays be able to represent itself on the screen. Thats because other views may cover part of it but then be removed, or the view itself might move. In any case, when called upon to do so, a view must always know enough about its present state to show itself properly. Note that this may mean that the view does nothing at all: It may bbe entirely covered, or it may nat even be on the screen, or the window that holds it might have shrunk to the point that the view {snot visible at all. Most of these situations are handled automatically, but itis important to remember that your view must always know how to draw itself. ‘This is different from a lot of other windowing schemes, where the writing on a window, for example, is persistent: You write it there and it stays, even if something covers it up then moves away. In Turbo Vision, you can’t assume that a view you uncover is correct—after all, something may have told it to change while it ‘was covered! ‘The behavior of a view is almost entirely determined by a method called HandleEvent. HandleEvent is passed an event record, which it must process in one of two ways. It can either perform some action in response to the event and then mark the event as having been handled, or it can pass the event along to the next view (if any) that should see it. ‘The key to behavior, really, is how the view responds to certain events. For example, ifa window receives an event containing a cmClose command, the expected behavior is that the window would close. It is possible that you might devise some other response to that command, but not likely.Complex views Groups and subviews ‘You've already leamed something about the most important immediate descendant of TView, the TGroup. TGroup and its, descendants are collectively referred to as groups. Views not descended from TGroup are called terminal views. Basically a group is just an empty box that contains and manages other views. Technically, its a view, and therefore responsible for all the things that any view must be able to do: manage a rectangular area of the screen, visually represent itself at any time, and handle events in its screen region. The difference is really in how it accomplishes these things: most of itis handled by subviews. A subview is a view that is owned by another view. That is, some view (a group) has delegated part of its region on the screen to be handled by another view, called a subview, which it will manage An excellent example is TApplication. TApplication is a view that controls a region of the screen—the whole screen, in fact. ‘TApplication is also a group that owns three subviews: the mem bar, the desktop, and the status line. The application delegates a region of the screen to each of these subviews. The menu bar gets the top line, the status line gets the bottom line, and the desktop {gets all the lines in between. Figure 4.2 shows a typical Application screen, Turbo Vision Guile Getting Chapter 4, Views Rowe 42 ‘application screen avout intoa group Notice that the application itself has no screen representation— ‘you don’t se the application. Its appearance is entirely determined by the views it owns. How does a subview get attached to a group? The process is called insertion. Subviews are created and then inserted into ‘groups. In the previous example, the constructor T Application Init ‘reates three objects and inserts them into the application: snitnesktop: Inieotatvckin nitrate S€ DeskTop © ntl then Insezt(Deekton); Af statusline © nil then Invert (Stateline); AE Henudor © nL then Taser Yerba) ‘Only when they have been inserted are the newly created views part ofthe group. In this particular case, TApplicatn has divided its region into three separate pieces and delegated one to each of its subviews. This makes the visual representation fairly straightforward, as the subviews do not overlap at all. There is no reason, however, that views cannot overlap. Indeed, one of the big advantages of a windowed environment is the ability to have multiple, overlapping windows on the desktop. Luckily, groups (including the desktop) know how to handle overlapping subviews. a788 Another angle on Z- order Fowe 43 Groups keep track ofthe order in which subviews are inserted. That onder is referred to as Z-order. As you wil see, Z-order determines the order in which subviews get drawn and the order in which events get passed to them. ‘The term Z-order refers to the fact that subviews have a three- dimensional spatial relationship. As you've already seen, every view has a position and size within the plane of the view as you seeit (the X and ¥ dimensions), determined by its Origin and Size fields. But views and subviews can overlap, and in order for Turbo Vision to know which view i in front of which others, we have to adda third dimension, the Z-dimension. Z-order, then, refers tothe order in which you encounter views as You start closest to you and move back “into” the screen. The last ‘view inserted is the “front” view. Rather than thinking of the screen as a flat plane with things ‘written on it, consider ita pane of glass providing a portal onto a three-dimensional world of views. Indeed, every group may be thought of as a “sandwich” of views, as illustrated in Figure 4.3. ‘The window itself is usta pane of glass covering a group of ‘views. Since all you see isa projection of the views behind the Turbo Vision Guide glass on the screen, you can’t see which views are in front of others unless they overlap. By default, a window has a frame, which is inserted before any other subviews. Itis therefore the “background” view. In creating a scrolling interior, two scroll bars get overlaid on the frame. To ‘you, in front of the whole scene, they look like part ofthe frame, ‘but from the side, you can see that they actually float “above” the frame, obscuring part of the frame from view. Finally, the scroller itself gets inserted, covering the entire area inside the border of the frame. Text gets written on the scroller, not on the window, but you can see it when you look through the window. ‘Ona larger scale, you can see the desktop as justa larger pane of glass, covering a larger sandwich, many ofthe contents of which are also smaller sandwiches, as shown in Figure 44. Figure 44 Side view ofthe desktop ‘TDesktoep ——- ‘TWindow, ——> ‘active and inactive SS Background ——+ Again, the group (this time the desktop) isa pane of glas. Is frst subview is a TBackground object, so that view is “behind” all the ‘others. This view also shows two windows with scrolling interior views on the desktop. Group portraits Groups are sort of an exception tothe rule that views must know how to draw themselves, because a group does not draw itself per se. Rather, a TGroup asks its subviews to draw themselves. The subviews are called upon to draw themselves in Z-order, ‘meaning that the first subview inserted into the group isthe first Chapter 4, Views 9%0 Relationships between views Figure 45 simple dciog box one drawn. That way, if subviews overlap, the one most recently inserted will be in front of any others. ‘The subviews owned by a group must cooperate to cover the entire region controlled by the group. A dialog box, for example, isa group, and its subviews—frame, interior, controls, and static text—-must combine to fully “cover” the full area of the dialog box view. Otherwise, “holes” in the dialog box would appear, with unpredictable (and unpleasant!) results. When the subviews of a group draw themselves, their drawing is automatically clipped at the borders of the group. Because subviews are clipped, when you initialize a view and give it toa ‘group, the view needs to reside at least partially within the group's boundaries. (You can grab a window and move it off the desktop until only one corner remains visible, for example, but something must remain visible for the view to be useful.) Only the part of a subview that is within the bounds of its owner group will be visible. ‘You may wonder where the desktop gets its visible background if it is a TGroup. At its initialization, the desktop creates and owns a subview called TBackGround, whose sole purpose is to draw in a uniform background for the whole screen. Since the background is the first subview inserted, itis obscured by the other views drawn in front of it. Views are related to each other in two distinct ways: They are ‘members of the Turbo Vision object hierarchy, and they are ‘members of the view tree. When you are new to Turbo Vision, itis important to remember the distinction. For example, consider the simple dialog box in Figure 4.5. It has a frame, a one-line text message, and a single button that closes the dialog box. In Turbo Vision terms, that’s a TDialog view that owns a Trame,a TStaticText, and a TButton. 9 bx Turbo Vision Guide ‘The object hi Tubo Velen object lerarchy gue 46 ierorehy Ownership Figure a7 [A imple dlalog Box view Chapter 4, Views ‘tee (One way views are related is as parent and child in the object hierarchy. Notice in the hierarchy diagram (Figure 4.6) that ‘TButton is a descendant of the TView object type. The TButfon actually is a TView, but it has additional fields and methods that make ita button. TDialog is also a descendant of TView (through ‘TGroup and TWindow), so it has much in common with TButton. ‘The two are distant “cousins” in the Turbo Vision hierarchy. HRs ins Wrapray inp teation THe ayer Butcfe a tn ete Trg ation— Horton Epeegpe ‘The other way that views are related is in a view tree. In the view tree diagram (Figure 4.7), the TDialog owns the TButton. Here the relationship is not between hierarchical object types (TDialog is not an ancestor of TButlon!), but between instances of objects, between owner and subview. a =a Watton ‘As you program, you'll need to make a TButton interact with its ‘owner in the view tree (TDialeg) and the TButton will also draw "upon attributes inherited from its ancestor (TView). Don't confuse the two relationships. ‘A running Turbo Vision application looks like a tree, with views instantiating and owning other views. As your Turbo Vision application opens and closes windows, the view tree grows and shrinks as object instances are inserted and removed. Of course, aSubviews and view trees Figure 48 Bawle Tube Vion view ree The same tind of object & ‘depicted somewhat tferenity in Figure 43 the object hierarchy only grows when you derive new object types from the standard objects. As noted earlier, the TApplication view owns and manages the ‘three subviews that it creates. You can think of this relationship as forming a view tree. Application is the trunk, and MenuBar, DeskTop, and StatusLine form the branches, as shown in Figure 4.8. Teplteation ge eel ena Beakton Searing ] ‘Remember, the relationship illustrated in Figure 4.8 is not an “object hierarchy, but a model of a data structure. The links indicate ownership, not inheritance. Ina typical application, as the user licks with the mouse or uses the keyboard, he creates more views. These views will normally appear on the desktop, and so form further branches of the tree. Itis important to understand these relationships between owners and subviews, as both the appearance and the behavior of a view depend a great deal on who owns the view. Let’ follow the process. Say, for instance, that the user clicks on a menu selection that calls fora file viewer window. The file viewer window will be a view. Turbo Vision will create the window and attach it to the desktop. ‘A window will most likely own a number of subviews: a TFrame (the frame around the window), a TSoroler (the interior view that holds a scrollable array of text), and a couple of TScolloars. When the window is called into being, it creates, owns, and manages its subviews. More views are now attached to our growing application, which now looks something like Figure 4.9. Tutbo Vision Guide Fours 49 Desktop with fle viewer ‘aoded Figure 410 View toe with fe viewer odded Chapter 4, Views ‘The view tree has also become somewhat more complex, as shown in Figure 4.10. (Again, these are ownership links.) ‘epi ieatton == [Serer feat ‘Now suppose the user clicks on the same menu selection and. ‘creates another file viewer window. Turbo Vision will create a second window and attach it to the desktop, as shown in Figure 4.Foe 412 View tro with two fle ‘lowers added Event routing & explained in oa ‘Chapter 6 ‘The view tree also becomes correspondingly more complex, as shown in Figure 4.12. oS el a —T[a_, Lz = Cate] Cat = ‘As you'll see in Chapter 5, program control flows down this view tree. In the preceding example, suppose you click on a scroll bar in the file viewer window. How does that click arrive at the right place? ‘The Application program sees the mouse click, realizes that it's within the area controlled by the desktop, and passes it to the desktop object. The desktop in tur sees that the click is within the area controlled by the file viewer, and passes it off to that view. The file viewer now sees that the click was on the scroll bar, and lets the scroll bar view handle the click, generating an appropriate response. ‘The actual mechanism for this is unimportant at this point. The important thing to remember is how views are connected. No Turbo Vision Guide ‘matter how complex the structure becomes, all views are ultimately connected to your application object. Af the user clicks on the second file viewer's close icon or ona ‘Close Window menu item, the second file viewer will close, Turbo ‘Vision then takes it off the view tree and disposes it. The window ‘will dispose all of its subviews, then be disposed itself. Eventually, the user will trim the views down to just the original four, and will indicate at some point that he is finished by pressing AILX or by selecting Exit from a menu. TApplication will dispose its three subviews, then dispose itself. Selected and focused views The focused view b the end ‘of he chain ofsolected ions tht sors ot the pplication Chapter 4, Views Within each group of views, one and only one subview is selected. For example, when your application sets up its memu bar, desktop, and status line, the desktop is the selected view, because that is where further work will take place. When you have several windows open on the desktop, the selected window is the one in which you're currently working. This is also called the active window (typically the topmost window). Within the active window, the selected subview is called the {focused view. You can think of the focused view as being the one you're looking at, or the one where action will take place. In an ‘editor window, the focused view would be the interior view with the text init. In a dialog box, the focused view is the highlighted. control. In the application diagrammed in Figure 4:12, Application is the modal view, and DeskTop is its selected view. Within the desktop, ‘the second (more recently inserted) window is selected, and ‘therefore active. Within that window, the scrolling interior is selected, and because itis a terminal view (that is, i's not a ‘group), itis the end of the chain, the focused view. Figure 4.13 depicts the same view tree with the chain of focused views highlighted by double-ined boxes.Flows 413 Te focus chaln Finding the focused view Onmonoetrome deploys, Turbo Vaion acics row characters to haleate the focus, How does a view get the focus? Toptiatton el i Years] Gee feo on [ero ar [eat ‘Among other things, knowing which view is focused tells you ‘which view gets information from the keyboard. For more information, see the section on focused events in Chapter 5, ““Bvent-driven programming,” ‘The currently focused view is usually highlighted in some way on the screen. For example, if you have several windows open on the desktop, the active window is the one with the double-lined frame; the others’ frames will be single-lined. Within a dialog box, the focused control (controls are views, too! is brighter than the others, indicating that itis the one that will be acted upon if you press Ener The focused controls therefore the default control as ‘well. A.view can get the focus in two ways, either by default when itis created, or by some action by the user. When a group of views gets created, the owner view specifies ‘which of its subviews is to be focused by calling that subview’s Select method. This establishes the default focus ‘The user may wish to change which view currently has the focus. Acommon way to do this isto click the mouse on a different view. For instance, if you have several windows open on the desktop, you can select different ones simply by clicking on them, Ina dialog box, you can move the focus among views by pressing Tab, which cycles through all the available views, or by clicking the mouse on a particular view, or by pressing a hot key. Turbo Vision Guide The focus chain ‘See Chapter 5 “Event-ctiven "programming." fora ful ‘explanation Modal views Note that there are some views that are not selectable, including the background of the desktop, frames of windows, and scroll ‘bars. When you create a view, you may designate whether that view is selectable, after which the view will determine whether it lets itself be selected. If you click on the frame of a window, for example, the frame does not get the focus, because the frame ‘knows it cannot be the focused view. If you start with the main application and trace to its selected subview, and continue following to each subsequent selected subview, you will eventually end up at the focused view. This chain of views from the TApplication object to the focused view is, called the focus chain. The focus chain is used for routing focused events, such as keystrokes, Chapter 4, Views A mode is a way of acting or functioning. A program may havea ‘number of modes of operation, usually distinguished by different control functions or different areas of control. Turbo Pascal's integrated environment, for example, has an editing and debugging mode, a compiler mode, and a run mode. Depending, ‘on which of these modes is active, keys on the keyboard may have varying effects (or no effect at alb. ‘A Turbo Vision view may define a mode of operation, in which ‘ase iti called a modal view. The classic example of a modal view {sa dialog box. Usually, when a dialog box is active, nothing outside it functions. You can’t use the menus or other controls not ‘owned by the dialog box. In addition, clicking the mouse outside ‘the dialog box has no effect. The dialog box has control of your program until closed. (Some dialog boxes are non-modal, but ‘these are rare exceptions.) When you instantiate a view and make it modal, only that view and its subviews can interact with the user. You can think of a modal view as defining the “scope” of a portion of your program, ‘When you ereate a block in a Turbo Pascal program (such as a function or a procedure), any identifiers declared within that block are only valid within that block. Similarly, a modal view determines what behaviors are valid within it—events are ”Ihe stots ine b awways “hot” ‘no matter what vow ‘modal handled only by the modal view and its subviews. Any part of the view tree that is not the modal view or owned by the modal view is inactive. ‘There is actually one exception to this rule, and that is the status line. Turbo Vision “cheats” a litle, and keeps the status line available at all times. That way you can have active status line items, even when your program is executing a modal dialog box that does not own the status line. Events and commands generated by the status line, however, will be handled as if they ‘were generated within the modal view. ‘There is always a modal view when a Turbo Vision application is running. When you start the program, and often for the duration of the program, the modal view is the application itself, the Application object atthe top of the view tree. Modifying default behavior 8 The Options flag word Up to this point, you have seen mostly the default behavior of the standard views. But sometimes you will want to make your views look or acta litle different, and Turbo Vision provides for that. ‘This section explains the ways you can modify the standard Every Turbo Vision view has four bitmapped fields that you can use to change the behavior of the view. Three of them are covered hhere: the Options word, the GrowMode byte, and the DragMode byte. The fourth, the EventMask word, is covered in Chapter 5, “Bvent-driven programming.” ‘There is also a Stale word that contains information about the current state of the view. Unlike the others, State is essentially read-only. Its value should only be changed by the SetState method. For more details, see the "State flag and SetState” section in this chapter, Options is a bitmapped word in every view. Various descendants cof TView have different Options set by default. ‘The Options bits are defined in Figure 4.14; explanations of the possible Options follow. Turbo Vision Guide Figure 414 Cptions Bi fogs ofSelectable offopselect offirstClick offramed ofPreProcess ofPostProcess Chapter 4, Views | Loe: If set, the user can select the view with the mouse. Ifthe view is in a group, the user can select it with the mouse or Tab key. If you. puta purely informational view on the screen, you might not ‘want the user to be able to select it. Static text objects and window frames, for example, are usually not selectable. ‘The view will be moved to the top of the owner's subviews if the ‘view is selected. This option is designed primarily for windows on the desktop. You shouldn't use it for views in a group. ‘The mouse click that selects the view is sent on to the view. Ifa button is clicked, you definitely want the process of selecting the ‘button and operating it to happen with one click, s0 a button has offirstClick set. But if someone clicks on a window, you may or ‘may not want the window to respond to the selecting mouse click other than by selecting itself. Ifset, the view has a visible frame around it. This is useful if you create multiple “panes” within a window, for example. If set, allows the view to process focused events before the focused view sees them. See the “Phase” section in Chapter 5, “Bvent-driven programming” for more details, If set, allows the view tn handle focused events after they have been seen by the focused view, assuming the focused view has rot cleared the event. See the “Phase” section in Chapter 5, “Bvent-driven programming” for more details.100 ofButfored offileable olCenterx ofCenterY ‘When this bit is set, groups can speed their output to the screen. ‘When a group is first asked to draw itself, it automatically stores the image of itself in a buffer if this bit is set and if enough ‘memory is available. The next time the group is asked to draw itself, it copies the buffered image to the screen instead of asking, all its subviews to draw themselves, Ifa New or GetMem call runs out of memory, Turbo Vision’s memory manager will begin disposing of these group buffers until the memory request can be Ifa group has a buffer, a call to Lock will stop all writes of the {group to the screen until the method Unlock is called. When Unlock is calted, the group's buffer is written to the screen. Locking can decrease flicker during complicated updates to the screen. For example, the desktop locks itself when itis tiling or cascading its subviews. ‘The desktop can tile or cascade the windows that are currently open. If you don’t want a window to be tiled, you can clear this Dit. The window will then stay in the same position, while the rest of the windows will be automatically tiled. ‘Tiling or cascading views from TApplication.HandleEvent is simple: nti: Degin Desktop cet Extent) Desktop 7826(8); aad; cxtazcade: begin Desktop". cettxtentR): DeskTop” cascade (82 ext; If there are too many views to be successfully cascaded, the desktop will do nothing. ‘When the view is inserted ina group, center it in the x dimension. ‘When the view is inserted in a group, center itin the y dimension, ‘You may find this an important step in making a window work ‘well with 25- or 43-line text modes. Turbo Vision Guide ofCentered The GrowMode flag byte Figure 415, GeowMlode Bt fags gfGrowLox gfGrowLoY afGrowHix gfGrowHy @fSrowAll gfGrowRel Chapter 4, Views Center the view in both the x and y dimensions when it is inserted in the group. [A view’s GrowMode field determines how the view will change ‘when its owner group is resized. ‘The GrowMode bits are defined as follows: ote LL rota Leet Leen fset, the left side of the view will maintain a constant distance from its owner$ left side. If set, the top of the view will maintain a constant distance from the top of its owner, If set, the right side of the view will maintain a constant distance from its owner’s right side. If set, the bottom of the view will maintain a constant distance from the bottom ofits owner. If set, the view will always remain the same size, and will move ‘with the lower right corner of the owner. If set, the view will maintain its size relative to the owner's size. ‘You should only use this option with TWindows (or descendants of TWindow) that are attached to the desk top. The window will ‘maintain its relative size when the user switches the application between 25- and 43/50-line mode. This flag isn’t designed to be used with views within a window. 101The DragMode flag byte Figur 416 ragMode bit fags dmDragMove dmDragGrow dmtimitlox dmlimitLoy ‘demLirnitHx ‘denLimitHiy dmLimitAll State flag and SetState ‘A view's DragMode field determines how the view will behave ‘when it is dragged. ‘The DragMode bits are defined as follows: ‘The DragMode settings include the following: When this bit is set, when you click on the top of a window's, frame, you can drag it. ‘When this bit is set, the view can grow. If set, the left side of the view cannot go out of the owner view. If st, the top of the view is not allowed to go out of the owner If set, the right side of the view cannot go out of the owner view. If set, the bottom of the view cannot go out of the owner view. If set, no part of the view can go out of the owner view. ‘A view also has a bitmapped flag called State which keeps track of varions aspects of the view, such a whether itie visible, dicabled, or being dragged. ‘The State flag bits are defined in Figure 4.17. Turbo Vision Guide gue 417 State fag bi mopeing Acting on a state Chapter 4, Views change ie Le iit Hs ie ‘The meanings of each of the state flags is covered in Chapter 14, “Global reference,” under “sfXXXX state flag constants.” This section focuses on the mechanics of manipulating the State field. ‘Turbo Vision changes a view's state flag through its SetState method. Ifthe view gets the focus, gives up the focus, or becomes selected, Turbo Vision calls SetState. This differs from the way the other bitmapped flags are handled, because those are set on initialization and then not changed (if a window is resizable, itis, always resizable, for example). The state of a view, however, will often change during the time itis on the screen. Because ofthis, ‘Turbo Vision provides a mechanism in SetState that allows you not only to change the state of a view, but also to react to those changes in state. SetState receives a state (ASiae) and a flag (Enable) indicating ‘whether the state is being set or cleared. If Enable is True, the bits in AState are set in State f Enable is False, the corresponding State bits are cleared. That much is essentially like what you would do ‘with any bitmapped field. The difference comes when you want a View todo something when you change it state, ‘Views often take some action when SetState is called, depending, on the resulting state flags. A button, for example, watches Stale and changes its color to cyan when it gets the focus. Here's a typical SetState for a descendant of TView: procedure maurton.serscato(astate: Word Bnable: sooteai Desi ‘ileu.setstate Astate, Bnable); (-set/etear state bits Af astate and (efSelected + sfActive) © 0 then Drawiew; Af astate and efFocused © 0 than vakeDefoule(Geable) end: Notice that you should always call TView.SetState from within a new SetState method. TView.SetState does the actual setting orThis the code used by the clearing of the state flags. You can then define any special actions. ‘based on the state of the view. TButton checks to see if it is in an active window in order to decide whether to draw itself. It also ‘checks to see if has the focus, in which case it cals its ‘MakeDefault method, which grabs or releases the focus, depending ‘on the Enable parameter, If you need to make changes in the view or the application when the state of a particular view changes, you can do it by overriding. the view's SetState. Suppose your application includes a text editor, and you want to enable or disable all the menu bar’ text editing commands depending on whether or not an editor is ‘open. The text editor's SetStafe is defined like this: ‘procedure Teditor.setstato(AState: Word Boable: Boolean); const ‘itorcomands = (enseaich, cateplace, cnsearchhgain, exfotoLine, caPindProc, caPindEzzor, ensave, ensavels] Dogia ‘Dies. setstate(Astate, Enable): Af AState and sfactive © 0 hen Af Enable then EnableCosnands(RditorCommands) false DisableConmands(altorComanda}: 2d; ‘This code comes directly from the Turbo Pascal integrated environment, so the behavior it describes should be familiar. ‘The programmer and Turbo Vision often cooperate when the state changes. Suppose you want a block cursor to appear in your text editor when the editor’ insert mode is toggled on, for example. First the editor insert mode will have been bound to a key- stroke—say, the ns key. When the text editor isthe focused view and the ins key is pressed, the text editor receives the Ins key ‘event. The text editor's HandleEvent method responds to the Ins event by toggling some internal state of the view saying that the insert mode has changed, and by calling the BlockCursor method ‘Turbo Vision does the rest. BlockCursor calls the view’s SetState to act the fCursorins state tue. What color is your view? No one ever seems to agree on what colors are “best” for any computer screen. Because of this, Turbo Vision allows you to Turbo Vision Guide Color palettes Petes for alstncerd vows aeistod n Chapter 15 “Gixoctrotoronce. owe 418 ‘serolers default Colo palette GefColor a TView method. Selecting non
aid) and (Oesktop®.Exe0Vlew(0}) = entes): Chapter 6, Witing sate programs 133134 Non-memory errors ValidView returns either a pointer to the view passed or nil if the ‘view was invalid. If LowMemory returns True, ValidView takes care of disposing the view in question and calling OutOfMemory. Of course, not all errors are memory related. For example, a view could be required to read a disk file for some information, and the file might be missing or invalid. This type of error must also be reported to the user. Fortunately, ValidView has a “hook” built in {for handling non-memory errors: It calls the view’s Valid method. ‘TView. Valid returns True by default. TGroup. Valid only returns ‘True if ll the subviews owned by the group return True from, their Valid functions. In other words, a group is valid if ll the subviews of the group are valid. When you create a view that may encounter non-memory errors, you will need to override Valid for that view to return True only ifit has been successfully instantiated, Valid can be used to indicate that a view should not be used for any reason; for example, ifthe view could not find its file. Note ‘hat what Valid checks for and how it checks are entirely up to you. A typical Valid method would look something like this: fenction Tyiev.Valid{camsand: Word): Booleans Dogin Valid :~ reve: 4€ Conmand = calaléa then begin Mf PerorEncountered then begin Reporter; lie i= Feleer end; od es: ‘When a view is first instantiated, its Valid method should be called with a Command parameter of emValid to check for any rnon-memory related errors involved in the creation of the view. ValidView(X) calls X. Valid(cmValid) automatically, as well as checking the safety pool, so calling Valid View before using any new view isa good idea. Valid is also called whenever a modal state terminates, with the Command parameter being the command that terminated the Turbo Vision Guide Reporting errors Major consumers ‘modal state (see Chapter 4, “Views"). This gives you a chance to trap for conditions like unsaved text in an editor window before terminating your application, EvrorEncountered could be, and most likely is, a (Boolean) instance variable of the object type that is specified at the call to Int. Before a Valid method returns False, it should let the user know about whatever error occurred, since the view is not going to ‘show up on the screen. This is what the ReportError call in the previous example does. Typically this involves popping up a message dialog box. Each individual view, then, is responsible for reporting any errors, so the program itself does not have to know how to check each and every possible condition. This is an important advance in programming technique, because itlets you program as if things were going right, instead of always looking for things going wrong. Group objects, including applications, don’t have to worry about checking for errors at all, except to see if any of the views they own were invalid, in which case the group simply disposes of itself and its subviews and indicates to its owner that it was invalid. The group can assume that its invalid subview already notified the user of the problem. Using Valid allows the construction of windows and dialog boxes to be treated as atomic operations. Each subview that makes up ‘the window can be constructed without checking for failure; ifthe constructor fails it simply sets Valid to False. The window then goes through its entire construction, at which point the entire ‘window can be passed to ValidView. If any of the subviews of the ‘window are invalid, the entire window returns Fulse from the valid check. ValidView will dispose of the window and return nil. All that needs to be done is to check the return result from ValidView. ‘The Valid function can also handle major consumers, which are views that allocate memory greater than the size of the safety ‘pool, such as reading the entire contents of a file into memory. ‘Major consumers should check LowMemory themselves, instead of ‘waiting until they have finished all construction and then allowing ValidView to do so for them. Chapter 6, Witing safe programs 135186 fa major consumer runs out of memory in the middle of constructing itself, it sets a flag in itself that indicates that it ‘encountered an error (such as the ErrorEncountered flag in the ‘earlier example) and stops trying to allocate more memory. The ‘lag would be checked in Valid and the view would call ‘Application OutOfMemory and return False from the Valid call, Obviously, this is not quite as nice as being able to assume that your constructors work, but it is the only way to manage the ‘onstruction of views that exceed the size of your safety pool. The program FILEVIEW-PAS included on the Turbo Pascal distribution disks demonstrates the use of these techniques to implement a safe file viewer. Turbo Vision Guide Chapter 7, Collections Collections Pascal programmers traditionally spend much programming time creating code that manipulates and maintains data structures, such as linked lists and dynamically-sized arrays. Virtually the same data structure code tends to be written and debugged again and again. As powerful as traditional Pascal is, it only provides you with built-in record and array types. Any structure beyond that is up to you. For example, if you're going to store data in an array, you typically need to write code to create the array, to import data into the array, to extract array data for processing, and perhaps to export data to1/O devices, Later, when the program needs a new array element type, you start all over again. ‘Wouldn’tit be great if an array type came with code that would handle many ofthe operations you normally perform on an array? An array type that could also be extended without disturbing the original code? ‘That’ the aim of Turbo Vision’ TCollecton type. Its an object that stores a collection of pointers and provides a host of methods for ‘manipulating them. 137Collection objects . Collections are dynamically sized 138 Collections are polymorphic Type checking and collections Besides being an object, and therefore having methods built into it, a collection has two additional features that address shortcomings of ordinary Pascal arrays—it is dynamically sized and polymorphic. ‘The size ofa standard Turbo Pascal array is fixed at compile time, ‘which is fine if you know exactly what size your array will always need to be, but it may not be a particularly good fit by the time someone is actually running your code. Changing the size of an array requires changing the code and recompiling With a collection, however, you set an initial size, but it can dynamically grow at run-time to accommodate the data stored in it This makes your application much more flexible in its compiled form, ‘A second aspect of arrays that can be limiting to your application is the fact that each element in the array must be of the same type, and that type must be determined when the code is compiled. Collections get around this limitation by using untyped pointers Not only is this fast and efficient, but a collection can then consist of objects (and even non-objects) of different types and sizes, Just like a stream, a collection doesn’t need to know anything about the objects its handed. It ust holds on to them and gives them back when asked. A collection is an end-run around Pascal's traditional strong type checking; That means that you can put anything into a collection, and when you take something back out, the compiler has no way. to check your assumptions about what that something is. You can. put in a PHedgehog and read it back out as a PSheep, and the collection will have no way of alerting you. ‘Asa Turbo Pascal programmer, you may rightfully feel nervous about such an end-run, Pascal's type checking, after all, saves hours and hours of hunting for some very elusive bugs. So you Turbo Vision Guide: Collecting non-objects should proceed with caution here: You may not even be aware of how difficult a mixed-type bug can be to find, because the compiler has been finding all of them for you! However, if you find that your programs are crashing or locking up, carefully check the types of objects being stored in and read from collections. You can even add something toa collection that isn’t an object at all, but ths raises another serious point of caution. Collections expect to receive untyped pointers to something: But some of ‘TCollecton’s methods act specifically on a collection of TObject derived instances. These inelude the stream access methods Pulltem and Getltem as well asthe standard Freeltem procedure. ‘This means that you can store a PString in a collection, for example, but if you try to send that collection to stream, the results aren’t going to be pretty unless you override the collection’s standard Getltem and Putltém methods. Similarly, ‘when you attempt to deallocate the collection, it will try to dispose of each item using Freeltem. If you plan to use non-TObject items in a collection, you need to redefine the meaning of “item” in Getltem, Putltem, and Freeltem. That is precisely what TtringCollection, for example, does. If you proceed with prudence, you will find collections (and the descendants of collections that you build) to be fas, flexible, dependable data structures. Creating a collection Remember to dene a pointer foreach new object ‘ype. Chapter 7, Collections Creating a collection is really just as simple as defining the data type you wish to collect. Suppose you're a consultant, and you ‘want to store and retrieve the account number, name, and phone number of each of your clients. First you define the client object (Client) that will be stored in the coilection: ‘re PClient = “Telient: Telient = object (object) fesount, Hane, Phone: PStringr constructor Init Dawlsoownt, Uewfane, Yevehone: String): astructor Dore; vistual; end 139Next you implement the Init and Done methods to allocate and dispose of the client data, Note that the object fields are of type String so that memory is only allocated for the portion of the string that is actually used. The NewStr and DisposeStr functions handle dynamic strings very efficiently. constructor Telient.tnit ewhccount, Wewtane, KewPhone: steing); Desi Tecount = oust fieeAccount): ane 1= Newser etonn) 2 Phone 2 HeeStr(evPhone); ot; dastractor Telient.Done? begin Disposestr {Accoun Disposests (ane): Disposeste (Phone); ot; ‘TClient.Done will be called automatically for each client when you dispose of the entire collection. Now you just instantiate a collection to store your clients, and insert the client records into it. ‘The main body of the program looks like this: Clientiist: ecoldection: ogi Cllenthist := voe(BColtection, Yt ($0, 10)); seen chientist” do begin Tnsect ew(PCLiont, Tnit("90-161, "Saith, Belde' a00) 55512127012 Insert er PCLient, Init "80-160", ‘Johnson, Agatha’, 302) 133-89137))13 Insert Wew{PCLiect, Tnit("90-377, "Saitty, John", "4g06) 987-43217)))2 Insert ow{PCLient, Tnit("SI-I00", "Andors, Saitty", aos) 111-22227))12 ont; Prineall(Chientuist); Welteln; Writein; SeazchPhone (Chienehist, *(406)")2 Dispose(cLieatList, Done); nd, PrintAlland SearchPhone are Notice how easy it was to build the collection. The first statement ‘procedures that wil be allocates a new TCollection called ClientList with an initial size of ascusedole 59 cients. If more than 50 clients are inserted into ClientList,its The VGUDIZ.PAS. 140 Turbo Vision Guide : { size will increase in increments of 10 clients whenever needed. ‘The next 2 statements create a new client object and insert it into the collection. The Dispose cal at the end frees the entire collection—clients and all, Nowhere did you have to tell the collection what kind of data it was collecting—it ust took a pointer Iterator methods Insert and deleting items arent the only common collection operations. Often you'll find yourself writing for loops to range over ail the objects in the collection to display the data or perform some calculation. Other times, you'll want to find the first or last item in the collection that satisfies some search criterion. For these purposes, collections have three iterator methods: ForEach, FirstThat, and LastThat. Bach of these takes a pointer to a procedure or function as its only parameter. The ForEach iterator ForEach takes a pointer toa procedure, The procedure has one parameter, whichis a pointer to an item stored in the collection, ForEach calls that procedure once for each item in the collection, in the order thatthe items appear in the collection. The Print procedure in TVGUIDI7 shows an example of a ForEach iterator. ‘ocedure PrintAil c: Reollection}; {print info for alt clients procedure PrintCliont (2: BCLient); fax; {toca procedsre } begin with do Weiteln(Account*, **:20-Length Account), (show client info } Nana, "7 :20-Length ta), Phone’, 1 :20-Length (Phone): { end of local procedure (Peintanh 8s In; *.Porzach(Q@rintchient); { Call Printlient for each item in ¢ ) ends For each item in the collection passed as a parameter to PrintAll, the nested procedure PrintClint is called. PrintClient simply prints the client object information in formatted columns, Chapter 7, Collections 141Iterator must cal tarlocol procedures The FirstThat and LasfThat iterators ‘You need to be careful about what sort of procedures you call ‘with iterators. In this example, PrinfClient must be a procedure— itcannot be an objec’s method —and it must be local to (nested in the same block with the routine that is callin i. It must also be declared asa far procedure, either with the far directive or with the $F+ compiler directive. Finally, the procedure must take a pointer to a collection item as its only parameter. In addition to being able to apply a procedure to every element in the collection, it is often useful to be able to find a particular ‘element in the collection based on some criterion. That isthe purpose of the FirsfThat and LastThat iterators. As their names imply, they search the collection in opposite directions until they find an item meeting the eriteria of the Boolean function passed as, an argument. FirstThat and LastThat return a pointer to the first (or last) item that matches the search conditions. Consider the earlier example ofthe client ist, and imagine that you can’t remember a client's account number or exactly how is last name is spelled. Luckily, ‘you distinctly recall that this was the first client you acquired in the state of Montana. Thus you want to find the first occurrence of a client in the 406 area code (since your list happens to be in chronological order). Here's a procedure using the First That ‘method that would do the job procedure SearchEhcno(C: PCLiontCollection; Phonetet ind function Phoneatch(Client: PCliest): Boolean; fats Dogin PhoneNaten := Pos(PhoneToPind, Client*.Phone) <> 0; ed; 9: Foundelient: PeLients ogi Foundchient := C*.Ficstthat (#Phonetatch) + AE Found ent = ail eben Weitela("Yo client met the search requirement’) se ‘with FoundcLient™ do Teivela(’Found client: *, Aeoount®, *, Mamet, * na Turbo Vision Guide Again notice that PhoneMatch is nested and uses the far call, ‘model. In this case, it’s a function that returns True only if the
You might also like
NXOpen Getting Started
PDF
No ratings yet
NXOpen Getting Started
138 pages
Borland Turbo Vision For C++ User's Guide
PDF
100% (5)
Borland Turbo Vision For C++ User's Guide
277 pages
Nxopen Getting Started v11
PDF
100% (5)
Nxopen Getting Started v11
137 pages
Java 2 - Black Book
PDF
No ratings yet
Java 2 - Black Book
554 pages
Using QuickC PDF
PDF
100% (1)
Using QuickC PDF
630 pages
Delphi 7 - Developers Guide
PDF
100% (2)
Delphi 7 - Developers Guide
1,113 pages
MS-DOS 5.0 User Guide and Reference
PDF
100% (2)
MS-DOS 5.0 User Guide and Reference
342 pages
MS-DOS 5.0 Getting Started
PDF
No ratings yet
MS-DOS 5.0 Getting Started
30 pages
Bronze Edition V 6 Manual
PDF
No ratings yet
Bronze Edition V 6 Manual
262 pages
Advanced Pascal
PDF
No ratings yet
Advanced Pascal
38 pages
Turbo C Version 2.0 Reference Guide 1988
PDF
No ratings yet
Turbo C Version 2.0 Reference Guide 1988
644 pages
Turbo Pascal Version 5.5 Object-Oriented Programming Guide 1989
PDF
No ratings yet
Turbo Pascal Version 5.5 Object-Oriented Programming Guide 1989
130 pages
Session 9 Tables and Arrays
PDF
No ratings yet
Session 9 Tables and Arrays
23 pages
Using Turbo Prolog
PDF
No ratings yet
Using Turbo Prolog
22 pages
Job Controlling Language: Srinivas.C 55462382
PDF
No ratings yet
Job Controlling Language: Srinivas.C 55462382
25 pages
Visual Basic 2015 - The Complete Beginners Guide 1
PDF
No ratings yet
Visual Basic 2015 - The Complete Beginners Guide 1
194 pages
Mainframes Refresher
PDF
No ratings yet
Mainframes Refresher
289 pages
Visual COBOL and COBOL For .NET Language Introduction en
PDF
No ratings yet
Visual COBOL and COBOL For .NET Language Introduction en
30 pages
RPG Programming
PDF
No ratings yet
RPG Programming
43 pages
Printer File AS400
PDF
No ratings yet
Printer File AS400
154 pages
Borland C++ 3.0 Library Reference
PDF
No ratings yet
Borland C++ 3.0 Library Reference
335 pages
B ILE Labs
PDF
No ratings yet
B ILE Labs
260 pages
Subfiles - RPG IV at Work
PDF
No ratings yet
Subfiles - RPG IV at Work
38 pages
Whats New and Exciting in RPG
PDF
100% (1)
Whats New and Exciting in RPG
32 pages
ADO.NET
PDF
No ratings yet
ADO.NET
369 pages
ISPF Tables
PDF
100% (1)
ISPF Tables
46 pages
Delphi Developer Certification Study Guide
PDF
No ratings yet
Delphi Developer Certification Study Guide
16 pages
Pli New 22012006
PDF
No ratings yet
Pli New 22012006
119 pages
Assembly Language Program - Part I
PDF
No ratings yet
Assembly Language Program - Part I
9 pages
Delphi Decompiler - Brainly
PDF
No ratings yet
Delphi Decompiler - Brainly
57 pages
Assembler New Manual PDF
PDF
100% (1)
Assembler New Manual PDF
159 pages
Lotus Script
PDF
No ratings yet
Lotus Script
222 pages
CLASSY
PDF
100% (1)
CLASSY
87 pages
Assembly Wiki Book
PDF
No ratings yet
Assembly Wiki Book
100 pages
Borland C++ 3.0 Programmer's Guide
PDF
No ratings yet
Borland C++ 3.0 Programmer's Guide
243 pages
AbendAid Debugging Tool
PDF
No ratings yet
AbendAid Debugging Tool
3 pages
Dvapb
PDF
No ratings yet
Dvapb
516 pages
Atari ST-3D Graphics Programming Text
PDF
100% (1)
Atari ST-3D Graphics Programming Text
364 pages
Abend Codes
PDF
100% (1)
Abend Codes
8 pages
Intdata An Array of Strings Twodarray A Two Dimensional Array
PDF
No ratings yet
Intdata An Array of Strings Twodarray A Two Dimensional Array
6 pages
Borland - Turbo Pascal 5.5 Object-Oriented Programming Guide
PDF
No ratings yet
Borland - Turbo Pascal 5.5 Object-Oriented Programming Guide
63 pages
Other Controls
PDF
No ratings yet
Other Controls
41 pages
Assembler
PDF
100% (1)
Assembler
49 pages
Turbo Pascal Version 6.0 Turbo Vision 1990
PDF
No ratings yet
Turbo Pascal Version 6.0 Turbo Vision 1990
427 pages
DG
PDF
No ratings yet
DG
968 pages
NXOpen_Getting_Started
PDF
No ratings yet
NXOpen_Getting_Started
137 pages
Vision Lab
PDF
No ratings yet
Vision Lab
23 pages
Before Using This Information and The Product It Supports, Be Sure To Read The General Information Under "Notices" On Page VII
PDF
No ratings yet
Before Using This Information and The Product It Supports, Be Sure To Read The General Information Under "Notices" On Page VII
110 pages
Module 10 - PCVue
PDF
No ratings yet
Module 10 - PCVue
19 pages
Delphi™ 5, Developer's Guide For Windows 98, Windows 95, & Windows NT
PDF
No ratings yet
Delphi™ 5, Developer's Guide For Windows 98, Windows 95, & Windows NT
1,020 pages
Visual Basic 2010 Programmer s Reference 1st Edition Rod Stephens - The ebook in PDF and DOCX formats is ready for download now
PDF
100% (1)
Visual Basic 2010 Programmer s Reference 1st Edition Rod Stephens - The ebook in PDF and DOCX formats is ready for download now
29 pages
Borland Turbo Assembler 5.0 User's Guide
PDF
100% (1)
Borland Turbo Assembler 5.0 User's Guide
312 pages
Borland C++ Builder 5 Developer's Guide DG
PDF
100% (1)
Borland C++ Builder 5 Developer's Guide DG
1,060 pages
(Ebook) Visual Basic .NET Codemaster's Library by Matt Tagliaferri ISBN 9780782141030, 078214103Xdownload
PDF
100% (4)
(Ebook) Visual Basic .NET Codemaster's Library by Matt Tagliaferri ISBN 9780782141030, 078214103Xdownload
56 pages
Turbo Pascal Version 6.0 Users Guide 1990
PDF
No ratings yet
Turbo Pascal Version 6.0 Users Guide 1990
271 pages
Beginning C 6 0 Programming with Visual Studio 2015 1st Edition Benjamin Perkins - Quickly download the ebook to never miss important content
PDF
100% (2)
Beginning C 6 0 Programming with Visual Studio 2015 1st Edition Benjamin Perkins - Quickly download the ebook to never miss important content
56 pages
Visual Basic Programming For Beginners - A Complete Beginners Guide To Learn The Fundamentals of Visual Basic
PDF
67% (3)
Visual Basic Programming For Beginners - A Complete Beginners Guide To Learn The Fundamentals of Visual Basic
187 pages
Module 10 - Basic Graphical Objects - Basics
PDF
No ratings yet
Module 10 - Basic Graphical Objects - Basics
19 pages
Quick Start: C Builder 5
PDF
No ratings yet
Quick Start: C Builder 5
90 pages
Dev Common
PDF
No ratings yet
Dev Common
1,222 pages
Visual Basic 2010 Programmer s Reference 1st Edition Rod Stephens download
PDF
No ratings yet
Visual Basic 2010 Programmer s Reference 1st Edition Rod Stephens download
60 pages
Lecce Magazine 2000 N. 10
PDF
No ratings yet
Lecce Magazine 2000 N. 10
46 pages
Lecce Magazine 2001 N. 8
PDF
No ratings yet
Lecce Magazine 2001 N. 8
43 pages
Burr-Brown The Handbook of Linear IC Applications
PDF
100% (1)
Burr-Brown The Handbook of Linear IC Applications
146 pages
Lecce Magazine 2001 N. 9
PDF
No ratings yet
Lecce Magazine 2001 N. 9
43 pages
Lecce Magazine 2001 N. 1
PDF
No ratings yet
Lecce Magazine 2001 N. 1
46 pages
Keytek ESD Protection Test Handbook 2nd Ed
PDF
No ratings yet
Keytek ESD Protection Test Handbook 2nd Ed
33 pages
Keytek Surge Protection Test Handbook 2nd Ed
PDF
No ratings yet
Keytek Surge Protection Test Handbook 2nd Ed
35 pages
Borland Objectwindows For C++ Users Guide
PDF
100% (1)
Borland Objectwindows For C++ Users Guide
205 pages
WordPerfect 6.0 For Windows Learning Word Perfect
PDF
No ratings yet
WordPerfect 6.0 For Windows Learning Word Perfect
135 pages
Borland C++ 3 0 Tools and Utilities Guide
PDF
No ratings yet
Borland C++ 3 0 Tools and Utilities Guide
133 pages
ChiWriter User Manual
PDF
100% (2)
ChiWriter User Manual
96 pages
Turbo Pascal 6.0 Library Reference
PDF
No ratings yet
Turbo Pascal 6.0 Library Reference
94 pages
HP48SX Owner Manual Vol 1
PDF
100% (10)
HP48SX Owner Manual Vol 1
459 pages
Quattro-Pro 5.0 For Windows Users Guide
PDF
No ratings yet
Quattro-Pro 5.0 For Windows Users Guide
329 pages
HP200LX User Manual
PDF
No ratings yet
HP200LX User Manual
460 pages