Gary Entsminger
TURBO PASCAL B
FOR WINDOWS
I B L E
The Most Comprehensive Tutorial and Reference for Experienced Pro...
223 downloads
2354 Views
16MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Gary Entsminger
TURBO PASCAL B
FOR WINDOWS
I B L E
The Most Comprehensive Tutorial and Reference for Experienced Programmers
E x a m p l e s , screen illustrations, and practical application samples Essential command reference section describes all features Exclusive coverage of ObjectWindows functions and the Windows A P I
The TPW Command-line Compiler T u r b o Pascal for W i n d o w s c o m m a n d - l i n e o p t i o n s u s e this syntax:
TPCW
[options]
w h e r e [options]
[options]
can b e o n e or m o r e options, separated by spaces. Y o u designate the
s t a t u s o f t h e c o m p i l e r o p t i o n b y s p e c i f y i n g a p l u s ( + ) o r a m i n u s (-) after t h e o p t i o n . •
P l a c e a + ( o r a s p a c e ) after a n o p t i o n t o t u r n it O n .
•
P l a c e a - after t h e o p t i o n t o t u r n it O f f . Compiler Options Directive
Option /$A /IB /$D /IF /|G /II /|L
options Option
Meaning Align data Boolean evaluation Debug information Force FAR calls Generate 286 instructions Input/output checking Local symbol information
Meaning
/IN /|R /IS /IV /|W
80x87 code (numeric coprocessor) Range checking Stack-overflow checking String var checking Windows stack frame
/IX
Extended syntax
Mode options Option
Option
Meaning
/B /F /L
Build all Find error Link buffer Conditional
Option /D
/M
Make
/Q
Quiet (no IDE equivalent)
defines
Meaning
Meaning
option
Option
Meaning
Conditional defines Debug options
Option
Meaning
/G
MAP file Directory
Option
Meaning
/E /I /O
E X E and TPU directory Include directories Object Files directories
Option
Meaning
/V
Debug info in EXE option
options Option
Meaning
/R /T /U
Resource directories Turbo directory Unit directories
C o m m a n d - l i n e Options a n d Their IDE Equivalents. Option
IDE
/|A /IB /ID /IF /|G /II /|L /|M /IN /|R /IS /IV
Options/Compiler/Align data Options/Compiler/Boolean evaluation Options/Compiler/Debug information Options/Compiler/Force far calls Options/Compiler/286 code Options/Compiler/I/O checking Options/Compiler/Local symbols Options/Compiler/Memory sizes Options/Compiler/80x87 code Options/Compiler/Range checking Options/Compiler/Stack checking Options/Compiler/String var checking options Optioni/Compiler/Windows stack frames Options/Compiler/Extended syntax
/|W /IX
Equivalent
Option
IDE
/B /D /E /F /G /I /L /M /O /Q /R /T /U /V
Compile/Build Options/Compiler/Conditional defines Options/Directories/EXE and TPU directory Search/Find error Options/Linker/MAP file Options/Compiler/Include directories Options/Linker/Link buffer Compile/Make Options/Directories/Object directories (none) • Options/Directories/Resource directories (none) Options/Directories/Unit directories Options/Linker/Debug info in EXE
Equivalent
Turbo Pascal® for Windows™ Bible
Turbo Pascal® for Windows Bible Gary Entsminger
SAMS A Division of Macmillan Computer Publishing 11711 North College, Carmel, Indiana 46032 USA
For Alison
© 1992 by SAMS FIRST EDITION FIRST PRINTING—1991 All rights reserved. No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or otherwise, without written permission from the publisher. N o patent liability is assumed with respect to the use of the information contained herein. Although every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omission. Neither is any liability assumed for damages resulting from the use of the information contained herein. For information, address SAMS, 11711 N. College Ave., Carmel, IN 46032. International Standard Book Number: 0-672-30212-8 Library of Congress Catalog No.: 91-66924
Publisher Richard K. Swadley Publishing Manager Joseph Wikert Managing Editor Neweleen A. Trebnik Acquisitions Editor Gregory S. Croy Development Editor Paula Northam Grady Editors Kezia Endsley Becky Freeman Jodi Jensen Rebecca Whitney Technical
Production Claudia Bell Sandy Grieshop Denny Hager Audra Hershman Bob LaRoche Laurie Lee Juli Pavey Howard Peirce Tad Ringo Bruce Steed Mary Beth Wakefield Lisa Wilson Phil Worthington Christine Young Book
Design Scott Cook Michele Laseau
Cover Design Tim Amrhein
Editor
Jeffrey Hsu
Indexer Johnna VanHoose
Composed in Garamond
and MCP Digital by Macmillan
Computer
Printed in the United States of America
Publishing.
Overview Parti
Working with TPW
1
G e t t i n g Started, 3
2 3 4
E l e m e n t s o f A p p l i c a t i o n D e v e l o p m e n t , 43 Objects for W i n d o w s , 77 Inheriting a n Interface, 111
5 6
Putting Pictures in W i n d o w s , 149 Painting, C o l l e c t i n g , a n d S t r e a m i n g , 185
Part II Advanced Topics 7 8 9 10 11 12 13
Part III A B C
M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface, 2 1 3 R e s o u r c e s a n d C o n t r o l O b j e c t s , 241 M e m o r y Matters, 2 7 9 D i s p l a y C o n t e x t s a n d D r a w i n g T o o l s , 301 F r o m Program to Program Using D D E (Dynamic Data Exchange), 343 S h a r i n g Libraries U s i n g D L L ( D y n a m i c L i n k Libraries), 3 6 9 D e s i g n i n g W i n d o w s A p p l i c a t i o n s , 383
References O b j e c t W i n d o w s O b j e c t s , 405 ObjectWindows Constants, 499 O b j e c t W i n d o w s P r o c e d u r e s a n d F u n c t i o n s , 505
D
O b j e c t W i n d o w s R e c o r d s , 509
E F G H I J K L M N O P Q R S
T h e W i n C r t Unit, 515 A W i n C r t E x a m p l e , 525 T h e Strings Unit, 539 T h e T u r b o Pascal for W i n d o w s S y s t e m Unit, 553 T h e T u r b o Pascal for W i n d o w s W i n D o s Unit, 561 D e b u g g i n g T u r b o Pascal for W i n d o w s A p p l i c a t i o n s , 587 T u r b o Pascal for W i n d o w s Error M e s s a g e s , 591 W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s , 635 S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s , 723 G D I ( G r a p h i c s D e v i c e Interface) P r o c e d u r e s a n d F u n c t i o n s , 793 O b j e c t G r a p h i c s (A W h i t e w a t e r G r o u p G r a p h i c s T o o l k i t ) , 861 N o t e s for M a n a g i n g a Project, 8 6 7 Glossary, 8 6 9 R e f e r e n c e s , R e s o u r c e s , a n d N o t e s , 881 A S C I I C o d e C h a r a c t e r Set, 8 8 7 I n d e x , 891
Contents I
WORKING WITH TPW
1
Getting Started, 3 C r e a t i n g Windows A p p l i c a t i o n s , 3 S y s t e m R e q u i r e m e n t s a n d Installation, 4 T h e T u r b o Pascal for Windows I D E , 4 T u r b o Pascal for Windows I D E M e n u C o m m a n d s , 7 T h e T u r b o Pascal for Windows D e s k t o p C o n t r o l M e n u , 7 Restore, 8 Move, 8 Size, 8 Minimize, 8 Maximize, 8 Close, 8 Switch T o , 9 T h e Edit Window
Control Menu, 9
Restore, 9 Move, 9 Size, 10 M i n i m i z e , 10 M a x i m i z e , 10 C l o s e , 10 N e x t , 10 T h e File M e n u , 10 N e w , 11 O p e n , 11 Save, 12 Save A s , 12 Save All, 12 Print, 12 Printer S e t u p , 13 Exit, 14 List o f C l o s e d Files, 14
vii
T u r b o Pascal for W i n d o w s B i b l e
T h e Edit M e n u , 14 U n d o , 14 R e d o , 15 C u t , 15 C o p y , 15 Paste, 15 C l e a r , 16 T h e S e a r c h M e n u , 16 F i n d , 16 R e p l a c e , 16 S e a r c h A g a i n , 16 G o t o L i n e N u m b e r , 17 S e a r c h / S h o w Last C o m p i l e Error, 18 Search/Find Error, 18 T h e R u n M e n u , 18 R u n / R u n , 18 R u n / D e b u g g e r , 18 Run/Parameters, 19 T h e C o m p i l e M e n u , 19 Compile/Compile, 20 C o m p i l e / M a k e , 20 C o m p i l e / B u i l d , 21 C o m p d e / P r i m a r y File, 21 C o m p i l e / C l e a r Primary File, 21 C o m p i l e / I n f o r m a t i o n , 21 C o m p i l e I n f o r m a t i o n B o x , 21 T h e O p t i o n s M e n u , 22 C o m p i l e r , 22 Linker, 23 Directories, 23 G u i d e l i n e s for E n t e r i n g Directory N a m e s , 24 Preferences, 25 E d i t o r O p t i o n s , 25 O p e n , 26 Save, 26 Save A s , 2 7 Directories List B o x , 28 T h e W i n d o w M e n u , 28 T i l e , 28 C a s c a d e , 28 A r r a n g e I c o n s , 28 C l o s e All, 29
viii
Contents
T h e H e l p M e n u (Alt-H), 29 I n d e x ( S h i f t - F l ) , 29 T o p i c S e a r c h ( C t r l - F l ) , 29 Help/Using H e l p , 30 C o m p i l e r Directives, 30 O b j e c t W i n d o w s , 30 P r o c e d u r e s a n d F u n c t i o n s , 30 Reserved W o r d s , 30 S t a n d a r d U n i t s , 31 T u r b o Pascal for W i n d o w s L a n g u a g e , 31 W i n d o w s A P I , 31 A b o u t T u r b o Pascal for W i n d o w s , 31 Editor, 31 T h e E d i t o r C o m m a n d s , 31 T h e B l o c k C o m m a n d s , 32 C o p y B l o c k , 32 C o p y Text, 32 C u t Text, 32 D e l e t e B l o c k , 32 M o v e B l o c k , 32 Paste f r o m C l i p b o a r d , 33 R e a d B l o c k from D i s k , 33 Write B l o c k t o D i s k , 33 E d i t o r - C o m m a n d T a b l e s , 33 A u t o I n d e n t , 36 C u r r e n t C o m p i l e r O p t i o n s , 36 C u r s o r t h r o u g h T a b s , 36 F i n d Place M a r k e r , 3 7 O p e n File, 3 7 O p t i m a l Fill, 3 7 Save File, 3 7 Set Place, 3 7 S h o w Last C o m p i l e Error, 3 7 T a b M o d e , 37 Unindent, 37 T h e T P W C o m m a n d - l i n e Compiler, 38 O n w a r d , F o r w a r d , a n d U p w a r d , 41
2
Elements of Application Development, 43 Units, 44 D a t a T y p e s a n d Identifiers, 50 O r d i n a l T y p e s , 52 B o o l e a n T y p e s , 52
ix
T u r b o Pascal for W i n d o w s B i b l e
C h a r T y p e , 53 E n u m e r a t e d T y p e s , 54 S u b r a n g e T y p e s , 54 Reals, 55 Strings, 55 S t r u c t u r e d T y p e s , 56 Arrays, 57 R e c o r d s , 57 O b j e c t T y p e s , 58 Sets, 59 Files, 59 Pointer T y p e s , 6 0 P C h a r , 61 P r o c e d u r a l T y p e s , 62 T u r b o Pascal for W i n d o w s Reserved W o r d s , 62 S t a t e m e n t s , 63 a s s i g n m e n t ( : = ) , 64 begin..end, 64 c a s e . . o f . . e l s e . . e n d , 65 for..to/downto..do, 66 g o t o , 66 if..then..else, 67 inline(...), 68 p r o c e d u r e call, 69 r e p e a t . . u n t i l , 70 w h i l e . . d o , 70 w i t h . . d o , 71 D e b u g g i n g T u r b o Pascal for W i n d o w s A p p l i c a t i o n s , 72 B e g i n . . , 75
3
Objects for Windows, 77 Overture, 77 A b o u t T u r b o Pascal W i n d o w s , 7 8 W h y D o e s t h e W o r l d M a k e S o M u c h Sense?, 81 T h e T a o o f O b j e c t s , 81 Inheritance, 84 P o l y m o r p h i s m , 86 Messages, 88 Static a n d D y n a m i c B i n d i n g , 9 0 D y n a m i c Style, 91 E x t e n d e d V i e w s , 92
X
Contents
A b o u t Microsoft W i n d o w s , 9 3 W i n d o w s Structure, 95 W h y O O P a n d W i n d o w s , 101 A b o u t O b j e c t W i n d o w s , 102 Events, M e s s a g e s , a n d O b j e c t s , 106 W i n d o w s M e s s a g e s , 107 A b o u t W i n C r t , 107 M o v i n ' O n , 109
4
Inheriting an Interface, 111 T h e Basiclnterface, 113 A p p l i c a t i o n a n d W i n d o w O b j e c t s , 114 T h e M a i n W i n d o w , 116 Details, 119 W i n d o w M e s s a g e s , 122 D i s p l a y C o n t e x t s , 126 U s i n g R e s o u r c e s , 127 Pascal a n d C Strings, 129 A F e w R u l e s , 130 A d d i n g D i a l o g s , 130 A d d i n g a File D i a l o g , 134 T w o K i n d s o f File D i a l o g s , 135 C o n s t a n t s , 136 C o n t r o l s , 136 A d d i n g List B o x e s , 138 M e s s a g e B o x e s , 141 C l o s i n g a n A p p l i c a t i o n , 142 W r a p p i n g U p t h e Basiclnterface, 143
5
Putting Pictures in Windows, 149 M e n u s , I D s , a n d M e s s a g e s , 150 Tasks, 156 O t h e r W i n d o w s , O t h e r T a s k s , 162 M o d e l Tasks, 162 M o d e l i n g , 163 C h a o s a n d S t r a n g e Attractors, 166 M a t h e m a t i c Attraction, 170 O r d e r i n C h a o s , 171 G r a n d F i n a l e , 175
xi
T u r b o Pascal for W i n d o w s B i b l e
6
Painting, Collecting, and Streaming, 185 P o l y m o r p h i c C o l l e c t i o n s , 187 C o l l e c t i n g Points, 189 Streams, 194 Putting Points in a Stream, 199 H o w Put Works, 2 0 0 G e t t i n g Points, 201 T h e S u m o f Streams, 203
II
ADVANCED TOPICS
7
Many Windows: A Multi-Document Interface, 213 A Basic M D I Interface, 214 Setting U p a Basic M D I Interface, 2 1 7 A M o d e l M D I , 219 M D I M e s s a g e Processing, 221 Editors, 222 A n M D I Editor, 226 M D I Wrap-up,
8
233
Resources and Control Objects, 241 R e s o u r c e s , 242 R e s o u r c e Editors, 255 D i a l o g Windows, 256 Details, 2 6 0 C o n t r o l O b j e c t s , 267 G r o u p Boxes, 270 C o n t r o l s in C o m b i n a t i o n , 274 Bit M a p s , 2 7 6 Wrap-up, 278
9
Memory Matters, 279 M e m o r y M a n a g e m e n t , Windows Style, 2 8 0 G l o b a l a n d L o c a l M e m o r y , 283 Allocating L o c a l M e m o r y B l o c k s , 284 G l o b a l Memory Blocks, 290 A F e w A d v a n c e d M e m o r y Matters, 2 9 7 Direct M e m o r y A c c e s s , 2 9 7
xii
Contents
Data Segments, 297 H e a p Errors, 298 C o d e Segments, 299 w m C o m p a c t i n g , 299 Wrap-up, 300
10 Display Contexts and Drawing Tools, 301 H a n d l i n g a D i s p l a y C o n t e x t , 302 M a p p i n g M o d e s , 315 D r a w i n g F i g u r e s , 322 A Stranger G r a p h i c s F u n c t i o n D e m o , 3 2 7 Wrap-up, 340
11 From Program to Program Using D D E (Dynamic Data Exchange), 343 T h e C l i p b o a r d , 344 Pasting from t h e C l i p b o a r d , 348 S h a r i n g D a t a B e t w e e n A p p l i c a t i o n s , 353 A t o m s , a n d S o O n , 354 W r a p - u p , 368
12 Sharing libraries: Using DLL (Dynamic Link Libraries), 369 D L L Details, 3 7 0 U s i n g D L L s , 371
13 Designing Windows Applications, 383 C o m m o n U s e r A c c e s s , 384 O b j e c t s a n d W i n d o w s , 386 D e s i g n i n g for C h a n g e , 3 8 9 O b j e c t - O r i e n t e d A p p l i c a t i o n D e s i g n , 392 A T a o o f W i n d o w s , 393 O b j e c t Discovery, 394 Star W a r s a n d D a n c e s : T h e S e q u e l , 395 Begin Discovering Objects, 400 W r a p - u p , 401
xiii
T u r b o Pascal for W i n d o w s B i b l e
III REFERENCES A
ObjectWindows Objects, 405 TApplication, 406 TBufStream, 411 T B u t t o n , 414 T C h e c k B o x , 416 TCollection, 419 T C o m b o B o x , 427 TControl, 430 T D i a l o g , 432 TDlgWindow, 436 TDosStream, 437 TEdit, 4 4 0 TEmsStream, 447 T G r o u p B o x , 450 TListBox, 452 TMDIClient, 457 TMDIWindow, 459 T O b j e c t , 464 T R a d i o B u t t o n , 465 TScrollBar, 4 6 6 TScroller, 471 TSortedCollection, 479 TStatic, 4 8 2 T S t r C o l l e c t i o n , 484 TStream, 486 T W i n d o w , 491
B
ObjectWindows Constants, 499 b f _ X X X X Constants, 499 c m X X X X Constants, 499 c o X X X X C o n s t a n t s , 501 e m X X X X C o n s t a n t s , 501 id_XXXX C o n s t a n t s , 502 n f X X X X C o n s t a n t s , 502 s t X X X X C o n s t a n t s , 502 t f _ X X X X C o n s t a n t s , 503 w b _ X X X X C o n s t a n t s , 503 w m _ X X X X C o n s t a n t s , 504
xiv
Contents
C
ObjectWindows Procedures and Functions, 505 Abstract, 506 A l l o c M u l t i S e l , 506 D i s p o s e S t r , 506 F r e e M u l t i S e l , 506 G e t O b j e c t P t r , 506 L o n g D i v , 507 L o n g M u l , 507 L o w M e m o r y , 507 M e m A l l o c , 507 N e w S t r , 508 RegisterType, 508 R e g i s t e r W O b j e c t s , 508 R e s t o r e M e m o r y , 508
D
ObjectWindows Records, 509 L o n g R e c , 509 PtrRec, 510 T D i a l o g A t t r , 510 T M e s s a g e , 510 T M u l t i S e l R e c , 511 T S c r o l l B a r T r a n s f e r R e c , 511 T S t r e a m R e c , 511 T W i n d o w A t t r , 512 W o r d R e c , 513
E
The WinCrt Unit, 515 A s s i g n C r t , 516 ClrEol, 517 C l r S c r , 517 C u r s o r T o , 518 D o n e W i n C r t , 518 G o t o X Y , 519 I n i t W i n C r t , 519 KeyPressed, 520 R e a d B u f , 520 R e a d K e y , 521 S c r o l l T o , 521 T r a c k C u r s o r , 522 W h e r e X , ^22
XV
T u r b o Pascal for W i n d o w s B i b l e
W h e r e Y , 523 WriteBuf, 523 W r i t e C h a r , 524
F
A WinCrt Example, 525
G
The Strings Unit, 539 StrCat, 540 S t r C o m p , 541 S t r C o p y , 542 S t r D i s p o s e , 542 S t r E C o p y , 543 S t r E n d , 543 S t r l C o m p , 544 StrLCat, 544 S t r L C o m p , 545 S t r L C o p y , 546 StrLen, 546 S t r L I C o m p , 547 StrLower, 547 S t r M o v e , 548 S t r N e w , 548 StrPas, 549 S t r P C o p y , 550 StrPos, 550 S t r R S c a n , 551 S t r S c a n , 551 S t r U p p e r , 552
H
The Turbo Pascal for Windows System Unit, 553
I
The Turbo Pascal for Windows WinDos Unit, 561 C o n s t a n t s , 561 T y p e s , 563 A n Index of W i n D o s Procedures and Functions b y F u n c t i o n (or C a t e g o r y ) , 566
J
xvi
Debugging Turbo Pascal for Windows Applications, 587
Contents
K
Turbo Pascal for Windows Error Messages, 591 C o m p i l e r Error M e s s a g e s , 592 R u n - t i m e Error M e s s a g e s , 6 2 6
L
Window Manager Interface Procedures and Functions, 635 C a r e t P r o c e d u r e s a n d F u n c t i o n s , 635 Clipboard Procedures and Functions, 638 C u r s o r P r o c e d u r e s a n d F u n c t i o n s , 642 D i a l o g - B o x P r o c e d u r e s a n d F u n c t i o n s , 645 Display and M o v e m e n t Procedures and Functions, 658 Error P r o c e d u r e s a n d F u n c t i o n s , 6 6 4 H a r d w a r e P r o c e d u r e s a n d F u n c t i o n s , 665 H o o k Procedures and Functions, 669 I n f o r m a t i o n P r o c e d u r e s a n d F u n c t i o n s , 671 Input Procedures and Functions, 676 M e n u P r o c e d u r e s a n d F u n c t i o n s , 681 M e s s a g e P r o c e d u r e s a n d F u n c t i o n s , 691 Painting P r o c e d u r e s a n d F u n c t i o n s , 6 9 8 Property P r o c e d u r e s a n d F u n c t i o n s , 705 Scrolling P r o c e d u r e s a n d F u n c t i o n s , 7 0 6 System Procedures a n d Functions, 710 W i n d o w - C r e a t i o n P r o c e d u r e s a n d F u n c t i o n s , 711
M
System Services Interface Procedures and Functions, 723 Application-Execution Functions, 723 A t o m - M a n a g e m e n t P r o c e d u r e s a n d F u n c t i o n s , 725 C o m m u n i c a t i o n Procedures and Functions, 729 File I/O P r o c e d u r e s a n d F u n c t i o n s , 735 Initialization-File P r o c e d u r e s a n d F u n c t i o n s , 7 4 0 M e m o r y - M a n a g e m e n t P r o c e d u r e s a n d F u n c t i o n s , 743 Module-Management Procedures and Functions, 757 O p e r a t i n g - S y s t e m Interrupt P r o c e d u r e s a n d F u n c t i o n s , 761 R e s o u r c e - M a n a g e m e n t P r o c e d u r e s a n d F u n c t i o n s , 762 Segment Procedures and Functions, 768 S o u n d Procedures and Functions, 773 S t r i n g - M a n i p u l a t i o n P r o c e d u r e s a n d F u n c t i o n s , 778 Task Procedures and Functions, 786 Utility M a c r o s a n d F u n c t i o n s , 788
xvii
T u r b o Pascal for W i n d o w s B i b l e
N
G D I (Graphics Device Interface) Procedures and Functions, 793 B i t m a p P r o c e d u r e s a n d F u n c t i o n s , 794 Clipping Procedures a n d Functions, 800 C o l o r Palette P r o c e d u r e s a n d F u n c t i o n s , 8 0 3 C o o r d i n a t e - T r a n s l a t i o n Procedures a n d F u n c t i o n s , 8 0 7 D e v i c e - C o n t e x t Procedures a n d F u n c t i o n s , 8 0 9 Device-Independent Bitmap Procedures a n d Functions, 812 Drawing-Attribute Procedures a n d F u n c t i o n s , 815 Drawing-Tool Procedures a n d Functions, 819 Environment Procedures and Functions, 826 F o n t Procedures a n d F u n c t i o n s , 8 2 7 Line-Drawing Procedures a n d F u n c t i o n s , 8 3 0 M a p p i n g Procedures and Functions, 832 Metafile P r o c e d u r e s a n d F u n c t i o n s , 8 3 7 Printer-Control P r o c e d u r e s a n d F u n c t i o n s , 8 4 1 R e c t a n g l e Procedures a n d F u n c t i o n s , 8 4 2 Region Procedures a n d Functions, 844 S h a p e - D r a w i n g P r o c e d u r e s a n d F u n c t i o n s , 851 T e x t - D r a w i n g P r o c e d u r e s a n d F u n c t i o n s , 855
O
ObjectGraphics (A Whitewater Group Graphics Toolkit), 861
P
Notes for Managing a Project, 867
Q
Glossary, 869
R
References, Resources, and Notes, 881 Quotation Acknowledgments, 884
S
ASCII Code Character Set, 887 Index, 891
xviii
Introduction
Look out of any window,
any morning,
any evening, any day. Robert H u n t e r
How This Book Is Organized W e l c o m e t o Turbo Pascal for Windows Bible, a b o o k that will clear m a n y o f t h e mysteries o f W i n d o w s p r o g r a m m i n g i n T u r b o Pascal for W i n d o w s style. W i n d o w s p r o g r a m m i n g is difficult, b u t T u r b o Pascal for W i n d o w s m a k e s t h e difficulty m a n a g e a b l e . I n fact, d e v e l o p i n g W i n d o w s applications w i t h T u r b o Pascal for W i n d o w s is m u c h m o r e f u n o n c e y o u get t h e h a n g o f it. T h i s bible s h o w s y o u h o w t o get t h e h a n g o f it. Turbo 1.
Pascal
for
Windows
Bible
consists of three sections:
Working With TPW A n introduction to object-oriented p r o g r a m m i n g and the T u r b o Pascal for W i n d o w s o b j e c t library, O b j e c t W i n d o w s , p l u s t h e l a n g u a g e s y n t a x a n d o t h e r d e t a i l s . T h i s s e c t i o n is l o a d e d w i t h p r a c t i c a l e x a m p l e s a n d is i n t e n d e d t o b r i n g y o u u p t o W i n d o w s application d e v e l o p m e n t s p e e d in a hurry.
2.
Advanced topics This section discusses s o m e of the m o r e c o m p l e x aspects of W i n d o w s a p p l i c a t i o n d e v e l o p m e n t , s u c h as m e m o r y m a n a g e m e n t ,
T u r b o Pascal for W i n d o w s B i b l e
d y n a m i c d a t a e x c h a n g e ( D D E ) , d y n a m i c l i n k libraries ( D L L ) , d e s i g n c o n s i d e r a t i o n s , a n d s o o n . T h i s s e c t i o n is t h e o n e t o r e a d a n d s t u d y after y o u k n o w t h e basics o f o b j e c t - o r i e n t e d p r o g r a m m i n g , TPW-style. 3.
Reference A d e t a i l e d a c c o u n t o f t h e O b j e c t W i n d o w o b j e c t - o r i e n t e d library, i n c l u d i n g o b j e c t s , p r o c e d u r e s , r e c o r d s , a n d c o n s t a n t s . T h e refere n c e a l s o is a c o m p l e t e d e s c r i p t i o n o f t h e W i n d o w s A P I f u n c t i o n s , a g l o s s a r y , a r e a d i n g list, a n d a n y t h i n g e l s e that is i m p o r t a n t b u t d o e s n o t fit i n t h e first t w o s e c t i o n s .
Reader, Who Are You? A l t h o u g h I c a n n o t b e sure, I a s s u m e that y o u already k n o w h o w t o p r o g r a m u s i n g T u r b o P a s c a l (for D O S ) . T u r b o P a s c a l f o r W i n d o w s u s e s s i m i l a r s y n t a x a n d m a n y o f t h e s a m e f u n c t i o n s a n d p r o c e d u r e s as T u r b o Pascal (for D O S ) . A n y t h i n g specific t o T u r b o Pascal for W i n d o w s is e x p l a i n e d , a n d a n y differences b e t w e e n T u r b o Pascal for W i n d o w s a n d T u r b o Pascal (for D O S ) are d i s c u s s e d . If y o u h a v e n e v e r p r o g r a m m e d i n T u r b o Pascal for W i n d o w s , b u t h a v e p r o g r a m m e d i n a p r o c e d u r a l l a n g u a g e s u c h as C , C + + , o r M o d u l a 2 , y o u p r o b a b l y will m a n a g e t o learn T u r b o Pascal for W i n d o w s p r o g r a m m i n g . T h i s b o o k m a k e s it easier for y o u w i t h a g e n e r a l i n t r o d u c t i o n t o T u r b o Pascal syntax a n d p r o g r a m m i n g . If y o u n e e d m o r e details a b o u t T u r b o Pascal i n g e n e r a l (not W i n d o w s - s p e c i f i c i n f o r m a t i o n ) , p i c k u p a g o o d T u r b o Pascal (for D O S ) b o o k , s u c h as T o m S w a n ' s Mastering Turbo Pascal 6 ( H a y d e n B o o k s ) t o u s e as a g e n e r a l T u r b o Pascal r e f e r e n c e . If y o u are already familiar w i t h t h e T u r b o Pascal for W i n d o w s integrated d e v e l o p m e n t e n v i r o n m e n t ( I D E ) a n d editor, y o u c a n either g l a n c e o v e r o r skip t h e first c h a p t e r . C h a p t e r 1 is primarily i n t e n d e d to familiarize y o u w i t h t h e preliminaries: h o w t o install T u r b o Pascal for W i n d o w s , system r e q u i r e m e n t s , h o w t h e I D E , c o m p i l e r , a n d e d i t o r w o r k , a n d s o o n . T h e "real" p r o g r a m m i n g a n d objecto r i e n t e d discussions start in C h a p t e r 2.
Conventions in This Book T h e s e c o n v e n t i o n s h a v e b e e n u s e d t h r o u g h o u t t h e b o o k t o increase its readability: • All p r o g r a m listings; " s n i p p e t s " o f p r o g r a m c o d e ; k e y w o r d s ; p r o c e d u r e , f u n c t i o n , a n d m e t h o d n a m e s ; types (such as b a s e a n d d e r i v e d ) ; a n d objects ( s u c h a s B a s i c I n t e r f a c e , MainWindow, TWindow, T A p p l i c a t i o n , B a s i c A p p l i c a t i o n ) are in m o n o s p a c e t y p e .
XX
Introduction
• B o o k titles, a l o n g with terms i n c l u d e d i n t h e G l o s s a r y ( o n first o c c u r r e n c e i n the text), a p p e a r i n italics. • U n i t s , p r o g r a m n a m e s , a n d library n a m e s ( O b j e c t W i n d o w s ) a p p e a r i n regular type.
Acknowledgments I'd like t o t h a n k a f e w folks w h o h a v e s u p p o r t e d , advised, offered s u g g e s t i o n s , r e a d t h e m a n u s c r i p t , p r o v i d e d software, o r just p l a i n b e e n h e l p f u l t o m e d u r i n g t h e writing o f Turbo Pascal for Windows Bible: G r e g C r o y a n d Paula N o r t h a m G r a d y at M a c m i l l a n C o m p u t e r P u b l i s h i n g ; N a n B o r e n s o n at B o r l a n d International; Phil Davis at the W h i t e w a t e r G r o u p ; A l i s o n B r o d y ; S u s a n A l l e n ; a n d Billy Ban* at t h e R o c k y M o u n t a i n B i o l o g i c a l Laboratory.
Trademarks S A M S h a s m a d e every attempt t o s u p p l y t r a d e m a r k i n f o r m a t i o n a b o u t c o m p a n y n a m e s , p r o d u c t s , a n d services m e n t i o n e d i n this b o o k . T r a d e m a r k s i n d i c a t e d b e l o w w e r e d e r i v e d from various s o u r c e s . S A M S c a n n o t attest t o t h e accuracy o f this i n f o r m a t i o n . A p p l e a n d M a c i n t o s h are registered trademarks o f A p p l e C o m p u t e r , I n c . B o r l a n d , B o r l a n d C + + , T u r b o D e b u g g e r , a n d T u r b o Pascal are registered trademarks o f B o r l a n d International, I n c . Intel is a registered t r a d e m a r k o f Intel C o r p o r a t i o n . Microsoft C , Microsoft E x c e l , a n d Microsoft W o r d are registered trademarks o f Microsoft C o r p o r a t i o n . W i n d o w s is a t r a d e m a r k o f Microsoft C o r p o r a t i o n . Smalltalk is a t r a d e m a r k o f ParcPlace systems. W h i t e w a t e r R e s o u r c e T o o l k i t is a t r a d e m a r k o f T h e W h i t e w a t e r G r o u p . Z o r t e c h is a t r a d e m a r k o f Z o r t e c h , I n c .
XXI
T u r b o Pascal for W i n d o w s B i b l e
About the Author G a r y E n t s m i n g e r is a writer, p r o g r a m m e r , a n d c o n s u l t a n t . H e w a s a n associate e d i t o r for Micro Cornucopia, (the technical journal) for five years, a n d a c o l u m n i s t for B o r l a n d ' s Turbo Technix m a g a z i n e . H e is t h e a u t h o r o f The Tao of Objects, a b e g i n n e r ' s g u i d e t o o b j e c t - o r i e n t e d p r o g r a m m i n g , a n d his articles h a v e a p p e a r e d in Dr. Dobb's Journal, Computer Language, AI Expert, Midnight Engineering, AI Week, a n d Neural Network News. G a r y lives i n t h e E l k M o u n t a i n s o f C o l o r a d o . Gary Entsminger c/o: R o c k y M o u n t a i n B i o l o g i c a l Laboratory B o x 519 Crested Butte, C O 81224
xxii
PART ONE
WORKING WITH TPW
1 CHAPTER
GETTING STARTED In earlier days, the video display was used solely to echo text that the user typed using the keyboard. In a graphical user interface, the video display itself becomes a source of user input. Charles Petzold
Creating Windows Applications Y o u c a n c r e a t e W i n d o w s a p p l i c a t i o n s u s i n g T u r b o Pascal f o r W i n d o w s i n t h r e e different ways: 1. T h e easiest w a y is t o u s e t h e WinCrt u n i t . T h i s u n i t e n a b l e s y o u t o w r i t e " s t a n d a r d " T u r b o Pascal f o r W i n d o w s a p p l i c a t i o n s that u s e T u r b o Pascal (for D O S ) f u n c t i o n s a n d p r o c e d u r e s , s u c h as Readln a n d Writeln i n a s c r o l l a b l e w i n d o w . T h e WinCrt u n i t a l s o lets y o u transfer y o u r e x i s t i n g T u r b o P a s c a l c o d e t o W i n d o w s w i t h t h e least a m o u n t o f effort. I d e s c r i b e t h e WinCrt u n i t i n m o r e d e t a i l i n C h a p t e r 2 , " E l e ments of Application Development," a n d in the reference section. 2. Y o u a l s o c a n w r i t e W i n d o w s a p p l i c a t i o n s i n t h e m o r e o r less "traditional" way, b y creating y o u r o w n w i n d o w s a n d w i n d o w s classes, a n d s e t t i n g u p y o u r o w n m e s s a g e l o o p . T h i s is t h e w a y " C ' e r s " u s u a l l y d o it, a n d I briefly d e s c r i b e this m e t h o d i n a n e x a m p l e i n C h a p t e r 2 . 3. T h e b e s t w a y t o w r i t e f u l l - f e a t u r e d , e x t e n d a b l e W i n d o w s a p p l i c a t i o n s is to u s e the O b j e c t W i n d o w s application framework (or object library).
4
P a r t i — W o r k i n g with T P W
ObjectWindows uses object-oriented techniques to encapsulate complex Windows behavior a n d make connections between Windows a n d y o u r a p p l i c a t i o n . If y o u u s e O b j e c t W i n d o w s , W i n d o w s a p p l i c a t i o n s a r e b o t h e a s i e r t o w r i t e a n d m o r e efficient. T h r o u g h o u t this b o o k , I u s e a n d describe in detail h o w t o u s e O b j e c t W i n d o w s .
System Requirements and Installation T o r u n T u r b o P a s c a l f o r W i n d o w s , y o u n e e d M i c r o s o f t W i n d o w s , a P C w i t h at least 2 M ( m e g a b y t e s ) o f R A M , a n d a n E G A , V G A , o r H e r c u l e s v i d e o a d a p t e r . Y o u also have t o r u n W i n d o w s in Standard or 386 E n h a n c e d m o d e because T u r b o Pascal f o r W i n d o w s d o e s n o t r u n i n R e a l m o d e . I n a d d i t i o n , if y o u p l a n t o d e b u g in S V G A (Super V i d e o Graphics Adapter) m o d e , y o u must u s e dual monitors. T o install T u r b o Pascal f o r W i n d o w s , u s e t h e Install p r o g r a m o n t h e T u r b o P a s c a l f o r W i n d o w s d i s t r i b u t i o n d i s k s . T h e T u r b o Pascal f o r W i n d o w s s y s t e m a n d e x a m p l e files o n t h e d i s t r i b u t i o n d i s k s a r e a r c h i v e d , s o Install d e - a r c h i v e s t h e m for y o u , puts t h e m in convenient subdirectories, a n d automatically c r e a t e s c o n f i g u r a t i o n files f o r b o t h t h e c o m m a n d - l i n e c o m p i l e r a n d t h e i n t e grated development environment (IDE). T o r u n t h e i n s t a l l a t i o n p r o g r a m f r o m drive A , e n t e r :
C:\ Win A:Install o r , if W i n d o w s is active, select t h e P r o g r a m M a n a g e r ' s
File/Run c o m m a n d
and enter:
A: Install Note: I f y o u a r e a h a n d s - o n k i n d o f p e r s o n , o r h a v e a n o t h e r m o t i v e , y o u c a n u s e U n p a k . e x e t o u n p a c k t h e a r c h i v e d files m a n u a l l y . After y o u h a v e c o m p l e t e d t h e i n s t a l l a t i o n , a d d t h e T u r b o Pascal f o r W i n d o w s d i r e c t o r i e s (for e x a m p l e , C: \TPW; C: \TPW\UTILS) i n t h e D O S p a t h y o u specify in A U T O E X E C . B A T . If y o u d o n o t k n o w h o w t o edit y o u r A U T O E X E C . B A T file, refer t o y o u r D O S m a n u a l s .
The Turbo Pascal for Windows IDE T u r b o Pascal f o r W i n d o w s is a c o m p l e t e d e v e l o p m e n t e n v i r o n m e n t f o r M i c r o soft W i n d o w s . It c o n s i s t s o f a n e d i t o r , c o m p i l e r , l i n k e r , a n d d e b u g g e r i n o n e p a c k a g e . Y o u c a n edit m a n y s o u r c e - c o d e files (as a p r o j e c t ) , c o m p i l e t h e m , a n d l i n k t h e m i n t o a n e x e c u t a b l e a p p l i c a t i o n w i t h o u t l e a v i n g t h e T u r b o Pascal for W i n d o w s e n v i r o n m e n t . F i g u r e 1.1 s h o w s t h e T u r b o Pascal for W i n d o w s startu p screen.
1 — G e t t i n g Started
M o s t o f y o u r v i s u a l activity (what y o u see) o c c u r s i n a T u r b o P a s c a l f o r W i n d o w s E d i t w i n d o w . T u r b o Pascal f o r W i n d o w s lets y o u h a v e as m a n y as 32 w i n d o w s o p e n at a t i m e , p r o v i d e d t h e r e is e n o u g h m e m o r y . O n l y o n e w i n d o w c a n b e active at a t i m e . T h e active w i n d o w is t h e o n e i n w h i c h y o u are w o r k i n g (editing, c o m p i l i n g , a n d so o n ) .
Figure
1.1. The Turbo Pascal for Windows start-up screen.
A n Edit w i n d o w consists o f • A title b a r • The Window Control menu box • Scroll bars • Minimize and Maximize buttons R e f e r t o f i g u r e 1.2 f o r a s a m p l e E d i t w i n d o w . I n a d d i t i o n t o E d i t w i n d o w s , T u r b o Pascal f o r W i n d o w s d i s p l a y s v a r i o u s dialog w i n d o w s in response to user m e n u selections, errors, a n d so o n . A R e p l a c e T e x t d i a l o g b o x , f o r e x a m p l e , a p p e a r s w h e n y o u select S e a r c h / R e p l a c e T e x t f r o m t h e M a i n m e n u , as s h o w n i n f i g u r e 1.3. D i a l o g s ( w h i c h y o u w i l l l e a r n m u c h m o r e a b o u t i n this b o o k ) c a n c o n s i s t o f input b o x e s , c o m m a n d b u t t o n s , a n d so o n . Typically, y o u c h e c k b o x e s , inp u t text, a n d specify o p t i o n s ; t h e n y o u c l i c k a c o m m a n d b u t t o n t o c l o s e t h e dialog box.
5
6
Part I — W o r k i n g w i t h T P W
Figure 1.2. An Edit
window.
Figure 1.3- A Replace Text dialog box.
1 — G e t t i n g Started
Turbo Pascal for Windows IDE Menu Commands T h e T u r b o Pascal f o r W i n d o w s I D E M e n u o p t i o n s are c o m p l e x a n d p o w e r f u l . F o r y o u r c o n v e n i e n c e , t h e m e n u s are s e p a r a t e d i n t o • Desktop control • Edit w i n d o w control •
File
•
Edit
•
Search
•
Run
•
Compile
•
Options
•
Window
• Help menus
The Turbo Pascal for Windows Desktop Control Menu T h e T u r b o Pascal f o r W i n d o w s C o n t r o l M e n u b o x is o n t h e far left s i d e o f t h e title b a r . C l i c k t h e c o n t r o l m e n u b o x o n c e o r p r e s s A l t - S p a c e b a r t o d i s p l a y t h e m e n u . T h e c o m m a n d s g r o u p e d i n this m e n u m a n a g e t h e T u r b o P a s c a l f o r Windows desktop. E a c h E d i t w i n d o w a n d d i a l o g b o x a l s o h a s a (similar) C o n t r o l m e n u . T h e D e s k t o p C o n t r o l m e n u c o m m a n d s are •
Restore
•
Move
•
Size
•
Minimize
•
Maximize
•
Close
• Switch
To
7
8
P a r t i — W o r k i n g with TPW
Restore W h e n y o u select t h e R e s t o r e c o m m a n d f r o m t h e D e s k t o p C o n t r o l m e n u , t h e T u r b o Pascal f o r W i n d o w s d e s k t o p w i n d o w r e t u r n s t o its p r e v i o u s s i z e . Note: Y o u c a n u s e this c o m m a n d o n l y if t h e T u r b o Pascal f o r W i n d o w s d e s k t o p w i n d o w is m a x i m i z e d o r m i n i m i z e d .
Move T h e M o v e c o m m a n d moves the desktop w i n d o w . Use t h e w i n d o w w h e r e y o u w a n t it a n d t h e n p r e s s E n t e r . w i n d o w b y d r a g g i n g its title b a r . T h e title b a r is t h e w i n d o w ; it c o n t a i n s t h e n a m e o f t h e file that is i n t h e Note:
the arrow keys to m o v e Y o u also can m o v e the top horizontal bar of a window.
Y o u c a n n o t u s e this c o m m a n d w h e n t h e d e s k t o p is m a x i m i z e d .
Size Y o u c a n alter t h e size o f t h e d e s k t o p w i n d o w w i t h t h e S i z e c o m m a n d . U s e t h e c u r s o r a r r o w k e y s t o m o v e t h e w i n d o w b o r d e r s . T h e n p r e s s E n t e r w h e n y o u are satisfied w i t h t h e w i n d o w ' s s i z e . Note: S i z e is a n available o p t i o n o n l y w h e n t h e T u r b o Pascal f o r W i n d o w s d e s k t o p is n o t m a x i m i z e d .
Minimize B y s e l e c t i n g t h e M i n i m i z e c o m m a n d , y o u c a n t u r n t h e T u r b o Pascal f o r W i n d o w s d e s k t o p i n t o t h e T P W i c o n . (An i c o n r e p r e s e n t s a w i n d o w i n its m i n i m i z e d state. A p p l i c a t i o n s , s u c h as T P W , c a n h a v e t h e i r o w n u n i q u e i c o n s . ) Note: Y o u c a n select this c o m m a n d o n l y if t h e d e s k t o p w i n d o w h a s n ' t b e e n m i n i m i z e d already.
Maximize If y o u select t h e M a x i m i z e c o m m a n d , t h e d e s k t o p w i n d o w fills t h e e n t i r e screen. Note: Y o u c a n select this c o m m a n d o n l y if t h e T u r b o Pascal for W i n d o w s d e s k t o p w i n d o w has not b e e n m a x i m i z e d already.
Close T h e C l o s e c o m m a n d c l o s e s t h e d e s k t o p a n d t h e n u n l o a d s T u r b o Pascal for W i n d o w s f r o m m e m o r y . T h e c o m m a n d is a c t i v a t e d i n t w o d i f f e r e n t w a y s , d e p e n d i n g o n the current m o d e :
1 — G e t t i n g Started
• I n C U A ( c o m m a n d u s e r a c c e s s ) m o d e , y o u p r e s s Alt-F4 t o c l o s e t h e desktop. • In Alternate m o d e , y o u press Alt-X to close the desktop. Y o u also can click the close b o x in the upper-left corner to close the window. If y o u h a v e m o d i f i e d a n E d i t w i n d o w b u t h a v e n o t s a v e d t h e file, a d i a l o g b o x a p p e a r s s o that y o u c a n verify w h e t h e r y o u w a n t t o save t h e file b e f o r e closing.
Switch To T h e S w i t c h T o c o m m a n d d i s p l a y s t h e T a s k List d i a l o g b o x that y o u c a n u s e t o switch from o n e application to another a n d to rearrange application w i n d o w s .
The Edit Window Control Menu E a c h E d i t w i n d o w h a s a C o n t r o l m e n u w h e n t h e w i n d o w is active. T h e c o m m a n d s o n this m e n u are s i m i l a r t o t h o s e o f t h e T u r b o P a s c a l f o r W i n d o w s Control menu. T h e s e c o m m a n d s are available o n t h e E d i t W i n d o w C o n t r o l m e n u : •
Restore
•
Move
•
Size
•
Minimize
•
Maximize
•
Close
•
Next
Restore T h e R e s t o r e c o m m a n d r e t u r n s t h e Edit w i n d o w t o its d e f a u l t s i z e . If y o u h a v e m i n i m i z e d o r m a x i m i z e d t h e E d i t w i n d o w , u s e R e s t o r e t o r e t u r n it t o its p r e v i o u s ( d e f a u l t ) s i z e . If y o u h a v e n o t m i n i m i z e d o r m a x i m i z e d t h e w i n d o w , t h e R e s t o r e c o m m a n d is d i s a b l e d .
Move U s e the M o v e c o m m a n d to m o v e y o u r Edit w i n d o w with keyboard keys or by d r a g g i n g its title b a r .
9
10
P a r t i — W o r k i n g with T P W
After y o u s e l e c t M o v e , u s e t h e a r r o w k e y s t o m o v e t h e w i n d o w . W h e n y o u ' r e satisfied w i t h t h e w i n d o w ' s n e w p o s i t i o n , p r e s s E n t e r . Note:
Y o u c a n u s e M o v e o n l y w h e n y o u r E d i t w i n d o w isn't m a x i m i z e d .
Size Y o u c a n c h a n g e t h e size o f y o u r E d i t w i n d o w u s i n g t h e k e y b o a r d ; o r , if a w i n d o w h a s a R e s i z e c o r n e r , y o u c a n d r a g t h e c o r n e r t o resize t h e w i n d o w . After s e l e c t i n g S i z e , u s e t h e a r r o w k e y s t o m o v e t h e w i n d o w b o r d e r s . W h e n y o u are satisfied, p r e s s E n t e r . Note: Y o u c a n u s e S i z e o n l y w h e n y o u r E d i t w i n d o w isn't m a x i m i z e d o r minimized.
Minimize Select the M i n i m i z e c o m m a n d to shrink y o u r Edit w i n d o w to an i c o n o n the T u r b o Pascal f o r W i n d o w s d e s k t o p . Note: Y o u c a n select this c o m m a n d o n l y if t h e w i n d o w h a s n o t b e e n m i n i m i z e d already.
Maximize T h e M a x i m i z e c o m m a n d e n l a r g e s t h e E d i t w i n d o w s o that it fills t h e T u r b o Pascal f o r W i n d o w s d e s k t o p . Note: Y o u c a n select this c o m m a n d o n l y w h e n t h e w i n d o w h a s n o t b e e n m a x i m i z e d already.
Close T h e C l o s e c o m m a n d closes the Edit w i n d o w . Y o u also can double-click the C l o s e b o x in the upper-left corner to close a window. If y o u h a v e m o d i f i e d text i n t h e w i n d o w a n d h a v e n o t s a v e d t h e text, a d i a l o g b o x a p p e a r s that g i v e s y o u t h e o p t i o n o f s a v i n g t h e file b e f o r e y o u c l o s e .
Next T h e N e x t c o m m a n d activates t h e n e x t o p e n w i n d o w o r i c o n .
The File Menu T h e File m e n u offers y o u c h o i c e s f o r c r e a t i n g n e w files, o p e n i n g a n d l o a d i n g e x i s t i n g files, s a v i n g files, p r i n t i n g files, a n d e x i t i n g T u r b o P a s c a l f o r W i n d o w s . T h e File m e n u c o m m a n d s i n c l u d e t h e f o l l o w i n g :
1 — G e t t i n g Started
•
New
•
Open
•
Save
• Save As • Save All •
Print
• Printer S e t u p •
Exit
• List o f c l o s e d files
New N e w o p e n s a n e w Edit w i n d o w w i t h t h e d e f a u l t n a m e N O N A M E x x . P A S ( t h e x x s t a n d s f o r a n u m b e r f r o m 00 t o 99), a n d m a k e s t h e n e w Edit w i n d o w active. A N O N A M E file is u s e d as a t e m p o r a r y edit buffer. If y o u try t o save a N O N A M E file, T u r b o Pascal f o r Windows p r o m p t s y o u t o n a m e it b e f o r e it c a n be saved.
Open T h e O p e n c o m m a n d d i s p l a y s t h e File O p e n d i a l o g b o x . I n this d i a l o g b o x , y o u s e l e c t t h e file y o u w a n t t o o p e n , as illustrated in figure 1.4.
Figure
1.4. The File Open dialog
box.
11
12
Part I — W o r k i n g w i t h T P W
N o t e : I n t h e T u r b o Pascal f o r W i n d o w s D e s k t o p , y o u c a n w o r k in either o f t w o edit m o d e s . Y o u specify y o u r c h o i c e o f m o d e s u s i n g t h e O p t i o n s / P r e f e r e n c e s m e n u . T h e t w o m o d e s are C U A , t h e s t a n d a r d W i n d o w s m o d e , a n d A l t e r n a t e , w h i c h is c o m m a n d compatible with other Borland editors.
I n A l t e r n a t e m o d e , p r e s s F 3 t o o p e n a file.
Save T h e S a v e c o m m a n d saves t o a d i s k t h e file i n t h e active E d i t w i n d o w . If t h e file h a s a d e f a u l t n a m e ( s u c h as N O N A M E 0 0 . P A S ) , T u r b o Pascal f o r W i n d o w s o p e n s t h e File S a v e A s d i a l o g b o x s o that y o u c a n r e n a m e t h e file a n d save it i n a different d i r e c t o r y o r o n a d i f f e r e n t d r i v e . If y o u u s e a n e x i s t i n g file n a m e t o n a m e t h e file, T u r b o Pascal f o r W i n d o w s asks w h e t h e r y o u w a n t t o o v e r w r i t e t h e e x i s t i n g file. If y o u w a n t t o save all m o d i f i e d files, n o t just t h e file i n t h e active E d i t w i n d o w , s e l e c t File/Save A l l . I n A l t e r n a t e m o d e , p r e s s F 2 t o save a file.
Save As S a v e A s o p e n s t h e File S a v e A s d i a l o g b o x , w h i c h lets y o u save t h e file i n t h e active Edit w i n d o w u n d e r a different n a m e , in a different directory, or o n a different drive (see figure 1.5). A l l w i n d o w s that c o n t a i n this file are u p d a t e d w i t h t h e n e w n a m e . If y o u select a file n a m e that a l r e a d y e x i s t s , T u r b o P a s c a l f o r W i n d o w s first asks w h e t h e r y o u w a n t t o o v e r w r i t e t h e e x i s t i n g file.
Save All T h i s c o m m a n d saves all t h e files i n o p e n E d i t w i n d o w s .
Print T h e Print c o m m a n d p r i n t s t h e c o n t e n t s o f t h e active E d i t w i n d o w . T u r b o Pascal f o r W i n d o w s e x p a n d s t h e T a b s (that is, it r e p l a c e s a n y T a b c h a r a c t e r s w i t h t h e a p p r o p r i a t e n u m b e r o f s p a c e s ) a n d t h e n p r i n t s t h e file. Note: T h e Print c o m m a n d is d i s a b l e d if t h e active w i n d o w c a n n o t b e p r i n t e d ; f o r e x a m p l e , if n o p r i n t e r is c o n n e c t e d t o y o u r s y s t e m .
1 — G e t t i n g Started
Figure
1.5. The File Save As dialog box.
Printer Setup T h e Printer S e t u p c o m m a n d d i s p l a y s a S e l e c t P r i n t e r d i a l o g b o x , w h i c h lets y o u s e l e c t a p r i n t e r t y p e f o r T u r b o Pascal f o r W i n d o w s (see f i g u r e 1.6).
Figure
1.6. The Select Printer dialog box.
13
14
P a r t i — W o r k i n g with TPW
Note:
If y o u d o n o t w a n t t o alter t h e w a y y o u r p r i n t e r is n o r m a l l y
c o n f i g u r e d , y o u d o n o t h a v e t o u s e Printer S e t u p .
Exit T h e Exit c o m m a n d exits T u r b o Pascal f o r W i n d o w s a n d r e m o v e s it f r o m memory. If y o u h a v e m o d i f i e d a s o u r c e file w i t h o u t s a v i n g it, T u r b o Pascal for W i n d o w s p r o m p t s y o u t o save t h e file b e f o r e e x i t i n g . T h e Exit c o m m a n d is mode-dependent: • I n C U A m o d e , p r e s s Alt-F4 t o exit. • I n A l t e r n a t e m o d e , p r e s s A l t - X t o exit.
list of Closed Files T h i s c o m m a n d lists all t h e files that h a v e b e e n c l o s e d s i n c e s t a r t - u p . S e l e c t a n y c l o s e d file f r o m t h e m e n u t o q u i c k l y r e o p e n it.
The Edit Menu T h e Edit m e n u includes c o m m a n d s to u n d o , r e d o , cut, copy, paste, a n d clear text i n E d i t w i n d o w s . A l s o , y o u c a n o p e n a Clipboard w i n d o w t o v i e w o r edit its c o n t e n t s . T h e E d i t m e n u c o m m a n d s are •
Undo
•
Redo
•
Cut
•
Copy
•
Paste
•
Clear
Undo T h e U n d o c o m m a n d r e s t o r e s t h e m o s t r e c e n t edit o r c u r s o r m o v e m e n t . U n d o inserts a n y c h a r a c t e r s y o u d e l e t e d , d e l e t e s a n y c h a r a c t e r s y o u inserted, replaces any characters y o u overwrote, a n d m o v e s y o u r cursor back to the previous position.
1 — G e t t i n g Started
If y o u u n d o a b l o c k o p e r a t i o n , t h e file r e a p p e a r s as it d i d b e f o r e y o u executed the block operation. If y o u p r e s s U n d o m o r e t h a n o n c e , it c o n t i n u e s t o u n d o c h a n g e s as l o n g as it c a n . H o w e v e r , t h e U n d o c o m m a n d d o e s n o t c h a n g e a n o p t i o n s e t t i n g that affects m o r e t h a n o n e w i n d o w . T h e G r o u p - U n d o o p t i o n in the Options/Preferences dialog b o x specifies U n d o and Redo behavior.
Redo R e d o reverses t h e effect o f t h e m o s t r e c e n t U n d o c o m m a n d . R e d o is effective o n l y i m m e d i a t e l y after a n U n d o o r a n o t h e r R e d o . A series o f R e d o c o m m a n d s reverses t h e effects o f a series o f U n d o commands.
Cut T h e C u t c o m m a n d r e m o v e s t h e s e l e c t e d text f r o m a d o c u m e n t i n t h e E d i t w i n d o w a n d p u t s t h e text i n t h e C l i p b o a r d . Y o u c a n t h e n u s e Edit/Paste t o c o p y t h e text t o a n o t h e r d o c u m e n t o r t o a different place in the current d o c u m e n t . T h e text r e m a i n s s e l e c t e d i n t h e C l i p b o a r d u n t i l y o u r e p l a c e it w i t h o t h e r text, s o y o u c a n p a s t e it m a n y t i m e s , i n as m a n y files as y o u w a n t .
Copy T h e C o p y c o m m a n d d o e s n o t r e m o v e t h e s e l e c t e d text; it l e a v e s t h e text intact a n d p l a c e s a n e x a c t c o p y o f it i n t h e C l i p b o a r d . T o p a s t e t h e c o p i e d text i n t o a n o t h e r d o c u m e n t , select Edit/Paste. Y o u a l s o c a n c o p y text f r o m a H e l p w i n d o w : • U s i n g t h e k e y b o a r d , p r e s s Shift a n d a n a r r o w k e y t o s e l e c t t h e text y o u want to copy. • U s e t h e m o u s e t o c l i c k a n d d r a g t h e text y o u w a n t t o c o p y .
Paste T h e Paste c o m m a n d inserts t h e s e l e c t e d text f r o m t h e C l i p b o a r d i n t o t h e active w i n d o w at t h e c u r r e n t c u r s o r p o s i t i o n .
15
16
P a r t i — W o r k i n g with T P W
Clear T h e C l e a r c o m m a n d removes t h e s e l e c t e d text f r o m t h e d o c u m e n t in t h e active w i n d o w , b u t d o e s n o t m o v e it t o t h e C l i p b o a r d . T h u s , y o u c a n n o t p a s t e " c l e a r e d " text in a d o c u m e n t as y o u c a n w h e n y o u u s e C u t o r C o p y . Note: A l t h o u g h y o u c a n n o t p a s t e t h e c l e a r e d text, y o u c a n u n d o t h e C l e a r c o m m a n d with U n d o . C l e a r is handy f o r d e l e t i n g text w i t h o u t o v e r w r i t i n g t h e c u r r e n t text in the Clipboard.
The Search Menu T h e S e a r c h m e n u includes t h e c o m m a n d s t o s e a r c h f o r text a n d e r r o r l o c a t i o n s in y o u r files. T h e S e a r c h m e n u c o m m a n d s are •
Find
•
Replace
• Search Again • G o to Line N u m b e r • S h o w Last C o m p i l e E r r o r • Find Error
Find T h e F i n d c o m m a n d d i s p l a y s t h e F i n d T e x t d i a l o g b o x , w h i c h lets y o u t y p e in t h e text y o u w a n t t o s e a r c h for. S e v e r a l o p t i o n s in this d i a l o g b o x let y o u specify t h e d e t a i l s o f t h e s e a r c h (see f i g u r e 1.7).
Replace T h e R e p l a c e c o m m a n d d i s p l a y s t h e R e p l a c e T e x t d i a l o g b o x , w h i c h lets y o u t y p e in t h e text y o u w a n t t o s e a r c h f o r a n d t h e text y o u w a n t t o replace it w i t h (see f i g u r e 1.8).
Search Again T h e S e a r c h A g a i n c o m m a n d repeats t h e p r e v i o u s F i n d o r R e p l a c e c o m m a n d . T h e p r e v i o u s s e t t i n g s y o u m a d e in t h e F i n d T e x t o r R e p l a c e T e x t d i a l o g b o x are in effect w h e n y o u c h o o s e S e a r c h A g a i n . In C U A m o d e , press F3 to search again.
1 — G e t t i n g Started
Figure
1.7. The Find Text dialog box.
Figure
1.8. The Replace Text dialog box.
Go to line Number T h e G o to Line N u m b e r c o m m a n d displays the G o to Line N u m b e r dialog b o x , w h i c h p r o m p t s y o u for the line n u m b e r y o u want to find.
17
18
P a r t i — W o r k i n g with T P W
T u r b o Pascal f o r W i n d o w s d i s p l a y s t h e c u r r e n t l i n e n u m b e r a n d c o l u m n n u m b e r i n t h e lower-left c o r n e r o f e v e r y E d i t w i n d o w .
Search/Show Last Compile Error T h e S e a r c h / S h o w Last C o m p i l e E r r o r c o m m a n d l o c a t e s t h e p r e v i o u s c o m p i l e r e r r o r . T h e c u r s o r m o v e s t o t h e l i n e that c a u s e d t h e e r r o r . If t h e e r r o r is n o t i n t h e active w i n d o w , T u r b o Pascal f o r W i n d o w s m a k e s active t h e w i n d o w w i t h t h e p r e v i o u s c o m p i l e r e r r o r , o p e n i n g a c l o s e d file if n e c e s s a r y . T h e e r r o r n u m b e r a n d m e s s a g e t h e n a p p e a r o n t h e status b a r .
Search/Find Error T h e S e a r c h / F i n d E r r o r c o m m a n d b r i n g s u p t h e F i n d E r r o r d i a l o g b o x , w h i c h lets y o u specify t h e a d d r e s s o f t h e m o s t r e c e n t r u n - t i m e e r r o r .
The Run Menu T h e R u n m e n u i n c l u d e s t h e c o m m a n d s f o r r u n n i n g y o u r a p p l i c a t i o n , starting T u r b o D e b u g g e r f o r W i n d o w s , a n d s p e c i f y i n g c o m m a n d - l i n e p a r a m e t e r s . It includes the following c o m m a n d s : •
Run
•
Debugger
•
Parameters
If y o u w a n t t o u s e t h e d e b u g g e r o n a file, c h e c k t h e O p t i o n s / L i n k e r / D e b u g Info in E X E c h e c k b o x before y o u c o m p i l e a n d link y o u r application. T h e D e b u g Info in E X E o p t i o n puts the necessary information in y o u r e x e c u t a b l e file.
Run/Run T h e Run/Run c o m m a n d runs the application, using any parameters y o u pass to it t h r o u g h t h e R u n / P a r a m e t e r s c o m m a n d . If y o u r s o u r c e c o d e h a s b e e n m o d i f i e d s i n c e t h e p r e v i o u s c o m p i l a t i o n , t h e c o m p i l e r automatically "does a m a k e " a n d links y o u r application.
Run/Debugger T h e R u n / D e b u g g e r c o m m a n d starts T u r b o D e b u g g e r f o r W i n d o w s , a n d a l l o w s y o u to d e b u g the application.
1 — G e t t i n g Started
T u r b o Pascal f o r Windows tells T u r b o D e b u g g e r f o r Windows which application to debug. C h e c k t h e O p t i o n s / L i n k e r / D e b u g I n f o in t h e E X E c h e c k b o x b e f o r e y o u c o m p i l e a n d l i n k y o u r a p p l i c a t i o n if y o u w a n t t o u s e T u r b o D e b u g g e r t o d e b u g it. T h e O p t i o n s / L i n k e r / D e b u g I n f o in E X E c h e c k b o x p u t s t h e necessary d e b u g information in t h e e x e c u t a b l e file. T o get the m o s t from T u r b o D e b u g g e r ' s symbolic d e b u g g i n g capabilities, y o u also should check the Options/Compiler/Debug Information b o x a n d the Options/Compiler/Local Symbols b o x before compiling your application.
Run/Parameters T h e Run/Parameters c o m m a n d p a s s e s p a r a m e t e r s t o y o u r a p p l i c a t i o n p r o g r a m w h e n y o u run it as t h o u g h y o u w e r e running t h e a p p l i c a t i o n f r o m t h e P r o g r a m M a n a g e r ' s File/Run m e n u . When y o u select this c o m m a n d , t h e Parameters d i a l o g b o x a p p e a r s . Y o u r j o b is t o specify t h e c o m m a n d - l i n e a r g u m e n t s (see figure 1.9).
Figure
1.9. The Parameters dialog box.
The Compile Menu Y o u use the c o m m a n d s o n the C o m p i l e m e n u to compile, m a k e , or build y o u r application program.
19
20
P a r t i — W o r k i n g with T P W
T o u s e t h e Compile c o m m a n d , y o u m u s t have a file o p e n in a n active w i n d o w . T o u s e Make a n d Build, y o u m u s t have a primary file d e f i n e d . S e l e c t from these c o m m a n d s : •
Compile
•
Make
•
Build
• Primary File • C l e a r Primary File •
Information
Compile/Compile T h e C o m p i l e / C o m p i l e c o m m a n d c o m p i l e s t h e file in t h e active Edit w i n d o w . A C o m p i l e S t a t u s information b o x displays t h e c o m p i l a t i o n progress a n d results. If a n error o c c u r r e d , t h e status b a r d i s p l a y s t h e error l i n e a n d highlights t h e error. C l i c k y o u r m o u s e o r p r e s s a k e y t o clear t h e m e s s a g e s o that y o u c a n correct t h e error.
Compile/Make T h e Compile/Make c o m m a n d creates a . E X E file a c c o r d i n g t o t h e s e
rules:
• I f a primary file has b e e n n a m e d in t h e Primary File d i a l o g b o x , that file is c o m p i l e d . O t h e r w i s e , t h e file in t h e active Edit w i n d o w is c o m p i l e d . T u r b o Pascal f o r Windows c h e c k s all files affecting t h e c o m p i l e d file's p e r f o r m a n c e t o verify that t h e y exist a n d that t h e y are c u r r e n t . • I f t h e s o u r c e file f o r a u n i t has b e e n m o d i f i e d s i n c e t h e . T P U ( o b j e c t c o d e ) file w a s c r e a t e d , t h e m o d i f i e d u n i t is recompiled. • I f t h e interface
f o r a u n i t has c h a n g e d , a n y u n i t that d e p e n d s o n it is
recompiled. • I f a u n i t links in a . O B J file ( e x t e r n a l routines), a n d t h e . O B J file is n e w e r t h a n t h e u n i t ' s . T P U file, t h e u n i t is recompiled. • I f a u n i t c o n t a i n s a n I n c l u d e file a n d t h e I n c l u d e file is n e w e r t h a n that u n i t ' s . T P U file, t h e u n i t is
recompiled.
• I f t h e s o u r c e t o a u n i t ( . T P U file) c a n n o t b e l o c a t e d , t h e u n i t is n o t compiled. T h i s o p t i o n is identical t o C o m p i l e / B u i l d , e x c e p t it is c o n d i t i o n a l . B u i l d rebuilds all files, w h e t h e r o r n o t t h e y are c u r r e n t .
1 — G e t t i n g Started
Compile/Build T h e C o m p i l e / B u i l d c o m m a n d rebuilds all t h e c o m p o n e n t s o f y o u r a p p l i c a t i o n , w h e t h e r o r n o t t h e y are c u r r e n t . T h i s o p t i o n is identical t o C o m p i l e / M a k e , e x c e p t it is u n c o n d i t i o n a l . M a k e rebuilds o n l y t h o s e files that are n o t c u r r e n t . T h e C o m p i l e / B u i l d c o m m a n d recompiles all t h e files included in t h e primary file. If y o u abort a C o m p i l e / B u i l d c o m m a n d b y p r e s s i n g C t r l - B r e a k o r receive errors that t e r m i n a t e t h e b u i l d , y o u c a n restart t h e b u i l d w h e r e it w a s terminated by selecting Compile/Make.
Compfle/Primary File T h e C o m p i l e / P r i m a r y File c o m m a n d d i s p l a y s t h e Primary File d i a l o g b o x , w h i c h lets y o u specify w h i c h .PAS file w i l l b e c o m p i l e d w h e n y o u c h o o s e C o m p i l e / M a k e or C o m p i l e / B u i l d . U s e C o m p i l e / P r i m a r y File w h e n y o u are w o r k i n g o n a n a p p l i c a t i o n that u s e s several u n i t ( . T P U ) o r I n c l u d e files. R e g a r d l e s s o f t h e file y o u are e d i t i n g , C o m p i l e / M a k e a n d C o m p i l e / B u i l d always o p e r a t e o n y o u r primary file. If y o u specify a n o t h e r file as a primary file, b u t w a n t t o c o m p i l e o n l y t h e file in t h e active Edit w i n d o w , c h o o s e C o m p i l e .
Compile/Clear Primary File T h e C o m p i l e / C l e a r Primary File c o m m a n d removes t h e n a m e o f t h e primary file y o u s p e c i f i e d w i t h t h e C o m p i l e / P r i m a r y File c o m m a n d . If a primary file has n o t b e e n s p e c i f i e d , however, t h e c o m m a n d is d i s a b l e d .
Compile/Information T h e Compile/Information c o m m a n d displays t h e C o m p i l e Information b o x , t h e n a m e o f y o u r primary file (if y o u are u s i n g o n e ) , a n d t h e n a m e o f t h e p r e v i o u s file c o m p i l e d .
Compile Information Box T h e C o m p i l e I n f o r m a t i o n b o x lists: • T h e n a m e o f t h e primary file (if y o u are u s i n g o n e ) • T h e n a m e o f t h e p r e v i o u s file c o m p i l e d • T h e source compiled • C o d e size • D a t a size
21
22
P a r t i — W o r k i n g with TPW
• S t a c k size • L o c a l h e a p size
The Options Menu T h e O p t i o n s m e n u contains c o m m a n d s for viewing a n d c h a n g i n g various d e f a u l t settings in T u r b o Pascal f o r Windows. M o s t o f t h e c o m m a n d s in this m e n u initiate a d i a l o g b o x . T h e c o m m a n d s are •
Compiler
•
Linker
•
Directories
•
Preferences
•
Open
•
Save
• Save As
Compiler T h e O p t i o n s / C o m p i l e r c o m m a n d displays t h e C o m p i l e r O p t i o n s d i a l o g b o x , w h i c h lets y o u select t h e o p t i o n s that d e t e r m i n e howyour c o d e is c o m p i l e d (see figure 1.10).
Figure
1.10. The Compiler
Options dialog
box.
1 — G e t t i n g Started
Linker T h e Options/Linker c o m m a n d displays the Linker O p t i o n s dialog b o x , w h i c h lets y o u select t h e o p t i o n s that d e t e r m i n e h o w y o u r a p p l i c a t i o n files are l i n k e d , as s h o w n i n figure 1.11.
Figure
1.11. The Linker Options dialog
box.
Map File o p t i o n s T h e M a p File o p t i o n s (Off, S e g m e n t s , P u b l i c s , a n d D e t a i l e d ) d e t e r m i n e t h e t y p e o f m a p file p r o d u c e d . Link Buffer File o p t i o n s T h e L i n k B u f f e r File o p t i o n s ( M e m o r y o r D i s k ) specify t h e l o c a t i o n o f t h e l i n k buffer. D e b u g Info in E X E o p t i o n T h e D e b u g I n f o in E X E o p t i o n p u t s d e b u g information
in y o u r p r o g r a m ' s
e x e c u t a b l e file.
Directories T h e D i r e c t o r i e s c o m m a n d o p e n s t h e D i r e c t o r i e s d i a l o g b o x , w h e r e y o u specify t h e directories y o u w a n t T u r b o Pascal for Windows t o u s e w h e n running and s t o r i n g y o u r a p p l i c a t i o n p r o g r a m s , as illustrated in figure 1.12.
23
24
Part I — W o r k i n g w i t h T P W
Figure
1.12. The Directories
dialog
box.
W i t h t h e o p t i o n s i n this d i a l o g b o x , y o u d e c i d e w h e r e T u r b o Pascal f o r W i n d o w s f i n d s t h e files it n e e d s t o c o m p i l e , l i n k , a n d o u t p u t e x e c u t a b l e files. T h e E X E a n d T P U D i r e c t o r y i n p u t b o x s p e c i f i e s t h e d i r e c t o r y that s t o r e s y o u r . E X E a n d . T P U ( o b j e c t c o d e ) files. T h e I n c l u d e D i r e c t o r i e s i n p u t b o x s p e c i f i e s t h e d i r e c t o r i e s that c o n t a i n y o u r s t a n d a r d I n c l u d e files. T h e U n i t D i r e c t o r i e s i n p u t b o x s p e c i f i e s t h e d i r e c t o r i e s that c o n t a i n y o u r T u r b o Pascal f o r W i n d o w s u n i t files. T h e O b j e c t D i r e c t o r i e s i n p u t b o x s p e c i f i e s t h e d i r e c t o r i e s that c o n t a i n y o u r . O B J files ( a s s e m b l y l a n g u a g e r o u t i n e s ) . T h e Resource Directories input b o x specifies the directories in w h i c h y o u r r e s o u r c e files are k e p t .
Guidelines for Entering Directory Names Use the following guidelines w h e n y o u enter directories in the Options/ Directories input boxes: • Separate m u l t i p l e directory p a t h n a m e s (if a l l o w e d ) w i t h a s e m i c o l o n (;). • U s e a m a x i m u m o f 127 c h a r a c t e r s ( i n c l u d i n g w h i t e s p a c e ) . W h i t e s p a c e b e f o r e a n d after t h e s e m i c o l o n is a l l o w e d b u t n o t r e q u i r e d . • Relative a n d a b s o l u t e p a t h n a m e s are a l l o w e d , i n c l u d i n g p a t h n a m e s relative t o t h e l o g g e d p o s i t i o n i n drives o t h e r t h a n t h e c u r r e n t o n e .
1 — G e t t i n g Started
For example:
C:\ ; D:\TPW D:\;C:\TPW;D:\TPW
Preferences T h e Options/Preferences m e n u c o m m a n d o p e n s the Preferences dialog box, w h i c h lets y o u d e c i d e t h e b e h a v i o r a n d p h y s i c a l a p p e a r a n c e o f t h e T u r b o Pascal for W i n d o w s e n v i r o n m e n t (see figure 1.13).
Figure
1.13. The Preferences
dialog
box.
Editor Options T h e E d i t o r O p t i o n s g r o u p h a s several c h e c k b o x e s that c o n t r o l text h a n d l i n g i n Edit w i n d o w s . T h e y are • C r e a t e B a c k u p File • Auto Indent M o d e • Use Tab Character • O p t i m a l Fill • Backspace Unindents
25
26
Part I — W o r k i n g w i t h T P W
• Cursor through Tabs • Group Undo • Block Overwrite T h e A u t o S a v e o p t i o n s d e f i n e w h e n a n d h o w o f t e n T u r b o Pascal f o r W i n d o w s saves y o u r o p e n files, s e t t i n g s , a n d o p t i o n s . T h e y are • E d i t o r Files •
Desktop
•
Configuration
W h e n y o u select a n e w f o n t d i s p l a y e d i n t h e list b o x , t h e F o n t list b o x c h a n g e s t h e size a n d a p p e a r a n c e o f t h e text. T h e T a b Size input b o x controls the n u m b e r o f c o l u m n s the cursor m o v e s for each tab stop. T h e Right M o u s e B u t t o n o p t i o n s (Nothing a n d T o p i c Search) d e t e r m i n e w h e t h e r T u r b o Pascal f o r W i n d o w s u s e s t h e right b u t t o n t o initiate a t o p i c search in H e l p . T h e C o m m a n d Set o p t i o n s ( C U A o r A l t e r n a t e ) d e t e r m i n e w h e t h e r t h e editor uses C o m m o n User Access (CUA) c o m m a n d s or Alternate c o m m a n d s .
Open T h e O p t i o n s / O p e n c o m m a n d d i s p l a y s t h e O p e n C o n f i g u r a t i o n File d i a l o g b o x , w h e r e y o u c a n retrieve n e w c o n f i g u r a t i o n - f i l e s e t t i n g s . T h e File N a m e i n p u t b o x lets y o u e n t e r t h e n a m e o f t h e c o n f i g u r a t i o n file c o n t a i n i n g t h e s e t t i n g s y o u w a n t ; y o u c h o o s e O K o r p r e s s E n t e r t o l o a d that file. T h e d e f a u l t c o n f i g u r a t i o n file n a m e is T P W . C F G . T h e Files list b o x lists t h e n a m e s o f files i n t h e c u r r e n t d i r e c t o r y that m a t c h the file-name mask in the File-Name input b o x . T h e D i r e c t o r i e s list b o x lets y o u select a d i f f e r e n t d i r e c t o r y t o v i e w . Press A l t - D t o p l a c e t h e c u r s o r i n this list b o x .
Save T h e O p t i o n s / S a v e c o m m a n d saves i n t h e c u r r e n t c o n f i g u r a t i o n file t h e p r i m a r y file n a m e , t h e s e t t i n g s y o u s e l e c t e d w i t h t h e O p t i o n s m e n u , a n d t h e d e s k t o p setup. U s e O p t i o n s / S a v e A s t o save o p t i o n s t o a d i f f e r e n t c o n f i g u r a t i o n file. T h e n a m e o f t h e c u r r e n t c o n f i g u r a t i o n file a p p e a r s n e x t t o t h e O p t i o n s / S a v e command. • A l l o p t i o n s a n d t h e e d i t o r c o m m a n d t a b l e are s t o r e d i n T P W . C F G , t h e d e f a u l t s a v e d - o p t i o n s file.
1 — G e t t i n g Started
• H i s t o r y lists, t h e d e s k t o p state, a n d b r e a k p o i n t l o c a t i o n s are s t o r e d in TPW.INI.
Save As T h e Options/Save As c o m m a n d o p e n s t h e Configuration Save As dialog b o x , w h e r e y o u e n t e r a n e w n a m e f o r y o u r c o n f i g u r a t i o n file (see figure 1.14).
Figure
1.14. The Configuration
Save As dialog
box.
Y o u c a n c r e a t e a n e w c o n f i g u r a t i o n file b y s e t t i n g o p t i o n s a n d t h e n s e l e c t i n g O p t i o n s / S a v e A s a n d e n t e r i n g a n e w c o n f i g u r a t i o n file n a m e . T h e n e w l y c r e a t e d c o n f i g u r a t i o n file is n o w i n effect. I n t h e File N a m e i n p u t b o x , e n t e r a n e w n a m e f o r t h e c o n f i g u r a t i o n file. C h o o s e O K o r p r e s s E n t e r t o c r e a t e a . C F G file w i t h t h e n e w n a m e . If y o u d o n o t specify a file e x t e n s i o n , T u r b o Pascal f o r W i n d o w s a d d s a . C F G extension for y o u . For example:
YOUR becomes YOUR.CFG. A h i s t o r y list is a t t a c h e d t o t h e File N a m e i n p u t b o x . If t h e C o n f i g u r a t i o n o p t i o n is o n , s e t t i n g s m a d e t o t h e c u r r e n t c o n f i g u r a t i o n file are s a v e d w h e n y o u exit.
27
28
P a r t i — W o r k i n g with T P W
Directories List Box U s e t h e D i r e c t o r i e s list b o x t o c h a n g e t o a n o t h e r directory. Press A l t - D t o p l a c e t h e c u r s o r in t h e D i r e c t o r i e s list b o x .
The Window Menu T h e Window m e n u has c o m m a n d s f o r m a n i p u l a t i n g a n d o p e n i n g w i n d o w s . M o s t o f t h e w i n d o w s y o u o p e n f r o m this m e n u have t h e s t a n d a r d w i n d o w e l e m e n t s s u c h as scroll b a r s , M i n i m i z e a n d M a x i m i z e b u t t o n s , a n d a C o n t r o l menu box. O p e n w i n d o w s with the File/Open or File/New c o m m a n d s . At t h e b o t t o m o f t h e Window m e n u is a list o f o p e n w i n d o w s . If m o r e t h a n o n e w i n d o w is o p e n , y o u c a n s w i t c h t o a n o t h e r w i n d o w a n d m a k e it active b y s e l e c t i n g it f r o m t h e list. T h e s e are t h e Window •
Tile
•
Cascade
menu commands:
• Arrange Icons • Close All
Tile C h o o s e Window/Tile
t o tile y o u r o p e n w i n d o w s . U s i n g this c o m m a n d a r r a n g e s
t h e w i n d o w s s o that t h e y c o v e r t h e entire d e s k t o p w i t h o u t o v e r l a p p i n g o n e another.
Cascade C h o o s e Window/Cascade
t o stack all o p e n Edit w i n d o w s . C a s c a d e o v e r l a p s
o p e n w i n d o w s s o that e a c h w i n d o w is t h e s a m e size, b u t part o f e a c h u n d e r l y i n g w i n d o w is visible.
Arrange Icons S e l e c t Window/Arrange I c o n s t o rearrange t h e icons. R e a r r a n g e d icons are e v e n l y s p a c e d , b e g i n n i n g at t h e lower-left c o r n e r o n t h e d e s k t o p . T h e o p e n files m u s t b e M i n i m i z e d o r this c o m m a n d is d i s a b l e d .
1 — G e t t i n g Started
Close All C h o o s e Window/Close A l l t o c l o s e all o p e n w i n d o w s o n t h e d e s k t o p . If t h e text w a s c h a n g e d s i n c e t h e p r e v i o u s t i m e y o u s a v e d it, a d i a l o g b o x w a r n s y o u t o save t h e file b e f o r e c l o s i n g t h e w i n d o w . C h o o s e Y e s , N o , o r C a n c e l .
The Help Menu (Alt-H) T h e H e l p m e n u p r o v i d e s a c c e s s t o o n - l i n e H e l p , w h i c h a p p e a r s in a s p e c i a l H e l p w i n d o w . T h e H e l p s y s t e m p r o v i d e s information about most aspects o f the integrated e n v i r o n m e n t a n d T u r b o P a s c a l for Windows. T h e f o l l o w i n g list shows the Help m e n u commands: •
Index
• Topic Search • Using Help • C o m p i l e r Directives •
ObjectWindows
• Procedures and Functions • Reserved
Words
• Standard Units • T u r b o P a s c a l for Windows • Windows
Language
API
• A b o u t T u r b o Pascal for
Windows
Index (Shift-Fl) T u r b o P a s c a l for Windows' o n - l i n e H e l p c o m e s w i t h a c o m p r e h e n s i v e index that s u m m a r i z e s t h e o r g a n i z a t i o n a n d c o n t e n t s o f t h e H e l p s y s t e m . T o g e t into t h e H e l p s y s t e m f r o m t h e index, select o n e o f t h e highlighted words or phrases in t h e index, click it o r T a b t o it, a n d t h e n p r e s s Enter. If y o u d o n ' t k n o w how t o u s e a H e l p s y s t e m u n d e r Windows, Help/Using H e l p M e n u c o m m a n d .
choose the
Topic Search (Ctrl-Fl) If y o u p l a c e y o u r c u r s o r o n a w o r d (a " t o k e n " ) in t h e active Edit w i n d o w a n d c h o o s e H e l p / T o p i c S e a r c h , a H e l p w i n d o w o p e n s w i t h information a b o u t that token.
29
30
P a r t i — W o r k i n g with T P W
Y o u c a n set u p t h e R i g h t m o u s e b u t t o n (in t h e O p t i o n s / P r e f e r e n c e s d i a l o g b o x ) t o initiate a t o p i c s e a r c h . H e l p p r o v i d e s o n - l i n e r e f e r e n c e f o r m a n y e l e m e n t s o f t h e T u r b o Pascal f o r W i n d o w s language, including functions a n d procedures, reserved w o r d s , global variables, O b j e c t W i n d o w s , the W i n d o w s API, a n d so o n .
Help/Using Help T h e Help/Using H e l p c o m m a n d displays information o n h o w to use T u r b o P a s c a l f o r W i n d o w s ' H e l p s y s t e m (or a n y o t h e r H e l p s y s t e m u n d e r W i n d o w s ) .
Compiler Directives W h e n y o u c h o o s e this m e n u c o m m a n d , y o u s e e a n i n d e x o f c o m p i l e r d i r e c t i v e s . C o m p i l e r d i r e c t i v e s c o n t r o l s o m e o f T u r b o Pascal f o r W i n d o w s ' f e a t u r e s . • S o m e t u r n c o m p i l e r f e a t u r e s o n o r off. • S o m e specify p a r a m e t e r s that affect h o w y o u r a p p l i c a t i o n p r o g r a m is compiled. • Others control the conditional compilation of your application. A c o m p i l e r d i r e c t i v e is a c o m m e n t w i t h a s p e c i a l s y n t a x that y o u c a n p u t a n y w h e r e a c o m m e n t is a l l o w e d .
ObjectWindows W h e n y o u select this m e n u c o m m a n d , y o u s e e a h i e r a r c h y o f O b j e c t W i n d o w s types.
Procedures and Functions W h e n y o u c h o o s e this m e n u c o m m a n d , y o u s e e a n i n d e x o f t h e T u r b o Pascal f o r W i n d o w s library p r o c e d u r e s a n d f u n c t i o n s that y o u c a n u s e t o d e v e l o p applications.
Reserved Words W h e n y o u select this m e n u c o m m a n d , y o u s e e a n i n d e x o f all t h e r e s e r v e d w o r d s i n t h e T u r b o Pascal f o r W i n d o w s l a n g u a g e . R e s e r v e d w o r d s h a v e s p e c i a l m e a n i n g to the compiler. D o not use a reserved w o r d to n a m e y o u r variables, procedures, functions, objects, and so o n .
1 — G e t t i n g Started
Standard Units W h e n y o u s e l e c t this m e n u c o m m a n d , y o u s e e a n i n d e x o f T u r b o P a s c a l f o r W i n d o w s ' s t a n d a r d u n i t s . A s t a n d a r d u n i t is a c o l l e c t i o n o f p r e d e f i n e d c o n s t a n t s , d a t a t y p e s , v a r i a b l e s , p r o c e d u r e s , a n d f u n c t i o n s . Y o u tell y o u r a p p l i c a t i o n p r o g r a m t o u s e o n l y t h e u n i t s it n e e d s .
Turbo Pascal for Windows Language W h e n y o u select this m e n u c o m m a n d , y o u s e e a list o f t h e e l e m e n t s that c o m p r i s e t h e T u r b o Pascal f o r W i n d o w s l a n g u a g e .
Windows API W h e n y o u select this m e n u c o m m a n d , y o u s e e a n i n d e x o f t h e c o n s t a n t s , styles, m e s s a g e s , t y p e s , f u n c t i o n s , a n d p r o c e d u r e s that c o m p r i s e t h e W i n d o w s A p p l i c a t i o n P r o g r a m m i n g I n t e r f a c e (API). T u r b o Pascal f o r W i n d o w s d e c l a r e s all t h e W i n d o w s styles, c o n s t a n t s , a n d t y p e s i n t h e WinTypes u n i t . T h e WinProcs u n i t h a s all t h e A P I p r o c e d u r e s a n d f u n c t i o n s .
About Turbo Pascal for Windows W h e n y o u select this c o m m a n d , a d i a l o g b o x a p p e a r s w i t h c o p y r i g h t a n d version information. Press E s c o r c l i c k O K o r C a n c e l t o c l o s e t h e b o x .
Editor T h e T u r b o Pascal f o r W i n d o w s e d i t o r is a c o m p l e t e p r o g r a m m i n g e d i t o r . I n a l m o s t all c a s e s , y o u u s e it t o d e v e l o p all facets o f y o u r a p p l i c a t i o n s . I n a d d i t i o n t o b e i n g a f u l l - s c r e e n , c o m m a n d - r i c h e d i t o r , it is b a s e d o n W i n d o w s ' m u l t i d o c u m e n t i n t e r f a c e , w h i c h y o u l e a r n h o w t o u s e i n C h a p t e r 7, " M a n y W i n d o w s : A M u l t i - D o c u m e n t I n t e r f a c e . " T h e m u l t i - d o c u m e n t i n t e r f a c e e n a b l e s m a n y files t o b e o p e n s i m u l t a n e o u s l y . T h u s , y o u c a n o p e n files f o r several u n i t s a n d s w i t c h b e t w e e n t h e m easily w i t h o u t c l o s i n g a n y f i l e s — a g r e a t f e a t u r e w h e n y o u d e v e l o p large projects.
The Editor Commands T u r b o Pascal for W i n d o w s ' editor c o m m a n d s are s u m m a r i z e d in t h e following groups of commands:
31
32
Part I — W o r k i n g w i t h T P W
• Block commands • B l o c k c o m m a n d s ( C U A a n d Alternate) • B l o c k c o m m a n d s ( B o r l a n d style) • Extending selected blocks • Other commands • Cursor-movement commands • Insert a n d D e l e t e c o m m a n d s • More about editor c o m m a n d s • Miscellaneous keyboard commands
The Block Commands T h e following sections describe the block c o m m a n d s .
Copy Block This c o m m a n d copies a previously selected block to the Clipboard a n d pastes it t o t h e c u r r e n t c u r s o r p o s i t i o n . T h e o r i g i n a l b l o c k is u n c h a n g e d . If n o b l o c k is s e l e c t e d , n o t h i n g h a p p e n s .
Copy Text T h i s c o m m a n d c o p i e s s e l e c t e d text t o t h e C l i p b o a r d . Press C t r l - I n s t o u s e t h e command.
Cut Text T h i s c o m m a n d s c u t s s e l e c t e d text t o t h e C l i p b o a r d . Press S h i f t - D e l t o u s e t h e command.
Delete Block This c o m m a n d deletes a selected block. Y o u can "undelete" a block with U n d o . Press C t r l - D e l o r C t r l - K Y t o u s e this c o m m a n d .
Move Block T h i s c o m m a n d m o v e s a p r e v i o u s l y s e l e c t e d b l o c k f r o m its o r i g i n a l t h e C l i p b o a r d a n d t h e n p a s t e s it t o t h e c u r s o r p o s i t i o n . T h e b l o c k f r o m its o r i g i n a l p o s i t i o n . If n o b l o c k is m a r k e d , n o t h i n g h a p p e n s . D e l t o m o v e text t o C l i p b o a r d a n d Shift-Ins t o p a s t e text i n c u r r e n t
position to disappears Press Shiftdocument.
1 — G e t t i n g Started
PastefromClipboard T h i s c o m m a n d p a s t e s t h e c o n t e n t s o f t h e C l i p b o a r d t o c u r s o r l o c a t i o n . Press Shift-Ins t o u s e t h e c o m m a n d .
Read BlockfromDisk T h i s c o m m a n d reads a d i s k file into t h e c u r r e n t text at t h e c u r s o r p o s i t i o n e x a c t l y as t h o u g h it w a s a b l o c k . Press Shift-Ctrl-R o r C t r l - K R t o u s e this command. T h e text read is t h e n s e l e c t e d as a b l o c k . When this c o m m a n d is initiated, y o u are p r o m p t e d f o r t h e n a m e o f t h e file t o read. Y o u c a n u s e w i l d c a r d s t o select a file t o read, a n d a d i r e c t o r y is d i s p l a y e d . T h e file s p e c i f i e d c a n b e a n y l e g a l file n a m e .
WWte Block to Disk T h i s c o m m a n d w r i t e s a s e l e c t e d b l o c k t o a file. Press Shift-Ctrl-W o r C t r l - K W t o u s e this c o m m a n d . When y o u s p e c i f y t h i s c o m m a n d , T u r b o Pascal f o r Windows p r o m p t s y o u f o r t h e n a m e o f t h e file t o w r i t e t o . T h e file c a n b e g i v e n a n y l e g a l n a m e ( t h e d e f a u l t e x t e n s i o n is . P A S ) . If y o u p r e f e r t o u s e a file n a m e w i t h o u t a n e x t e n s i o n , a p p e n d a p e r i o d t o t h e e n d o f its n a m e . Note: If t h e file s p e c i f i e d a l r e a d y e x i s t s , a w a r n i n g is issued b e f o r e t h e e x i s t i n g file is o v e r w r i t t e n . If n o b l o c k is s e l e c t e d , n o t h i n g happens.
Editor-Command Tables T h e t a b l e s t h r o u g h o u t this s e c t i o n list t h e e d i t o r c o m m a n d s a n d t h e i r f u n c t i o n or meaning. Table
1.1.
The Block
Movement
commands
(CUA and
CUA
Alternate).
Both
Delete block
Ctrl-Del
Ctrl-Del
C o p y to Clipboard
Ctrl-Ins
Ctrl-Ins
Cut to Clipboard
Shift-Del
Shift-Del
Paste f r o m C l i p b o a r d
Shift-Ins
Shift-Ins
Alternate
Read block from disk
Shift-Ctrl-R
Ctrl-KR
Write b l o c k t o d i s k
Shift-Ctrl-W
Ctrl-KW
Indent block
Shift-Ctrl-I
Ctrl-KI
Unindent block
Shift-Ctrl-U
Ctrl-KU
33
34
P a r t i — W o r k i n g with TPW
Table
1.2.
The Block
commands
(Borland
style).
Command
Keys
Function
Text selection O n
Ctrl-KB
B e g i n s t h e s e l e c t i o n o f text; text s e l e c t i o n e n d s w i t h c o p y i n g (Ctrl-KK) o r c u t t i n g (Ctrl-KV) t o t h e C l i p b o a r d , o r t u r n i n g text s e l e c t i o n o f f w i t h Ctrl-KH
Text selection Off
Ctrl-KH
S t o p s t h e s e l e c t i o n o f text, a n d t h e s e l e c t e d text b e c o m e s unselected
C o p y text t o C l i p b o a r d
Ctrl-KK
C o p i e s t h e s e l e c t e d text t o t h e Clipboard
C u t text t o C l i p b o a r d
Ctrl-KV
C u t s t h e s e l e c t e d text t o t h e Clipboard
Paste f r o m C l i p b o a r d
Ctrl-KC
Pastes t h e c o n t e n t s o f t h e C l i p b o a r d i n t o y o u r active E d i t window
Extending
selected
blocks
Movement
CUA
Both
Left 1 character
Shift-Left
Shift-Left
Right 1 character
Shift-Right
Shift-Right
E n d o f line
Shift-End
Shift-End
Beginning of line
Shift-Home
Shift-Home
Same column, n e x t line
Shift-Down
Shift-Down
Same column,
Shift-Up
Shift-Up
O n e page down
Shift-PgDn
Shift-PgDn
O n e page u p
Shift-PgUp
Shift-PgUp
Left o n e w o r d
Shift-Ctrl-Left
Shift-Ctrl-Left
Right o n e w o r d
Shift-Ctrl-Right
Shift-Ctrl-Right
End of
Shift-Ctrl-End
Shift-Ctrl-End
Shift-Ctrl-PgDn
Shift-Ctrl-Home
Shift-Ctrl-Home
Shift-Ctrl-PgUp
Alternate
p r e v i o u s line
file
Beginning of
file
1 — G e t t i n g Started
N o t e : T u r b o Pascal for Windows' Borland-style block c o m m a n d s w o r k o n l y w i t h t h e A l t e r n a t e c o m m a n d set.
Table
1.3- Commands
that extend
selected
blocks.
Movement
CUA
Both
Alternate
Left 1 c h a r a c t e r
Shift-Left
Shift-Left
Right 1 character
Shift-Right
Shift-Right
E n d o f line
Shift-End
Shift-End
Beginning o f line
Shift-Home
Shift-Home
Same column, next line
Shift-Down
Shift-Down
Same column,
Shift-Up
Shift-Up
O n e page down
Shift-PgDn
Shift-PgDn
O n e page u p
Shift-PgUp
Shift-PgUp
previous line
Left o n e w o r d
Shift-Ctrl-Left
Shift-Ctrl-Left
Right o n e w o r d
Shift-Ctrl-Right
Shift-Ctrl-Right
E n d o f file
Shift-Ctrl-End
Shift-Ctrl-End
Shift-Ctrl-PgDn
B e g i n n i n g o f file
Shift-Ctrl-Home
Shift-Ctrl-Home
Shift-Ctrl-PgUp
Table
1.4. The cursor-movement
Movement
commands
CUA
(CUA and
Alternate).
Both
Alternate
C h a r a c t e r left
Left
Left
Ctrl-S
C h a r a c t e r right
Ctrl-Right
Right
Ctrl-D
W o r d left
Ctrl-Left
Ctrl-Left
Ctrl-A
Scroll d o w n 1 line
Ctrl-Z
Ctrl-Z
Ctrl-Z
Line u p
Up
Up
Ctrl-E
Line d o w n
Down
Down
Ctrl-X
Scroll u p 1 line
Ctrl-W
Ctrl-W
Ctrl-W
Scroll d o w n 1 line
Ctrl-Z
Ctrl-Z
Ctrl-Z
Page u p
PgUp
PgUp
Ctrl-R continues
35
36
P a r t i — W o r k i n g with TPW
Table
1.4.
continued
Movement
CUA
Both
Alternate
Page d o w n
PgDn
PgDn
Ctrl-C
Last c u r s o r p o s i t i o n
Ctrl-QP
Beginning of line
Home
Home End
Ctrl-QS
E n d of line
End
Top of window
Ctrl-E
Ctrl-QE
Bottom of window
Ctrl-X
Ctrl-QX
T o p o f file
Ctrl-Home
Ctrl-Home
Ctrl-QR, Ctrl-PgUp
B o t t o m o f file
Ctrl-End
Ctrl-End
Ctrl-QC, Ctrl-PgDn
Table
1.5-
The Insert
and Delete
commands
Ctrl-QD
(CUA and
Movement
CUA
Both
Delete char
Del
Ctrl-G
D e l e t e c h a r t o left
Backspace
Backspace
Delete line
Ctrl-Y
Ctrl-Y
Delete line e n d
Shift-Ctrl-Y
Alternate). Alternate
Ctrl-QY
Delete word
Ctrl-T
Insert l i n e
Ctrl-N
Insert m o d e O n / O f f
Ins
Ctrl-N Ins
Ctrl-V
Auto Indent This c o m m a n d toggles the automatic indenting o f successive lines. Y o u also can use Options/Preferences/Autolndent in the I D E to turn automatic indenting o n a n d off.
Current Compiler Options I n s e r t s t h e c u r r e n t c o m p i l e r - o p t i o n s e t t i n g s at t h e h e a d o f y o u r active E d i t window.
Cursor through Tabs T h e a r r o w k e y s m o v e t h e c u r s o r t o t h e m i d d l e o f tabs w h e n this o p t i o n is o n ; o t h e r w i s e t h e c u r s o r w o u l d j u m p several c o l u m n s w h e n it m o v e s o v e r m u l t i p l e t a b s . C t r l - O R is a t o g g l e .
1 — G e t t i n g Started
Find Place Marker T h i s c o m m a n d finds a m a x i m u m o f t e n p l a c e m a r k e r s ( N c a n b e a n y n u m b e r i n t h e r a n g e z e r o t o n i n e ) i n text. M o v e t h e c u r s o r t o a n y p r e v i o u s l y set m a r k e r b y pressing Ctrl-Q and the marker number.
Open File O p e n s a n e x i s t i n g file i n a n E d i t w i n d o w .
Optimal Fill O p t i m a l Fill b e g i n s every l i n e w i t h t h e m i n i m u m n u m b e r o f c h a r a c t e r s p o s s i b l e , u s i n g T a b s a n d s p a c e s as n e c e s s a r y . T h i s o p t i o n p r o d u c e s l i n e s w i t h f e w e r characters.
Save File T h i s c o m m a n d saves t h e file a n d r e t u r n s t o t h e e d i t o r .
Set Place T h i s c o m m a n d m a r k s a m a x i m u m o f t e n p l a c e s i n text w h e n y o u p r e s s C t r l - K , f o l l o w e d b y a s i n g l e - m a r k e r digit ( z e r o t o n i n e ) . After m a r k i n g y o u r l o c a t i o n , y o u c a n w o r k e l s e w h e r e i n t h e file a n d t h e n r e t u r n t o a m a r k e d l o c a t i o n b y u s i n g the Find Place Marker c o m m a n d (be sure to use the same marker n u m b e r ) . Y o u c a n h a v e as m a n y as t e n p l a c e s m a r k e d i n e a c h w i n d o w .
Show last Compile Error T h i s c o m m a n d h i g h l i g h t s t h e last s y n t a x e r r o r that t h e c o m p i l e r f o u n d d u r i n g t h e p r e v i o u s c o m p i l e . T h e e r r o r m e s s a g e a p p e a r s o n t h e status b a r . If y o u h a v e a l r e a d y c l o s e d that file, T u r b o P a s c a l f o r W i n d o w s r e o p e n s it a n d h i g h l i g h t s t h e error.
Tab Mode Y o u c a n specify t h e u s e o f t r u e T a b c h a r a c t e r s i n t h e I D E w i t h t h e O p t i o n s / Preferences/Use T a b Character o p t i o n .
Unindent Y o u can turn U n i n d e n t o n a n d off from the I D E with the Options/Preferences/ Backspace Unindents option.
37
38
P a r t i — W o r k i n g with T P W
Table
1.6. Miscellaneous
Movement
keyboard CUA
commands. Both
Alternate
A u t o i n d e n t on/off
Ctrl-OI
Compiler options
Ctrl-OO
Cursor through Tabs
Ctrl-OR
on/off Find place marker N
Ctrl-N*
Ctrl-Q-N*
Help
Fl
Fl
Help index
Shift-Fl
Shift-Fl
Maximize window
F5
Open
F3
file
O p t i m a l fill m o d e
Ctrl-OF
on/off Pair m a t c h i n g
Alt-[, Alt-]
Ctrl-Q
[, C t r l - Q ]
S a v e file
F2, Ctrl-KJ
Search
Ctrl-QF
Search again
F3
F3
Search and replace
Ctrl-QA
S h o w last c o m p i l e
Ctrl-QW
error Set m a r k e r
Shift-Ctrl-N*
Ctrl-K-N*
T a b s m o d e on/off
Ctrl-OT
Topic Help
Ctrl-Fl
Exit
Alt-F4
Undo
Alt-Backspace
Unindent mode on/off Insert c o n t r o l character
Ctrl-Fl Alt-X Alt-Backspace Ctrl-OU
Ctrl-P * *
Ctrl-P * *
* TV indicates a number from zero to nine. * To enter a control character, first enter Ctrl-P, and then enter the control
r
character.
The TPW Command-line Compiler T h e T u r b o Pascal f o r W i n d o w s c o m m a n d - l i n e c o m p i l e r ( T P C W . E X E ) lets y o u i n v o k e all t h e f u n c t i o n s o f t h e I D E c o m p i l e r ( T P W . E X E ) f r o m t h e D O S c o m m a n d line.
1 — G e t t i n g Started
TPCW
T u r b o Pascal f o r W i n d o w s c o m m a n d - l i n e o p t i o n s u s e this s y n t a x : [options] < f i l e name> [options]
where [ o p t i o n s ] can be o n e or m o r e options, separated by spaces. Y o u d e s i g n a t e t h e status o f t h e c o m p i l e r o p t i o n b y s p e c i f y i n g a p l u s ( + ) o r a m i n u s (-) after t h e o p t i o n . • P l a c e a + (or a s p a c e ) after a n o p t i o n t o t u r n it O n . • P l a c e a - after t h e o p t i o n t o t u r n it Off.
Table Option
1.7. Compiler
options.
Meaning Directive
/$A
Align data
/$B
Boolean evaluation
/$D
Debug
options
information
/$F
F o r c e F A R calls
/$G
Generate 286
/$!
Input/Output checking
/$L
Local Symbol
instructions
information
/$N
80x87 C o d e (numeric coprocessor)
/$R
Range checking
/$S
Stack-overflow checking
/$V
String variable c h e c k i n g
/$W
Windows
/$X
E x t e n d e d syntax
/B
B u i l d all
/F
Find error
/L
Link buffer
stack f r a m e
Mode
options
/M
Make
/Q
Quiet (no I D E equivalent)
/D
Conditional defines
Conditional
defines
option
continues
39
40
P a r t i — W o r k i n g with T P W
Table
1.7.
Option
continued Meaning Debug
options
/G
. M A P file
/V
D e b u g information in E X E o p t i o n Directory
options
/E
E X E a n d T P U directory
/I
Include directories
/O
O b j e c t Files d i r e c t o r i e s
/R
Resource directories
/T
T u r b o directory
/U
Unit directories
Most of the command-line options have equivalent m e n u c o m m a n d s . Table
1.8.
Command-line
options
and
their IDE
equivalents.
Option
IDE
Equivalent
/$A
Options/Compiler/Align data
/$B
Options/Compiler/Boolean evaluation
/$D
Options/Compiler/Debug information
/$¥
O p t i o n s / C o m p i l e r / F o r c e far calls
/$G
Options/Compiler/286 code
/$!
Options/Compiler/I/O checking
/$L
Options/Compiler/local symbols
/$M
O p t i o n s / C o m p i l e r / M e m o r y sizes
/$N
Options/Compiler/80x87 code
/$R
Options/Compiler/Range checking
/$S
Options/Compiler/Stack checking
/$V
Options/Compiler/String Variable C h e c k i n g O p t i o n s
/$W
Options/Compiler/Windows Stack Frames
/$X
Options/Compiler/Extended Syntax
/B
Compile/Build
1 — G e t t i n g Started
Option
IDE
Equivalent
ID
Options/Compiler/Conditional Defines
IE
Options/Directories/EXE and T P U Directory
/F
Search/Find Error
/G
O p t i o n s / L i n k e r / M a p File
/I
Options/Compiler/lnclude Directories
IL
Options/Linker/Link Buffer
/M
Compile/Make
/O
Options/Directories/Object Directories
/Q
(none)
/R
Options/Directories/Resource Directories
IT
(none)
/U
Options/Directories/Unit Directories
/V
Options/Linker/Debug Information in E X E
Onward, Forward, and Upward T u r b o Pascal f o r W i n d o w s is a f l e x i b l e , p o w e r f u l a p p l i c a t i o n d e v e l o p m e n t e n v i r o n m e n t for M i c r o s o f t W i n d o w s , c o m p l e t e w i t h e d i t o r , c o m p i l e r , d e b u g g e r , l i n k e r , a n d a p o w e r f u l library o f o b j e c t s a n d t o o l s . Y o u d o n ' t h a v e t o b e a W i n d o w s o r T u r b o P a s c a l e x p e r t t o u s e T u r b o Pascal for W i n d o w s ; i n s t e a d it helps y o u b e c o m e the W i n d o w s expert. A T u r b o Pascal for W i n d o w s a p p l i c a t i o n is l i m i t e d o n l y b y y o u r i m a g i n a t i o n . Y o u c a n u s e u n i t s a n d libraries t o c r e a t e l a r g e a n d p o w e r f u l W i n d o w s applications using either the I D E or the command-line compiler. I n t h e n e x t f e w h u n d r e d p a g e s , I'll s h o w y o u just h o w e a s y a n d f u n it c a n b e t o c r e a t e W i n d o w s a p p l i c a t i o n s T u r b o Pascal style, u s i n g t h e p o w e r a n d flexibility o f o b j e c t - o r i e n t e d p r o g r a m m i n g t e c h n i q u e s . S o u n d easy? It is. I n t h e n e x t c h a p t e r , y o u w i l l g o t o it!
41
2 CHAPTER
ELEMENTS OF APPLICATION DEVELOPMENT Your Windows program doesn't interact directly with the screen, keyboard, printer, or any other device. Windows does all that, and places the results in an application message queue (in a device-independent fashion). Lee and Mark Atkinson If y o u h a v e p r o g r a m m e d i n a n y l a n g u a g e , y o u u n d o u b t e d l y h a v e y o u r o w n i d e a s a b o u t h o w t o d e v e l o p a n a p p l i c a t i o n , w h e t h e r it is f o r W i n d o w s o r o t h e r w i s e . T o develop an application for W i n d o w s , y o u have to learn h o w W i n d o w s works, b u t o n l y at a n easy l e v e l . Y o u a l s o h a v e t o p r e p a r e y o u r a p p l i c a t i o n t o r u n i n a W i n d o w s w i n d o w a n d y o u h a v e t o t h i n k (at least s o m e w h a t ) i n t e r m s o f e v e n t s . T h e b e a n s a n d rice o f a W i n d o w s a p p l i c a t i o n is w h a t y o u are u s e d t o : c o d e f o r s o l v i n g p r o b l e m s — c o d e that m a n i p u l a t e s i n f o r m a t i o n (or d a t a ) . T h e biggest difference b e t w e e n developing a D O S application and a W i n d o w s a p p l i c a t i o n is that, w i t h D O S , y o u are r e q u i r e d t o c r e a t e y o u r o w n u s e r i n t e r f a c e ( u n l e s s y o u are w r i t i n g a p r i m i t i v e a p p l i c a t i o n o r o n e that d o e s n o t r e q u i r e a n i n t e r f a c e ) . If y o u are w r i t i n g a W i n d o w s a p p l i c a t i o n , y o u m u s t "connect" to the W i n d o w s G U I (graphical user interface), but y o u d o not have t o c r e a t e it. Y o u u s e t h e W i n d o w s I n t e r f a c e , a n d y o u c o n t i n u e t o u s e m o s t o f what y o u already k n o w about p r o g r a m m i n g .
44
Part I — W o r k i n g w i t h T P W
T o use a W i n d o w s application to solve a p r o b l e m , y o u have to 1. I n t e r a c t w i t h W i n d o w s ( m o s t l y u s i n g O b j e c t W i n d o w s ) . 2. G e t i n f o r m a t i o n i n t o t h e a p p l i c a t i o n (the i n p u t c o m p o n e n t ) . 3. S t o r e i n f o r m a t i o n (the d a t a c o m p o n e n t ) . 4. M a n i p u l a t e t h e i n f o r m a t i o n , u s i n g p r o c e d u r e s , f u n c t i o n s , o r o b j e c t m e t h o d s (the o p e r a t i o n s c o m p o n e n t ) . 5. G e t t h e r e s u l t s (the o u t p u t c o m p o n e n t ) . T h e s e s t e p s are s t r a i g h t f o r w a r d a n d p r o b a b l y familiar t o y o u , e x c e p t f o r the W i n d o w s connection. T o connect with W i n d o w s , use ObjectWindows, the T u r b o P a s c a l for W i n d o w s O O P library. O b j e c t W i n d o w s is a n o b j e c t - o r i e n t e d library, p a c k a g e d w i t h T u r b o Pascal for W i n d o w s , that greatly s i m p l i f i e s W i n d o w s applications development by encapsulating (packaging) c o m p l e x W i n d o w s i n f o r m a t i o n i n a s i m p l e r , m o r e easily a c c e s s i b l e f o r m . T o h a n d l e a c t i o n s 2 t h r o u g h 5, y o u s t r u c t u r e y o u r a p p l i c a t i o n a l o n g traditional "structured" p r o g r a m m i n g lines. Y o u use conditional statements ( I t s ) and l o o p s ( w h i l e s , r e p e a t s , and so o n ) . Y o u divide groups o f instructions i n t o s e c t i o n s that c a n b e r e f e r e n c e d b y n a m e ( p r o c e d u r e s , f u n c t i o n s , o b j e c t s ) . T h i s a g a i n is p r o g r a m m i n g as y o u p r o b a b l y a l r e a d y k n o w it ( w h e t h e r y o u p r o g r a m i n Pascal o r a n o t h e r similarly s t r u c t u r e d l a n g u a g e s u c h as C o r C + + ) . T u r b o Pascal for W i n d o w s , like T u r b o P a s c a l for D O S , s u p p l i e s a r i c h set o f d a t a t y p e s a n d b u i l t - i n o p e r a t o r s , c o n t r o l s , p r o c e d u r e s , a n d f u n c t i o n s for m a n i p u l a t i n g i n f o r m a t i o n . T u r b o Pascal for W i n d o w s lets y o u c r e a t e l a r g e a p p l i c a t i o n s b y d i v i d i n g a n y p r o g r a m (or a p p l i c a t i o n ) i n t o p i e c e s (units) that c a n b e c o m p i l e d separately. T h e r e m a i n d e r o f this c h a p t e r briefly c o v e r s s o m e o f t h e b a s i c a s p e c t s o f T u r b o Pascal for W i n d o w s a n d its d e v e l o p m e n t c a p a b i l i t i e s . If y o u a l r e a d y k n o w T u r b o P a s c a l , f e e l free t o s k i p this s e c t i o n a n d m o v e o n t o t h e n e x t c h a p t e r , w h e r e y o u learn h o w to develop W i n d o w s applications using the objectoriented techniques of O b j e c t W i n d o w s . (You will not see any Windows-specific c o d e u n t i l t h e n e x t c h a p t e r . ) If y o u w a n t m o r e i n f o r m a t i o n a b o u t t h e s t a n d a r d (or built-in) T u r b o Pascal for W i n d o w s p r o c e d u r e s a n d f u n c t i o n s , c h e c k o u t t h e reference section.
Units T o d e v e l o p a n y T u r b o Pascal for W i n d o w s a p p l i c a t i o n , y o u m u s t u s e at least o n e T u r b o Pascal for W i n d o w s s t a n d a r d u n i t , b u t y o u c a n u s e m a n y m o r e u n i t s if y o u h a v e t o (either s t a n d a r d o n e s o r u n i t s y o u c r e a t e ) . A unit is a c o l l e c t i o n o f c o n s t a n t s , d a t a t y p e s , v a r i a b l e s , p r o c e d u r e s , a n d f u n c t i o n s . I n a n u t s h e l l , a u n i t is t h e basis o f m o d u l a r p r o g r a m m i n g i n T u r b o Pascal for D O S a n d T u r b o Pascal for W i n d o w s . Y o u u s e u n i t s t o c r e a t e libraries a n d to divide large applications into logically related m o d u l e s .
2—Elements of Application Development
T u r b o Pascal for W i n d o w s supplies t h e following standard units: Strings System
WinCrt WinDOS WinProcs WinTypes T h e s e standard units (which are stored in TPW.TPL) support y o u r T u r b o Pascal for W i n d o w s applications in m a n y ways, taking m u c h o f the w o r k o u t o f developing applications. T h e Strings unit s u p p o r t s a type o f character strings called nullterminated strings. N u l l - t e r m i n a t e d strings a r e t h e t y p e o f strings r e q u i r e d b y t h e W i n d o w s A p p l i c a t i o n P r o g r a m m i n g I n t e r f a c e (API). (Previously, T u r b o P a s c a l d i d n o t s u p p o r t n u l l - t e r m i n a t e d strings.) T h e S y s t e m u n i t ( S Y S T E M . T P U ) is t h e T u r b o P a s c a l f o r W i n d o w s r u n - t i m e library. It i m p l e m e n t s l o w - l e v e l , r u n - t i m e s u p p o r t r o u t i n e s ( p r o c e d u r e s a n d f u n c t i o n s ) f o r all t h e b u i l t - i n T u r b o P a s c a l f o r W i n d o w s " f e a t u r e s , " s u c h as file I n p u t / O u t p u t , floating p o i n t o p e r a t i o n s , s t r i n g - h a n d l i n g , a n d d y n a m i c m e m o r y allocation. All units a n d programs automatically u s e the System unit, so y o u d o not h a v e t o s p e c i f y it i n a uses d e c l a r a t i o n . ( Y o u l e a r n m o r e a b o u t t h e uses d e c l a r a t i o n i n this s e c t i o n ) . T h e WinCrt u n i t i m p l e m e n t s a t e r m i n a l - l i k e text s c r e e n i n a w i n d o w . Y o u d o n o t h a v e t o w r i t e " W i n d o w s - s p e c i f i c " c o d e if y o u r a p p l i c a t i o n u s e s WinCrt. I n m a n y c a s e s , y o u c a n start w i t h T u r b o P a s c a l f o r W i n d o w s q u i c k l y b y t r a n s l a t i n g e x i s t i n g T u r b o P a s c a l (for D O S ) c o d e a n d u s i n g t h e WinCrt s c r e e n t o " r u n " it. Y o u w i l l l e a r n h o w t o u s e WinCrt i n t h e n e x t c h a p t e r . T h e WinDos u n i t i m p l e m e n t s o p e r a t i n g s y s t e m a n d file-handling p r o c e dures a n d functions. T h e s e p r o c e d u r e s a n d functions are specific t o T u r b o Pascal a n d are n o t d e f i n e d b y standard Pascal. T h e WinProcs u n i t d e f i n e s f u n c t i o n a n d p r o c e d u r e h e a d e r s f o r t h e W i n d o w s A P I . Y o u c a n a c c e s s e v e r y f u n c t i o n i n t h e s t a n d a r d W i n d o w s libraries t h r o u g h WinProcs. T h e WinProcs a n d WinTypes u n i t s b o t h d e f i n e t h e T u r b o Pascal for W i n d o w s i m p l e m e n t a t i o n o f t h e W i n d o w s API. T h e WinTypes u n i t d e f i n e s T u r b o P a s c a l v e r s i o n s o f all t h e t y p e s u s e d b y the W i n d o w s API functions, including simple types a n d data structures (records, a n d s o o n ) a n d all t h e s t a n d a r d W i n d o w s c o n s t a n t s , i n c l u d i n g flags, m e s s a g e s , a n d styles. Units are b o t h conceptually a n d pragmatically important because • T h e y are p r e c o m p i l e d s o y o u c a n u s e the functions, p r o c e d u r e s , a n d so o n in a unit without recompiling the unit each time y o u compile a n o t h e r part o f y o u r a p p l i c a t i o n . T h u s , u n i t s save t i m e .
45
46
Part I—Working with T P W
• U n i t s a l s o let y o u b r e a k u p f u n c t i o n a l i t y for s e p a r a t e d e v e l o p m e n t , modification, a n d u s e . Projects thus c a n b e large a n d their d e v e l o p ment a n d m a n a g e m e n t simplified. U n i t s are nifty, u s e f u l s t r u c t u r e s that c h a n g e t h e w a y y o u r T u r b o Pascal f o r W i n d o w s a p p l i c a t i o n c o d e is s t o r e d i n m e m o r y . C o n s i d e r first h o w a c o m p i l e d T u r b o Pascal for W i n d o w s a p p l i c a t i o n ( w i t h o u t u n i t s ) s t o r e s itself i n m e m o r y . It d i v i d e s itself i n t o f o u r m a i n s e c t i o n s : 1. C o d e s e g m e n t 2. D a t a s e g m e n t 3. S t a c k s e g m e n t 4.
Heap
The code segment contains the application's procedures, functions, a n d the main program body of the application. T h e d a t a segment contains the a p p l i c a t i o n ' s g l o b a l variables a n d c o n s t a n t s . T h e s t a c k s e g m e n t c o n t a i n s r e t u r n a d d r e s s e s for t h e a p p l i c a t i o n s ' f u n c t i o n s a n d p r o c e d u r e s a n d m o s t o f t h e l o c a l variables d e c l a r e d i n s i d e f u n c t i o n s a n d p r o c e d u r e s . T h e heap c o n t a i n s a n y variables y o u c r e a t e d y n a m i c a l l y u s i n g t h e T u r b o Pascal for W i n d o w s k e y w o r d , New. E a c h s e c t i o n ( c o d e , d a t a , a n d s t a c k s e g m e n t s ) c a n u s e as m u c h as 6 4 K (kilobytes) o f m e m o r y , a n d t h e h e a p c a n g r o w as l a r g e as available m e m o r y a l l o w s . F i g u r e 2.1 s h o w s a m e m o r y m a p o f this s c h e m e .
Memory Map W i t h o u t units
High Memory
Heap
?K
Stack Segment
64K
Data Segment
64K
Code Segment
64K
Low Memory
Figure
2.1. A memory map of three segments, plus the heap.
2—Elements of Application Development
Without u n i t s , a c o m p i l e d T u r b o P a s c a l f o r Windows application can be a b o u t 1 9 2 K p l u s t h e h e a p ( w h o s e size d e p e n d s o n t h e n u m b e r o f d y n a m i c a l l y allocated variables). In c o n t r a s t , t h e p r o c e d u r e s a n d f u n c t i o n s i n a u n i t are s t o r e d i n s e p a r a t e s e g m e n t s apart f r o m t h e m a i n m o d u l e . E a c h u n i t c a n u s e as m u c h as 6 4 K o f m e m o r y . T h u s , a n a p p l i c a t i o n that u s e s u n i t s c a n c o n s i s t o f as m a n y o f t h e s e 6 4 K u n i t s as m e m o r y (the s y s t e m ' s , n o t y o u r s ) a l l o w s . O f c o u r s e , a p p l i c a t i o n s that u s e u n i t s c a n b e l a r g e . F i g u r e 2.2 s h o w s a m e m o r y m a p o f a n a p p l i c a t i o n segmented into units.
Memory Map
High memory
Heap
?K
Stack Segment
64K
Data Segment
64K
Unit
64K
Unit
64K
Code Segment
with units
64K
Low memory
Figure 2.2. A memory map of units.
T o u s e a s t a n d a r d ( o r p r e c o m p i l e d ) unit, a d d a u s e s d e c l a r a t i o n at the b e g i n n i n g o f the m a i n m o d u l e o f y o u r a p p l i c a t i o n : Program
Main;
uses WinCrt; {
....
body h e r e
...
}
T o use m o r e than o n e unit, separate the units by c o m m a s : Program
Main;
uses WinTypes, Strings,
47
48
Parti—Working with T P W
WinProcs, WObjects; { ... body here ... } Y o u u s e t h e s t a n d a r d T u r b o P a s c a l for W i n d o w s u n i t s t h r o u g h o u t this b o o k , a n d t h e y a r e d i s c u s s e d i n m o r e d e t a i l as y o u m o v e a l o n g . C r e a t i n g y o u r o w n u n i t s is s i m i l a r t o c r e a t i n g t h e main m o d u l e o f a n application, with a couple of exceptions: 1. R a t h e r t h a n d e s i g n a t e t h e m o d u l e as a p r o g r a m , y o u d e s i g n a t e it as a unit:
Unit YourUnit; 2. Y o u also divide the unit into parts: Unit heading I n t e r f a c e part I m p l e m e n t a t i o n part I n i t i a l i z a t i o n part T h e unit h e a d i n g specifies t h e unit's n a m e (the n a m e y o u u s e w h e n y o u refer t o this u n i t i n a n o t h e r m o d u l e ' s Uses d e c l a r a t i o n ) . T h e i n t e r f a c e part d e c l a r e s c o n s t a n t s , t y p e s , v a r i a b l e s , p r o c e d u r e s , a n d f u n c t i o n s that a r e p u b l i c (available t o a n y m o d u l e that u s e s t h e u n i t ) . List t h e p r o c e d u r e s a n d f u n c t i o n s as h e a d i n g s o n l y i n t h e i n t e r f a c e part. T h e i m p l e m e n t a t i o n part d e f i n e s t h e b o d i e s o f all p u b l i c p r o c e d u r e s a n d f u n c t i o n s . I n a d d i t i o n , it d e c l a r e s c o n s t a n t s , t y p e s , v a r i a b l e s , p r o c e d u r e s , a n d f u n c t i o n s that a r e p r i v a t e a n d , t h u s , a r e n o t available t o u s e r s o f t h e u n i t . T h e i n i t i a l i z a t i o n part is t h e last part o f a u n i t . It c o n s i s t s o f e i t h e r : • T h e r e s e r v e d w o r d end ( n o i n i t i a l i z a t i o n c o d e ) or • A s t a t e m e n t part t o b e e x e c u t e d t o initialize t h e u n i t L i s t i n g 2.1 s h o w s t h e l a y o u t o f a u n i t . Listing
2.1. The general
Unit YourUnit; Interface { Use something here }
layout
of a
unit.
2 — E l e m e n t s o f Application D e v e l o p m e n t
{ CONST, TYPE, VAR declarations here } { PROCEDURE and FUNCTION declarations here } Implementation { Another Use here, if you want it } { Any Private LABEL, CONST, TYPE, VAR declarations here } { Procedure and function bodies here } Begin { Initialization statements } End.
49
50
Part I — W o r k i n g w i t h T P W
T u r b o P a s c a l f o r W i n d o w s h a n d l e s u n i t s i n t e l l i g e n t l y . F o r e x a m p l e , if several m o d u l e s (or u n i t s ) i n a n a p p l i c a t i o n refer t o t h e s a m e u n i t , o n l y o n e c o p y o f that u n i t — n o t s e v e r a l — i s l o a d e d i n t o m e m o r y .
Data Types and Identifiers Application d e v e l o p m e n t begins a n d e n d s with variables. W h e n e v e r d e c l a r e a v a r i a b l e , y o u m u s t specify its t y p e . T h e v a r i a b l e t y p e i n d i c a t e s
you
• T h e range o f values the variable can take • T h e o p e r a t i o n s that c a n b e p e r f o r m e d o n it W h e n y o u s p e c i f y a t y p e (in a t y p e d e c l a r a t i o n ) y o u specify a n i d e n t i f i e r that d e n o t e s a t y p e . Y o u u s e identifiers t h r o u g h o u t y o u r a p p l i c a t i o n , a n d a T u r b o Pascal f o r W i n d o w s identifier c a n d e n o t e any o f the following: •
Constants
• Fields in records •
Functions
•
Labels
•
Procedures
•
Programs
•
Types
•
Units
•
Variables
I d e n t i f i e r s c a n b e a n y l e n g t h , b u t o n l y t h e first 6 3 c h a r a c t e r s are significant ( r e c o g n i z e d b y T u r b o Pascal for W i n d o w s ) . Y o u have to f o l l o w a f e w rules w h e n y o u u s e identifiers: • T h e first c h a r a c t e r o f a n i d e n t i f i e r m u s t b e a letter. • T h e c h a r a c t e r s that f o l l o w t h e first c h a r a c t e r m u s t b e letters, d i g i t s , o r underscores (no spaces). • I d e n t i f i e r s are n o t c a s e - s e n s i t i v e . A s this c h a p t e r states, a p p l i c a t i o n s d e v e l o p m e n t b e g i n s a n d e n d s w i t h v a r i a b l e s . V a r i a b l e s m u s t b e t y p e d i n T u r b o P a s c a l . It is h e l p f u l t o d i v i d e t h e s e t y p e s i n t o six m a j o r c l a s s e s , w h i c h are c o v e r e d n e x t . F o r m o r e i n - d e p t h i n f o r m a t i o n a b o u t T u r b o Pascal for W i n d o w s t y p e s , c o n s u l t t h e T u r b o P a s c a l for Windows manuals.
2—Elements of Application Development
Qualified Identifiers W h e n your application declares several instances of the same identifier, you might have to qualify the identifier by specifying a unit identifier to select the correct instance of the identifier. The combined Unit. Identifier specification is called a identifier.
qualified
For example, the following are qualified identifiers: System. Exit
(unit = System, identifier = Exit)
Dos. Exec (unit = Dos, identifier = Exec ) Crt .Window
( unit = Crt, identifier = Window)
Y o u c a n d i v i d e t y p e s as f o l l o w s : 1. S i m p l e t y p e s that d e f i n e o r d e r e d sets o f v a l u e s : A. Ordinal types, which
include:
Integer types B o o l e a n types C h a r type E n u m e r a t e d types Subrange types B. Real types 2. String t y p e s that represent a s e q u e n c e o f characters w i t h a d y n a m i c l e n g t h attribute a n d a c o n s t a n t size attribute. 3. S t r u c t u r e d t y p e s that hold m o r e t h a n o n e v a l u e . T h e s e
include:
Array t y p e s Record types O b j e c t types Set types File t y p e s 4. P o i n t e r t y p e s that d e f i n e a set o f v a l u e s that p o i n t t o d y n a m i c variables o f s o m e t y p e . A d y n a m i c variable is o n e that is a l l o c a t e d o n t h e heap a n d m a n i p u l a t e d u s i n g p o i n t e r s . B e c a u s e t h e heap c a n b e q u i t e large ( m u c h larger t h a n a s t a c k a l l o c a t e d in t h e d a t a s e g m e n t , w h i c h is l i m i t e d t o 6 4 K ) , d y n a m i c variables a l s o c a n b e q u i t e l a r g e . 5. P r o c e d u r a l t y p e s that a l l o w p r o c e d u r e s a n d f u n c t i o n s t o b e t r e a t e d as o b j e c t s . A n o b j e c t , w h i c h y o u l e a r n m u c h m o r e a b o u t t h r o u g h o u t this
51
52
Part I — W o r k i n g w i t h T P W
b o o k , c o n s i s t s o f d a t a a n d t h e p r o c e d u r e s a n d f u n c t i o n s that y o u u s e t o m a n i p u l a t e that d a t a . F o r e x a m p l e :
AWindow = object x1, x2, y1, y2 :Integer; procedure minimize; procedure maximize; end; 6. O b j e c t t y p e s are s t r u c t u r e s that c o n s i s t o f a f i x e d n u m b e r o f c o m ponents.
Ordinal Types T u r b o Pascal h a s n i n e p r e d e f i n e d o r d i n a l t y p e s . Five o f t h e s e i n t e g e r t y p e s d e n o t e a specific subset o f the w h o l e n u m b e r s : Type
Range
Size
Shortint
1 2 8 . . 127
8-bit
Integer
-32768.32767
16-bit
Longint
-2147483648. .2147483647
32-bit
Byte
0.255
8-bit
Word
0.65535
16-bit
T h e o t h e r f o u r p r e d e f i n e d o r d i n a l t y p e s are t h e B o o l e a n s WordBool, LongBool), and Char.
(Boolean,
T w o o t h e r classes o f u s e r - d e f i n e d o r d i n a l t y p e s are e n u m e r a t e d t y p e s a n d subrange types. T h r e e s t a n d a r d f u n c t i o n s c a n b e u s e d w i t h all o r d i n a l t y p e s : 1. Ord ( w h i c h r e t u r n s t h e o r d i n a l i t y o f t h e v a l u e ) . F o r e x a m p l e : Ord(False)
= 0;
2. P r e d ( w h i c h r e t u r n s t h e p r e d e c e s s o r o f t h e v a l u e ) . F o r e x a m p l e : Pred(True)
=
False;
3. S u c c ( w h i c h r e t u r n s t h e s u c c e s s o r o f t h e v a l u e ) . F o r e x a m p l e : Succ(True)
=
False;
Boolean Types T u r b o Pascal for W i n d o w s has three p r e d e f i n e d B o o l e a n types: B o o l e a n , W o r d B o o l , a n d L o n g B o o l , w h i c h are d e f i n e d as f o l l o w s :
2—Elements of Application Development
type Boolean = (False, True); WordBool = (False, True); LongBool = (False, True); T h e s e t y p e s h a v e t h e f o l l o w i n g sizes: • Boolean is b y t e - s i z e d (8 b i t s ) . • WordBool is w o r d - s i z e d ( 1 6 b i t s ) . • LongBool is longint-sized (32 b i t s ) . B e c a u s e B o o l e a n s a r e e n u m e r a t e d o r d i n a l t y p e s , t h e following r e l a t i o n s h i p s exist a m o n g B o o l e a n t y p e s : T r u e > False Ord(False)
= 0
Ord(True) = 1 Succ(False) = T r u e Pred(True) = F a l s e A m o n g t h e " B o o l e a n s , " Boolean is t h e p r e f e r r e d t y p e a n d u s e s t h e least m e m o r y . WordBool a n d LongBool exist p r i m a r i l y for c o m p a t i b i l i t y w i t h y o u r applications in the Windows environment. I n a n e x p r e s s i o n , t h e following r e l a t i o n a l o p e r a t o r s p r o d u c e r e s u l t s o f t y p e Boolean:
>
= < = IN For W i n d o w s compatibility, Booleans c a n assume ordinal values other t h a n z e r o a n d o n e . A B o o l e a n e x p r e s s i o n is c o n s i d e r e d false w h e n its o r d i n a l v a l u e is z e r o , a n d t r u e w h e n its o r d i n a l v a l u e is n o n z e r o .
Char Type U s e variables o f t h e o r d i n a l t y p e C h a r t o s t o r e A S C I I c h a r a c t e r s . W r i t e c h a r a c t e r c o n s t a n t s b e t w e e n s i n g l e q u o t a t i o n s , as i n t h e f o l l o w i n g :
5 3
54
Part I — W o r k i n g w i t h T P W
'9'
'A' 'L' 'i' '&' T h e s i n g l e q u o t a t i o n c h a r a c t e r is w r i t t e n as t w o s i n g l e q u o t a t i o n s w i t h i n s i n g l e q u o t a t i o n s , like t h i s : i
i
i i
T h e Chr f u n c t i o n c o n v e r t s a n i n t e g e r v a l u e i n t o a c h a r a c t e r w i t h t h e corresponding ASCII value. T h e Ord f u n c t i o n r e t u r n s a c h a r a c t e r ' s A S C I I v a l u e .
Enumerated Types E n u m e r a t e d t y p e s d e f i n e o r d e r e d sets o f v a l u e s b y e n u m e r a t i n g t h e i d e n t i f i e r s that d e n o t e t h e v a l u e s . T h e i r o r d e r i n g is d e t e r m i n e d b y t h e s e q u e n c e i n w h i c h the identifiers are e n u m e r a t e d . For example:
type Food = (Apple, Kiwi, Peach, Date); I n this d e c l a r a t i o n , Kiwi is a c o n s t a n t o f t y p e Food. T h e Ord s t a n d a r d f u n c t i o n r e t u r n s t h e o r d i n a l i t y o f a n e n u m e r a t e d c o n s t a n t . I n this e x a m p l e :
Ord (Apple) Ord(Kiwi) Ord(Peach) Ord(Date)
= = = =
0 1 2 3
T h e identifiers in the type definition b e c o m e constants o f the e n u m e r a t e d type. T h e first c o n s t a n t h a s a n o r d i n a l i t y o f z e r o , t h e s e c o n d h a s a n o r d i n a l i t y o f o n e , the third a n ordinality o f t w o , a n d s o o n .
Subrange Types A s u b r a n g e t y p e is a r a n g e o f v a l u e s f r o m a n o r d i n a l t y p e s o m e t i m e s c a l l e d t h e host type. For example:
LittleConstant .. BiggerConstant
2—Elements of Application Development
specifies t h e s m a l l e s t a n d largest v a l u e in t h e s u b r a n g e . I n this c a s e , t h e s u b r a n g e is f r o m L i t t l e C o n s t a n t t o B i g g e r C o n s t a n t . B o t h c o n s t a n t s m u s t b e o f t h e s a m e o r d i n a l t y p e , a n d t h e first c o n s t a n t m u s t b e less t h a n o r e q u a l t o t h e s e c o n d c o n s t a n t . T h e $R c o m p i l e r directive c o n t r o l s range-checking of subrange types. T h e f o l l o w i n g are s u b r a n g e e x a m p l e s :
0. .49 -128..127
Reals A real t y p e has a set o f v a l u e s that is a s u b s e t o f t h e real n u m b e r s , w h i c h c a n b e represented in f l o a t i n g - p o i n t n o t a t i o n w i t h a f i x e d n u m b e r o f digits. A v a l u e ' s floating-point n o t a t i o n n o r m a l l y c o n s i s t s o f three v a l u e s : M, B, a n d E, s u c h that M x B E = N w h e r e B is always 10, M is a rational n u m b e r , a n d E is a n integer in t h e real t y p e ' s range. T u r b o P a s c a l f o r Windows s u p p l i e s f o u r p r e d e f i n e d real t y p e s . E a c h t y p e has a specific range a n d p r e c i s i o n :
Type
Range
Digits
Bytes
Real
2.9e-39..1.7e38
11-12
6
Single
1.5e-45..3.4e38
7-8
4
Double
5.0e-324..1.7e308
15-16
8
Extended
3.4e-4932..1.1e4932
19-20
10
N o t e : T u r b o Pascal f o r W i n d o w s s u p p o r t s t w o m o d e l s o f floating-point code generation: 1. S o f t w a r e
floating
point
2. 8 0 x 8 7 floating p o i n t U s e t h e $N c o m p i l e r d i r e c t i v e t o s w i t c h b e t w e e n t h e t w o models.
Strings A T u r b o Pascal string t y p e v a r i a b l e ( n o t a n u l l - t e r m i n a t e d string t y p e ) is a s e q u e n c e o f c h a r a c t e r s w i t h a d y n a m i c l e n g t h , a n d a c o n s t a n t m a x i m u m size between 1 and 255.
5 5
56
Parti—Working with T P W
If y o u d e c l a r e a string w i t h o u t a m a x i m u m size, it a u t o m a t i c a l l y b e c o m e s a size o f 2 5 5 . S t r i n g c o n s t a n t s a r e w r i t t e n i n q u o t a t i o n s ; for e x a m p l e :
'Windows
1
'Bible' N o t i c e that t w o c o n s e c u t i v e s i n g l e q u o t a t i o n s a r e u s e d t o i n d i c a t e a s i n g l e q u o t a t i o n i n a string. T h e f o l l o w i n g o p e r a t o r s c a n b e u s e d w i t h string t y p e v a l u e s :
+
< > < = > = O p e r a t o r s c o m p a r e strings b y u s i n g t h e A S C I I c o d e s for letters a n d n u m b e r s . F o r e x a m p l e , t h e A S C I I c o d e for Af is 7 7 a n d 7* is 8 4 . T h u s , a string b e g i n n i n g w i t h a n M is less t h a n o n e b e g i n n i n g w i t h a T. T h e A S C I I c o d e for a l o w e r c a s e ra, h o w e v e r , is 1 0 9 . T h u s , a n u p p e r c a s e 7*is less t h a n a l o w e r c a s e m. K e e p this i n m i n d w h e n y o u c o m p a r e s t r i n g s .
Structured Types A structured type c a n h o l d m o r e than o n e value. Structured types are • Array (types) • File (types) • O b j e c t (types) • R e c o r d (types) • S e t (types) If a c o m p o n e n t t y p e is s t r u c t u r e d , t h e r e s u l t i n g s t r u c t u r e d t y p e h a s m o r e t h a n o n e l e v e l o f s t r u c t u r i n g a n d c a n , i n fact, h a v e u n l i m i t e d levels o f structuring (memory permitting). In other w o r d s , a structured type c a n contain other t y p e s that a r e t h e m s e l v e s s t r u c t u r e d . T h e s e o t h e r t y p e s c a n , i n t u r n , c o n t a i n m o r e t y p e s that a l s o are s t r u c t u r e d . T h e m a x i m u m size o f a n y s t r u c t u r e d t y p e i n T u r b o Pascal is 6 5 , 5 2 0 b y t e s ( a b o u t 6 4 K ) . T h e r e s e r v e d w o r d packed i n a s t r u c t u r e d t y p e ' s d e c l a r a t i o n tells t h e c o m p i l e r t o c o m p r e s s d a t a w h e n it s t o r e s t h e t y p e . Note: T u r b o Pascal for W i n d o w s a c c e p t s t h e r e s e r v e d w o r d packed, b u t i g n o r e s it.
2—Elements of Application Development
Arrays A n array is a c o l l e c t i o n o f v a l u e s o f t h e s a m e t y p e . Arrays m a k e d a t a m u c h m o r e manageable. Y o u d e c l a r e a n array as f o l l o w s : array
[index-type]
of
element-type
T h e element type c a n b e any type, b u t the i n d e x type must b e a n ordinal t y p e . Y o u c a n u s e several i n d e x t y p e s if y o u s e p a r a t e t h e m b y c o m m a s . E a c h i n d e x t y p e s e p a r a t e d b y a c o m m a r e p r e s e n t s a d i m e n s i o n o f t h e array. For example: type CharData = array[ A ' . . Z ] of Byte; NumList = array[1..600] of Integer; Matrix = array[0..21, 0..21] of real; 1
1
1
{ 1 Dimension } { 1 Dimension } { 2 Dimensions }
Records A r e c o r d c o n t a i n s a n u m b e r o f c o m p o n e n t s , o r f i e l d s , that c a n b e o f d i f f e r e n t types. A r e c o r d d e c l a r a t i o n b e g i n s w i t h t h e k e y w o r d record a n d e n d s w i t h a n end. For example: ThisRecord = Record Month: 0 .. 12; Day : 1 .. 31; Year
: Integer;
end; A r e c o r d a l s o c a n b e variant. I n o t h e r w o r d s , a g r o u p o f r e c o r d s c a n h a v e different structures d e p e n d e n t o n a c o n d i t i o n . For example: type ClassType
= (Num, Dat, Str);
Date = record D, M, Y: Integer; end; Facts = record Name: string[10];
5 7
58
Parti—Working with T P W
case Kind: Num: (N: Dat: (D: Str: (S:
ClassType of real); Date); string);
end; D e p e n d i n g o n w h e t h e r Kind is a Num, Dat, o r Str, t h e Facts r e c o r d c o n t a i n s a n N, D, o r S d a t a f i e l d .
Object Types A n o b j e c t t y p e is a d a t a s t r u c t u r e s i m i l a r t o a r e c o r d , a l s o c o n t a i n i n g a f i x e d n u m b e r o f c o m p o n e n t s . E a c h c o m p o n e n t is e i t h e r a field ( w h i c h c o n t a i n s d a t a of a particular type) o r a m e t h o d (procedure o r function), w h i c h "operates" o n an object's data. For example: GenericObject = object Fieldl : integer; Field2 : real; procedure Methodl; procedure Method2; end;
{ Object data }
{ Object behavior }
W h e n y o u d e c l a r e a f i e l d , y o u specify a n i d e n t i f i e r that n a m e s t h e fields a n d t h e i r d a t a t y p e s . W h e n y o u d e c l a r e a m e t h o d , y o u specify a p r o c e d u r e , function, constructor, or destructor heading. Here's the scenario in somewhat formal form: Field
= FieldName(s):
Method
= procedure
type; MethodName(<parameter(s)>\type);
o r = function MethodName(<parameter(s)>:type):type; o r = constructor MethodName(<parameter(s)>:type [;<parameter(s)>: type]); /"virtual/; o r = destructor MethodName[(<parameters>\ type)/;/virtual/; A n o b j e c t t y p e c a n i n h e r i t t h e d a t a a n d b e h a v i o r (its c o m p o n e n t s ) f r o m a n o t h e r o b j e c t t y p e . T h e i n h e r i t i n g o b j e c t is a d e s c e n d a n t , a n d t h e o b j e c t that s u p p l i e s t h e d a t a a n d b e h a v i o r f o r i n h e r i t a n c e is a n a n c e s t o r .
2—Elements of Application Development
59
T h e d o m a i n o f a n o b j e c t t y p e c o n s i s t s o f itself a n d all its d e s c e n d a n t s .
Sets S e t s d e f i n e c o l l e c t i o n s o f e l e m e n t s o f a s p e c i f i c scalar o r s u b r a n g e t y p e . F o r e x a m p l e , t h e f o l l o w i n g a r e set t y p e s : type Day = (Sun, Mon, Tue, Wed, Thu, Fri, Sat); CharSet = set of Char; Digits = set of 0..4; Days = set of Day; Months = (January, February, March, April, May, June, July, August, September, October, November, December); T h e b a s e t y p e o f a set m u s t b e a n o r d i n a l t y p e w i t h n o t m o r e t h a n 2 5 6 possible values. Thus, the ordinal values of the u p p e r a n d lower b o u n d s of the base type must b e in the range 0..255. A set c o n s t r u c t o r , w h i c h d e n o t e s a set t y p e v a l u e , is f o r m e d b y w r i t i n g e x p r e s s i o n s i n b r a c k e t s . E a c h e x p r e s s i o n d e n o t e s a v a l u e o f t h e set. T h e b r a c k e t n o t a t i o n [ ] d e n o t e s t h e e m p t y s e t — c o m p a t i b l e w i t h all set types. F o r e x a m p l e , t h e f o l l o w i n g a r e set c o n s t r u c t o r s : [Mon..Sat] [1, 3, I + 1 .. J - 1] ['0'..'5', 'A'..'Q', 'd'..'z',
'_']
Files A file t y p e c o n s i s t s o f a l i n e a r s e q u e n c e o f c o m p o n e n t s o f s o m e c o m p o n e n t t y p e , w h i c h c a n b e a n y t y p e e x c e p t a file t y p e . If y o u o m i t t h e c o m p o n e n t t y p e , t h e t y p e d e n o t e s a n u n t y p e d file. T h e p r e d e f i n e d file t y p e Text signifies a file c o n t a i n i n g c h a r a c t e r s o r g a nized into lines. F o r e x a m p l e , t h e f o l l o w i n g a r e File t y p e d e c l a r a t i o n s : type Employee = record ID : Integer; FirstName: string[10]; LastName : string[20]; Address : string[40]; end;
60
Parti—Working with T P W
EmployeeFile = file of Employee; NumberFile = file of Real; SwapFile = file;
Pointer Types A pointer type variable contains t h e m e m o r y address o f a d y n a m i c variable o f s o m e "specified" base type. In other words, a pointer d o e s not contain a data v a l u e ; it c o n t a i n s a m e m o r y a d d r e s s . A p o i n t e r " p o i n t s t o " a u n i q u e l o c a t i o n i n m e m o r y . P o i n t e r s c a n p o i n t t o l o c a t i o n s that c o n t a i n b y t e v a l u e s , i n t e g e r s , r e a l s , records, strings, o r any other data type. Pointers are extremely important in object-oriented p r o g r a m m i n g a n d are u s e d t h r o u g h o u t this b o o k . A l t h o u g h y o u m i g h t t h i n k that p o i n t e r s a r e c o m p l i c a t e d c r e a t u r e s ( r u m o r h a s i t ) , t h e y are n o t . K e e p i n m i n d that a p o i n t e r holds a m e m o r y address, n o t a data value. Y o u assign data values to the a d d r e s s e s h e l d i n t h e p o i n t e r b y u s i n g t h e p o i n t e r . T h e p o i n t e r is t h e o n l y w a y y o u c a n g e t at t h e d a t a . T h i s p r o c e d u r e s o u n d s a little i n d i r e c t , b u t it is i m p o r t a n t i n b o t h o b j e c t - o r i e n t e d a n d W i n d o w s p r o g r a m m i n g , a n d it is discussed in detail t h r o u g h o u t the b o o k . Y o u c a n assign a value t o a pointer variable with: • T h e NeworGetMem p r o c e d u r e s • T h e @ operator • T h e Ptr f u n c t i o n T h e r e s e r v e d w o r d nil d e n o t e s a p o i n t e r c o n s t a n t that p o i n t s n o w h e r e . T h e p r e d e f i n e d t y p e Pointer d e n o t e s a n u n t y p e d p o i n t e r (a p o i n t e r that d o e s n o t point t o any specific type). F o r a n a p p l i c a t i o n t o u s e a p o i n t e r , it m u s t first r e q u e s t m e m o r y f o r t h e t y p e o f d a t a t h e p o i n t e r p o i n t s t o . It r e q u e s t s m e m o r y b y initializing t h e p o i n t e r w i t h New:
var APointer : "Integer; begin New(APointer); end; I n this c a s e , New reserves s p a c e f o r a n i n t e g e r v a l u e .
2—Elements of Application Development
Y o u c a n t h e n store a v a l u e at t h e a d d r e s s p o i n t e d t o b y APointer, u s i n g a caret after t h e p o i n t e r n a m e :
APointer" := 28; T h e caret indicates that y o u d o n o t w a n t t h e p o i n t e r itself (as a n a d d r e s s ) , b u t t h e v a l u e at t h e a d d r e s s p o i n t e d t o b y t h e p o i n t e r . T h i s is c a l l e d dereferencing the pointer. T h e f o l l o w i n g are p o i n t e r t y p e d e c l a r a t i o n s :
type BytePtr = "Byte; WordPtr = "Word; IdentPtr = "IdentRec; IdentRec = record Ident: string[24]; RefCount: Word; Next: IdentPtr; end; If y o u are n o t u s e d t o u s i n g p o i n t e r s , y o u m i g h t w o n d e r w h y it is w o r t h g o i n g t o t h e extra t r o u b l e o f u s i n g t h e m , b e c a u s e p o i n t e r s are, b y their n a t u r e , indirect. O n e g o o d reason t o u s e p o i n t e r s is that variables p o i n t e d t o b y p o i n t e r s u s e m e m o r y that is in t h e heap, n o t in t h e data s e g m e n t . T h e heap is d y n a m i c a n d c a n g r o w as large as it has t o ( m e m o r y p e r m i t t i n g ) . T h e data s e g m e n t is a fixed size, a n d variables in t h e data s e g m e n t are o f a fixed size as w e l l . If y o u are d e s i g n i n g a p p l i c a t i o n s s u c h as a d a t a b a s e , w h i c h has t o b e flexible a b o u t how m u c h m e m o r y it e v e n t u a l l y u s e s , p o i n t e r s a d d t h e flexibility. D a t a b a s e s , s p r e a d s h e e t s , a n d a n y t h i n g e l s e that d e p e n d s o n l i n k e d lists, trees, a n d o t h e r d y n a m i c s t r u c t u r e s rest o n p o i n t e r s . A n array m u s t have p r e c i s e d i m e n s i o n s , a n d t h u s m u s t specify in a d v a n c e (at c o m p i l e t i m e ) how m u c h m e m o r y it u s e s . V a r i a b l e s a d d r e s s e d t h r o u g h p o i n t e r s d o n o t have t o specify their e x a c t size at c o m p i l e t i m e . D e c i s i o n s c a n b e d e l a y e d u n t i l run-time—a d e f i n i t e p l u s in m a n y a p p l i c a t i o n s . F o r e x a m p l e , if o n e c o m p u t e r s y s t e m has 8 M ( m e g a b y t e s ) o f m e m o r y a n d a n o t h e r 6 4 0 K , a d a t a b a s e o r s p r e a d s h e e t that u s e s p o i n t e r s t o a l l o c a t e m e m o r y c a n utilize t h e extra m e m o r y t o create larger d a t a sets o n t h e larger s y s t e m .
PChar T h e p r e d e f i n e d t y p e PChar d e n o t e s a p o i n t e r t o a n u l l - t e r m i n a t e d string. D e c l a r e PChar as f o l l o w s :
type PChar = "Char;
61
62
Part I — W o r k i n g w i t h T P W
T u r b o Pascal f o r W i n d o w s s u p p o r t s a set o f e x t e n d e d s y n t a x r u l e s ( c o n t r o l l e d b y t h e $X c o m p i l e r directive) t o facilitate h a n d l i n g o f strings u s i n g t h e PChar t y p e .
Procedural Types S t a n d a r d Pascal r e g a r d s p r o c e d u r e s a n d f u n c t i o n s strictly as p r o g r a m p a r t s that c a n b e e x e c u t e d t h r o u g h p r o c e d u r e o r f u n c t i o n calls. T u r b o P a s c a l a n d T u r b o Pascal f o r W i n d o w s h a v e m u c h b r o a d e r v i e w s o f p r o c e d u r e s a n d functions. T h r o u g h p r o c e d u r a l types, T u r b o Pascal allows y o u t o treat p r o c e d u r e s a n d f u n c t i o n s as o b j e c t s that c a n b e a s s i g n e d t o v a r i a b l e s a n d p a s s e d as p a r a m e t e r s . A p r o c e d u r a l type declaration specifies the parameters a n d , for a function, t h e result t y p e . T h e k e y d i f f e r e n c e b e t w e e n a p r o c e d u r e a n d a f u n c t i o n is that a p r o c e d u r e d o e s n o t r e t u r n a v a l u e f o r t h e p r o c e d u r e itself. A f u n c t i o n always returns a value o f s o m e type: integer, real, a n d s o o n . T h e s y n t a x f o r a p r o c e d u r a l t y p e d e c l a r a t i o n is e x a c t l y t h e s a m e as that f o r a p r o c e d u r e o r f u n c t i o n h e a d e r , e x c e p t y o u o m i t t h e i d e n t i f i e r after t h e procedure o r function k e y w o r d . For example: type AProc = procedure; ASwapProc = procedure(var A, B: Integer); AStrProc = procedure(S: String); AMathFunc = function(A: Real): Real; ADeviceFunc = function(var F: Text): Integer; AMinFunc = function(A,B: Real; F: AMathFunc): Real; T h e p a r a m e t e r n a m e s i n a p r o c e d u r a l t y p e d e c l a r a t i o n h a v e n o effect o n the meaning o f the declaration. T u r b o P a s c a l f o r W i n d o w s d o e s n o t let y o u d e c l a r e f u n c t i o n s that r e t u r n p r o c e d u r a l t y p e v a l u e s . A f u n c t i o n result v a l u e m u s t b e a String, Real, Integer, Char, Boolean, Poinfer, o r a u s e r - d e f i n e d e n u m e r a t i o n .
Turbo Pascal for Windows Reserved Words R e s e r v e d w o r d s a r e w o r d s that h a v e f i x e d m e a n i n g s i n t h e T u r b o P a s c a l f o r W i n d o w s language. I n other w o r d s , y o u cannot redefine reserved w o r d s . Y o u m u s t u s e t h e m as t h e y a r e . T u r b o Pascal f o r W i n d o w s is n o t c a s e - s e n s i t i v e , s o y o u c a n u s e u p p e r - o r l o w e r c a s e letters t o specify r e s e r v e d w o r d s .
2—Elements of Application Development
T h e T u r b o P a s c a l f o r W i n d o w s r e s e r v e d w o r d s are as f o l l o w s :
and asm array begin case const constructor destructor div do downto else end exports file for function
goto if implementation in inline interface label library mod nil not object of or packed pointer procedure
Statements A s t a t e m e n t is o n e o f t h e f o l l o w i n g : • a s s i g n m e n t (: =)
• begin..end • case..of ..else..end • f or..to/downto..do • goto • if ..then..else • inline(...) • procedure call • repeat..until • while..do • with..do
program record repeat set shl shr string then to type unit until uses var while with xor
63
64
Part I — W o r k i n g w i t h T P W
T a b l e 2.1 s h o w s t h e o p e r a t o r p r e c e d e n c e f o r t h e m a t h e m a t i c a l , r e l a t i o n a l , a n d l o g i c a l o p e r a t o r s i n T u r b o Pascal f o r W i n d o w s . Table
2.1. Operator
precedence
Operators
from
high to low. Precedence
@, not
First ( h i g h )
*, /, d i v , m o d , a n d , s h l , s h r
Second
+ , - , or, x o r
Third
= , < > , < , > , < = , > = , in
Fourth (low)
assignment (:=) A n a s s i g n m e n t o p e r a t o r (: =) assigns t h e v a l u e o f a n e x p r e s s i o n t o a variable. T h e variable m u s t b e a s s i g n m e n t - c o m p a t i b l e w i t h t h e result t y p e o f t h e e x p r e s s i o n . T h e variable that is a s s i g n e d t h e n e w v a l u e is o n t h e left o f t h e a s s i g n m e n t o p e r a t o r . T h e v a l u e its a s s i g n e d t o is o n t h e right. For example: A := B; C[I] LoopR
{ A is assigned the value B. }
:= C[I] + 1 ;
{ C[I] is assigned the value C{I} + 1 }
:= (I > 0) and (I < 30)
{ LoopR is assigned the value that } { results from the evaluation of } { the expression on the right. }
begin..end T h e begin...end c o n s t r u c t s serve as s t a t e m e n t b r a c k e t s . For example: begin Statementl; Statement2; StatementX; end;
2—Elements of Application Development
W h e n t h e y a r e b r a c k e t e d i n this w a y , a n y n u m b e r o f c o n s e c u t i v e statem e n t s c a n b e t r e a t e d as a s i n g l e s t a t e m e n t . F o r e x a m p l e :
{Compound statement used in an ' i f statement } if First < Last then begin Temp := First; First := Last; Last := Temp; end;
case..of..else..end T h e case s t a t e m e n t c o n s i s t s o f a n e x p r e s s i o n ( t h e s e l e c t o r ) a n d a list o f statements, each prefixed with a case. F o r example, a simple case:
case AnExpression of case: Statementl; case: Statement2; end; o r a case-else: case AnExpression of case: Statementl; case: Statement2; else Statement3; end; A c a s e consists o f o n e o r m o r e constants o r ranges, separated by c o m m a s . T h e else part is o p t i o n a l . F o r e x a m p l e :
case Ch of 'A'..'Z', 'a'-.'z : WriteLn('Letter'); '0'..'9': WriteLn('Digit'); '+', '-', '*', '/': WriteLn('Operator'); else WriteLn('A Special character'); end; 1
6 5
66
Part I — W o r k i n g w i t h T P W
for..to/downto..do T h e for s t a t e m e n t c a u s e s t h e s t a t e m e n t after do to b e e x e c u t e d o n c e f o r e a c h v a l u e in the range first to last. F o r e x a m p l e , a f or-to: for Var1 := First to Last do Statementl; or for Var1 := First to last do begin Statementl; Statement2: end; o r a f or-downto: for Var1
:= First downto Last do
Statementl; T h e c o n t r o l variable a n d initial a n d final v a l u e s m u s t b e o r d i n a l t y p e s . I f y o u u s e a Downto, t h e v a l u e o f t h e c o n t r o l variable falls in increments of o n e for each l o o p . With downto, t h e v a l u e o f t h e c o n t r o l variable falls in d e c r e m e n t s b y o n e for each l o o p . For example: { for
... to, for
... downto }
for I := 1 to ParamCount do WriteLn(ParamStr(I); for I := 1 to 15 do for J := 1 to 15 do begin X := 0; for K := 1 to 15 do X := X + Matrix1[I,K] Matrix[I,J] := X; end;
* Matrix2[K,J];
goto A goto s t a t e m e n t transfers p r o g r a m e x e c u t i o n t o t h e s t a t e m e n t p r e f i x e d b y t h e l a b e l referenced in t h e s t a t e m e n t .
2—Elements of Application Development
For example:
goto ALabel T h e l a b e l m u s t b e i n t h e s a m e b l o c k as t h e goto s t a t e m e n t ; y o u c a n n o t transfer e x e c u t i o n o u t o f a p r o c e d u r e o r a f u n c t i o n . For example:
label 1, 2; goto 1
1: WriteLn ('Something can happen here'); 2: WriteLn ('Something different here');
i£.then..else I f, t h e n, a n d else specify t h e c o n d i t i o n s u n d e r w h i c h a s t a t e m e n t is e x e c u t e d . F o r e x a m p l e , a s i m p l e if-then:
if AnExpression then Statementl; or
if AnExpression then begin Statementl; Statement2; end; O r a n if-then-else: if AnExpression then Statementl else Statement2; If t h e B o o l e a n e x p r e s s i o n after t h e if is t r u e , t h e s t a t e m e n t after then is e x e c u t e d . O t h e r w i s e , if t h e r e is a n else part, t h e s t a t e m e n t after else is executed. For example:
{ 'if statements } if (X < Min) or (X > Max) then X := 0;
67
68
Parti—Working with T P W
if ParamCount 2 then begin WriteLn('Can not execute the command l i n e ) ; Halt(1); end else begin ReadFile(ParamStr(1)); WriteFile(ParamStr(2)); end; 1
inline(...) Inline s t a t e m e n t s a n d directives a l l o w y o u t o insert m a c h i n e - c o d e i n s t r u c t i o n s directly i n t o t h e c o d e o f a m a i n p r o g r a m m o d u l e o r a u n i t . For example: inline
(data/data/...data)
If y o u u s e inline as a s t a t e m e n t , t h e inline d a t a e l e m e n t s a r e i n s e r t e d directly in the c o d e . If y o u u s e inline as a directive i n a p r o c e d u r e o r a f u n c t i o n d e c l a r a t i o n , t h e inline d a t a e l e m e n t s a r e i n s e r t e d i n t h e c o d e e a c h t i m e t h e p r o c e d u r e o r f u n c t i o n is c a l l e d . A n inline d a t a e l e m e n t c o n s i s t s o f a c o n s t a n t o r a variable identifier, o p t i o n a l l y p r e f i x e d b y a size s p e c i f i e r : < o r > . A v a r i a b l e identifier c a n b e f o l l o w e d b y a + o r a - a n d a c o n s t a n t that s p e c i f i e s a n offset f r o m t h e v a r i a b l e ' s a d d r e s s . A n inline e l e m e n t g e n e r a t e s o n e b y t e o f c o d e if it is a c o n s t a n t i n t h e r a n g e 0 . . 2 5 5 . O t h e r w i s e , it g e n e r a t e s o n e w o r d . Y o u u s e t h e < a n d > o p e r a t o r s t o o v e r r i d e t h e a u t o m a t i c size s e l e c t i o n : < m e a n s "always g e n e r a t e a b y t e . " > m e a n s "always g e n e r a t e a w o r d . " For example: { 'inline' statement } procedure FillWord(var Dest; Count: Word; Data: Word); begin inline( $C4/$7E/ RangeXI) then X := round((InitX - RangeXI)/(RangeX2 - RangeXI) * (Attr.W - Attr.X)); Y := Attr.H - (round((InitY - RangeYI)/(RangeY2 - RangeYI) * (Attr.H - Attr.Y))); end; destructor Modell.Done; begin TWindow.Done; { Call ancestor's destructor } end;
5 —Putting Pictures in Windows
procedure Modell.Iterate; var I : integer; TempX, TempY : real; begin InvalidateRect(HWindow, nil,True); SetCapture(HWindow); DC := GetDC(HWindow); { Get a display context } for I := 1 to Iterations do begin TempX := InitX; { Save last state } TempY := InitY; { Save last state } InitX := TempY + 1 - (A * TempX * TempX); {This model } InitY := B * TempX; { This model } Scale; { Scale new state to a window } X := I; TextOut(DC,X,Y,'.',1); { Draw a point } end; ReleaseCapture; ReleaseDC(HWindow,DC); { Release display context } end; end.
{ unit timel }
{ Attract 2 } unit Attract2;
{ Contains Henon Attractor } { Responds to cm_Task2 (message) }
interface uses WObjects, WinTypes, WinProcs, strings, StdDlgs, WIF5;
{ Units specific to this unit }
{ Basiclnterface unit }
{$R ATTRACT2.RES} const cm_ChangeFactor_A
=303;
{ ''
........
y continues
179
180
Parti—Working with TPW
Listing
53-
continued
type PModel2 = "Model2; Model2 = object(MainWindow)
{ Henon Attractor } { Model's data fields } InitX, InitY : real; { Initial points } RangeXI, RangeX2, RangeYI, RangeY2 : real; { Range to view } X, Y : integer; { Point to plot } A, B : real; { factors for this model } { Model's methods } constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Scale; { Scale point to window } procedure Iterate; { Iterate model } destructor Done; virtual; { Clean up } procedure cm_Iterate(var Msg: TMessage); { Iterate } virtual cm_First + cm_Task2; procedure cm_ChangeFactorA(var Msg: TMessage); virtual cm_First + cm_ChangeFactor_A; end; implementation const Iterations = 3000;
{ Number of iterations }
constructor Model2.Init(AParent: PWindowsObject; ATitle: PChar) begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, PChar(102)); DisableAutoCreate; Attr.Style := ws_PopupWindow or ws_Caption or ws_Visible; Attr.X Attr.Y Attr.W Attr.H RangeXI RangeX2 RangeYI RangeY2
:= := := := := := := :=
A := 1.4;
150; 100; 300; 200; -1.03; 1.27; -0.3; 0.45;
{ Window dimensions }
{ Set ranges to view }
{ Set factors }
5 — P u t t i n g Pictures i n W i n d o w s
B := 0.3; InitX := 0.4; InitY := 0; X := 0; Y := 0; end;
{ Initial point in space }
procedure Model2.cm_Iterate(var Msg: TMessage); begin Iterate; { Iterate the model } end; procedure Model2.cm_ChangeFactorA(var Msg: TMessage); var InputText: array[0..5] of Char; New_A : real; ErrorPos : integer; begin { Use dialog to change A factor } Str(A,InputText); if Application".ExecDialog(New(PInputDialog, Init(@Self, Factor A', Input a new A Factor:', InputText, SizeOf(InputText)))) = id_Ok then begin Val(InputText,New_A,ErrorPos); if ErrorPos = 0 then A := New_A; end; end; 1
1
procedure Model2.Scale; begin { Scale point in space to window } If (InitX = RangeXI) then { A little troubleshooting } X := Attr.X; If (InitX = RangeX2) then X := Attr.W; { And here } If (InitX = 0) then X := X; If (InitX > RangeXI) then X := round((InitX - RangeXI)/(RangeX2 - RangeXI) * (Attr.W - Attr.X)); Y := Attr.H - (round((InitY - RangeYI)/(RangeY2 - RangeYI) * (Attr.H - Attr.Y))); end; continues
181
182
Parti—Working with T P W
Listing
53-
continued
destructor Model2.Done; begin TWindow.Done; { end;
Call ancestor's destructor }
procedure Model2.Iterate; var I : integer; TempX, TempY : real; begin SetCapture(HWindow); DC := GetDC(HWindow); { Get a display context } for I := 1 to Iterations do begin TempX := InitX; { Save last state } TempY := InitY; { Save last state } InitX := TempY + 1 - (A * TempX * TempX); {This model} InitY := B * TempX; {This model} Scale; { Scale new state to a window } TextOut(DC,X,Y,'.',1); { Draw a point } end; ReleaseCapture; ReleaseDC(HWindow,DC); { Release Display context } end; end. { end unit Attract2 } { ModelWnd } unit ModelWnd;
{ Contains a Model Window } { Responds to cm_Task1 (message)} { Responds to cm_Task2 (message) }
interface uses WObjects, WinTypes, WinProcs, strings, StdDlgs, WIF5,
timel,
{ Units specific to this unit }
{ Basiclnterface unit } { TaskList } { Task 1 }
5 — P u t t i n g Pictures i n W i n d o w s
attract2; {$R M0DWND2.RES}
{ Task 2
183
}
{ ModelWnd resource }
type ModelApp = object(BasicApplication) procedure InitMainWindow; virtual;
{ ModelApp=a kind of BasicApplication } { Init a specific MainWindow }
end; PModelWindow = "ModelWindow;
{ ModelWnd is a kind of MainWnd }
ModelWindow = object(MainWindow) constructor Init(AParent : PWindowsObject; ATitle : PChar); procedure cm_Task1(var Msg: TMessage); virtual {Run Taskl } cm_First + cm_Task1; procedure cm_Task2(var Msg: TMessage); virtual {Run Task2 } cm_First + cm_Task2; end;
implementation
procedure ModelApp.InitMainWindow;
{ Init a model application window }
begin if FirstApplication then MainWindow := New(PModelWindow, Init(nil, 'Model Windows Interface')) else MainWindow := New(PModelWindow, Init(nil,'Additional Instance of MI')); end; constructor ModelWindow.Init(AParent ATitle : PChar); begin TWindow.Init(AParent, ATitle);
: PWindowsObject;
{ Send message to ancestor's constructor } Attr.Menu := LoadMenu(HInstance, PChar(99)); { 99 = menu ID } ButtonDown := False; { Set status flag } end; procedure ModelWindow.cm_Task1(var Msg: TMessage); var continues
184
Parti—Working with T P W
Listing
5-3.
continued
Taskl : PModell; { Pointer to a task } begin Taskl := New(PModell, Init(@Self, 'TimeSeries Model')); Application".MakeWindow(Task1); Taskl".cm_Iterate; { Iterate the task } end; procedure ModelWindow.cm_Task2(var Msg: TMessage); var Task2 : PModel2; { Pointer to a task } begin Task2 := New(PModel2, Init(@Self, 'Henon Attractor')); Application".MakeWindow(Task2); Task2".Iterate; { Iterate the task } end; end.
{ unit Modelwnd }
{ Main test program } program Test_Interface;
{ Generic way to test each phase of interface development }
uses WIF5, modelwnd;
{ Basiclnterface unit } { contains ModelApp, multitasking units }
type App = object(TaskApp) end; var Application: App;
{ An instance of BasicApplication }
{ Run Applicationl } begin Application.Init('Basiclnterface'); { init application instance } Application.Run; { Message loop } Application.Done; { Destroy application instance } end. { end Main test program }
6
CHAPTER
PAINTING, COLLECTING, AND STREAMING Programming in an object-oriented ing a number of objects, according predict at compile time.
language to a pattern
consists in dynamically creatwhich is usually impossible to Bertrand Meyer
A significant s h o r t c o m i n g o f all t h e w i n d o w s d i s c u s s e d s o far ( i n c l u d i n g t h e M a i n , T a s k a n d M o d e l w i n d o w s d e r i v e d f r o m TWindow i n C h a p t e r 4, " I n h e r i t i n g A n I n t e r f a c e , " a n d C h a p t e r 5, " P u t t i n g P i c t u r e s I n W i n d o w s " ) is t h e i r tentativen e s s . I n o t h e r w o r d s , a n y o f t h e text a n d g r a p h i c s d i s p l a y e d i n a w i n d o w c a n d i s a p p e a r w h e n e v e r a w i n d o w is c o v e r e d b y a n o t h e r w i n d o w (for e x a m p l e , w h e n y o u s w i t c h w i n d o w s ) . W h e n a w i n d o w is s u b s e q u e n t l y u n c o v e r e d it n e e d s t o h a v e its c o n t e n t s u p d a t e d (or P a i n t e d ) . Part o f t h e s c r e e n h a s b e e n c o v e r e d b y a n o t h e r w i n d o w , l e a v i n g a w i n d o w ( w h e n u n c o v e r e d ) o n l y partially c o r r e c t . D o t s s h o u l d h a v e filled b o t h s i d e s o f t h e s c r e e n . F i g u r e 6.1 illustrates this p o i n t .
1 8 6 Parti—Working with T P W
Figure
6.1. A time series
model.
W h e n a w i n d o w needs to update its contents, W i n d o w s sends it a Paint message. It is then the window's responsibility to paint itself because W i n d o w s does not keep track of the contents of a window. As you might expect, the mechanics of receiving that message from W i n d o w s are handled automatically by TWindow and any w i n d o w you derive from it. The TWindow Paint method automatically responds to any wm_Paint message, but it does not actually paint the window. TWindow. Paint is abstract, and if you think about it, it is abstract for a good reason; it does not k n o w what is going to be displayed in any of its descendant's windows. Thus, any derived w i n d o w needs to handle the crucial detail of painting itself. T o paint itself, the w i n d o w overrides the TWindow.Paint method to handle the paint. H o w it decides to paint itself is entirely u p to the window. Reconsider the multitasking windows from Chapter 5, "Putting Pictures in Windows," and determine h o w to go about reimplementing a Pain t method for them. The two models generate points corresponding to calculations, and display each point just after it is calculated. If the windows containing the model tasks are covered and required to respond to Paint messages, they have to recalculate each point toredisplayit— not very efficient. Calculating and displaying point-by-point worksfineonly if you do not have to consider redisplaying (Painting) the window. Y o u do have to consider this, however, and you need a classier solution. A good approach (do not hesitate to think of a better one) is to calculate a set of points and store the calculated points where they can be easily retrieved and redisplayed whenever you need them.
6—Painting, Collecting, a n d Streaming
T h e s i m p l e s t ( a n d a typical Pascal) w a y t o c o l l e c t i t e m s s u c h as p o i n t s is t o s t o r e t h e p o i n t s i n a n array. A n array, t h o u g h s i m p l e a n d d i r e c t , is a s i n g l e type, single-size s o l u t i o n , a n d O O P offers a m o r e flexible, d y n a m i c , a n d p o l y m o r p h i c s o l u t i o n — o n e with m o s t o f the details already h a n d l e d b y O b j e c t W i n d o w s . T y p i c a l l y , if y o u s t o r e d a t a i n a n array y o u h a v e t o w r i t e t h e c o d e t o c r e a t e a n d m a n i p u l a t e t h e array. S i m p l e e n o u g h , b u t still a little m o r e w o r k , m o s t o f w h i c h y o u d o n o t n e e d . O O P offers a g e n e r i c s o l u t i o n : a c o l l e c t i o n o f p o i n t e r s to objects a n d the corresponding methods for manipulating the collection.
Polymorphic Collections T h e O b j e c t W i n d o w s TCollection o b j e c t is a n abstract t y p e a n d h a s t w o significant a d v a n t a g e s o v e r arrays: TCollection o b j e c t s c a n size t h e m s e l v e s d y n a m i c a l l y at r u n - t i m e , a n d t h e y c a n b e p o l y m o r p h i c . T h u s , a c o l l e c t i o n c a n g r o w as y o u n e e d it t o , w i t h o u t c h a n g i n g a n y c o d e . B e c a u s e it is p o l y m o r p h i c as w e l l , y o u c a n p u t a n y k i n d o f o b j e c t ( a n d e v e n n o n - o b j e c t s ) i n it. Y o u c a n e v e n m i x the object types within a single collection! B e c a u s e a c o l l e c t i o n u s e s n o n t y p e d p o i n t e r s , it d o e s n o t n e e d t o k n o w a n y t h i n g a b o u t t h e o b j e c t s it's g i v e n t o p r o c e s s . It just s t o r e s t h e m a n d g i v e s t h e m b a c k ; very f l e x i b l e ( s e e f i g u r e 6.2).
A C o l l e c t i o n of P o i n t e r s
Integer
Model
String
(any T O b j e c t d e s c e n d a n t type)
Figure 6.2. A collection of pointers.
Editor
187
188
P a r t i — W o r k i n g with T P W
B e c a u s e c o l l e c t i o n s are g e n e r a l - p u r p o s e , t h e y are u s e f u l i n m a n y d i f f e r e n t kinds of situations. O n e package o f m e t h o d s designed for handling the general t y p e c a n h a n d l e a n y s p e c i f i c t y p e . T h u s , if y o u u s e a c o l l e c t i o n , y o u d o n o t reinvent data-handling m e t h o d s each time y o u change the data type. Bravo, bravo. R e t u r n i n g t o t h e m o d e l tasks o f C h a p t e r 5, " P u t t i n g P i c t u r e s i n W i n d o w s , " w h a t d o y o u n e e d t o d o t o h a n d l e t h e Paint p r o b l e m ? R e c a l l that t h e m o d e l o b j e c t h a s fields t o d e f i n e t h e X a n d Y s c r e e n c o o r d i n a t e s w h e r e p o i n t s a r e d i s p l a y e d a n d a n iterate m e t h o d f o r g e n e r a t i n g p o i n t s . Y o u c a n r e d e f i n e t h o s e c o o r d i n a t e s as a p o i n t o b j e c t , i n c l u d e that o b j e c t i n t h e ModelWindow o b j e c t , c o l l e c t t h o s e p o i n t s r a t h e r t h a n d i s p l a y t h e m i n t h e Iterate m e t h o d , a n d d e f i n e a Pain t m e t h o d f o r d i s p l a y i n g t h e p o i n t s w h e n t h e w i n d o w r e c e i v e s t h e wm_Paint m e s s a g e . First, d e f i n e a point ( o b j e c t ) :
APoint = object(TObject) X, Y: Integer; constructor Init(AX, AY: Integer); end; D e r i v e t h e point f r o m TOb j ect, t h e b a s e o b j e c t for all O b j e c t W i n d o w s o b j e c t s , b e c a u s e a n y o b j e c t that u s e s O b j e c t W i n d o w s ' s t r e a m s m u s t b e d e r i v e d f r o m ( o r trace its o r i g i n t o ) TOb j ect. T h e n i m p l e m e n t a constructor t o create each point:
constructor APoint.Init(AX, AY: Integer); begin X := AX; Y := AY; end; Y o u a l s o n e e d t o d e f i n e a p o i n t e r t o APoint b e c a u s e y o u a r e g o i n g t o c o n s t r u c t p o i n t s d y n a m i c a l l y (as y o u n e e d t h e m ) , u s i n g t h e New p r o c e d u r e a n d APoin t's c o n s t r u c t o r (I n it). B e c a u s e a c o l l e c t i o n a l r e a d y h a s a m e t h o d , c a l l e d Insert for i n s e r t i n g i t e m s i n t o t h e c o l l e c t i o n , y o u d o n o t e v e n h a v e t o w o r r y about adding the point to the collection. D e f i n e a p o i n t e r t o APoint:
PtrPoint = "APoint; C r e a t e a c o l l e c t i o n o f p o i n t s b y d e c l a r i n g a v a r i a b l e o f t y p e PCollect ion (a p r e d e f i n e d p o i n t e r t o a TCollection o b j e c t ) , a n d t h e n d y n a m i c a l l y c r e a t e t h e collection ( o b j e c t ) :
6—Painting, Collecting, and Streaming
189
var Points : PCollection; Points := New(PCollection, Init(1000, 100)); where 1000 is the size of the initial collection and 100 represents the incremental growth of the collection. In other words, you specify an initial sizeforacollection,butthecollectionis not limited to that size; it can grow dynamically by the increment you select. In fact, it can grow to a m a x i m u m size of about 16K, m e m o r y permitting, with each object requiring 4 bytes (the pointer size). If there is not enough m e m o r y to add elements to the collection, the TCollection m e t h o d — T C o l l e c t i o n . Error—automatically receives a message specifying this not-enough-memory condition. The objects you derive from TCollection mightwant to handle this error themselves. For now, do not worry too m u c h about out-of-memory errors; just leave them until Chapter 9 , "Memory Matters," which explores m e m o r y and other more complex matters. Construct and insert a point into the collection in a single step: Points".Insert(New(APoint, Init(X, Y))); Although you are only going to collect points in this collection, remember that you can insert (and retrieve) other types of objects in this same collection using the same technique.
Collecting Points N o w to change a model task from Chapter 5, "Putting Pictures in Windows": 1. A d d the collection to the object (see listing 6.1). Listing
6.1. Adding
the collection
PModell = ~Model1; Modell = object(MainWindow)
to the
object.
{ { { {
Pointer to this task } Time series } Task's data fields } InitX, InitY : real; Initial points } RangeXI, RangeX2, RangeYI, RangeY2 : real; { Range to view } A, B : real; { Factors for this model task } Points : PCollection; { Add the collection } { Task's methods } continues
190
Part I — W o r k i n g w i t h T P W
Listing
6.1.
continued
constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Scale; { Scale point to window } procedure Iterate; { Iterate model task } destructor Done; virtual; { Clean up } procedure cm_Iterate(var Msg: TMessage); virtual cm_First + cm_Task1; procedure Paint(PaintDC: HDC; { Override Paint } var Paintlnfo: TPaintStruct); virtual; end; 2. Y o u a l s o have t o c o n s t r u c t t h e c o l l e c t i o n a n d let t h e m o d e l k n o w a b o u t it. A g o o d p l a c e t o handle this detail is in t h e M o d e l ' s c o n s t r u c t o r . S e e listing 6.2. Listing
6.2.
The Models
constructor.
constructor Modell.Init(AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, PChar(111)); DisableAutoCreate; Attr.Style := ws_PopupWindow or ws_Caption or ws_Visible; Attr.X Attr.Y Attr.W Attr.H RangeXI RangeX2 RangeYI RangeY2
:= := := := := := := :=
100; 50; 300; 200; -1.03; 1.27; -0.3; 0.45;
A := 1.4; B := 0.3; InitX := 0.4; InitY := 0;
{ Set window dimensions }
{ Set ranges to view }
{ Set factors }
6 —Painting, Collecting, a n d Streaming
X := 0; Y := 0;
191
{ Initial point in space }
Points := New(PCollection, Init(50, 50)); { Construct the collection } end; 3. T h e n , rather
t h a n ( o r after y o u ) d i s p l a y a p o i n t , insert t h e p o i n t i n t h e
c o l l e c t i o n ( s e e listing 6.3). Listing
6.3- Inserting
the point
in the
collection.
procedure Modell.Iterate; var I : integer; TempX, TempY : real; begin InvalidateRect(HWindow, nil,True); { Clear screen } SetCapture(HWindow); DC := GetDC(HWindow); { Get a display context } for I := 1 to Iterations do begin TempX := InitX; { Save last state } TempY := InitY; { Save last state } InitX := TempY + 1 - (A * TempX * TempX);{ This model InitY := B * TempX; { This model Scale; { Scale new state to a window X := I; TextOut(DC,X,Y, ,1); { Draw a point } Points".Insert(New(APoint, Init(X, Y))); { Insert it in collection end; ReleaseCapture; ReleaseDC(HWindow,DC); { Release Display context end;
} } }
1
4. T h e n d i s p l a y t h e c o l l e c t i o n i n t h e revised Paint m e t h o d u s i n g t h e b u i l t - i n TCollection m e t h o d , ForEach ( s e e listing 6.4).
}
}
192
Part I — W o r k i n g w i t h T P W
Listing
6.4. Displaying
the
collection.
procedure Modell.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var First: Boolean; { A where-are-you flag } procedure DisplayPoints(P: PAPoint); far; begin TextOut(PaintDC,P".X,P".Y,'. ,1); First := False; end; 1
begin First := True; Points".ForEach(@DisplayPoints); end; ForEach is o n e o f t h e m a n y TCollection iterator m e t h o d s that y o u c a n
u s e t o traverse a n d m a n i p u l a t e t h e collection. FirstThat a n d LastThat, for e x a m p l e , w o r k m u c h t h e s a m e w a y t o a l l o w a c c e s s t o s p e c i f i c i t e m s i n
t h e collection. N o t e a l s o that Paint u s e s a s p e c i f i c d i s p l a y c o n t e x t , c a l l e d PaintDC. PaintDC is o b t a i n e d a u t o m a t i c a l l y b y TWindow ( a n d its d e s c e n d a n t s ) b e f o r e t h e Paint m e s s a g e is s e n t . PaintDC is r e l e a s e d a u t o m a t i c a l l y after Paint is f i n i s h e d . ( R e m e m b e r that y o u m u s t r e l e a s e a n y d i s p l a y c o n t e x t i m m e d i a t e l y after y o u a r e finished w i t h it b e c a u s e it eats u p s o m u c h m e m o r y . ) A collection is a n a m a z i n g l y u s e f u l t o o l , a n d a n y collection, as s t a t e d earlier, c a n c o n t a i n a m i x t u r e o f o b j e c t s . S u p p o s e , for e x a m p l e , that y o u h a d two objects: • A point • A string o f text:
AString = object(TObject) S: array[0..5] of Char; constructor Init(AnS: array[0..5] of Char); end; Y o u c o u l d a d d t h e m t o t h e s a m e c o l l e c t i o n a n d p l a y t h e m b a c k o n e at a t i m e . C r e a t e t h e n e w string o b j e c t w i t h its c o n s t r u c t o r :
constructor Init(AnS: array[0..5] of Char);
6—Painting, Collecting, a n d Streaming
a n d insert it:
Points".Insert(New(PtrAStr, Init(S))); N o t e that it is y o u r r e s p o n s i b i l i t y t o m a k e s u r e that y o u g e t t h e c o r r e c t o b j e c t b a c k f r o m a collection. T h e p r e v i o u s f r a g m e n t w o r k s , b u t f o r illustrative p u r p o s e s o n l y . I n a m o r e c o m p l e x s i t u a t i o n , y o u p r o b a b l y w a n t s o m e w a y o f i d e n t i f y i n g t h e o b j e c t . If y o u d o p l a n t o u s e m i x e d collections, y o u s h o u l d i m p l e m e n t s o m e f o o l p r o o f p l a n for r e c o g n i z i n g o b j e c t s i n t h e collections. A n a p p r o a c h u s e d w i t h s u c c e s s is t o a d d a n I D field t o e a c h o b j e c t y o u w a n t t o
p u t i n t h e collection. F o r e x a m p l e :
APoint = object(TObject) ID : word; X, Y: Integer; constructor Init(AnID: word AX, AY: Integer); end; T h e n w h e n y o u insert t h e point, y o u insert its ID as w e l l :
Id := 100; { 100 indicates a point } Points".Insert(New(APoint, Init(ID,X,Y))); T h e s a m e g o e s for t h e string:
Id := 102; { 102 indicates a string } Points".Insert(New(AStr, Init(ID,S))); 5. T h e n traverse t h e collection a n d g e t o n l y t h e i t e m s y o u n e e d — f o r e x a m p l e , just t h e p o i n t s . A r e v i s e d Paint m e t h o d t o h a n d l e this s c e n a r i o m i g h t l o o k l i k e listing 6 . 5 .
Listing
6.5. The revised
Paint
method.
procedure Modell.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var First: Boolean; { A where-are-you flag } procedure DisplayPoints(P: PAPoint); far; begin If P".ID = 100 then begin TextOut(PaintDC,P".X,P".Y, . ,1); 1
1
continues
193
194
Part I — W o r k i n g w i t h T P W
Listing
6.5-
continued
First end;
:= False;
end; begin First := True; Points".ForEach(@DisplayPoints); end;
Streams T h e collections y o u h a v e c r e a t e d s o far h a n d l e t h e Paint p r o b l e m b e a u t i f u l l y as l o n g as y o u d o n o t t u r n o f f t h e c o m p u t e r , q u i t t h e p r o g r a m , o r fall p r e y t o s o m e u n f o r e s e e n n a t u r a l disaster, s u c h as a p o w e r f a i l u r e . T h e p r o b l e m is that t h e s e collections exist o n l y i n m e m o r y . W h a t if y o u n e e d t o p r e s e r v e t h e collection for a n o t h e r c o m p u t i n g s e s s i o n ? I n o t h e r w o r d s , h o w c a n y o u Paint a w i n d o w later, after t h e p o i n t s a r e n o l o n g e r r e t a i n e d i n m e m o r y ? Answer: by using streams. A s t r e a m is a c o l l e c t i o n o f o b j e c t s o n its w a y t o s o m e d e v i c e : a file, a p o r t , E M S , a n d s o o n . Again, O b j e c t W i n d o w s already has i m p l e m e n t e d the m e t h o d s y o u n e e d to h a n d l e streams. R e m e m b e r , streams are dynamic a n d polymorp h i c , s o they are capable o f h a n d l i n g d y n a m i c a n d p o l y m o r p h i c collections. Y o u just p u t o b j e c t s i n a s t r e a m a n d g e t t h e m b a c k ( s e e f i g u r e 6.3). A s t r e a m d o e s n o t n e e d t o k n o w t h e k i n d o f o b j e c t s it w i l l s e e , as l o n g as t h e o b j e c t s it s e e s h a v e b e e n r e g i s t e r e d as " s t r e a m a b l e " o b j e c t s . T o u s e a stream, y o u need to 1. D e f i n e a s t r e a m r e g i s t r a t i o n r e c o r d for t h e o b j e c t y o u w a n t t o m a k e streamable. 2. R e g i s t e r t h e s t r e a m b y c a l l i n g t h e g l o b a l p r o c e d u r e RegisterType w i t h t h e s p e c i f i c s t r e a m r e c o r d as its p a r a m e t e r . H e r e is h o w t o d e f i n e a s t r e a m r e c o r d for Apoint: const RPoint: TStreamRec = ( ObjType: 500; VmtLink: 0fs(Type0f(APoint)"); Load: @Point.Load; Store: @Point.Store); end;
6—Painting, Collecting, and Streaming
Streams
Put
Figure
Get
6.3- Streams.
By c o n v e n t i o n any stream constant begins with an R prefix. T h e Ob j Type field is a n u m b e r (a w o r d type) t h a t y o u d e f i n e . O b j e c t W i n d o w s reserves the registration n u m b e r s 0 t h r o u g h 9 9 , so y o u r registration n u m b e r s c a n b e a n y t h i n g f r o m 100 t h r o u g h 6 5 , 5 3 5 . T h e c h o i c e is y o u r s , a n d it c a n b e e n t i r e l y arbitrary, b u t it is a g o o d i d e a t o m a i n t a i n a file o r library o f s t r e a m r e g i s t r a t i o n n u m b e r s t o m a k e it e a s i e r t o k e e p u p w i t h t h e m . T h e V m t L i n k field l i n k s y o u r o b j e c t t o t h e V i r t u a l m e t h o d t a b l e ( V M T ) . Y o u s i m p l y a s s i g n it as t h e offset t o y o u r o b j e c t t y p e . T h e L o a d a n d S t o r e fields h o l d t h e a d d r e s s e s o f t h e L o a d a n d S t o r e methods of the object. After y o u h a v e c o n s t r u c t e d t h e s t r e a m r e g i s t r a t i o n r e c o r d , y o u r e g i s t e r t h e s t r e a m . B e c a u s e all t h e e x a m p l e s i n this c h a p t e r p u t c o l l e c t i o n s i n s t r e a m s , y o u n e e d t o r e g i s t e r t h e c o l l e c t i o n t y p e as w e l l as t h e p o i n t t y p e , w h i c h is i n t h e collection: procedure StreamRegistration; begin RegisterType(RCollection); RegisterType(RPoint); end; M o d i f y t h e m o d e l t o i n c l u d e m e t h o d s f o r h a n d l i n g t h e s t r e a m (see listing 6 . 6 ) .
195
196
Part I — W o r k i n g w i t h T P W
Listing
6.6. Stream
handling.
PModell = "Modell; Modell = object(MainWindow)
{ { { {
Pointer to this task } Time series } Task's data fields } InitX, InitY : real; Initial points } RangeXI, RangeX2, RangeYI, RangeY2 : real; { Range to view } X, Y : integer; { Point to plot } A, B : real; { Factors for this model task } Points : PCollection;
FileName: array[0..fsPathName] of Char; IsDirty, IsNewFile: Boolean; { Task's methods } constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Scale; { Scale point to window } procedure Iterate; { Iterate model task } destructor Done; virtual; { Clean up } procedure cm_Iterate(var Msg: TMessage); virtual cm_First + cm_Task1; procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; procedure LoadFile; procedure SaveFile; end; D e f i n e Point's Load m e t h o d t o s p e c i f i c a l l y handle t h e reading o f t h e X a n d Y fields. Read is a n abstract m e t h o d o f TSt ream a n d m u s t b e o v e r r i d d e n t o l o a d specific o b j e c t s :
constructor Point.Load(var S: TStream); begin S.Read(X, SizeOf(X)); S.Read(Y, SizeOf(Y)); end; ^ D e f i n e t h e Store M e t h o d t o handle t h e w r i t i n g o f Point's X a n d Y fields. Write, like Read, is a n abstract TSt ream m e t h o d , w h i c h m u s t b e o v e r r i d d e n b y
a n y TStream d e s c e n d a n t : procedure Point.Store(var S: TStream); begin S.Write(X, SizeOf(X)); S.Write(Y, SizeOf(Y)); end;
6—Painting, Collecting, a n d Streaming
N e x t , a d d t h e m e n u m e s s a g e r e s p o n s e m e t h o d s t o t h e m o d e l task. A l t h o u g h y o u n e e d t o c r e a t e o n l y FileOpen a n d FileSave m e t h o d s ( t o c o r r e s p o n d t o loading a n d saving points t o a file), y o u c a n e x p a n d the m o d e l task at this p o i n t t o i n c l u d e c r e a t i n g a n e w file (FileNew) a n d s a v i n g a file u n d e r a d i f f e r e n t n a m e (FileSave As). T h e s e files m a k e spiffy a d d i t i o n s t o a n y w i n d o w o r task that n e e d s t o d o g e n e r a l file I/O. A l l t h e s e n e w m e t h o d s u s e file d i a l o g s ( d i s c u s s e d i n C h a p t e r 3, " O b j e c t s f o r W i n d o w s " ) a n d e m p l o y t h e s a m e s t r e a m m e t h o d s for saving a n d getting points. A d d these four m e t h o d s to the m o d e l object: 1. procedure CMFileNew(var Msg: TMessage); virtual cm_First + cm_New; 2. procedure CMFileOpen(var Msg: TMessage); virtual cm_First + cm_Open; 3. procedure CMFileSave(var Msg: TMessage); virtual cm_First + cm_Save; 4. procedure CMFileSaveAs(var Msg: TMessage); virtual cm_First + cm_SaveAs; A g a i n , t h e CM p r e f i x is u s e d t o d e s i g n a t e that t h e m e t h o d r e s p o n d s t o m e n u c o m m a n d m e s s a g e s . T h a t w a y , it's e a s i e r t o r e c o g n i z e t h e s e r e s p o n s e methods. T h e m e n u c o m m a n d m e s s a g e s (cm_Save, cm_SaveAs, cm_Open, a n d c m N e w ) a l r e a d y h a v e b e e n a d d e d t o t h e Basiclnterface ( C h a p t e r 4 , " I n h e r i t i n g a n I n t e r f a c e " ) , s o y o u n e e d t o just d e f i n e a n d i m p l e m e n t t h e r e s p o n s e s . File New l o o k s l i k e t h i s : procedure Modell.FileNew(var Msg: TMessage); begin Points"-FreeAll; { New collection } InvalidateRect(HWindow, nil, True); { Clear screen } IsDirty := False; { Unchanged file flag } IsNewFile := True; { New file flag } end; First FileNew d e l e t e s a n d d i s p o s e s of all t h e i t e m s i n t h e collection ( u s i n g t h e TCollection m e t h o d FreeAll). T h e n it f o r c e s a Paint m e s s a g e (InvalidateRect), which c a u s e s t h e d i s p l a y t o b e u p d a t e d , u s i n g t h e n e w Paint m e t h o d . B e c a u s e t h e r e a r e n o p o i n t s t o d i s p l a y , it c l e a r s t h e w i n d o w . Finally, it sets s o m e flags t o s p e c i f y that t h e file is n e w (IsNewFile : = True) a n d that n o t h i n g n e w h a s b e e n a d d e d t o t h e file (IsDirty : = False).
197
198
P a r t i — W o r k i n g with T P W
FileOpen l o o k s like t h i s :
procedure Modell.FileOpen(var Msg: TMessage); begin if CanClose then if Application".ExecDialog(New(PFileDialog, Init(@Self, PChar(sd_FileOpen), StrCopy(FileName, '*.PTS')))) = id_Ok then LoadFile; end; FileOpen s e n d s a m e s s a g e (ExecDialog) t o c r e a t e a n e w file d i a l o g o b j e c t , a n d t h e n o p e n s t h e file (sdOpen). If all g o e s w e l l , it l o a d s t h e file, u s i n g t h e m o d e l ' s LoadFile m e t h o d , w h i c h i n t u r n u s e s t h e s t r e a m facilities y o u h a v e just set u p . FileSave l o o k s like t h i s :
procedure Modell.FileSave(var Msg: TMessage); begin if IsNewFile then FileSaveAs(Msg) else SaveFile; end; FileSave s i m p l y d e c i d e s w h e t h e r it is d e a l i n g w i t h a NewFile, a n d if n o t , saves t h e file ( u s i n g SaveFile, w h i c h is d i s c u s s e d i n a m o m e n t ) . FileSaveAs l o o k s like t h i s :
procedure Modell.FileSaveAs(var Msg: TMessage); var FileDlg: PFileDialog; begin if IsNewFile then StrCopy(FileName, ' ' ) ; if Application".ExecDialog(New(PFileDialog, Init(@Self, PChar(sd_FileSave), FileName))) = id_0k then SaveFile; end; FileSaveAs a l s o s e n d s a m e s s a g e (ExecDialog) t o c r e a t e a file d i a l o g , a n d after it g e t s a SaveName, calls SaveFile t o a c t u a l l y save t h e file. SaveFile is i n listing 6 . 6 . N o w y o u c a n Store p o i n t s t o a file a n d Load t h e m i n t o t h e a p p l i c a t i o n m e n u w h e n e v e r y o u n e e d t o . T h e c o d e i n listing 6 . 8 at t h e e n d o f this c h a p t e r shows the completely u p d a t e d m o d e l simulation allowing storing a n d loading f r o m files.
A d d Load a n d Store M e t h o d s t o p o i n t :
6—Painting, Collecting, a n d Streaming
PAPoint = "APoint; APoint = object(TObject) X, Y: Integer; constructor Init(AX, AY: Integer); constructor Load(var S: TStream); procedure Store(var S: TStream); end; B e f o r e y o u l e a r n h o w a p o i n t ( o r a n y o b j e c t ) is p u t i n a s t r e a m , n o t e that a d d i n g c o l l e c t a b l e , s t r e a m a b l e o b j e c t s t o t h e m o d e l a l s o c o u l d b e h a n d l e d a bit differently. Y o u c a n d e r i v e a n e w m o d e l o b j e c t that o n l y a d d s t h e n e w c o l l e c t a b l e , s t r e a m a b l e d e t a i l s . T h a t m o d e l c o u l d l o o k like t h i s :
PStreamModell = "StreamModell; StreamModell = object(Modell)
{ Pointer to this task } { Time Series } { Task's data fields }
Points : PCollection; FileName: array[0..fsPathName] of Char; IsDirty, IsNewFile: Boolean; { Task's methods } constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure CMIterate(var Msg: TMessage); virtual cm_First + cm_Task1; procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; procedure LoadFile; procedure SaveFile; end; O n l y t h e n e w fields a n d n e w o r r e i m p l e m e n t e d m e t h o d s n e e d t o b e d e s i g n a t e d i n this n e w s t r e a m a b l e o b j e c t . T h e c h o i c e o f w h e n t o d e r i v e a n d w h e n t o a d d t o a n e x i s t i n g o b j e c t is a m a t t e r o f taste a n d , t o a c e r t a i n e x t e n t , a matter of w h e r e y o u draw the general-specific line. Because the "unstreamable" m o d e l d e v e l o p e d i n C h a p t e r 5, " P u t t i n g P i c t u r e s i n W i n d o w s , " n e e d s s t r e a m a n d c o l l e c t i o n c a p a b i l i t y t o b e g e n e r a l - p u r p o s e , a d d that f u n c t i o n a l i t y t o it r a t h e r t h a n d e r i v e n e w o b j e c t s t o r e p r e s e n t 1) a c o l l e c t a b l e a n d 2) a s t r e a m a b l e v e r s i o n . T h r o u g h o u t y o u r W i n d o w s ( O O P p r o g r a m m i n g ) life, y o u h a v e t o decide h o w to handle many such decisions.
Putting Points in a Stream D e c l a r e a variable o f a s t r e a m t y p e d e s c e n d e d f r o m TSt ream (either TDosSt ream,
TBufStream, o r TEmsStream).
199
200
P a r t i — W o r k i n g with T P W
TDosStream irriplements u n b u f f e r e d D O S file s t r e a m s . Its c o n s t r u c t o r a l l o w s y o u t o s p e c i f y a file a c c e s s m o d e (stCreate, stOpenRead, stOpenWrite, a n d stOpen). U s e a TDosSt ream if y o u d o n o t h a v e t o r e a d a n d w r i t e m a n y s m a l l chunks o f data. TBufStream i m p l e m e n t s b u f f e r e d D O S file s t r e a m s . It a l l o w s y o u t o specify t h e size o f a b u f f e r , a n d t h u s is u s e f u l f o r r e a d i n g a n d w r i t i n g s m a l l c h u n k s o f data. TEMSStream i m p l e m e n t s s t r e a m s i n E M S m e m o r y . I n this e x a m p l e , y o u u s e TDosStream: var TheFile: TDosStream; a n d initialize it: TheFile.Init(FileName, stCreate); After t h e s t r e a m is i n i t i a l i z e d , y o u c a n Put t o it a n d Get f r o m it. T h e f o l l o w i n g l i n e p u t s all t h e p o i n t s i n t h e c o l l e c t i o n i n t h e s t r e a m : TheFile.Put(Points);
How Pat Works Y o u put o b j e c t s o n a s t r e a m a n d Put d o e s all t h e w o r k . Y o u d o n o t n e e d t o k n o w h o w Put w o r k s , b u t f o r t h e p l e a s u r e o f it, t h e u n d e r l y i n g w o r k i n g s a r e covered here. First t h e s t r e a m t a k e s t h e V M T p o i n t e r f r o m offset 0 o f t h e o b j e c t ( p o i n t , i n this c a s e ) a n d tries t o m a t c h it w i t h a n o b j e c t r e g i s t e r e d w i t h it. I f it f i n d s a m a t c h i n g r e g i s t e r e d o b j e c t , it w r i t e s t h e s t r e a m ' s r e g i s t r a t i o n n u m b e r t o t h e s t r e a m ' s d e s t i n a t i o n . I n this e x a m p l e , t h e s t r e a m ' s d e s t i n a t i o n is a file, s o t h e first t h i n g it w r i t e s t o t h e file is t h e o b j e c t ' s I D n u m b e r . T h i s s t e p is i m p o r t a n t b e c a u s e it u s e s that I D later w h e n it tries t o g e t o b j e c t s f r o m t h e s t r e a m . T h e s t r e a m t h e n s e n d s a m e s s a g e t o t h e o b j e c t ' s Store m e t h o d ( w h i c h y o u h a v e t o d e f i n e w h e n y o u d e f i n e t h e o b j e c t ) , w h i c h s t o r e s t h e o b j e c t itself. Store u s e s t h e l o w - l e v e l w r i t e p r o c e d u r e f o r w r i t i n g t h e o b j e c t t o t h e s t r e a m . It is b e s t t o u s e t h e SizeOf f u n c t i o n , as y o u d i d i n s t o r i n g a p o i n t , t o m a k e s u r e that t h e c o r r e c t n u m b e r o f b y t e s a r e w r i t t e n t o t h e s t r e a m : S.Write(X, SizeOf(X)); S.Write(Y, SizeOf(Y)); T h a t is all t h e r e is t o p u t t i n g a n o b j e c t i n a s t r e a m . T h e o b j e c t d o e s n o t n e e d t o k n o w a n y t h i n g a b o u t t h e s t r e a m , just h o w t o l o a d a n d s t o r e itself. T h e
6—Painting, Collecting, a n d Streaming
s t r e a m i n g d e t a i l s (like m o s t e v e r y t h i n g e l s e i n t h e O b j e c t W i n d o w s b a g o f tricks) are handled f o r y o u . T h e o n l y o t h e r d e t a i l y o u n e e d t o t a k e care o f is e x p l i c i t l y s e n d i n g a destructor message to cleanup: TheFile.Done; B e c a u s e TheFile (in this c a s e ) is a s t r e a m t y p e d e r i v e d f r o m TDosSt ream, it a l r e a d y has a d e s t r u c t o r (TDosSt ream. Done), w h i c h t a k e s c a r e o f t h e c l e a n u p a u t o m a t i c a l l y . Y o u d o n o t n e e d t o reimplement it. T h e c o d e i n listing 6 . 7 saves all t h e p o i n t s c r e a t e d b y M o d e l l . Listing
6.7. Saving
all points
created
by Model 1.
procedure Modell.SaveFile; var TheFile: TDosStream; begin TheFile.Init(FileName, stCreate); TheFile.Put(Points); TheFile.Done; IsNewFile := False; IsDirty := False; end; Alternatively, y o u c o u l d have u s e d o t h e r s t r e a m s (TBuf Stream, a n d s o o n ) , a n d t h e i m p l e m e n t a t i o n w o u l d have b e e n similar.
Getting Points G e t t i n g p o i n t s o u t o f a s t r e a m is just as s i m p l e . Y o u d e c l a r e v a r i a b l e s t o represent t h e collection a n d t h e stream: var: TempColl: PCollection; AFile: TDosStream; Initialize t h e s t r e a m (AFile), a n d specify that y o u w a n t t o o p e n it f o r reading ( u s i n g stOpen): AFile.Init(FileName, stOpen);
201
202
P a r t i — W o r k i n g with T P W
T h e n get the objects:
TempColl := PCollection(TheFile.Get); T h e Get p r o c e s s is t h e r e v e r s e of t h e Put. First Get retrieves t h e o b j e c t ' s I D n u m b e r a n d s c a n s t h e r e g i s t e r e d s t r e a m t y p e s u n t i l it finds a m a t c h i n g I D n u m b e r . T h e r e g i s t r a t i o n r e c o r d c o n t a i n s t h e a d d r e s s of t h e Load m e t h o d f o r t h e o b j e c t . Get t h e n s e n d s a m e s s a g e t o t h e Load m e t h o d , w h i c h u s e s t h e s t r e a m ' s Read m e t h o d t o a c t u a l l y r e a d o b j e c t s f r o m t h e file o n e at a t i m e :
S.Read(X, SizeOf(X)); S.Read(Y, SizeOf(Y)); N o t e a g a i n that Read relies o n t h e SizeOf f u n c t i o n t o d e t e r m i n e t h e c o r r e c t size of t h e o b j e c t it n e e d s t o r e a d . T h e n c l e a n u p , b y s e n d i n g a Done m e s s a g e :
TheFile.Done; A g a i n , t h e destructor h a s a l r e a d y b e e n i m p l e m e n t e d f o r y o u , s o y o u d o n o t h a v e t o d o a n y t h i n g o t h e r t h a n s e n d t h e Done m e s s a g e t o TheFile (a
TDosStream). L i s t i n g 6.8 s h o w s t h e c o m p l e t e c o d e n e c e s s a r y f o r r e a d i n g t h e p o i n t s s t o r e d t o t h e s t r e a m earlier. N o t e a g a i n t h e InvalidateRect p r o c e d u r e , w h i c h f o r c e s a r e p a i n t m e s s a g e t o b e s e n t t o t h e o b j e c t . A s d i s c u s s e d earlier, t h e Paint m e s s a g e ( w h i c h is n o w d e f i n e d for t h e Model 1 o b j e c t ) c a u s e s t h e p o i n t s t o b e displayed. Listing
6.8. Reading
points
already
stored
to the
procedure Modell.LoadFile; var TempColl: PCollection; TheFile: TDosStream; begin TheFile.Init(FileName, stOpen); TempColl := PCollection(TheFile.Get); TheFile.Done; if TempColl nil then begin Dispose(Points, Done); Points := TempColl; InvalidateRect(HWindow, nil, True); end; IsDirty := False; IsNewFile := False; end;
stream.
{forces Paint message}
6—Painting, Collecting, a n d Streaming
P u t t i n g it all t o g e t h e r , listing 6 . 8 s h o w s h o w t o e x t e n d t h e m o d e l task f r o m C h a p t e r 5, " P u t t i n g P i c t u r e s i n W i n d o w s , " m a k i n g it c o l l e c t a b l e , s t r e a m a b l e , and repaintable.
The Sum of Streams S t r e a m s a r e p o l y m o r p h i c . A l l a s t r e a m n e e d s t o k n o w is that it is d e a l i n g w i t h a n o b j e c t d e r i v e d f r o m TOb j ect. T h u s , y o u c a n p u t d i f f e r e n t o b j e c t t y p e s i n t h e same stream. Y o u r p r o g r a m m i n g r e s p o n s i b i l i t y is s i m p l y t o d e f i n e a n d r e g i s t e r t h e kinds of objects y o u want the stream to handle. Y o u c a n then p u t objects in the stream and get t h e m b a c k u s i n g the m e t h o d s provided f o r y o u in ObjectWindows. R e g i s t e r i n g o b j e c t s , as s h o w n , is a s i m p l e m a t t e r , a l m o s t a u t o m a t i c . P u t t i n g a n d g e t t i n g o b j e c t s t o a n d f r o m a s t r e a m is a l m o s t a u t o m a t i c as w e l l . Y o u r p r i m a r y p r o g r a m m i n g task is t o r e g i s t e r o b j e c t s w i t h a s t r e a m a n d k e e p a n inventory o f y o u r registered object records. S t r e a m s a n d c o l l e c t i o n s a r e classic c a s e s o f p o t e n t i a l l y difficult p r o g r a m m i n g tasks b e c o m i n g a l m o s t trivial w i t h T u r b o P a s c a l f o r W i n d o w s . ( Y o u p r o b a b l y t h i n k that T u r b o P a s c a l f o r W i n d o w s h a s t a k e n m o s t t h e w o r k o u t o f d e v e l o p i n g W i n d o w s applications. Y o u are right.) U s i n g t h e Basiclnterface a n d its m u l t i t a s k e x t e n s i o n s d i s c u s s e d i n C h a p t e r 5, " P u t t i n g P i c t u r e s i n W i n d o w s , " y o u c a n a l m o s t r o l l i n t o a n y application p r o b l e m a n d a d d t h e n e w behaviors y o u n e e d for y o u r specific p r o b l e m . Y o u modify a n d extend, not reinvent, using O O P techniques. W i n d o w s c o m p l e x i t y is e n c a p s u l a t e d i n O b j e c t W i n d o w s o b j e c t s , f r o m w h i c h y o u derive y o u r objects, using inheritance. M a n y o f the basic p r o g r a m m i n g p r o b l e m s , s u c h as file I/O a n d d a t a c o l l e c t i n g , h a v e b e e n g e n e r a l i z e d beautifully, s o y o u u s e p o l y m o r p h i s m t o h a n d l e t h e m . Streams a n d collections are e x c e l l e n t e x a m p l e s o f h o w O O P s i m p l i f i e s , y e t e m p o w e r s , p r o g r a m m i n g tasks. W i n d o w s a n d O O P ( T u r b o Pascal f o r W i n d o w s - s t y l e ) a r e f i n e e x a m p l e s o f h o w a sophisticated graphics environment a n d a programming language can b o t h s i m p l i f y a n d e m p o w e r . If y o u h a v e t r i e d t o d e v e l o p W i n d o w s a p p l i c a t i o n s u s i n g t h e S D K o r e v e n B o r l a n d ' s C + + , y o u a l r e a d y k n o w t h i s . T u r b o Pascal f o r W i n d o w s a l l o w s y o u t o a v o i d m a n y m u s t y levels ( s e e listing 6 . 9 ) . Listing
6.9- Making
unit Time3;
a collectable,
streamable,
and repaintable
task.
{ A Model Task } { Responds to cm_Taskt (message) } { Adds streams to Time2 }
interface uses WObjects,
{ Units specific to this unit } continues
203
204
Parti—Working with TPW
Listing
6.9.
continued
WinTypes, WinProcs, strings, StdDlgs, WinDos, WIF5;
{ Basic Interface : contains MainWindow } { : BasicApplication }
{$R TIME1.RES}
{ This task's new resources }
type PModell = "Modell; Modell = object(MainWindow)
{ Pointer to this task } { Time Series } { Task's data fields } InitX, InitY : real { Initial points } RangeXI, RangeX2, RangeYI, RangeY2 : real; { Range to view } X, Y : integer; { Point to plot } A, B : real; { Factors for this model task } Points : PCollection; FileName: array[0..fsPathName] of Char; IsDirty, IsNewFile: Boolean; { Task's methods } constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Scale; { Scale point to window } procedure Iterate; { Iterate model task } destructor Done; virtual; { Clean up } procedure cm_Iterate(var Msg: TMessage); virtual cm_First + cm_Task1; procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; procedure virtual procedure virtual procedure virtual
FileNew(var Msg: TMessage); cm_First + cm_New; FileOpen(var Msg: TMessage); cm_First + cm_0pen; FileSave(var Msg: TMessage); cm First + cm Save;
6—Painting, Collecting, a n d Streaming
procedure virtual procedure procedure
205
FileSaveAs(var Msg: TMessage); cm_First + cm_SaveAs; LoadFile; SaveFile;
end; PAPoint = "APoint; APoint = object(TObject) X, Y: Integer; constructor Init(AX, AY: Integer); constructor Load(var S: TStream); procedure Store(var S: TStream); end; implementation
const RAPoint: TStreamRec = ( ObjType: 500; VmtLink: Ofs(TypeOf(APoint) ); Load: @APoint.Load; Store: ^APoint.Store); A
procedure StreamRegistration; begin RegisterType(RCollection); RegisterType(RAPoint); end;
constructor APoint.Init(AX, AY: Integer); begin X := AX; Y := AY; end;
const Iterations = 3000;
{ Number of iterations for this model } continues
206
P a r t i — W o r k i n g with TPW
Listing
6.9-
continued
constructor Modell.Init(AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(Hlnstance, PChar(111)); DisableAutoCreate; Attr.Style := ws_PopupWindow or ws_Caption or ws_Visible; Attr.X Attr.Y Attr.W Attr.H RangeXI RangeX2 RangeYI RangeY2
:= := := := := := := :=
100; 50; 300; 200; -1.03; 1.27; -0.3; 0.45;
{ Set window dimensions }
{ Set ranges to view }
A := 1.4; B := 0.3; InitX := 0.4; InitY := 0;
{ Set factors }
X := 0; Y := 0;
{ Initial point in space }
Points := New(PCollection, Init(50, 50)); IsDirty := False; IsNewFile := True; StreamRegistration;
{ Register stream }
end; procedure Modell.cm_Iterate(var Msg: TMessage); begin Iterate; { Iterate the model } end; procedure Modell.Scale;
6—Painting, Collecting, and Streaming 2 0 7
begin { Scale point in space to window } If (InitX = RangeXI) then { A little troubleshooting } X := Attr.X; If (InitX = RangeX2) then X := Attr.W; { and here } If (InitX = 0) then X := X; If (InitX > RangeXI) then X := round((InitX - RangeXI)/(RangeX2 - RangeXI) * (Attr.W - Attr.X)); Y := Attr.H - (round((InitY - RangeYI)/(RangeY2 - RangeYI) * (Attr.H - Attr.Y))); end; destructor Model"!.Done; begin Dispose(Points,Done); TWindow.Done; end;
{ Clean up points } { Call ancestor's destructor }
procedure Modell.Iterate; var I : integer; TempX, TempY : real; begin InvalidateRect(HWindow, nil,True); SetCapture(HWindow); DC := GetDC(HWindow); { Get a display context } for I := 1 to Iterations do begin TempX := InitX; { Save last state } TempY := InitY; { Save last state } InitX := TempY + 1 - (A * TempX * TempX); {This model } InitY := B * TempX; {This model } Scale; { Scale new state to a window } X := I; TextOut(DC,X,Y,'.',1); { Draw a point } Points".Insert(New(PAPoint, Init(X, Y))); end; continues
208
Part I — W o r k i n g w i t h T P W
Listing
6.9-
continued
ReleaseCapture; ReleaseDC(HWindow,DC); end;
{ Release Display context }
procedure Modell.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var First: Boolean; procedure DisplayPoints(P: PAPoint); far; begin TextOut(PaintDC,P".X,P".Y,'.',1); First := False; end; begin First := True; Points".ForEach(@DisplayPoints); end;
procedure Modell.FileNew(var Msg: TMessage); begin Points".FreeAll; InvalidateRect(HWindow, nil, True); IsDirty := False; IsNewFile := True; end; procedure Modell.FileOpen(var Msg: TMessage); begin if CanClose then if Application".ExecDialog(New(PFileDialog, Init(@Self, PChar(sd_FileOpen), StrCopy(FileName, '*.PTS')))) = id_0k then LoadFile; end; procedure Modell.FileSave(var Msg: TMessage); begin if IsNewFile then FileSaveAs(Msg) else SaveFile; end;
6—Painting, Collecting, and Streaming
procedure Modell.FileSaveAs(var Msg: TMessage); var FileDlg: PFileDialog; begin if IsNewFile then StrCopy(FileName, ' ' ) ; if Application".ExecDialog(New(PFileDialog, Init(@Self, PChar(sd_FileSave), FileName))) = id_0k then SaveFile; end; procedure Modell.LoadFile; var TempColl: PCollection; TheFile: TDosStream; begin TheFile.Init(FileName, stOpen); TempColl := PCollection(TheFile.Get); TheFile.Done; if TempColl nil then begin Dispose(Points, Done); Points := TempColl; InvalidateRect(HWindow, nil, True); { Forces Paint message } end; IsDirty := False; IsNewFile := False; end;
procedure Modell.SaveFile; var TheFile: TDosStream; begin TheFile.Init(FileName, stCreate); TheFile.Put(Points); TheFile.Done; IsNewFile := False; IsDirty := False; end;
constructor APoint.Load(var S: TStream); begin S.Read(X, SizeOf(X)); continues
209
210
P a r t i — W o r k i n g with TPW
Listing
6.9-
continued
S.Read(Y, SizeOf(Y)); end; procedure APoint.Store(var S: TStream); begin S.Write(X, SizeOf(X)); S.Write(Y, SizeOf(Y)); end;
end. { Unit time3 }
PART T W O
ADVANCED TOPICS
7
CHAPTER
MANY WINDOWS: A MULTIDOCUMENT INTERFACE It's an inherent property of intelligence that it can jump out of the task which it's performing, and survey what it has done; it is always looking for, and often finding, patterns. D o u g l a s R. H o f s t a d t e r O b j e c t W i n d o w s supports the W i n d o w s M u l t i - D o c u m e n t Interface (MDI) stand a r d , w h i c h a l l o w s a n a p p l i c a t i o n o r task t o w o r k s i m u l t a n e o u s l y w i t h m a n y o p e n d o c u m e n t s . U s u a l l y y o u t h i n k o f t h e s e d o c u m e n t s as text, d a t a b a s e , o r s p r e a d s h e e t files. Y o u m i g h t t h i n k o f this as a s p e c i a l k i n d o f m u l t i t a s k i n g s y s t e m , similar yet decidedly different f r o m the multitasking version o f the B a s i c l n t e r f a c e d e v e l o p e d i n C h a p t e r 5, " P u t t i n g P i c t u r e s i n W i n d o w s . " T h e k e y d i f f e r e n c e b e t w e e n t h e B a s i c l n t e r f a c e a n d M D I is that M D I m a k e s it e a s y f o r a s i n g l e a p p l i c a t i o n w i n d o w t o w o r k w i t h m a n y o p e n files. A g o o d e x a m p l e o f this k i n d o f a p p l i c a t i o n is a m u l t i f i l e e d i t o r , d e m o n s t r a t e d later i n this c h a p t e r . T h e B a s i c l n t e r f a c e can have many applications running simultaneously, w h i c h m e a n s m a n y o p e n files, b u t it is still p r i m a r i l y a " 1 w i n d o w , 1 task, 1 o p e n file" s y s t e m . I n t h e B a s i c l n t e r f a c e , o n e file is o p e n f o r e a c h w i n d o w , a n d e a c h w i n d o w h a s its o w n m e n u .
214
Part I I — A d v a n c e d T o p i c s
I n a n M D I s y s t e m , a s i n g l e m e n u serves as t h e c o n t r o l c e n t e r f o r several w i n d o w s at o n c e . T h e T u r b o Pascal I D E a n d M i c r o s o f t E x c e l are e x c e l l e n t e x a m p l e s o f M D I i n s o p h i s t i c a t e d a c t i o n (see figure 7 . 1 ) .
Basicl nterf ace
MDI
M ain W i n d o w
MainWindow
can
control
always controls
child
Child (can have
Figure
child
Child menu)
(no
menu)
7.1. Basiclnterface versus MDI
Y o u can a d d m u l t i d o c u m e n t capability to the B a s i c l n t e r f a c e by writing m o r e c o d e t o h a n d l e a d d i t i o n a l o p e n files, b u t a n e a s i e r w a y is t o u s e a n M D I o b j e c t a n d d e r i v e f r o m it t h e s p e c i f i c a p p l i c a t i o n s y o u n e e d . T h i s c h a p t e r s h o w s y o u h o w t o c r e a t e a B a s i c MDI I n t e r f a c e , w h i c h is then u s e d to derive t w o additional M D I applications.
A Basic MDI Interface J u s t as t h e B a s i c l n t e r f a c e d o e s , t h e MDI I n t e r f a c e c o n s i s t s o f t w o basic o b j e c t s : a n A p p l i c a t i o n a n d a MainWindow. A s y o u m i g h t e x p e c t , t h e y l o o k similar. T h e M D I A p p l i c a t i o n o b j e c t (also d e r i v e d f r o m T A p p l i c a t i o n ) reimplements two methods: InitMainWindow a n d I n i t A p p l i c a t i o n (see figure 7 . 2 ) .
7 — M a n y Windows: A Multi-Document Interface 2 1 5
Using
Pointers
InitApplication
(pointer)
A
Window
(pointer)
Child
Figure
7.2. Using
Window
pointers.
T o designate between the Basiclnterface and theMDI Interface, add "MDI" to M D I object names. A Basic M D I Application object looks like this: MDIApplication = object(TApplication) { Derive an application object } FirstApplication : boolean; procedure InitMainWindow; virtual; { Init a mainwindow } procedure InitApplication; virtual; end; The MainMDIWindow looks like this: PMainMDIWindow = "MainMDIWindow; MainMDIWindow = object(TMDIWindow) function InitChild : PWindowsObject; virtual; end; There are two n e w things to notice: 1. Y o u derive the MainMDIWindow from TMDIWindow. 2. Y o u need to reimplement an InitChild method, which is responsible for constructing the specific kind of child w i n d o w you want to attach to the MainMDIWindow.
216
Part I I — A d v a n c e d T o p i c s
A c h i l d c a n b e a n y w i n d o w t y p e d e r i v e d f r o m TWindow. F o r e x a m p l e : PChildWindow = "ChildWindow; ChildWindow = object(TWindow) end; or PChildWindow = "ChildWindow; ChildWindow = object(MainWindow) end; or PChildWindow = "ChildWindow; ChildWindow = object(ModelWindow) end; A n InitChild m e t h o d that c o n s t r u c t e d a ChildWindow m i g h t l o o k l i k e this: function MainMDIWindow.InitChild : PWindowsObject; begin InitChild := New(PChildWindow, Init(@Self, 'New child')); end; T h e InitChild m e t h o d is n o t l i m i t e d , h o w e v e r , t o c o n s t r u c t i n g a ChildWindow o n l y ; it c a n just as easily c o n s t r u c t a TWindow o r MainWindow directly: function MainMDIWindow.InitChild : PWindowsObject; begin InitChild := New(PMainWindow, Init(@Self, 'New child')); end; S e v e r a l c o m p o n e n t s ( o r f e a t u r e s ) are c o m m o n t o a n y M D I a p p l i c a t i o n . Every M D I a p p l i c a t i o n h a s a m a i n w i n d o w ( c a l l e d a frame w i n d o w ) , a n d w i t h i n t h e f r a m e w i n d o w a n invisible w i n d o w c a l l e d t h e M D I c l i e n t w i n d o w , w h i c h h o l d s M D I c h i l d w i n d o w s . T h e c l i e n t w i n d o w m a n a g e s ( b e h i n d t h e s c e n e s ) its M D I c h i l d w i n d o w s . I n fact, TMDIWindow's m e t h o d s m a i n l y c o n s t r u c t a n d manage child w i n d o w s a n d process m e n u selections. E a c h M D I f r a m e w i n d o w m u s t h a v e a m e n u that c o n t r o l s its c h i l d w i n d o w s . E a c h c h i l d w i n d o w is m a i n t a i n e d i n t h e f r a m e w i n d o w ' s ChildList (a l i n k e d list). T h e f r a m e w i n d o w ' s m e n u is c a l l e d a child window menu. E a c h t i m e a c h i l d w i n d o w is c o n s t r u c t e d a n d o p e n e d , it is a p p e n d e d t o this m e n u a u t o m a t i cally, a n d t h e c u r r e n t l y s e l e c t e d c h i l d w i n d o w is m a r k e d b y a c h e c k .
7 — M a n y Windows: A Multi-Document Interface 2 1 7
Each child w i n d o w can be maximized, minimized, tiled, and cascaded (features implemented for you already). A few restrictions are placed o n a child window: 1. It cannot have a m e n u ; thus all its methods must be controlled by the frame window. This limitation is a good reason to use the Basiclnterface if you need a multitasking system in which each w i n d o w controls its o w n destiny. 2. The child w i n d o w cannot extend outside the frame window's boundaries (Basiclnterface child windows can).
Setting Up a Basic MDI Interface It is simple enough to establish a Basic MDI Interface. It consists of an application object and an MDI W i n d o w (plus its menu). Actually, you have already seen the objects you need for a bare-bones interface. See listing 7.1 for the complete "first go" at the MDI Interface. Figure 7.3 shows the application created by this "first go."
Figure
7.3. The application
created by listing 7.1.
218
Part I I — A d v a n c e d T o p i c s
Listing
7.1. The first
unit WIFmdil;
listing
for
the MDI
Interface.
{ Creates a Basic MDI Windows application interface derived from ObjectWindows; ChildWindows are derived from TWindow object }
interface uses WObjects, WinTypes, WinProcs, WIF5; {$R WIFMdil.RES } type MDIApplication = object(TApplication) { Derive an application object } FirstApplication : boolean; procedure InitMainWindow; virtual; { Init a main window } procedure InitApplication; virtual; end; PMainMDIWindow = "MainMDIWindow; MainMDIWindow = object(TMDIWindow) function InitChild : PWindowsObject; virtual; end; PChildWindow = "ChildWindow; ChildWindow = object(TWindow) end;
implementation
function MainMDIWindow.InitChild : PWindowsObject; begin InitChild := New(PChildWindow, Init(©Self, 'New child')); end;
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
{ MDIApplication method implementation } procedure MDIApplication.InitMainWindow; begin if FirstApplication then MainWindow
:= New(PMainMDIWindow,
Init('MDI
Interface',
LoadMenu(HInstance, 'MDIMenul'))) else MainWindow := New(PMainMDIWindow, Init('MDI Additional Instance ,LoadMenu(HInstance, 'MDIMenul'))); end; 1
procedure MDIApplication.InitApplication; begin FirstApplication := True; end; end. L o o k familiar? It s h o u l d — i t is a s i m p l i f i e d v e r s i o n o f t h e first v e r s i o n o f t h e Basiclnterf ace. It u s e s s i m i l a r InitApplication a n d InitMainWindow m e t h o d s . InitMainWindow, a s i n t h e Basiclnterf ace, d e c i d e s w h i c h w i n d o w to construct a n d w h i c h m e n u to load. O n e minor difference between MDIWindows a n d TWindows is that t h e s e c o n d p a r a m e t e r o f t h e LoadMenu m e t h o d m u s t b e a string.
A Model MDI A s w r i t t e n , a ChildWindow c a n b e a n y k i n d o f w i n d o w d e r i v e d f r o m TWindow. F o r e x a m p l e , y o u c o u l d c h a n g e o n e o f t h e task m o d e l s ( w i n d o w s o b j e c t s ) f r o m C h a p t e r 5, " P u t t i n g P i c t u r e s i n W i n d o w s , " t o a c h i l d w i n d o w a n d h a v e a task w i n d o w c r e a t e d e a c h t i m e y o u c r e a t e a c h i l d . L i s t i n g 7.2 s h o w s t h e c o d e t o h a n d l e it, a n d f i g u r e 7.4 s h o w s t h e result. N o t e that t h e m o d e l w i n d o w a p p e a r s , b u t w i t h o u t its m e n u b e c a u s e c h i l d w i n d o w s , r e g a r d l e s s o f t y p e , a r e e x p e c t e d t o b e c o n t r o l l e d b y t h e f r a m e w i n d o w ' s c h i l d m e n u . T h e m o d e l , as it is d e s i g n e d , w o r k s w h e n it is r e s p o n d i n g t o t h e m a i n m e n u ' s c o m m a n d m e s s a g e s , but n o t otherwise—a definite, a n d probably u n w a n t e d , variation o n the m o d e l theme.
219
220
Part I I — A d v a n c e d T o p i c s
Figure Listing
7.4. The result of listing 7*2. Creating
unit WIFmdi3;
7.2.
a task window
for
each child
window.
{ Creates a Basic MDI Windows application interface derived from ObjectWindows; ChildWindows are derived from Model2 object }
interface uses WObjects, WinTypes, WinProcs, WIF5, attract2; {$R WIFMdi3.RES } type MDIApplication = object(TApplication) { Derive an application object } FirstApplication : boolean; procedure InitMainWindow; virtual; { Init a main window } procedure InitApplication; virtual; end;
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
221
PMainMDIWindow = "MainMDIWindow; MainMDIWindow = object(TMDIWindow) function InitChild : PWindowsObject; virtual; end; PChildWindow = "ChildWindow; ChildWindow = object(Model2) end;
implementation function MainMDIWindow.InitChild : PWindowsObject; begin InitChild := New(PChildWindow, Init(@Self, 'New child')); end;
{ MDIApplication method implementation }
procedure MDIApplication.InitMainWindow; begin if FirstApplication then MainWindow := New(PMainMDIWindow, Init('MDI Interface', LoadMenu(HInstance, 'MDIMenu3'))) else MainWindow := New(PMainMDIWindow, Init('MDI Additional Instance', LoadMenu(HInstance, 'MDIMenu3'))); end; procedure MDIApplication.InitApplication; begin FirstApplication := True; end; end.
MDI Message Processing M e s s a g e p r o c e s s i n g i n M D I w i n d o w s is s i m i l a r t o that i n n o n - M D I w i n d o w s . E a c h W i n d o w s c o m m a n d m e s s a g e (cm_J g o e s first t o t h e c h i l d w i n d o w c u r r e n t l y s e l e c t e d . A c h i l d , t h e r e f o r e , g e t s t h e first c h a n c e t o r e s p o n d t o t h e
222
Part I I — A d v a n c e d T o p i c s
m e s s a g e . I f it d o e s n o t r e s p o n d , t h e m e s s a g e g o e s t o t h e M D I c l i e n t w i n d o w , a n d finally t o t h e M D I f r a m e w i n d o w . E a c h t i m e y o u select a n M D I c h i l d w i n d o w , it b e c o m e s active a n d r e c e i v e s a W i n d o w s w m M D I A c t i v a t e m e s s a g e . Y o u c a n , if y o u w a n t , d e f i n e a m e s s a g e r e s p o n s e m e t h o d for this m e s s a g e ( u s e f u l w h e n y o u n e e d t o k e e p track o f t h e active ChildWindow). M D I child windows d o not respond to c o m m a n d messages generated by t h e c h i l d w i n d o w m e n u . T h a t is a j o b f o r t h e f r a m e w i n d o w .
Editors B e f o r e y o u g e t t o t h e g r a n d f i n a l e o f this c h a p t e r , a m u l t i - d o c u m e n t text e d i t o r u s i n g t h e MDI Interface, y o u c a n i m p l e m e n t a c o u p l e o f s i m p l e e d i t o r s t o s h o w y o u h o w easy it is t o a d d p o w e r f u l t e x t - e d i t i n g c a p a b i l i t y t o a w i n d o w . O b j e c t W i n d o w s s u p p l i e s t w o d e s c e n d a n t s o f TWindow, w h i c h a r e s p e c i a l i z e d w i n d o w s for text e d i t i n g . TEditWindow is a text e d i t o r that e n a b l e s y o u t o e d i t text i n a w i n d o w : c u t , c o p y , p a s t e , a n d s o o n , t o t h e c l i p b o a r d , b u t d o e s n o t a l l o w y o u t o r e a d a n d w r i t e files. O n e o f its d e s c e n d a n t s , TFileWindow, a d d s r e a d i n g a n d w r i t i n g t o file capability. T h e s e e d i t o r s a r e r e a d y t o g o a n d a r e u s e f u l right o u t o f t h e b o x . T o u s e a n Ed i t w i n d o w r e q u i r e s n o m o r e t h a n a m e s s a g e t o its constructor w h e n y o u initialize a n a p p l i c a t i o n ' s MainWindow. T h e definition: FileWindow = "FileWindow; FileWindow = object(TFileWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); end; The Implementation: procedure begin
Application.InitMainWindow;
MainWindow end;
:= New(PEditWindow,
Init(nil,
'Edit Window Tester'));
S i m p l e , yes? L i s t i n g 7.3 s h o w s t h e c o m p l e t e c o d e for g e n e r a t i n g t h e text e d i t o r s h o w n in figure 7.5.
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
Figure Listing
7.5. The text editor generated 7 . 3 . Generating
a text
by listing
223
73.
editor.
program EditWin; {$R EditWin.RES} uses WObjects, WinTypes, WinProcs, Strings, StdWnds;
type EditApp = object(TApplication) procedure InitMainWindow; virtual; end; PEditWindow = "EditWindow; EditWindow = object(TEditWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); end; constructor EditWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin continues
224
Part I I — A d v a n c e d T o p i c s
Listing
73.
continued
TEditWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, MakeIntResource(105)); end;
procedure EditApp.InitMainWindow; begin MainWindow := New(PEditWindow, Init(nil, 'Edit Window')); HAccTable := LoadAccelerators(HInstance, MakeIntResource(100)); end; var App : EditApp; begin App.Init('EditWnd'); App.Run; App.Done; end. A d d i n g a FileWindow t o a n a p p l i c a t i o n is just as easy. J u s t d e r i v e t h e EditWindow f r o m TFileWindow r a t h e r t h a n f r o m TEditWindow:
EditWindow = "EditWindow; EditWindow = object(TFileWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); end; constructor EditWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin TFileWindow.Init(AParent, ATitle, nil); Attr.Menu := LoadMenu(HInstance, 'FileCommands'); end; T h e FileWindow c o m e s c o m p l e t e w i t h a FileDialog f o r c r e a t i n g , o p e n i n g , a n d s a v i n g files; c o m p l e t e c l i p b o a r d c o n n e c t i o n s i n c l u d i n g a n U n d o c o m m a n d , a n d a s e a r c h a n d r e p l a c e facility. T h e o n l y " p r o g r a m m i n g " r e q u i r e d o f y o u is c r e a t i n g a m e n u that c o n t a i n s t h e p r e d e f i n e d I D s f o r file m a n i p u l a t i o n . A l l y o u n e e d t o a d d is a S e a r c h m e n u c h o i c e . Note: T h e T u r b o Pascal s o u r c e c o d e a n d r e s o u r c e s a r e o n t h e u s e r d i s k i n t h e b a c k o f this b o o k . C h a p t e r 8, " R e s o u r c e s a n d C o n t r o l O b j e c t s , " d e t a i l s resource creation. L i s t i n g 7.4 s h o w s t h e c o m p l e t e c o d e f o r i m p l e m e n t i n g t h e File w i n d o w e d i t o r s h o w n i n figure 7.6.
7 — M a n y Windows: A Multi-Document Interface 2 2 5
Figure
Listing
7.6. A file window editor.
7.4.
Generating
a file
window
editor.
program EditWin; {$R EditWin.RES} uses WObjects, WinTypes, WinProcs, Strings, StdWnds;
type EditApp = object(TApplication) procedure InitMainWindow; virtual; end; PEditWindow = "EditWindow; EditWindow = object(TFileWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); end; constructor EditWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin TEditWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, MakeIntResource(105)); end; continues
2 2 6 Part II—Advanced Topics
Listing
73-
continued
procedure EditApp.InitMainWindow; begin MainWindow := New(PEditWindow, Init(nil, 'Edit Window')); HAccTable := LoadAccelerators(HInstance, MakeIntResource(100)); end; var App : EditApp; begin App.Init('FileWnd'); App.Run; App.Done; end.
An MDI Editor N o w that you have created a FileWindow, you can use it as your M D I child window. It is just another w i n d o w as far as the M D I application is concerned. TFileWindow already has a rich set of methods for handling m a n y of the m e n u c o m m a n d messages an editor needs to respond to, such as cut, copy, saving afile,and so on. Table 7.1 lists the command-message response methods you use "as is," with no modification, in this example. Table
7.2. FileWindow
methods.
Method
Responds
CMEditClear
cm_First + c m E d i t C l e a r
CMEditCopy
cmFirst +
CMEditCut
cmFirst + cmJEditCut
CMEditDelete
cmFirst + cmEditDelete
CMEditPaste
cmFirst + cmEditPaste
CMEditUndo
cmFirst +
CMFileSave
cmFirst + cmFileSave
CMFileSaveAs
c m First + c m F i l e S a v e A s
to Command
cmEditCopy
cmEditUndo
Message
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
227
Y o u n e e d t o m o d i f y t h e MDI MainWindow t o h a n d l e t h e m e n u c o m m a n d m e s s a g e s t o c r e a t e a n d o p e n files. T h e n e w CMNewFile m e t h o d n e e d s t o c o n s t r u c t a n e w file e d i t o r . It l o o k s like this:
procedure MDIFileWindow.CMNewFile(var Msg: TMessage); begin Application".MakeWindow(New(PFileEditor, Init(@Self, ''))); end; T h e n e w CMOpenFile m e t h o d n e e d s t o e x e c u t e a file d i a l o g a n d c o n s t r u c t a n e w file e d i t o r . It l o o k s l i k e this:
procedure MDIFileWindow.CMOpenFile(var Msg: TMessage); var FileName: array[0..fsPathName] of Char; begin if Application".ExecDialog(New(PFileDialog, Init(@Self, PChar(sd_FileOpen), StrCopy(FileName, '*.*')))) = id_Ok then Application".MakeWindow(New(PFileEditor, Init(@Self, FileName))); end; It a l s o w o u l d b e c o n v e n i e n t if m e n u i t e m s c o u l d b e t u r n e d o n a n d off, d e p e n d i n g o n w h e t h e r a m e n u i t e m is u s a b l e at t h e t i m e . T h e easiest way t o h a n d l e this e n a b l i n g a n d d i s a b l i n g is t o o v e r r i d e MDI FileWindows' Set upWindow m e t h o d t o d i s a b l e s p e c i f i c m e n u i t e m s . T h e n w h e n a FileWindow is c r e a t e d , you enable the m e n u items. T h e n e w SetupWindow m e t h o d simply u s e s TMDIWindow's d e f a u l t Set upWindow ( w h i c h h a s b e e n c a l l e d automatically if you h a v e n o t o v e r r i d d e n it) a n d t h e n calls t h e EnableMenuItems m e t h o d .
N o t e : W h e n e v e r y o u o v e r r i d e b a s i c m e t h o d s , s u c h as SetupWindow, destructors, a n d s o o n , y o u o f t e n n e e d t o s e n d a message explicitly to the ancestor's m e t h o d to h a n d l e default p r o c e s s i n g . S e n d i n g a m e s s a g e t o a m e t h o d is s i m p l e r t h a n rewriting the default c o d e !
T h e n e w SetupWindow l o o k s l i k e this:
procedure MDIFileWindow.SetupWindow; begin TMDIWindow.SetupWindow; EnableMenuItems(Disable); end;
228
Part I I — A d v a n c e d T o p i c s
T h e EnableMenuItems i m p l e m e n t a t i o n e n s u r e s that m e n u s e l e c t i o n s a r e available o n l y w h e n a n e d i t o r is active. Its i m p l e m e n t a t i o n is s h o w n i n t h e c o d e f o r t h e e n t i r e M D I e d i t o r u n i t i n listing 7.6 at t h e e n d of this c h a p t e r . O n e o t h e r e s s e n t i a l m o d i f i c a t i o n is t o o v e r r i d e t h e d e f a u l t FileWindow destructor t o e n a b l e it t o d e s t r o y all t h e e d i t o r s c r e a t e d d u r i n g a n M D I s e s s i o n . T h e d e f a u l t destructor d o e s n o t look a u t o m a t i c a l l y f o r t h e file e d i t o r s you or your user might have created. F o r t u n a t e l y , it is a s i m p l e m a t t e r t o i m p l e m e n t this n e w destructor,
u s i n g t h e MDI ForEach m e t h o d . A n e w destructor for MDIFileWindow l o o k s like t h i s :
destructor MDIFileWindow.Done; procedure DestroyEditors(AnEditor begin PFileEditor(AnEditor) .Done; end; begin if (Edit'orCount) 0 then ForEach(@DestroyEditors); TMDIWindow.Done; end;
: PWindowsObject); far;
A
T h e r e a r e a l s o a f e w nifty f e a t u r e s y o u c a n a d d t o this e d i t o r t o m a k e it look e v e n m o r e s i m i l a r t o t h e T u r b o Pascal for W i n d o w s I D . Y o u c a n l o a d a n Icon
for t h e FileEditor b y m o d i f y i n g t h e GetWindowClass m e t h o d :
procedure FileEditor.GetWindowClass(var AWndClass: TWndClass); begin TFileWindow.GetWindowClass(AWndClass); AWndClass.hlcon := LoadIcon(HInstance, 'FILEICON'); end; Y o u a l s o c a n save a n d r e s t o r e states ( T u r b o Pascal for W i n d o w s style) b y w r i t i n g t h e w i n d o w ' s c u r r e n t state a n d c u r s o r p o s i t i o n t o a s t r e a m (in this c a s e , a file) a n d r e a d i n g it b a c k . T o save a state:
begin S := New(PBufStream, Init(DskFile, stCreate, 1024)); PutChildren(S ); { Handles the save } if S .Status stOk then { Status check } begin Dispose(S, Done); FileDelete(DskFile); MessageBox(HWindow, 'Unable to write desktop file.', 'Disk error', A
A
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
mb_0k or mb_IconExclamation); end else Dispose(S, Done); PutChildren, aTWindows o b j e c t m e t h o d , is t h e k e y t o s a v i n g t h e s t a t e . It iterates t h r o u g h t h e w i n d o w ' s c h i l d w i n d o w list, w r i t i n g t h e c o n t e n t s o f e a c h of the child w i n d o w s to the stream. T o r e s t o r e a s t a t e , u s e a n o t h e r TWindows o b j e c t m e t h o d , GetChildren, t o d o m o s t o f t h e w o r k . TWindowsObj ect .GetChildren r e a d s t h e s t o r e d contents' child w i n d o w s from the stream, a n d puts t h e m in the window's child w i n d o w list. R e s t o r e l o o k s l i k e this:
procedure MDIFileWindow.CMRestoreState(var Msg: TMessage); var S: PStream; ErrorMsg: PChar; begin ErrorMsg := nil; S := New(PBufStream, Init(DskFile, stOpenRead, 1024)); if S".Status stOk then { Error checking } ErrorMsg := 'Unable to open desktop file.' else begin CloseChildren; GetChildren(S'); { Handles the restore } if S".Status stOk then ErrorMsg := 'Error reading desktop file.'; if LowMemory then { More error checking } begin CloseChildren; ErrorMsg := 'Not enough memory to open file.' end else CreateChildren; end; if ErrorMsg nil then MessageBox(HWindow, ErrorMsg, 'Disk error', mb_0k or mb_IconExclamation); end; Finally, y o u c a n a d d a H e l p W i n d o w t o t h e MDI FileEditor, u s i n g a H e 1 pWn d u n i t l i k e t h e o n e i n l i s t i n g 7.5 that u s e s a list b o x , b u t t o n s , a n d a c o n t r o l to implement a sample help window.
229
230
Part I I — A d v a n c e d T o p i c s
Listing
7.5- Creating
a Help
window.
unit HelpWind; interface uses Strings, WObjects, WinTypes, WinProcs; const id_LB1 id_BN1 id_BN2 id_EC1 id_ST1
= = = = =
201; 202; 203; 204; 205;
type PHelpWindow = "THelpWindow; THelpWindow = object(TWindow) LB1: PListBox; EC1: PEdit; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure SetupWindow; virtual; procedure IDLB1(var Msg: TMessage); virtual id_First + id_LB1; procedure IDBN1(var Msg: TMessage); virtual id_First + id_BN1; procedure IDBN2(var Msg: TMessage); virtual id_First + id_BN2; procedure FillEdit(SelStringPtr: PChar); virtual; end; implementation constructor THelpWindow.Init(AParent: PWindowsObject; ATitle: PChar); var TempStat : PStatic; TempBtn: PButton; begin TWindow.Init(AParent, ATitle); DisableAutoCreate; Attr.Style := ws_PopupWindow or ws_Caption or ws_Visible; Attr.X := 100; Attr.Y := 100;
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
231
Attr.W := 300; Attr.H := 300; LB1 := New(PListBox, Init(@Self, id_LB1, 20, 20, 180, 80)); TempBtn := New(PButton, Init(@Self, id_BN1, 'Help', 220, 20, 60, 30, True)); TempBtn := New(PButton, Init(@Self, id__BN2, 'Cancel', 220, 70, 60, 30, False)); EC1 := New(PEdit, Init(@Self, id_EC1, '', 20, 180, 260, 90, 40, True)); EC1".Attr.Style := EC1 .Attr.Style or ws_Border or ws_VScroll; TempStat := New(PStatic, Init(@Self, id_ST1,'Help Information:', 20, 160, 160, 20, 0)); end; A
procedure THelpWindow.SetupWindow; begin TWindow.SetupWindow; { Fill the listbox } LB1".AddString('Helpl ); LB1".AddString('Help2'); LB1".AddString('Help3'); LB1".AddString('Help4'); LB1".SetSelIndex(0); end; 1
procedure THelpWindow.IDLB1(var Msg: TMessage); var SelString: array[0..25] of Char; begin if Msg.LParamHi = lbn_DblClk then begin LB1".GetSelString(SelString, 25); FillEdit(SelString); end; end; procedure THelpWindow.IDBN1(var Msg: TMessage); var SelString: array[0..25] of Char; begin LB1 .GetSeIString(SelString, 25); FillEdit(SelString); end; A
procedure THelpWindow.IDBN2(var Msg: TMessage); begin CloseWindow; end; continues
232
Part I I — A d v a n c e d T o p i c s
Listing
7.5-
continued
procedure THelpWindow.FillEdit(SelStringPtr: PChar); var TheString: PChar; begin if StrComp(SelStringPtr, 'List Boxes') = 0 then TheString := 'Helpl. else if StrComp(SelStringPtr, 'Buttons') = 0 then TheString := 'Help2.' else if StrComp(SelStringPtr, 'Scroll Bars') = 0 then TheString := 'Help3' else if StrComp(SelStringPtr, 'Edit Controls') = 0 then TheString := 'Help4. ; EC1 .SetText(TheString); end; 1
1
A
end. F i g u r e 7.7 s h o w s t h e c o m p l e t e M D I File E d i t o r w i t h several file e d i t o r s o p e n , a n d listing 7.6 s h o w s t h e c o m p l e t e M D I File e d i t o r c o d e that p r o d u c e d f i g u r e 7.7.
Figure
7.7. The MDI file
editor.
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
MDI map-up T h a t a b o u t w r a p s u p t h e MDI Interface a n d t h e first s t a g e o f t h e i n t r o d u c t i o n t o d e v e l o p i n g Windows a p p l i c a t i o n s u s i n g T u r b o P a s c a l for Windows. Chapter 8, " R e s o u r c e s a n d C o n t r o l O b j e c t s , " e x p l a i n s how t o d e v e l o p resources using t h e Whitewater G r o u p ' s Resource Toolkit. B y n o w y o u s h o u l d b e g e t t i n g t h e m e s s a g e that d e v e l o p i n g s o p h i s t i c a t e d a p p l i c a t i o n s for Windows is n o t a c o m p l i c a t e d , m e s s y affair, b u t a c t u a l l y a p l e a s a n t o n e if y o u u s e T u r b o P a s c a l for Windows. Windows d e v e l o p m e n t is n o t difficult if y o u u s e t h e O O P t e c h n i q u e s o u t l i n e d i n t h e s e first s e v e n c h a p t e r s . T h e c o m p l e x part o f Windows d e v e l o p m e n t is t e a c h i n g a n a p p l i c a t i o n t o interact w i t h Windows, a n d that i n t e r a c t i o n is a l r e a d y handled for y o u w h e n y o u u s e O b j e c t W i n d o w s . Y o u just n e e d t o m a k e y o u r a p p l i c a t i o n s respond to events and messages and use O O P techniques to derive y o u r applications and w i n d o w s . When y o u have l e a r n e d t o a d j u s t y o u r o w n t h i n k i n g t o O O P t e r m s , a p p l i c a t i o n d e v e l o p m e n t for Windows is just as e a s y as a p p l i c a t i o n d e v e l o p m e n t for a n y o t h e r e n v i r o n m e n t . I n fact, a p p l i c a t i o n d e v e l o p m e n t for Windows is e a s i e r b e c a u s e t h e i n t e r f a c e , i n c l u d i n g d e v i c e d r i v e r s , I/O, a n d s o f o r t h , is a l r e a d y handled for y o u . Developing one-window or many-window applications using Turbo P a s c a l for Windows is a p i e c e o f d e l i c i o u s c a k e — t o p p i n g , y o u r c h o i c e — r e a l l y . Listing
7.6.
Creating
the complete
unit mdi_ed2;
MDI
editor.
{ Adds File Editor to MDI }
{$R MDIed.RES} interface uses WObjects, WinTypes, WinProcs, WinDos, StdDlgs, StdWnds, Strings, HelpWind; const cm_SaveState = 200; cm_RestoreState = 201; cm_Help = 901; continues
233
234
Part I I — A d v a n c e d T o p i c s
Listing
7.6.
continued
const DskFile = MDI.DSK ; 1
1
type { Declare MDIApp, a TApplication descendant } MDIApp = object(TApplication) procedure InitMainWindow; virtual; procedure Initlnstance; virtual; end; { Declare MDIFileWindow, a TMDIWindow descendant } PMDIFileWindow = "MDIFileWindow; MDIFileWindow = object(TMDIWindow) destructor Done; virtual; procedure SetupWindow; virtual; procedure CMNewFile(var Msg: TMessage); virtual cm_First + cm_MDIFileNew; procedure CMOpenFile(var Msg: TMessage); virtual cm__First + cm_MDIFileOpen; procedure CMSaveState(var Msg: TMessage); virtual cm_First + cm_SaveState; procedure CMRestoreState(var Msg: TMessage); virtual cm_First + cm_RestoreState; procedure CMHelp(var Msg: TMessage); virtual cm_First + cm_Help; end;
{ Declare TFileEditor, a TFileWindow descendant } PFileEditor = "FileEditor; FileEditor = object(TFileWindow) constructor Init(AParent: PWindowsObject; AFileName: PChar); destructor Done; virtual; procedure GetWindowClass(var AWndClass: TWndClass); virtual; function GetClassName: PChar; virtual; end; const RFileEditor: TStreamRec = ( ObjType: 1000; VmtLink: Ofs(TypeOf(TFileEditor) ); Load: ^TFileEditor.Load; A
7 — M a n y Windows: A Multi-Document Interface 2 3 5
Store:
@TFileEditor.Store);
{ TFileEditor } const EditorCount: Integer = 0; type TMenuState = (Enable, Disable); implementation procedure MDIFileWindow.CMHelp(var Msg: TMessage); var HelpWnd: PWindow; begin HelpWnd := New(PHelpWindow, Init(@Self, 'Help System')); Application".MakeWindow(HelpWnd); end; procedure EnableMenuItems(State: TMenuState); procedure EnableCommand(Command: Word); var NewState: Word; begin NewState := mf_ByCommand; if State = Enable then Inc(NewState, mf_Enabled) else Inc(NewState, mf_Disabled + mf_Grayed); EnableMenuItem(PWindow(Application".MainWindow) .Attr.Menu, end; A
begin EnableCommand(cm_FileSave); EnableCommand(cm_FileSaveAs); EnableCommand(cm_ArrangeIcons); EnableCommand(cm_TileChildren); EnableCommand(cm_CascadeChildren); EnableCommand(cm_CloseChildren); EnableCommand(cm_EditCut); EnableCommand(cmJEditCopy); EnableCommand(cm_EditPaste); EnableCommand(cm_EditDelete);
Command, NewState);
{ Response methods already built-in } { To TFileWindow } { To TFileWindow }
continues
236
Part I I — A d v a n c e d T o p i c s
Listing
7.6.
continued
EnableCommand(cm_EditClear); EnableCommand(cm_EditUndo); EnableCommand(cm_EditFind); EnableCommand(cm_EditReplace); EnableCommand(cm_EditFindNext); end; procedure IncEditors; begin if EditorCount = 0 then EnableMenuItems(Enable); { New editor } Inc(EditorCount); end; procedure DecEditors; begin Dec(EditorCount); if EditorCount = 0 then EnableMenuItems(Disable); end; constructor FileEditor.Init(AParent: PWindowsObject; AFileName:PChar); begin TFileWindow.Init(AParent, ' A F i l e N a m e ) ; IncEditors; { Keep track of the number of editors } end; destructor FileEditor.Done; begin TFileWindow.Done; DecEditors; end;
{ Auto destruct using ancestor's Done }
procedure FileEditor.GetWindowClass(var AWndClass: TWndClass); begin TFileWindow.GetWindowClass(AWndClass); { Optional icon } AWndClass.hlcon := LoadIcon(HInstance, 'FILEICON'); end; function FileEditor.GetClassName: begin GetClassName := FileEditor'; end;
PChar;
1
procedure MDIFileWindow.CMNewFile(var
Msg: TMessage);
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
begin Application".MakeWindow(New(PFileEditor, end; destructor MDIFileWindow.Done;
Init(@Self,
237
'')));
{ Destroy all editors }
procedure DestroyEditors(AnEditor : PWindowsObject); far; begin PFileEditor(AnEditor) .Done; end; begin if (EditorCount) 0 then ForEach(@DestroyEditors); { Use ForEach to destroy all editors } TMDIWindow.Done; end; A
procedure MDIFileWindow.SetupWindow; begin TMDIWindow.SetupWindow; EnableMenuItems(Disable); { Menu items are not usable yet, so disable them } end; procedure MDIFileWindow.CMOpenFile(var Msg: TMessage); var FileName: array[0..fsPathName] of Char; begin if Application".ExecDialog(New(PFileDialog, Init(@Self, PChar(sd_FileOpen), StrCopy(FileName, '*-*')))) = id_Ok then Application".MakeWindow(New(PFileEditor, Init(@Self, FileName))); end; { Save the position and contents of the windows to a desktop file. } procedure MDIFileWindow.CMSaveState(var Msg: TMessage); var S: PStream; function FileDelete(Name: PChar): Integer; assembler; asm PUSH DS LDS DX,Name MOV AH,41H INT 21H JC (a@l XOR AX,AX continues
238
Part I I — A d v a n c e d T o p i c s
Listing
7.6.
@@1:
NEG
continued
AX POP
DS
end; begin S := New(PBufStream, Init(DskFile, stCreate, 2048)); PutChildren(S"); if S".Status stOk then begin Dispose(S, Done); FileDelete(DskFile); MessageBox(HWindow, 'Unable to write desktop f i l e . , 'Disk error', mb_Ok or mb_IconExclamation); end else Dispose(S, Done); end; { Read windows positions and contents from a "desktop" file. } procedure MDIFileWindow.CMRestoreState(var Msg: TMessage); var S: PStream; ErrorMsg: PChar; begin ErrorMsg := nil; S := New(PBufStream, Init(DskFile, stOpenRead, 1024)); if S".Status stOk then ErrorMsg := 'Unable to open desktop file.' else begin CloseChildren; GetChildren(S'); if S .Status stOk then ErrorMsg := 'Error reading desktop file.'; if LowMemory then begin CloseChildren; ErrorMsg := 'Not enough memory to open file.' end else CreateChildren; end; if ErrorMsg nil then MessageBox(HWindow, ErrorMsg, 'Disk error', mb_Ok or mb_IconExclamation); end; 1
A
7 — M a n y W i n d o w s : A M u l t i - D o c u m e n t Interface
procedure MDIApp.InitMainWindow; begin MainWindow := New(PMDIFileWindow, Init('MDI Files', LoadMenu(HInstance, 'Commands'))); PMDIFileWindow(MainWindowp.ChildMenuPos := 3; { Register types to be written to stream } RegisterType(RWindow); RegisterType(REdit); RegisterType(RFileEditor); end; procedure MDIApp.Initlnstance; begin TApplication.Initlnstance; if Status = 0 then { Optional loading of accelerator table } begin HAccTable := LoadAccelerators(HInstance, 'FileCommands ); if HAccTable = 0 then Status := em_InvalidWindow; end; end; 1
end.
239
8
CHAPTER
RESOURCES A N D CONTROL OBJECTS
Everyone agrees that the world is also full of large projects.
is full
of large
objects.
Sometimes
the
world
Andrei Codrescu T h e previous seven chapters discussed object-oriented programming in general a n d its a p p r o p r i a t e n e s s t o W i n d o w s a p p l i c a t i o n d e v e l o p m e n t i n p a r t i c u l a r . T h e T u r b o Pascal f o r W i n d o w s s i d e o f W i n d o w s a p p l i c a t i o n d e v e l o p m e n t w a s covered, using resources and control objects, but without detailing h o w you create a n d maintain resources a n d control objects. B e f o r e y o u g o a little d e e p e r i n t o r e s o u r c e s a n d c o n t r o l o b j e c t s , m a k e s u r e that y o u u n d e r s t a n d t h e Pascal s i d e o f W i n d o w s a p p l i c a t i o n d e v e l o p m e n t . I n g e n e r a l , it is a t h r e e - s t e p p r o c e s s : 1. D e r i v i n g a n a p p l i c a t i o n a n d a MainWindow ( f r o m t h e abstract o b j e c t s i n ObjectWindows). 2. C o n n e c t i n g t h e a p p l i c a t i o n a n d its MainWindow t o r e s o u r c e s . 3. T e a c h i n g t h e n e w a p p l i c a t i o n t o r e s p o n d t o e v e n t s a n d m e s s a g e s g e n e r a t e d b y W i n d o w s a n d r e s o u r c e s , s u c h as m e n u s .
242
Part I I — A d v a n c e d T o p i c s
A s it h a s b e e n s h o w n , O O P t e c h n i q u e s s i m p l i f y W i n d o w s a p p l i c a t i o n development by • Encapsulating W i n d o w s ' complexity in objects. • A l l o w i n g y o u t o d e r i v e n e w o b j e c t s f r o m e x i s t i n g o n e s ( u s i n g inheritance). • A l l o w i n g y o u r a p p l i c a t i o n s t o s e n d g e n e r a l m e s s a g e s that a n o t h e r w i n d o w o r a p p l i c a t i o n r e s p o n d s t o as it s e e s fit ( u s i n g p o l y m o r p h i s m ) . • M a k i n g it e a s y f o r a p p l i c a t i o n s t o u s e d y n a m i c o b j e c t s , c o l l e c t i o n s , a n d s t r e a m s , a n d t h u s a l l o w i n g a p p l i c a t i o n s t o m i x a n d m a t c h o b j e c t s , lists, a n d files o f v a r y i n g size a n d n u m b e r . T h e first part o f this c h a p t e r shifts g e a r s a n d e x p l a i n s h o w y o u c r e a t e a n d m a i n t a i n r e s o u r c e s . T h e s e c o n d part s h o w s y o u several m o r e w a y s t o u s e t h e user interface devices called controls o r control objects.
Resources R e s o u r c e s are t h e m e n u s , d i a l o g b o x e s (or w i n d o w s ) , bit m a p s , i c o n s , keyb o a r d a c c e l e r a t o r s , s t r i n g s , a n d c u r s o r s that y o u r T u r b o Pascal f o r W i n d o w s applications use to establish a consistent, user-friendly interface. Y o u c r e a t e r e s o u r c e s o u t s i d e o f T u r b o Pascal f o r W i n d o w s b y 1. U s i n g a r e s o u r c e e d i t o r t o g e n e r a t e a l i n k a b l e (binary) file. 2 . U s i n g a text e d i t o r t o c r e a t e a r e s o u r c e script file, w h i c h y o u " c o m p i l e " o r l i n k i n t o y o u r e x e c u t a b l e ( . E X E ) file u s i n g t h e M i c r o s o f t R e s o u r c e Compiler. R e s o u r c e c o d e a n d P a s c a l c o d e are s t o r e d i n s e p a r a t e files (with R E S a n d P A S e x t e n s i o n s ) a n d m a i n t a i n e d as s e p a r a t e e n t i t i e s . T h i s s e p a r a t i o n o f e n t i t i e s is a d v a n t a g e o u s f o r several r e a s o n s : • O n e resource, for e x a m p l e , can b e u s e d by m o r e than o n e application. • A resource or an application can be changed (and recompiled) without recompiling the other. • R e s o u r c e s a r e , b y d e f a u l t , not loaded i n t o m e m o r y w h e n t h e a p p l i c a t i o n starts. R a t h e r , t h e y are l o a d e d w h e n t h e a p p l i c a t i o n r e q u e s t s t h e m . F i g u r e 8.1 illustrates this c o n c e p t .
8—Resources and Control Objects
R e s o u r c e s aren't loaded until requested
Windows
1)
Load Resource!
Application
2) r e q u e s t
Resource2
Resource3
Figure
8.1. Resources are loaded when an application requests them.
R e s o u r c e s are t h e s p e c i f i c a t i o n s ( e x p r e s s e d as d a t a ) f o r t h e c o r r e s p o n d ing interface e l e m e n t s ( m e n u s , d i a l o g s , a n d s o forth) that Windows constructs for y o u r a p p l i c a t i o n . R e s o u r c e d a t a are s t o r e d in t h e E X E file, b u t n o t in t h e application's data segment, where y o u might expect t h e m to b e stored. R e s o u r c e d a t a a n d Pascal s o u r c e c o d e d a t a d o n o t c o m p e t e f o r t h e s a m e s p a c e . Y o u " c o n n e c t " resources
t o t h e E X E file in o n e o f t h e f o l l o w i n g w a y s :
1. C o p y i n g resources f r o m a R E S file into t h e c o m p i l e d a p p l i c a t i o n ' s E X E file u s i n g t h e Whitewater R e s o u r c e T o o l k i t (or a n o t h e r resource editor) 2. A d d i n g t h e {$R} c o m p i l e r directive t o y o u r . PAS file 3. U s i n g t h e M i c r o s o f t R e s o u r c e C o m p i l e r T h e s i m p l e s t alternative, u s e d in t h e e x a m p l e s s o far, is t o u s e t h e {$R} c o m p i l e r directive. T h i s directive tells t h e c o m p i l e r that y o u w a n t t o a d d t h e s p e c i f i e d resource file t o t h e e n d o f t h e e x e c u t a b l e file. N o t e that y o u c a n c o m p i l e Pascal s o u r c e c o d e that u s e s resources b e f o r e y o u a c t u a l l y create t h e resources. T h u s , y o u c a n write a n d test t h e P a s c a l o r resource part o f t h e a p p l i c a t i o n in either order. If y o u u s e t h e {$R} directive t o a t t a c h resources, however, it m e a n s that t h e resource a n d t h e Pascal s o u r c e c o d e are b o u n d u n l e s s y o u u n b i n d t h e m b y recompiling t h e Pascal s o u r c e c o d e . I n o t h e r w o r d s , y o u c a n n o t e l i m i n a t e a resource s p e c i f i e d b y t h e {$R} directive w i t h o u t recompiling t h e Pascal source c o d e . Y o u c a n still a d d n e w resources b y c o p y i n g n e w resources into t h e E X E
243
244
Part I I — A d v a n c e d T o p i c s
file, b u t y o u risk s o m e c o n f u s i o n b y m i x i n g r e s o u r c e s i n this m a n n e r . W h e n y o u c o m p i l e c o d e e x c l u s i v e l y f o r yourself, it is p r o b a b l y e a s i e r t o u s e t h e { $ R } d i r e c t i v e t o specify r e s o u r c e s . F o r m e , it is s i m p l e s t t o a t t a c h e a c h w i n d o w t o its o w n r e s o u r c e file. If y o u w a n t t o c h a n g e a w i n d o w ' s r e s o u r c e , y o u edit t h e r e s o u r c e file f o r that w i n d o w . A one-window, one-resource-file scenario reduces confusion. F o r e x a m p l e , i n C h a p t e r 7, " M a n y W i n d o w s : A M u l t i - D o c u m e n t Interf a c e , " y o u d e r i v e d a MainMDIWindow f r o m TMDIWindow: PMainMDIWindow = "MainMDIWindow; MainMDIWindow = object(TMDIWindow) function InitChild
: PWindowsObject; virtual;
end; a n d c o n n e c t e d it t o its r e s o u r c e , first u s i n g t h e { $ R } d i r e c t i v e t o attach its r e s o u r c e s t o t h e E X E file: {$R WIFMdil.RES } and then by attaching a m e n u MainMDIWindow: procedure begin
resource
(in M D I M a i n W i n d o w . R E S )
to
MDIApplication.InitMainWindow;
if FirstApplication then MainWindow := New(PMainMDIWindow, Init('MDI LoadMenu(HInstance, MDIMenul ))) 1
Interface , 1
1
else MainWindow := New(PMainMDIWindow, Init('MDI Additional LoadMenu(HInstance, 'MDIMenul')));
Instance ,
end; T h e r e s o u r c e e d i t o r ( t h e W h i t e w a t e r R e s o u r c e T o o l k i t ) is u s u a l l y p r e f e r r e d t o c r e a t e r e s o u r c e s interactively. T o h a v e f u n a n d t o i l l u m i n a t e w h a t a resource editor d o e s for y o u b e h i n d the scenes, however, y o u will p o k e a r o u n d a bit i n a r e s o u r c e script file. Listing 8.1 s h o w s a s i m p l e r e s o u r c e script file g e n e r a t e d w i t h t h e W h i t e w a t e r R e s o u r c e T o o l k i t (after c r e a t i n g t h e r e s o u r c e interactively) a n d t h e T u r b o Pascal f o r W i n d o w s e d i t o r . T h e r e s o u r c e Scriptfile c o n s i s t s e n t i r e l y o f a m e n u r e s o u r c e s p e c i f i c a t i o n . Later i n this c h a p t e r , y o u learn easier ways t o create resources using the Whitewater Resource Toolkit.
1
8—Resources and Control Objects
Listing
8.1. A simple
resource
script
file.
106 MENU LOADONCALL MOVEABLE PURE DISCARDABLE BEGIN POPUP "&File" BEGIN Menultem "&New", 101 Menultem "&Open", 102 Menultem "&Save", 103 Menultem "Save&As", 104 END Menultem "&WriteText", 501 Menultem "&Help", 901 END E a c h r e s o u r c e is a s h o r t b l o c k o f i n f o r m a t i o n w i t h a b e g i n n i n g a n d a n e n d . T h e m e n u resource, for example, has a n a m e :
EditMenu MENU f o l l o w e d b y a Pascal-like b l o c k o f c o d e :
BEGIN END w h i c h specifies m e n u items a n d their c o r r e s p o n d i n g c o m m a n d messages:
MENUITEM " ..." cm_F.. T h e s p e c i f i c a t i o n for a d i a l o g b o x m i g h t l o o k l i k e this i n a . R C (script) file:
AbOUtBox DIALOG 30, 35, 150,100 CAPTION "A Dialog" STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU FONT 10, "Helv" BEGIN CTEXT "A Dialog" -1, 0, 20, 160, CTEXT "More text" -1, 0, 28, 160, ICON "An Icon" -1,8, 8, 0, DEFPUSHBUTTON "OK", IDOK, 50, 45, 30, END
10 10 0 14
L i s t i n g 8.2 s h o w s a m u c h m o r e c o m p l e x r e s o u r c e ( . R C ) file. N o t e that it includes not only m e n u a n d s u b m e n u resource specifications but also m a n y o t h e r r e s o u r c e s as w e l l : d i a l o g s , bit m a p s , s t r i n g s , a c c e l e r a t o r s , a n d s o o n .
245
246
Part I I — A d v a n c e d T o p i c s
Listing
8.2.
A complex
resource
file.
#include "rwpdemoc.pas" men_Main MENU BEGIN POPUP "&File" BEGIN MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM END
"&New", cm_New "&Open...", cm_Open SEPARATOR "&Save", cm_Save "Save &as...", cm_SaveAs SEPARATOR "&Print...", cm_Print SEPARATOR "E&xit", cm_Exit
POPUP "&Edit" BEGIN MENUITEM "&Undo Alt+Backspace", cmJJndo, GRAYED MENUITEM SEPARATOR MENUITEM "Cu&t Shift+Del", cm_Cut, GRAYED MENUITEM "&Copy Ctrl+Ins", cm_Copy, GRAYED MENUITEM "&Paste Shift+Ins", cm_Paste, GRAYED MENUITEM SEPARATOR MENUITEM "Cl&ear \ cm_Clear, GRAYED MENUITEM "D&elete", cm_Delete, GRAYED END POPUP "&View" BEGIN MENUITEM "&A11", cm_All, GRAYED, CHECKED MENUITEM "&Some...", cm_Some, GRAYED MENUITEM SEPARATOR MENUITEM "&By...", cm_By, GRAYED END POPUP "&Options" BEGIN MENUITEM "&Directories...", cm_Directories MENUITEM SEPARATOR POPUP "&Environment" BEGIN MENUITEM "&Preferences...", cm_Preferences
8—Resources and Control Objects
247
MENUITEM "&Mouse...", cm_Mouse END MENUITEM MENUITEM MENUITEM MENUITEM
SEPARATOR "&0pen...", cm_0ptions_0pen "&Save", cm_Options_Save "Save &as...", cm_Options_SaveAs
END POPUP "&Window" BEGIN MENUITEM "&Tile", cm_Tile MENUITEM "&Cascade", cm_Cascade MENUITEM "Arrange &icons", cm_ArrangeIcons MENUITEM "Close &all", cm_CloseAll, GRAYED END POPUP "&Help" BEGIN MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM MENUITEM END
"&Index Shift+F1", cm_Index, GRAYED "&Topic Search Ctrl+F1", cm_Topic_Search, GRAYED "&Glossary", cm_Glossary, GRAYED "Using &Help", cm_Using_Help, GRAYED SEPARATOR "&About RWPDemo...", 145
END dlg_0pen DIALOG 5, 17, 165, 149 CAPTION "Open" STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU BEGIN LTEXT "File &name:", -1, 5, 3, 38, 12 CONTROL "", 100, "COMBOBOX", CBS_DROPDOWN | WS_VSCROLL | WS_GROUP | WS_TABSTOP, 46, 2, 111, 44 LTEXT "Path:", - 1 , 8 , 18, 16, 8 LTEXT "", 103, 29, 18, 127, 9, SS_LEFT | WS_GROUP LTEXT "&Files:", -1, 12, 32, 16, 8 LTEXT "&Directories", -1, 96, 33, 51, 9 CONTROL "", 101, "LISTBOX", LBS_STANDARD, 6, 43, 70, 59 CONTROL "", 102, "LISTBOX", LBS_STANDARD, 92, 43, 70, 59 CONTROL "Options", -1, "button", BS_GROUPBOX | WS_GROUP, 8, 105, 150, 22 continues
248
Part I I — A d v a n c e d T o p i c s
Listing
8.2.
continued
CONTROL "&Text", 205, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 17, 113, 37, 12 CONTROL "&Scribble", 206, "BUTTON", BS_AUTORADIOBUTTON j WS_TABSTOP, 68, 113, 36, 12 CONTROL &Graph", 207, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 118, 113, 35, 12 DEFPUSHBUTTON "&0K", 1, 11, 130, 24, 14 PUSHBUTTON "&Cancel", 2, 71, 130, 28, 14 PUSHBUTTON "&Help", 210, 135, 130, 24, 14 H
END dlg_SaveAs DIALOG 10, 18, 129, 147 CAPTION "Save As" STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU BEGIN LTEXT "File &name:", -1, 8, 2, 38, 12 CONTROL "", 100, "COMBOBOX", CBS_DROPDOWN | WS_VSCROLL | WS_GROUP | WS_TABSTOP, 48, 2, 76, 38 LTEXT "Path:", -1, 9, 19, 16, 8 LTEXT "", 101, 29, 21, 92, 8 LTEXT "&Directories", -1, 14, 30, 68, 9 CONTROL "", 103, "LISTBOX", LBS_STANDARD, 11, 40, 70, 59 DEFPUSHBUTTON "&OK", 1, 6, 127, 24, 14 PUSHBUTTON "&Cancel", 2, 51, 127, 28, 14 PUSHBUTTON "&Help", 210, 98, 127, 24, 14 END dlg_Print DIALOG 36, 14, 163, 133 CAPTION "Print" STYLE WS_POPUP | WS_CAPTION J WS_SYSMENU BEGIN LTEXT "Copies:", -1, 5, 11, 28, 8 LTEXT "", 211, 35, 12, 16, 8, WSJ3ROUP CONTROL "", -1, "static", SS_BLACKFRAME, 35, 10, 16, 10 CONTROL "Pages", -1, "button", BS_GROUPBOX, 4, 24, 155, 30 CONTROL "&A11", 212, "BUTTON", BS_AUTORADIOBUTTON j WS_TABSTOP, 36, 29, 28, 12 CONTROL "&Partial", 213, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 36, 41, 35, 8 CONTROL "", 214, "static", SS_GRAYFRAME, 98, 41, 12, 8 LTEXT "From:", -1, 75, 41, 19, 8 LTEXT "To:", -1, 114, 41, 16, 8 CONTROL "", 215, "static", SS_GRAYFRAME, 134, 41, 11, 8 LTEXT "Printers", -1, 6, 61, 31, 8 CONTROL "", 216, "LISTBOX", LBS_STANDARD, 3, 70, 143, 37 DEFPUSHBUTTON "P&rint", 217, 5, 114, 24, 14 PUSHBUTTON "Printer &setup...\ 218, 37, 114, 51, 14
8 — R e s o u r c e s and Control Objects
PUSHBUTTON "&Cancel", 2, 97, 114, 27, 14 PUSHBUTTON "&Help", 210, 133, 114, 24, 14 END acc_Main ACCELERATORS BEGIN VK_BACK, 24325, VIRTKEY, ALT VK_DELETE, 24320, VIRTKEY, SHIFT VK_INSERT, 24321, VIRTKEY, CONTROL VK_INSERT, 24322, VIRTKEY, SHIFT VK_F1, 141, VIRTKEY, SHIFT VK_F1, 142, VIRTKEY, CONTROL END
dlg_About DIALOG 82, 19, 121, 86 CAPTION "About CUA" STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU BEGIN LTEXT "Common User Access Example", -1, 10, 5, 108, 11 LTEXT "Copyright (c) 1990, Borland International", -1, 26, 49, 70, 15 DEFPUSHBUTTON "&0K", 1, 49, 69, 24, 14 ICON "icon_1", -1, 53, 25, 16, 16 END
DIAL0G_5 DIALOG 11, 18, 177, 79 CAPTION "Directories" STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU BEGIN LTEXT "&Scribble Directory", -1, 9, 5, 66, 10, SS_LEFT | WS_GROUP LTEXT "&Text Directory", -1, 9, 22, 64, 10, SS_LEFT j WS_GROUP LTEXT "&Graphics Directory", -1, 9, 40, 64, 8, SS_LEFT | WS_GROUP CONTROL "", ID_ScribbleDirectory, "COMBOBOX", CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP, 80, 4, 95, 32 CONTROL "", id_TextDirectory, "COMBOBOX", CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP, 80, 22, 95, 32 CONTROL "", id_GraphicDirectory, "COMBOBOX", CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP, 80, 40, 95, 32 continues
249
250
Part I I — A d v a n c e d T o p i c s
Listing
8.2.
continued
DEFPUSHBUTTON "&0K", id_0k, 16, 61, 24, 14 PUSHBUTTON "&Cancel", id_Cancel, 68, 61, 26, 14 PUSHBUTTON "&Help", id__Help, 122, 61, 24, 14 END dlg_Preferences DIALOG 13, 21, 210, 88 CAPTION "Preferences" STYLE WS_P0PUP | WS_CAPTION | WS_SYSMENU BEGIN CONTROL "Desktop file", -1, "button", BS_GROUPBOX, 5, 7, 88, 52 CONTROL "&None", 222, "BUTTON", BS_AUTORADIOBUTTON | WSJTABSTOP, 11, 17, 78, 11 CONTROL "C&urrent directory", 223, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 11, 28, 74, 13 CONTROL "Conf&ig file directory", 224, "BUTTON", BS_AUTORADIOBUTTON | WSJTABSTOP, 11, 41, 73, 12 CONTROL "Autosave", -1, "button", BS_GROUPBOX, 97, 7, 109, 52 CONTROL "&Editor files", 225, "BUTTON", BS_AUTOCHECKBOX i WS_TABSTOP, 102, 18, 91, 9 CONTROL "&Environment", 226, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 102, 31, 88, 9 CONTROL &Desktop", 227, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 102, 44, 60, 9 DEFPUSHBUTTON "&0K", 1, 23, 67, 24, 14 PUSHBUTTON "&Cancel", 2, 72, 67, 37, 14 PUSHBUTTON "&Help", 210, 134, 67, 24, 14 END H
dlg_Mouse DIALOG 14, 12, 190, 97 CAPTION "Mouse" STYLE WS_POPUP | WS__CAPTION | WS__SYSMENU BEGIN CONTROL "&Right mouse button", -1, "button", BS_GROUPBOX, 8, 5, 77, 59 CONTROL "", 231, "scrollbar", SBS_HORZ, 95, 32, 86, 9 LTEXT "Mouse Click", -1, 93, 11, 90, 9 LTEXT "Fast", -1, 95, 22, 16, 8 LTEXT "Slow", -1, 161, 22, 16, 8 CONTROL "&Reverse mouse buttons", 232, "BUTTON", BS_AUTOCHECKBOX | WSJTABSTOP, 97, 48, 90, 9 CONTROL "&Nothing", 228, "BUTTON", BS_AUTORADIOBUTTON WSJTABSTOP, 18, 19, 55, 12
8—Resources and Control Objects
CONTROL "&Clear Window", 229, "BUTTON", BS_AUTORADIOBUTTON \ WS_TABSTOP, 18, 33, 55, 12 CONTROL "&lnverse Color", 230, "BUTTON", BS_AUTORADIOBUTTON | WSJTABSTOP, 18, 47, 55, 12 DEFPUSHBUTTON "&0k", 1, 11, 76, 24, 14 PUSHBUTTON "&Cancel", 2, 64, 76, 30, 14 PUSHBUTTON "&Help", 210, 123, 76, 24, 14 END
R C D A T A J RCDATA BEGIN "\07\07Wake up!!\07\07\0" , "\11Hello world" , 25 0x05f "\07" END CURSOR 1 CURSOR rwdemo.CUR
ico RWPDemo ICON rwdemo.ICO
STRINGTABLE BEGIN sth_FileNew, "Help on New" sth_FileOpen, "Help on Open" sth_FileSave, "Help on Save" sth_FileSaveAs, "Help on SaveAs" sth_FilePrint, "Help on Print" sth_FileExit, "Help on Exit" sth_File, "Help on File" sth_EditUndo, "Help on Undo" sth_EditCut, "Help on Cut" sth_EditCopy, "Help on Copy" sth_EditPaste, "Help on Paste" sth_EditClear, "Help on Clear" sth_EditDelete, "Help on Delete" sth_Edit, "Help on Edit" sth_ViewAll, "Help on View All" sth_ViewSome, "Help on View Some" sth_ViewBy, "Help on View By" continues
251
252
Part I I — A d v a n c e d T o p i c s
Listing
8.2.
continued
sth_View, "Help on View" sth__OptionsDirectory, "Help on Directories" sth_OptionsEnvironment, "Help on Environment" sth_OptionsOpen, "Help on Options Open" sth_OptionsSave, "Help on Options Save" sth_OptionsSaveAs, "Help on Options Save As" sth_Option, "Help on Option" sth_EnvironmentPreferences, "Help on Preferences" sth_EnvironmentMouse, "Help on Mouse" sth_WindowTile, "Help on Window Tile" sth_WindowCascade, "Help on Window Cascade" sth_WindowArrange, "Help on Window Arrange" sth_WindowIcon, "Help on Window Icon" sth_WindowCloseAll, "Help on Window CloseAll" sthJA/indow, "Help on Window" sth_HelpIndex, "Help on Index" sth_HelpTopic, "Help on Topic" sth_HelpSearch, "Help on Search" sth_HelpGlossary, "Help on Glossary" sth_HelpUsing, "Help on Using Help" sth_HelpAbout, "Help on About" sth_Help, "Help on Help" END bmp_StatusLine BITMAP BEGIN '42 4D F6 02 00 00 00 '00 00 40 00 00 00 14 '00 00 80 02 00 00 00 '00 00 00 00 00 00 00 '00 00 00 80 80 00 80 '00 00 80 80 80 00 C0 '00 00 00 FF FF 00 FF '00 00 FF FF FF 00 88 '88 88 88 88 88 88 88 '88 88 88 88 88 88 87 '77 77 77 77 77 77 77 '77 77 77 77 77 F8 87 '88 88 88 88 88 88 88 '88 88 88 88 88 F8 87 '88 88 88 88 88 88 88 '88 88 88 88 88 F8 87 '88 88 88 88 88 88 88 '88 88 88 88 88 F8 87 '88 88 88 88 88 88 88
00 00 00 00 00 C0 00 88 88 77 77 88 88 88 88 88 88 88 88
00 00 00 00 00 C0 00 88 88 77 77 88 88 88 88 88 88 88 88
00 00 00 00 00 00 00 88 88 77 77 88 88 88 88 88 88 88 88
76 01 00 00 80 00 FF 88 88 77 77 88 88 88 88 88 88 88 88
00 00 00 00 00 00 00 88 88 77 77 88 88 88 88 88 88 88 88
00 04 00 80 80 FF FF 88 88 77 77 88 88 88 88 88 88 88 88
00 00 00 00 00 00 00 88 88 77 77 88 88 88 88 88 88 88 88
28 00 00 00 80 00 FF 88 88 77 77 88 88 88 88 88 88 88 88
00' 00' 00' 80' 80' FF' FF' 88' 88' 77' 77' 88' 88' 88' 88' 88' 88' 88' 88'
8—Resources and Control Objects
•88 '88 '88 '88 '88 '88 *88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 '88 'FF 'FF '88 '88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 87 88 88 F8 8F FF FF F8 88 88 88 88'
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 FF FF 88 88
88* 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' 88' FF' FF 88' 88' 1
END
N o t e : These bit maps must be developer-generated, either through the use of ASCII codes (the tedious way), or through the Whitewater Resource Toolkit (the easy way).
1 FONT rwdemo.FNT dlg_FileNew DIALOG 37, 18, 130, 129 CAPTION "New" STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION BEGIN CONTROL "Text", id_Text, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 39, 17, 41, 12 continues
253
254
Part I I — A d v a n c e d T o p i c s
Listing
8.2.
continued
CONTROL "Scribble", id_Scribble, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 39, 39, 40, 12 CONTROL "Graphics", id_Graphics, "BUTTON", BS_AUTORADIOBUTTON \ WS_TABSTOP, 39, 61, 41, 12 CONTROL "", -1, "button", BS_GROUPBOX, 32, 8, 66, 74 CONTROL "OK", id_OK, "BUTTON", BS_DEFPUSHBUTTON | WS_TABSTOP, 31, 98, 30, 14 CONTROL "Cancel", id_Cancel, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 71, 98, 31, 14 END B I T M A P J BITMAP BEGIN '42 4D 16 01 00 00 00 00 '00 00 0A 00 00 00 14 00 '00 00 A0 00 00 00 00 00 '00 00 10 00 00 00 00 00 '00 00 00 80 80 00 80 00 '00 00 80 80 80 00 C0 C0 '00 00 00 FF FF 00 FF 00 *00 00 FF FF FF 00 88 88 '87 77 77 00 00 00 88 8F '87 88 88 80 88 88 88 8F '87 88 88 00 00 00 88 8F '87 88 88 00 00 04 88 8F '87 88 88 00 00 40 88 8F '87 88 88 00 00 00 88 8F '87 88 88 00 00 00 88 8F '87 88 88 00 00 00 88 8F '87 88 88 00 00 00 FF FF '88 88 88 00 00 00' END 1000 MENU BEGIN POPUP "Color" BEGIN MENUITEM "Red", 1 MENUITEM "Green", 1 MENUITEM "Blue", 1 END POPUP "Width" BEGIN MENUITEM "Thin", 108
00 00 00 00 00 C0 00 88 87 87 87 87 87 87 87 87 8F
00 00 00 00 00 00 00 88 88 88 88 88 88 88 88 88 FF
76 01 00 00 80 00 FF 88 88 88 88 88 88 88 88 88 FF
00 00 00 00 00 00 00 08 00 44 00 00 A0 08 00 00 00
00 04 00 80 80 FF FF 88 00 00 00 10 82 00 00 00 00
00 00 00 00 00 00 00 00 00 04 00 00 02 22 00 00 00
28 00 00 00 80 00 FF 77 88 88 88 88 88 88 88 88 88
00' 00' 00' 80' 80' FF FF 7F' 8F' 8F 8F' 8F 8F' 8F 8F' 8F' 88' 1
1
1
1
1
8—Resources and Control Objects
MENUITEM MENUITEM
255
"Normal", 1 "Item", 1
END END 1001 MENU BEGIN POPUP "Shape" BEGIN MENUITEM "Circle", 1 MENUITEM "Rectangle", 1 END POPUP BEGIN
"Color" MENUITEM MENUITEM MENUITEM
"Red", 1 "Green", 1 "White", 1
END END S c r i p t files s u c h as t h e o n e s i n listing 8 . 1 a n d 8 . 2 h a v e a . R C e x t e n s i o n , a r e c o m p i l e d with the Microsoft Resource C o m p i l e r , a n d t h e n are a p p e n d e d to t h e P a s c a l a p p l i c a t i o n ( u s u a l l y u s i n g t h e { $ R } d i r e c t i v e ) . Y o u r a p p l i c a t i o n is, o f c o u r s e , still r e s p o n s i b l e f o r a t t a c h i n g t h e r e s o u r c e t o a w i n d o w ( i n t h e Pascal for W i n d o w s c o d e ) . F o r e x a m p l e , y o u load a m e n u already specified in a r e s o u r c e file b y ID 99: constructor ATaskWindow.Init(AParent : PWindowsObject; ATitle : PChar); begin TWindow.Init(AParent, ATitle); { Send message to ancestor's constructor } Attr.Menu := LoadMenu(HInstance, PChar(99)); { 99 = menu ID } end;
Resource Editors R e s o u r c e e d i t o r s , s u c h as t h e o n e s i n t h e W h i t e w a t e r R e s o u r c e T o o l k i t ( W R T ) , c a n g e n e r a t e script files ( R C ) a n d l i n k a b l e r e s o u r c e files ( R E S ) . U s i n g t h e W h i t e w a t e r R e s o u r c e T o o l k i t , y o u u s u a l l y w a n t t o g e n e r a t e R E S files, t h e d e f a u l t . I n that c a s e , y o u s e l e c t W R T ' s S a v e M e n u i t e m a n d s p e c i f y a file.
256
Part II—Advanced Topics
T o indicate that you want to generate a scriptfile(.RC) rather than a resource file (RES), use the WRT's SaveAs m e n u item and select the .RC control button from the ensuing dialog window. Notice that the dialogs, menus, keyboard accelerators, and so on, you use to interact with the Whitewater Resource Toolkit are similar to those you create for your applications. This is a beauty of the W i n d o w s interface: these resource editors are examples of the kinds of applications you can create using W i n d o w s development tools like Turbo Pascal for W i n d o w s and W R T . The way these (and other) applications use and interact with W i n d o w s resources is covered in Chapter 13, "Designing W i n d o w s Applications." T o give you a feel for using a resource editor, the Whitewater Resource Toolkit is used to create a dialog w i n d o w and m e n u for an application.
Dialog Windows A dialog box is a w i n d o w m a d e u p of controls like those you see infigure8.2.
Figure
8.2. A dialog
box.
Recall that controls are such items as list boxes, push buttons, edit fields, and so on. Each control is a child w i n d o w that acts as an input device; in other words, it is an interactive componentforcommunicating with a user. The dialog box (or window) is the parent window.
8—Resources and Control Objects
T o c r e a t e , e d i t , o r d e s i g n a d i a l o g b o x , y o u start w i t h a g e n e r i c d i a l o g b o x (with o r w i t h o u t a c a p t i o n ) . Y o u m o v e it a r o u n d a n d c h a n g e t h e t y p e , c o n t e n t , a n d location o f controls in the dialog b o x t o create t h e specific dialog b o x y o u want. T h e dialog b o x editor allows y o u to w o r k with t w o palettes: •
Tools
•
Alignment
U s e t h e T o o l s p a l e t t e t o c r e a t e a d i a l o g b o x a n d its c o n t r o l s . U s e t h e Alignment palette to align the controls within the dialog b o x . By using the controls in a dialog b o x — t h a t is, by clicking buttons, c h e c k i n g b o x e s , a n d s e l e c t i n g i t e m s f r o m a list, a u s e r c a n " c o n t r o l " a n application. Controls enable a user to 1. K n o w w h i c h f u n c t i o n s a r e available t o h i m . 2. A l t e r t h e f l o w o f a n a p p l i c a t i o n ( f r o m o b j e c t t o o b j e c t , f r o m task t o task, f r o m f u n c t i o n t o f u n c t i o n ) . G o o d u s e o f d i a l o g b o x e s ( a n d its c o n t r o l s ) c a n e l i m i n a t e a n a p p l i c a t i o n ' s m y s t e r i e s a n d i l l u m i n a t e its p u r p o s e s . T h e A p p l e M a c i n t o s h b e c a m e p o p u l a r i n l a r g e part b e c a u s e it is s o e a s y t o u s e . W i n d o w s b r i n g s that e a s e o f u s e t o t h e P C . W i n d o w s d e f i n e s a set o f m e s s a g e s that c o o r d i n a t e t h e e x c h a n g e o f i n f o r m a t i o n b e t w e e n a n a p p l i c a t i o n a n d its c o n t r o l s . F o r e x a m p l e , list b o x " r e t u r n " m e s s a g e s a r e p r e f i x e d b y lb_. C o m b o b o x " r e t u r n " m e s s a g e s a r e p r e f i x e d b y cb_. B u t t o n " r e t u r n " m e s s a g e s a r e p r e f i x e d b y bn_, a n d s o o n . I n a d i a l o g b o x (a w i n d o w ) , m e s s a g e s g o b o t h w a y s : t o t h e c o n t r o l a n d b a c k f r o m t h e c o n t r o l . T o s e n d a m e s s a g e — t o a d d a string t o a list b o x f o r e x a m p l e — y o u might d o this:
procedure ADialog.AddStrings(var Msg: TMessage); var Txt : PChar; begin Txt := 'SomeText'; SendDlgItemMsg(id_LB1, lb_AddString,0, Longlnt(Txt)); end; SendDlgltemMsg is a TDialog m e t h o d . T h u s , a n y d i a l o g w i n d o w y o u d e r i v e f r o m TDialog a u t o m a t i c a l l y k n o w s h o w t o s e n d d i a l o g m e s s a g e s . id_LB1 is a c o n s t a n t r e p r e s e n t i n g a list b o x I D . Y o u u s e it t o specify t h e c o n t r o l t o r e c e i v e t h e SendDlgltemMsg. T o g e t a result (of a u s e r click, f o r e x a m p l e ) , y o u r d i a l o g w i n d o w r e s p o n d s to a control notification message, w h i c h represents the user's action. Each c o n t r o l n o t i f i c a t i o n m e s s a g e i n c l u d e s a n o t i f i c a t i o n c o d e (sent t h r o u g h Msg. lParamHi) that s p e c i f i e s t h e c o n t r o l ' s c h a n g e o f state.
257
258
Part I I — A d v a n c e d T o p i c s
Write a response m e t h o d for any control notification message y o u want the dialog w i n d o w or application to respond to. For example:
ADialog = object(TDialog) procedure Handlel_istBox1Msg(var Msg: TMessage); virtual id_First + id_BN1; end; procedure ADialog.HandleListBoxlMsg(var Msg: TMessage); begin case Msg.lParamHi of lbn_SelChange: { Handle selection here } lbn_DblClk: { Handle a double click here } end; end; lbn_ p r e f i x e d m e s s a g e s a r e g e n e r a t e d w h e n a u s e r clicks i n t h e list b o x . T h e HandleListBoxl Msg m e t h o d t h u s c a n b e u s e d t o r e s p o n d t o t h e m e s s a g e s y o u w a n t t h e list b o x t o r e s p o n d t o . N o t i f i c a t i o n m e s s a g e s y o u d o n o t i n t e r c e p t are h a n d l e d a u t o m a t i c a l l y ( b u t w i t h o u t a n y r e s p o n s e ) b y TDialog m e t h o d s ( w h i c h ADialog i n h e r i t e d ) . A d i a l o g is t h u s a t w o - w a y c o m m u n i c a t i o n , s e n d i n g m e s s a g e s t o c o n t r o l s a n d r e s p o n d i n g t o their notification messages. F o r e x a m p l e , create a dialog w i n d o w that r e s p o n d s t o a c o n t r o l (a b u t t o n ) b y s e n d i n g a m e s s a g e t o a n o t h e r c o n t r o l (a list b o x ) . Listing 8.3 s h o w s t h e c o m p l e t e c o d e ( w h i c h is c o v e r e d i n t h e f o l l o w i n g s e c t i o n ) , a n d figure 8.3 s h o w s t h e d i s p l a y e d r e s u l t s . Listing
8.3. A dialog
box
program DialEx;
example.
{ Chapter 8, example dialog }
{$R EX_DIAL.RES} uses WinTypes, WinProcs, WObjects; const TheMenu id_LB1 id__BN1
= 100; = 151; =152;
cm_DialogEx
=101;
{ Menu command message }
type PExDialog = "ExDialog; ExDialog = object(TDialog) procedure IDBN1(var Msg: TMessage); virtual id_First + id_BN1; procedure IDLB1(var Msg: TMessage); virtual id_First + id_LB1; end;
8—Resources and Control Objects
259
PDialogWindow = "DialogWindow; DialogWindow = object(TWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure CMDialogEx(var Msg: TMessage); virtual cm_First + cm_DialogEx; end; DlgApplication = object(TApplication) procedure InitMainWindow; virtual; end; { ExDialog } procedure ExDialog.IDBN1(var Msg: TMessage); var Textltem : PChar; begin Textltem := 'Menus'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Accelerators'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Bitmaps'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Cursors'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Icons'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Dialogs'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'File Dialogs'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); end; procedure ExDialog.IDLB1(var Msg: TMessage); var Idx : Integer; SelectedText: array[0..10] of Char; begin if Msg.LParamHi = lbn_SelChange then begin Idx := SendDlgItemMsg(id_LB1, lb_GetCurSel, 0, Longlnt(O)); SendDlgItemMsg(id_LB1, lb_GetText, Idx, Longlnt(^SelectedText)); MessageBox(HWindow, SelectedText, 'List Box Notification', MB_OK); end; end; continues
260
Part I I — A d v a n c e d T o p i c s
Listing
8.3-
continued
{ DialogWindow } constructor DialogWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(Hinstance, MakelntResource(TheMenu)); end; procedure DialogWindow.CMDialogEx(var Msg: TMessage); var Return : Integer; begin Return := Application".ExecDialog(New(PExDialog, Init(@Self, 'EXDialog'))); If Return = id_Cancel then MessageBox(HWindow, 'id_cancel', 'List Box Notification', MB_0K); end; { DlgApplication } procedure DlgApplication.InitMainWindow; begin MainWindow := New(PDialogWindow, Init(nil, 'Example Dialog, Chapter 8')); end; var MyApp: DlgApplication; begin MyApp.Init('Example ) ; MyApp.Run; MyApp.Done; end. 1
Details First, u s e t h e W h i t e w a t e r R e s o u r c e T o o l k i t t o c r e a t e a list b o x . U s e t h e d i a l o g editor to 1. First e x p a n d t h e size o f t h e d e f a u l t d i a l o g ( w h i c h p o p s u p w h e n e v e r y o u o p e n the dialog editor). 2. S e l e c t a list b o x f r o m t h e c o n t r o l m e n u a n d , u s i n g t h e m o u s e , p l a c e it i n t h e d i a l o g w i n d o w (see f i g u r e 8 . 4 ) .
8—Resources and Control Objects
Figure
8.3. A dialog box
example.
Figure
8.4. A list box from the control menu, placed
into a dialog
window.
3. Edit the attributes of the list box by clicking Controls/Attributes as s h o w n in figure 8.5.
261
262
Part II—Advanced Topics
Figure
8.5.
Controls/Attributes.
4. Select button objects to interact with the user and place them using the m o u s e (see figure 8.6).
Figure
8.6. Button objects placed by using the mouse.
5. Select a button for completing the dialog and place it, as in figures 8.7 and 8.8.
8—Resources and Control Objects
Figure
8.7. A button for completing
the
6. D e f i n e n o t i f i c a t i o n c o d e s .
Figure
8.8. The new button in
context.
dialog.
263
264
Part I I — A d v a n c e d T o p i c s
7. Finally, create the usual gang of objects that interact with the resources you just created. As usual, create a n e w application object (deriving it from BasicApplication) and a DlgWindow (deriving it from MainWindow), and aDialogto handle list box and button messages: type PExDialog = "ExDialog; ExDialog = object(TDialog) procedure IDBN1(var Msg: TMessage); virtual id_First + id_BN1; procedure IDLB1(var Msg: TMessage); virtual id_First + id_LB1; end; PDialogWindow = "DialogWindow; DialogWindow = object(TWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure CMDialogEx(var Msg: TMessage); virtual cm_First + cm_DialogEx; end; DlgApplication = object(TApplication) procedure InitMainWindow; virtual; end; InitMainWindow should look familiar: construction of a type of w i n d o w for the DlgApplication. In this case, a DlgWindow: procedure DlgApplication.InitMainWindow; begin MainWindow := New(PDialogWindow, Init(nil, 'Example Dialog, Chapter 6' end; Construct the DlgWindow: constructor DialogWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(Hinstance, MakelntResource(TheMenu)); end; Note the use ofMakelntResource, a W i n d o w s function that typecasts integers into resource names. It is equivalent to typecasting into a PChar type: Attr.Menu := LoadMenu(Hinstance, PChar(100)); which attaches the same m e n u to DialogWindow.
8—Resources and Control Objects
265
ExDialogis u s e d o n l y to interpret notification m e s s a g e s a n d has no fields. B e c a u s e it is also a standard d i a l o g , y o u d o n o t n e e d to d e f i n e a n e w constructor. TDialog's constructor is c a l l e d w h e n DialogWindow s e n d s a n " e x e c u t e d i a l o g " m e s s a g e in response to t h e CMDialogEX m e n u c o m m a n d message: procedure DialogWindow.CMDialogEx(var Msg: TMessage); var Return : Integer; begin Return := Application".ExecDialog(New(PExDialog, Init(@Self, 'EXDialog'))); If Return = id_Cancel then MessageBox(HWindow, 'id_cancel', 'List Box Notification', MB_0K); Notice in this e x a m p l e that you take a quick l o o k at the R e t u r n v a l u e of Application" .ExecDialog. S o m e t i m e s it is u s e f u l to check this result just in c a s e Application". ExecDialog fails. F o r e x a m p l e , if you specify t h e n a m e of a d i a l o g that c a n b e e x e c u t e d , ExecDialog returns zero. If the d i a l o g c a n n o t b e e x e c u t e d (for e x a m p l e , if t h e d i a l o g n a m e is m i s s p e l l e d ) , ExecDialog returns a negative v a l u e corresponding to a pred e f i n e d c o n s t a n t . T o e x p e r i m e n t with t h e s e error results, t y p e s o m e garbage into the d i a l o g n a m e field, a n d look at t h e result. For e x a m p l e , if y o u d o n o t have a dialog resource n a m e d "NoDialog," t y p e that n a m e in t h e n a m e field, where "ExDialog" is n o w . This p r o c e s s g e n e r a t e s a n error. D e f i n e t h e m e t h o d for responding to a n AddString m e s s a g e : { ExDialog } procedure ExDialog.IDBN1(var Msg: TMessage); var Textltem : PChar; begin Textltem := 'Menus'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Accelerators'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Bitmaps'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Cursors ; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Icons '; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'Dialogs ; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); Textltem := 'File Dialogs'; SendDlgItemMsg(id_LB1, lb_AddString, 0, Longlnt(Textltem)); end; 1
1
266
Part I I — A d v a n c e d T o p i c s
H e r e is a m e t h o d f o r r e s p o n d i n g t o a list-box n o t i f i c a t i o n
message
i n d i c a t i n g that t h e u s e r s e l e c t e d a n i t e m :
procedure ExDialog.IDLB1(var Msg: TMessage); var Idx : Integer; SelectedText: array[0..10] of Char; begin if Msg.LParamHi = lbn_SelChange then begin Idx := SendDlgItemMsg(id_LB1, lb_GetCurSel, 0, Longlnt(0)); SendDlgItemMsg(id_LB1, lb_GetText, Idx, Longlnt(^SelectedText)); MessageBox(HWindow, SelectedText, 'List Box Notification', MB_0K); end; end; N o t e that y o u c a n d e f i n e d i a l o g s i n s e p a r a t e files s p e c i f i e d b y . D L G e x t e n s i o n s . F o r e x a m p l e , t h e p r e v i o u s d i a l o g ' s . D L G file l o o k s like t h i s :
EXDIALOG DIALOG DISCARDABLE L0AD0NCALL PURE MOVEABLE 30, 49, 188, 100 STYLE WS_P0PUP | WS_DLGFRAME BEGIN CONTROL "Fill List Box" 152, "BUTTON", WS_CHILD | WS_VISIBLE j WS_TABSTOP, 111, 13, 68, 12 CONTROL "Cancel" 2, "BUTTON", WS_CHILD | WS_VISIBLE | WSJTABSTOP, 112, 66, 68, 12 CONTROL "LISTBOX" 151, "LISTBOX", WS_CHILD J WS_VISIBLE | WS_BORDER | WS_VSCROLL | 0x3L, 8, 8, 83, 73 END If y o u d o m a i n t a i n d i a l o g s , m e n u s , a n d s o f o r t h , i n s e p a r a t e files, y o u can combine them whenever you need to by using the Whitewater Resource T o o l k i t B r o w s e r t o c o p y r e s o u r c e s b e t w e e n files. D o this b y o p e n i n g t w o browsers a n d using the Browser C o p y c o m m a n d to c o p y resource specificat i o n s b e t w e e n files. F i g u r e 8.9 illustrates this i d e a .
N o t e : T h e W h i t e w a t e r R e s o u r c e T o o l k i t is c o m p l e t e l y m e n u driven. T o add resources (controls, boxes, button, and so o n ) , use y o u r m o u s e t o click the m e n u items, t h e n drag t h e m across the screen.
8—Resources and Control Objects 2 6 7
Figure
8.9. Using the Whitewater Resource
Toolkit to copy resources between
files.
Control Objects Dialog boxes are composed of control objects, but control objects do not have to be part of a dialog. Y o u might want to use control objects as stand-alone "windows." ObjectWindows object types m a k e it easy for you to incorporate any of ten controls in your o w n applications. These controls are listed in table 8 . 1 . Table
8.1. Controls
to incorporate
in your
Control
ObjectWindows
Check box
TCheckBox
C o m b o box
TComboBox
Edit control
TEdit
Group box
TGroupBox
List box
TListBox
M D I client
TMDIClient
Push button
TButton
own
applications. Object
Type
continues
268
Part I I — A d v a n c e d T o p i c s
Table
8.1.
continued
Control
ObjectWindows
Radio button
TRadioButton
Scroll bar
TScrollBar
Static c o n t r o l
TStatic
Object
Type
T h e O b j e c t W i n d o w s type, TControl, is t h e a n c e s t o r f o r all c o n t r o l o b j e c t s . It is b a s e t y p e , s o y o u n e v e r instantiate a TControl; y o u instantiate its descendents. TControl is d e s c e n d e d from TWindow. T h u s , a n y c o n t r o l is a k i n d o f w i n d o w that c a n d i r e c t t h e flow o f a n a p p l i c a t i o n . A l t h o u g h y o u c a n derive n e w c o n t r o l s f r o m t h e c o n t r o l s in O b j e c t W i n d o w s , y o u p r o b a b l y n e v e r w i l l ; i n s t e a d y o u m i x a n d m a t c h t h e m t o create t h e c o n t r o l w i n d o w y o u w a n t . A l s o n o t e that a c o n t r o l is a child w i n d o w t o its p a r e n t (the M a i n a p p l i c a t i o n w i n d o w ) a n d i s , i n t u r n , u n d e r t h e p a r e n t w i n d o w ' s " c o n t r o l . " It is t h e responsibility o f t h e p a r e n t w i n d o w t o create t h e c o n t r o l (its child). Derive a n e w k i n d o f MainWindow, c a l l e d a TaskControlWindow: PTaskControlWindow = "TaskControlWindow; TaskControlWindow = object(MainWindow) constructor Init(AParent: PWindowsObject; ATitle: PChar); end; a n d a d d a radio b u t t o n t o it: PTaskControlWindow = "TaskControlWindow; TaskControlWindow = object(MainWindow) Rad1: PRadioButton; end; In this e x a m p l e , t h e c o n t r o l (Rad1, a p o i n t e r t o a RadioButton) is represented b y a d a t a f i e l d . Alternatively, it c a n b e represented b y a variable in its p a r e n t ' s c o n s t r u c t o r . F o r e x a m p l e : constructor Init(AParent: PWindowsObject; ATitle: PChar); var Rad1 : PRadioButton; begin {....} end;
8—Resources and Control Objects
269
E i t h e r w a y , t h e c o n t r o l is c o n s t r u c t e d b y its p a r e n t ' s c o n s t r u c t o r . V e r s i o n 1:
constructor TaskControlWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin MainWindow.Init(AParent, ATitle); Rad1 := New(PRadioButton, Init(@Self, id_Rad1, 'Task 1', 74, 64, 138, 24, Groupl)); end; O r ( V e r s i o n 2):
constructor TaskControlWindow.Init(AParent: PWindowsObject; ATitle: PChar); var Rad1 : PRadioButton; begin MainWindow.Init(AParent, ATitle); Rad1 := New(PRadioButton, Init(@Self, id_Rad1, 'Task 1', 74, 64, 138, 24, Groupl)); end; Y o u c r e a t e o t h e r c o n t r o l o b j e c t s similarly. F o r e x a m p l e , a list b o x :
constructor TaskControlWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin MainWindow.Init(AParent, ATitle); ListBoxl := New(PListBox, Init(@Self, id_LB1, 74, 64, 138, 24)); end; or a c o m b o box:
constructor TaskControlWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin MainWindow.Init(AParent, ATitle); ListBoxl := New(PComboBox, Init(@Self, id_CB1, 74, 64, 138, 24, cbs_DropList,40)); end; E a c h c o n t r o l s u p p o r t e d b y a n O b j e c t W i n d o w s o b j e c t is a s e l f - c o n t a i n e d o b j e c t w i t h its o w n m e t h o d s a n d d a t a . Y o u r a p p l i c a t i o n s i m p l y : 1. C o n s t r u c t s a n o b j e c t . 2. S e n d s it m e s s a g e s . 3. P r o c e s s e s t h e r e s u l t s .
270
Part I I — A d v a n c e d T o p i c s
Group Boxes O n e w a y o f u s i n g c o n t r o l s is t o p r o c e s s t h e m " a s a g r o u p , " b y u n i f y i n g t h e m i n a g r o u p b o x . A g r o u p b o x is a s p e c i a l k i n d o f i n t e r f a c e o b j e c t that c o r r e s p o n d s t o t h e g r o u p b o x e l e m e n t i n W i n d o w s . A g o o d w a y t o set u p a g r o u p b o x is t o c r e a t e it as a s t a n d - a l o n e c h i l d w i n d o w w i t h i n a n o t h e r w i n d o w ' s c l i e n t a r e a . C r e a t e a g r o u p b o x that u n i f i e s a g r o u p o f r a d i o b u t t o n s . E a c h b u t t o n e n a b l e s a u s e r t o specify a task. I n o t h e r w o r d s , t h e g r o u p b o x acts as a task c o n t r o l l e r . T h e u s e r selects a task t o e x e c u t e b y c l i c k i n g a r a d i o b u t t o n . T h e a p p l i c a t i o n r e s p o n d s b y i t e r a t i n g t h e task. R e c a l l t h e w a y y o u b u i l t t h e task m a n a g e r i n C h a p t e r s 5, 6, a n d 7 b y d e r i v i n g a n e w k i n d of m a i n w i n d o w ( c a l l e d T a s kWi n d ow), w h i c h r e s p o n d e d t o c o m m a n d m e s s a g e s ( g e n e r a t e d b y a m e n u ) . T h e TaskWindow r e s p o n d e d t o a R u n T a s k m e s s a g e b y c r e a t i n g a n i n s t a n c e of t h e w i n d o w that c o n t a i n e d t h e task. T h e p l a n h e r e is similar: 1. D e r i v e a n e w w i n d o w c a l l e d TaskControlWindow f r o m MainWindow. 2. A d d c o n t r o l s t o it: t w o r a d i o b u t t o n s (to r e p r e s e n t t w o t a s k s ) , a c o n t r o l b o x t o u n i f y t h e task b u t t o n s , a n d a m e t h o d t o m a i n t a i n t h e g r o u p :
PTaskControlWindow = "TaskControlWindow; TaskControlWindow = object(MainWindow) TaskButtonl, TaskButton2: PRadioButton; TaskGroupl: PGroupBox; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure HandleTaskGroup1Msg(var Msg: TMessage); virtual id_First + id_Group1; end; T h e TaskControlWindow c o n s t r u c t o r c r e a t e s all t h e c o n t r o l s :
constructor TaskControlWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin MainWindow.Init(AParent, ATitle); TaskGroupl := New(PGroupBox, Init(@Self, id_Group1, 'Task Box', 58, 52, 176, 108)); TaskButtonl := New(PRadioButton, Init(@Self, id_Rad1, 'Task 1', 74, 64, 138, 24, Groupl)); TaskButton2 := New(PRadioButton, Init(@Self, id_Rad2, 'Task 2', 74, 84, 138, 24, Groupl)); end;
8—Resources and Control Objects
T h e g r o u p handler decides h o w to interpret the button-state c h a n g e s in the group:
procedure TaskControlWindow.HandleGroup1Msg(var Msg: TMessage); var TextBuff: array[0..20] of Char; { A button ID } Compare : integer; { Int to record comparison } Taskl : PModell; { Pointer to a task } Task2 : PModel2; { Pointer to a task } begin if Rad1 .GetCheck 0 { User wants a task } then GetWindowText(Rad1 .HWindow, TextBuff, SizeOf(TextBuff)) else GetWindowText(Rad2 .HWindow, TextBuff, SizeOf(TextBuff)); A
A
A
Compare := StrComp(TextBuff,'Task 1'); { Which task ID is it? } If Compare = 0 then { 0 = a match } begin Taskl := New(PModel1, Init(@Self, 'TimeSeries Model')); Application".MakeWindow(Task1); Taskl .Iterate; { Iterate the task } end else { Run the other task } begin Task2 := New(PModel2, Init(@Self, 'Henon Attractor')); Application".MakeWindow(Task2); Task2".Iterate; { Iterate the task } end; end; A
L i s t i n g 8.4 s h o w s t h e c o m p l e t e TaskCont rol a p p l i c a t i o n , a n d f i g u r e 8.10 s h o w s a s c r e e n d i s p l a y g e n e r a t e d b y t h e c o d e i n listing 8.4.
271
272
Part I I — A d v a n c e d T o p i c s
Figure 8.10. Result of the TaskControl
Listing
8.4. The complete
application.
TaskControl
application.
program TaskButtons; uses WObjects, WinTypes, WinProcs, Strings, wif5, timel, attract2;
{ Basic Interface } { Task 1 } { Task 2 }
const id_Push1 =101; id_Rad1 =102; id_Rad2 = 103; id_Check1 = 1 0 4 ; id_Group1 = 105; type TestApplication = object(TApplication) procedure InitMainWindow; virtual;
8—Resources and Control Objects
end; PTaskControlWindow = "TaskControlWindow; TaskControlWindow = object(MainWindow) Rad1, Rad2: PRadioButton; Groupl: PGroupBox; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure HandleGroup1Msg(var Msg: TMessage); virtual id_First + id_Group1; end; {
TaskControlWindow methods
}
constructor TaskControlWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin MainWindow.Init(AParent, ATitle); Groupl := New(PGroupBox, Init(@Self, id_Group1, 'Task Box', 58, 52, 176, 108)); Rad1 := New(PRadioButton, Init(@Self, id_Rad1, 'Task 1', 74, 64, 138, 24, Groupl)); Rad2 := New(PRadioButton, Init(@Self, id_Rad2, 'Task 2', 74, 84, 138, 24, Groupl)); end; procedure TaskControlWindow.HandleGroup1Msg(var Msg: TMessage); var TextBuff: array[0..20] of Char; { A button ID } Compare : integer; { Int to record comparison } Taskl : PModell; { Pointer to a task } Task2 : PModel2; { Pointer to a task } begin if Rad1".GetCheck 0 then GetWindowText(Rad1".HWindow, TextBuff, SizeOf(TextBuff)) else GetWindowText(Rad2".HWindow, TextBuff, SizeOf(TextBuff)); Compare := StrComp(TextBuff,'Task 1'); If Compare = 0 then begin Taskl := New(PModel1, Init(@Self, 'TimeSeries M o d e l ) ) ; Application".MakeWindow(Task1); Taskl".Iterate; { Iterate the task } 1
continues
273
274
Part I I — A d v a n c e d T o p i c s
Listing
8.4.
continued
end else begin Task2 := New(PModel2, Init(@Self, 'Henon Attractor')); Application".MakeWindow(Task2); Task2".Iterate; { Iterate the task } end; MessageBox(HWindow, TextBuff, 'You have selected:', MB_OK); end; {
TestApplication Methods
}
procedure TestApplication.InitMainWindow; begin MainWindow := New(PTaskControlWindow, Init(nil, 'Task Button Controller')); end; var TestApp : TestApplication; begin TestApp.Init('ButtTest'); TestApp.Run; TestApp.Done; end. U s i n g c o n t r o l s this w a y m i g h t s e e m s i m i l a r t o u s i n g a m e n u r e s o u r c e . It is, b u t c o n t r o l s a r e m o r e f l e x i b l e a n d m o r e p o w e r f u l t h a n m e n u s . R a t h e r t h a n a m e n u , the g r o u p can b e m a d e o f pushbuttons, radio buttons, check boxes, a n d s o o n . T h u s , y o u have interesting graphics possibilities, a n d s o m e controls, s u c h as a n EditControl, f o r e x a m p l e , that a l l o w y o u t o easily m a n i p u l a t e data fields.
Controls in Combination R e v i e w t h e HelpWindow f r o m listing 7.5 i n C h a p t e r 7, " M a n y W i n d o w s : A M u l t i D o c u m e n t I n t e r f a c e . " T h e HelpWindow c o n s i s t e d o f t w o c o n t r o l o b j e c t s : a list b o x a n d a n edit c o n t r o l , a c o n s t r u c t o r (to c o n s t r u c t t h e HelpWindow), a n d several m e t h o d s f o r h a n d l i n g t h e r e s u l t s f r o m t h e c o n t r o l o b j e c t s :
8—Resources and Control Objects
275
PHelpWindow = "HelpWindow; HelpWindow = object(TWindow) LB1: PListBox; EC1: PEdit; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure SetupWindow; virtual; procedure IDLB1(var Msg: TMessage); virtual id_First + id_LB1; procedure IDBN1(var Msg: TMessage); virtual id_First + id_BN1; procedure IDBN2(var Msg: TMessage); virtual id_First + id_BN2; procedure FillEdit(SelStringPtr: PChar); virtual; end; All the control o b j e c t s for HelpWindow are c o n s t r u c t e d w h e n HelpWindow is c o n s t r u c t e d , u s i n g the New p r o c e d u r e :
constructor HelpWindow.Init(AParent: PWindowsObject; ATitle: PChar); var TempStat : PStatic; TempBtn : PButton; begin TWindow.Init(AParent, ATitle); DisableAutoCreate; Attr.Style := ws_PopupWindow or ws_Caption or ws_Visible; Attr.X := 100; Attr.Y := 100; Attr.W := 300; Attr.H := 300; LB1 := New(PListBox, Init(@Self, id_LB1, 20, 20, 180, 80)); TempBtn := New(PButton, Init(@Self, id_BN1, 'Help', 220, 20, 60, 30, True)); TempBtn := New(PButton, Init(@Self, id_BN2, 'Cancel', 220, 70, 60, 30, False)); EC1 := New(PEdit, Init(@Self, id_EC1, '', 20, 180, 260, 90, 40, True)); EC1 .Attr.Style := EC1".Attr.Style or ws_Border or ws_VScroll; TempStat := New(PStatic, Init(@Self, id_ST1,'Help Information:', 20, 160, 160, 20, 0)); end; A
Y o u f i l l e d the list b o x b y overriding TWindow's SetupWindow (in HelpWindow): procedure HelpWindow.SetupWindow; begin TWindow.SetupWindow;
276
Part I I — A d v a n c e d T o p i c s
{ Fill the listbox } LB1 .AddString( List Boxes'); LB1 .AddString('Buttons '); LB1".AddString('Scroll Bars'); LB1".AddString('Edit Controls'); LB1".AddString('Static Controls'); LB1".AddString('Combo Boxes'); LB1".SetSellndex(O); { Set to beginning of list } end; A
1
A
Y o u then specified various actions based o n messages from buttons and lists. F o r e x a m p l e , l i s t - b o x m e s s a g e 1:
procedure HelpWindow.IDLB1(var Msg: TMessage); var SelString: array[0..25] of Char; begin if Msg.LParamHi = lbn_DblClk then begin LB1".GetSelString(SelString, 25); FillEdit(SelString); end; end; B u t t o n m e s s a g e 1:
procedure THelpWindow.IDBN1(var Msg: TMessage); var SelString: array[0..25] of Char; begin LB1".GetSelString(SelString, 25); FillEdit(SelString); end;
Bit Maps Y o u a l s o c a n u s e a r e s o u r c e e d i t o r t o c r e a t e a bit m a p that c a n , i n t u r n , b e u s e d f o r v a r i o u s p u r p o s e s : f o r e x a m p l e , as a b r u s h f o r filling f i g u r e s , s u c h as rectangles, ellipses, a n d so o n . C r e a t i n g a bit m a p w i t h t h e W h i t e w a t e r R e s o u r c e T o o l k i t is straightf o r w a r d . Y o u u s e t h e B i t m a p e d i t o r a n d select t o o l s t o c r e a t e t h e s p e c i f i c a s p e c t s o f t h e bit m a p . Y o u t h e n save t h e bit m a p as a . B M P file, w h i c h y o u c a n l o a d i n t o
8—Resources and Control Objects
y o u r a p p l i c a t i o n s later. F i g u r e s 8 . 1 1 , 8 . 1 2 , a n d 8 . 1 3 s h o w v a r i o u s a s p e c t s o f a bit m a p b e i n g c r e a t e d w i t h t h e W h i t e w a t e r R e s o u r c e G r o u p ' s B i t m a p e d i t o r p a c k a g e d w i t h T u r b o Pascal f o r W i n d o w s .
Figure
8.11. One aspect of a bit map created with the Whitewater Resource Bitmap editor.
Figure
8.12. Another aspect of a bit map.
Group's
277
278
Part I I — A d v a n c e d T o p i c s
Figure
8.13. A third aspect of a bit map created with the WRG's Bitmap
editor.
Wrap-up R e s o u r c e s a n d c o n t r o l o b j e c t s a r e , i n effect, t h e i n t e r f a c e c o m p o n e n t s o f y o u r W i n d o w s a p p l i c a t i o n s . T h e y g i v e y o u r a p p l i c a t i o n t h e l o o k a n d f e e l that m a k e it a familiar, illustrative, easy-to-use G U I ( g r a p h i c a l u s e r i n t e r f a c e ) . M o s t T u r b o Pascal f o r W i n d o w s a p p l i c a t i o n s y o u w r i t e w a n t t o u t i l i z e t h e s e i n t e r f a c e c o m p o n e n t s . W h e n e v e r p o s s i b l e , let y o u r u s e r interact w i t h y o u r a p p l i c a t i o n t h r o u g h c o n t r o l s a n d r e s o u r c e s . It is e a s i e r f o r h e r a n d e a s i e r f o r y o u if y o u d e v e l o p a p p l i c a t i o n s this w a y . R e s o u r c e e d i t o r s m a k e it a s n a p f o r y o u t o interactively d e s i g n a n d m o d i f y r e s o u r c e s , a n d c o n t r o l o b j e c t s are a l m o s t p l u g - i n s , t h a n k s t o O b j e c t W i n d o w s .
9
CHAPTER
MEMORY MATTERS I have a good memory, though is a tendency to over-remember
"good" is somewhat questionable, since life rather than to look for new life to be J i m Harrison
there lived.
W i n d o w s is a c o m p l e x m u l t i t a s k i n g e n v i r o n m e n t , w i t h c o m p a r a b l y c o m p l e x m e m o r y - m a n a g e m e n t capability. B e c a u s e W i n d o w s a l l o w s a p p l i c a t i o n s t o s h a r e m e m o r y , m o r e a p p l i c a t i o n s c a n r u n effectively at t h e s a m e t i m e . F o r e x a m p l e , if y o u r u n m u l t i p l e i n s t a n c e s o f a n a p p l i c a t i o n , W i n d o w s u s e s t h e same c o d e segments a n d resources for each instance. This multi-utilization o f r e s o u r c e s ( i c o n s , m e n u s , d i a l o g s , c u r s o r s , a n d s o o n ) is a n i m p o r t a n t a d v a n t a g e in separating resources from source c o d e . In addition, W i n d o w s can " m o v e " m e m o r y y o u allocate for your a p p l i c a t i o n ' s c o d e a n d d a t a s e g m e n t s a n d r e s o u r c e s , if y o u specify t h e m e m o r y as " m o v e a b l e . " W i n d o w s m o v e s m e m o r y t o c r e a t e l a r g e r c o n t i g u o u s m e m o r y b l o c k s . C o d e s e g m e n t s a n d r e s o u r c e s a l s o c a n b e d i s c a r d e d t o free m e m o r y (if y o u d e s i g n a t e t h e s e s e g m e n t s a n d r e s o u r c e s as " d i s c a r d a b l e " ) . O n e k e y result o f W i n d o w s ' m e m o r y m a n a g e m e n t is that l a r g e a p p l i c a t i o n s c a n r u n s i m u l t a neously in a m e m o r y space m u c h smaller than w o u l d b e required without W i n d o w s . A s a n a p p l i c a t i o n d e v e l o p e r , y o u w a n t t o t a k e as m u c h a d v a n t a g e o f t h e W i n d o w s m a n a g e m e n t s y s t e m as y o u c a n . A l t h o u g h m e m o r y m a n a g e m e n t s o u n d s d a u n t i n g , it is n o t . If y o u u s e t h e h o o k s p r o v i d e d b y T u r b o P a s c a l f o r W i n d o w s , y o u c a n t a p i n t o this c o m p l e x m e m o r y - m a n a g e m e n t s y s t e m . Essentially, y o u u s e a f e w b u i l t - i n p r o c e d u r e s s u c h as New, Dispose, GetMem, FreeMem, a n d MemAlloc t o a l l o c a t e d y n a m i c
280
Part I I — A d v a n c e d T o p i c s
v a r i a b l e s , a n d t h e T u r b o Pascal f o r W i n d o w s c o m p i l e r e n s u r e s that e n o u g h m e m o r y is i n t h e W i n d o w s g l o b a l h e a p t o a l l o c a t e t h e v a r i a b l e s . ( M o r e o n this in the next section). T h e w a y y o u w r i t e a p p l i c a t i o n s is n o t a f f e c t e d m u c h b y t h e s p e c i f i c W i n d o w s m o d e y o u are u s i n g , b u t y o u s h o u l d at least b e a w a r e o f t h e m o d e s a v a i l a b l e . T h e t h r e e m o d e s (real, s t a n d a r d , a n d e n h a n c e d ) are d e p e n d e n t o n the a m o u n t of m e m o r y the system r u n n i n g W i n d o w s has. W i n d o w s r u n s o n l y i n real m o d e o n s y s t e m s h a v i n g less t h a n 1 M ( m e g a b y t e ) o f R A M . I n this m o d e , W i n d o w s r u n s i n m e m o r y b e t w e e n 6 4 0 K (kilobytes) a n d 1 M . T h i s is, o f c o u r s e , t h e m o s t l i m i t i n g m o d e p r i m a r i l y b e c a u s e W i n d o w s h a s less m e m o r y t o u s e f o r s w a p p i n g c o d e s e g m e n t s , a n d s o o n . W i n d o w s c a n u s e E M S ( L o t u s - I n t e l - M i c r o s o f t E x p a n d e d M e m o r y S p e c i f i c a t i o n ) 4 . 0 i n real m o d e . E M S specifies a standard s c h e m e for accessing a n d using m e m o r y above 6 4 0 K . B e c a u s e this " e x t r a m e m o r y " w a s n o t a c c o u n t e d f o r i n early v e r s i o n s o f D O S , a p p l i c a t i o n s d e a l t w i t h this m e m o r y i n a n y w a y t h e y s a w fit, u n t i l this s p e c i f i c a t i o n w a s i n t r o d u c e d . W i n d o w s r e q u i r e s that a p p l i c a t i o n s u s e m e m o r y i n a similar, s t a n d a r d i z e d w a y s o that t h e y c a n b e s w a p p e d , f o r e x a m p l e , a n d are generally compatible. W i n d o w s c a n r u n in either real or standard m o d e in systems with b e t w e e n 1 M a n d 2 M o f m e m o r y . I n s t a n d a r d m o d e , W i n d o w s c a n a c c e s s as m u c h as 1 6 M o f m e m o r y . Finally, W i n d o w s c a n r u n i n 386 e n h a n c e d m o d e o n systems w i t h at least 2 M o f m e m o r y . 3 8 6 e n h a n c e d m o d e is s t a n d a r d m o d e p l u s t h e ability t o i m p l e m e n t virtual m e m o r y , w h i c h , i n effect, m e a n s that W i n d o w s c a n s w a p " p a g e s " t o d i s k i n o r d e r t o free a d d i t i o n a l m e m o r y . P a g e s w a p p i n g is s o m e thing y o u normally d o not have to worry about w h e n y o u develop W i n d o w s applications. I n g e n e r a l , W i n d o w s f i g u r e s o u t t h e b e s t m o d e f o r a s y s t e m w h e n it starts. A l l t h e e x a m p l e s i n this b o o k w e r e c o m p i l e d a n d r u n u n d e r W i n d o w s i n b o t h s t a n d a r d a n d 3 8 6 e n h a n c e d m o d e s ( T u r b o Pascal f o r W i n d o w s r e q u i r e s o n e o f t h e s e m o d e s ; it d o e s n o t r u n i n real m o d e ) .
Memory Management, Windows Style T y p i c a l l y , w h e n y o u w r i t e a p p l i c a t i o n s f o r D O S (but n o t W i n d o w s ) , m e m o r y is a l l o c a t e d at f i x e d (specific) l o c a t i o n s . If y o u are u s i n g T u r b o P a s c a l (for D O S ) m e m o r y - a l l o c a t i o n a n d d e a l l o c a t i o n p r o c e d u r e s , this is h a n d l e d a u t o m a t i c a l l y f o r y o u . Y o u just u s e New, Dispose, a n d s o o n , a n d T u r b o Pascal's m e m o r y m a n a g e m e n t system ensures e n o u g h m e m o r y to allocate space for a variable. W i n d o w s , h o w e v e r , t a k e s a m o r e flexible a p p r o a c h t o m e m o r y a l l o c a t i o n . M e m o r y blocks can be fixed, but also m o v e d and discarded. By not forcing b l o c k s o f m e m o r y t o b e f i x e d , W i n d o w s c a n significantly i m p r o v e m e m o r y u s e . F o r e x a m p l e , m e m o r y that is " m o v e a b l e " c a n b e " c o m p a c t e d " t o c r e a t e a l a r g e r b l o c k o f free m e m o r y f r o m s m a l l e r b l o c k s o f free m e m o r y , as illustrated i n figure 9.1.
9 — M e m o r y Matters
M e m o r y c a n be c o m p a c t e d
Block 1
Free
Free
Free
Block 2
Block 1
Free
Block 2
before
Figure
after
9.1. Creating a larger block of free memory from smaller blocks of free memory.
Another way W i n d o w s improves m e m o r y use is compaction through "discardable" m e m o r y blocks (see figure 92).
Memory can be discarded
Block 1
Free
Free
Free
Block 2
free
Free
Block 2
before
Figure
after
9.2. Compacting through "discardable" memory blocks.
281
282
Part I I — A d v a n c e d T o p i c s
H o w d o e s y o u r T u r b o Pascal f o r Windows a p p l i c a t i o n k n o w w h a t is g o i n g o n w i t h m e m o r y ? Easy. M o s t o f t h e t i m e , it d o e s n o t e v e n b o t h e r itself w i t h t h e p h y s i c a l l o c a t i o n o f a m e m o r y b l o c k . It a c c e s s e s m e m o r y t h r o u g h a handle t o t h e m e m o r y b l o c k . I n o t h e r w o r d s , rather t h a n g e t a p o i n t e r t o a m e m o r y b l o c k (a typical n o n - W i n d o w s a p p r o a c h ) , t h e a p p l i c a t i o n g e t s a handle (a n a m e ) that represents a p o i n t e r t o a p o i n t e r t o t h e m e m o r y b l o c k (see figure 9 3 ) .
Handles -> Pointers -> Memory
Handle
Figure
Pointer
Memory block
93. A handle to access a memory block.
T o access m e m o r y m a n a g e d by W i n d o w s , y o u r application only has to d e t e r m i n e w h e r e a c h u n k o f m e m o r y is "right n o w . " I n o t h e r w o r d s , y o u m u s t still o b t a i n t h e a d d r e s s o f t h e b l o c k , b u t f o r t h e t i m e o n l y i n w h i c h y o u are u s i n g it. W h e n y o u are d o n e w i t h a b l o c k , y o u g i v e u p t h e h a n d l e t o it, f r e e i n g it s o that W i n d o w s c a n m o v e it if it n e e d s t o . T h e n , w h e n n e x t y o u n e e d t o a c c e s s t h e b l o c k o f m e m o r y , y o u ask W i n d o w s a g a i n w h e r e it is b y g e t t i n g its c u r r e n t address. F o r e x a m p l e , if G H a n d l e is a h a n d l e t o a b l o c k o f g l o b a l l y a l l o c a t e d m e m o r y , y o u g e t its a d d r e s s b y l o c k i n g t h e h a n d l e a n d a s s i g n i n g t h e r e s u l t i n g address to a pointer: var GHandle : THandle; PtrGData: { A pointer
}
begin GHandle
:= G l o b a l A l l o c ( g m e m _ M o v e a b l e ,
50000);
{ Memory t y p e a n d s i z e
}
9 — M e m o r y Matters
PtrGData:= {
GlobalLock(GHandle); }
end; I n this f r a g m e n t , P t r G D a t a " g e t s " t h e a d d r e s s o f t h e m e m o r y b l o c k . B y l o c k i n g t h e b l o c k , y o u t e m p o r a r i l y "fix" t h e b l o c k at s o m e s p e c i f i c l o c a t i o n s o that W i n d o w s c a n n o t m o v e o r d i s c a r d it u n t i l y o u " u n l o c k " t h e block using o n e of the U n l o c k procedures: GlobalUnlock(GHandle); o r , if L H a n d l e is a h a n d l e t o a l o c a l l y a l l o c a t e d m e m o r y b l o c k : LocalUnlock(LHandle); W h e n the block has b e e n u n l o c k e d , the pointer to the m e m o r y b l o c k (you just o b t a i n e d ) is n o l o n g e r v a l i d b e c a u s e W i n d o w s c a n a g a i n m o v e o r d i s c a r d t h e m e m o r y . If y o u h a v e t o k n o w w h e r e a b l o c k o f m e m o r y is t h r o u g h o u t t h e life o f t h e a p p l i c a t i o n , a l l o c a t e it as a fixed b l o c k : GHandle
:=
GlobalAlloc(gmem_fixed,10000);
T h i s s t e p " f i x e s " t h e b l o c k , p r e v e n t i n g W i n d o w s f r o m m o v i n g it a b o u t . I n g e n e r a l , t h o u g h , y o u d o n o t w a n t t o fix m e m o r y b l o c k s ; i n s t e a d y o u a l l o c a t e t h e m as m o v e a b l e : GHandle
:=
GlobalAlloc(gmem_Moveable,2000);
o r as m o v a b l e a n d d i s c a r d a b l e : GHandle
:= GlobalAlloc(gmem_Moveable or
gmem_Discardable);
T h i s l i n e m e a n s that W i n d o w s c a n " d i s c a r d " m e m o r y a n d " r e l o a d " it w h e n it is n e e d e d a g a i n as w e l l as m o v e i t — t h u s f r e e i n g u p e v e n m o r e m e m o r y w h e n necessary. Y o u n o d o u b t have noticed the prefix g l o b a l in most of the previous short examples. D e c i d i n g whether to allocate a n d use local or global m e m o r y blocks is a n i m p o r t a n t i s s u e , d i s c u s s e d in s o m e d e t a i l i n t h e n e x t s e c t i o n .
Global and Local Memory Y o u r a p p l i c a t i o n s c a n a l l o c a t e m e m o r y b l o c k s in e i t h e r o f t w o areas: t h e g l o b a l or the local heap. T h e g l o b a l h e a p is all t h e m e m o r y that W i n d o w s " c l a i m s " w h e n y o u r u n it. T h e g l o b a l h e a p is s h a r e d b y W i n d o w s , W i n d o w s a p p l i c a t i o n s , a n d t h e " g l o b a l " m e m o r y b l o c k s a l l o c a t e d b y W i n d o w s a p p l i c a t i o n s (like y o u r s ) . G l o b a l m e m o r y is fantastically p o w e r f u l b e c a u s e it is s y s t e m - s i z e d ; it c o n t a i n s m e m o r y w i t h i n a n d b e y o n d y o u r a p p l i c a t i o n s . A g l o b a l m e m o r y b l o c k c a n b e as l a r g e as 1 M i n W i n d o w s s t a n d a r d m o d e a n d 6 4 M i n 3 8 6 e n h a n c e d m o d e . A g l o b a l m e m o r y block can b e u s e d to access the data in other programs.
283
284
Part I I — A d v a n c e d T o p i c s
T h e l o c a l h e a p is m e m o r y that is a c c e s s i b l e o n l y b y a s p e c i f i c i n s t a n c e o f y o u r a p p l i c a t i o n . I n o t h e r w o r d s , it is " p r i v a t e " t o y o u r a p p l i c a t i o n a n d just like t h e h e a p y o u w e r e u s e d t o i n T u r b o Pascal ( b e f o r e W i n d o w s ) . T h e l o c a l h e a p is l i m i t e d t o w h a t e v e r is left o f t h e 6 4 K d a t a s e g m e n t after y o u r a p p l i c a t i o n h a s u s e d s o m e f o r a stack a n d its o w n g l o b a l v a r i a b l e s . T h e l o c a l h e a p is o n l y 8 K b y d e f a u l t , b u t y o u c a n a d j u s t its size u s i n g e i t h e r t h e $M c o m p i l e r d i r e c t i v e o r t h e T u r b o Pascal f o r W i n d o w ' s I D E o p t i o n / C o m p i l e r / M e m o r y S i z e m e n u s . I n a d d i t i o n , t h e m a x i m u m size o f t h e l o c a l h e a p c a n d e p e n d o n w h e t h e r y o u r a p p l i c a t i o n ' s d a t a s e g m e n t is f i x e d o r m o v a b l e . If it is f i x e d , t h e l o c a l h e a p is r e s t r i c t e d t o t h e size y o u a l l o c a t e d u s i n g t h e $M c o m p i l e r d i r e c t i v e (or t h e I D E ) at c o m p i l e t i m e . I f t h e d a t a s e g m e n t is m o v e a b l e , y o u r a p p l i c a t i o n c a n r e q u e s t a l a r g e r size t h a n t h e o n e y o u s p e c i f i e d at c o m p i l e t i m e . S o u n d s c o n v e n i e n t , b u t t h e r e is a p o s s i b l e s i d e effect: W i n d o w s m i g h t g e t a bit o f e x t r a m e m o r y f o r y o u r application b y m o v i n g the data s e g m e n t , w h i c h in turn probably invalidates any far ( o r l o n g ) p o i n t e r s t o l o c a l d a t a . W h e t h e r y o u u s e local o r global m e m o r y d e p e n d s primarily o n t w o factors: 1. H o w b i g a b l o c k y o u n e e d 2. W h e t h e r t h e b l o c k is u s e d f o r a l o c a l o r g l o b a l task If y o u n e e d o n l y a little bit o f m e m o r y ( I K o r l e s s ) , t h e n y o u p r o b a b l y w a n t t o u s e l o c a l m e m o r y b e c a u s e it is faster a n d d o e s n o t r e q u i r e t h e 2 0 b y t e s o f W i n d o w s overhead required to allocate a global m e m o r y block. G l o b a l m e m o r y is y o u r c h o i c e if y o u n e e d a b i g g e r b l o c k o r t o c o n n e c t t o s y s t e m - w i d e r e s o u r c e s , s u c h as a n o t h e r a p p l i c a t i o n ' s d a t a o r t h e C l i p b o a r d — m o r e o n this i n C h a p t e r 1 1 , " F r o m P r o g r a m t o P r o g r a m U s i n g D D E ( D y n a m i c D a t a E x c h a n g e ) . " G l o b a l m e m o r y is s o m e w h a t s l o w e r b e c a u s e it is a c c e s s e d t h r o u g h W i n d o w s g l o b a l m e m o r y h a n d l e s , b u t it c a n b e far larger.
Allocating Local Memory Blocks A l l o c a t i n g l o c a l a n d g l o b a l m e m o r y b l o c k s is similar. T h e f o l l o w i n g s e g m e n t shows h o w to allocate a moveable, local m e m o r y block o f 256K:
var ALocalHandle : THandle; begin ALocalHandle := LocalAlloc(lmem_Moveable,256); { } end; A l l o c a t e t h e l o c a l m e m o r y as e i t h e r fixed, m o v e a b l e , o r m o v e a b l e a n d d i s c a r d a b l e , u s i n g t h e W i n d o w s A P I f u n c t i o n , LocalAlloc.
9 — M e m o r y Matters
LocalAlloc r e t u r n s a m e m o r y b l o c k i d e n t i f i e r (a n u m b e r ) if it is s u c c e s s f u l a n d z e r o if it is n o t s u c c e s s f u l . T h i s i d e n t i f i e r is t h e h a n d l e t o t h e m e m o r y block. ALocalHandle is a THandle, a l r e a d y d e c l a r e d i n O b j e c t W i n d o w s , w h i c h c a n b e a c c e s s e d b y o t h e r f u n c t i o n s n e e d i n g t o find t h e h a n d l e . After y o u h a v e a s k e d t o a l l o c a t e t h e m e m o r y b l o c k , c h e c k t o s e e w h e t h e r the m e m o r y allocation has b e e n successful. If t h e allocation w a s successful, LocalAlloc r e t u r n s t h e h a n d l e t o t h e m e m o r y b l o c k . If u n s u c c e s s f u l , it r e t u r n s a zero: if ALocalHandle
0 then
{..-.} If t h e a l l o c a t i o n h a s n o t b e e n s u c c e s s f u l , b a i l o u t . I f t h e a l l o c a t i o n w a s s u c c e s s f u l , l o c k t h e m e m o r y b l o c k a n d g e t its a d d r e s s : var APtrLocalData:
{ Pointer }
begin APtrLocalData {
:= LocalLock(ALocalHandle);
}
end; If t h e l o c k is s u c c e s s f u l , LocalLock r e t u r n s a p o i n t e r t o t h e b l o c k ( a n a d d r e s s ) . I f n o t , it r e t u r n s n i l . C h e c k f o r s u c c e s s b e f o r e m o v i n g o n : if APtrLocalData nil then {
}
If s u c c e s s f u l , p r o c e s s t h e d a t a . W h e n y o u a r e f i n i s h e d w i t h t h e b l o c k , u s e t h e W i n d o w s A P I f u n c t i o n LocalUnlock t o u n l o c k it, a n d e i t h e r free o r d i s c a r d it s o that W i n d o w s c a n r e c o v e r t h e m e m o r y if n e c e s s a r y . F r e e t h e m e m o r y b y freeing the handle: LocalUnlock(ALocalHandle); LocalFree(ALocalHandle): or discard: LocalUnlock(ALocalHandle); LocalDiscard(ALocalHandle); Y o u m u s t U n l o c k t h e b l o c k ( w h i c h sets t h e L o c k C o u n t t o z e r o ) b e f o r e y o u free o r d i s c a r d it. O t h e r w i s e , t h e free o r d i s c a r d o p e r a t i o n fails b e c a u s e it a u t o m a t i c a l l y c h e c k s t h e L o c k c o u n t t o s e e w h e t h e r it is z e r o . Z e r o i n d i c a t e s that the block c a n b e freed or discarded. F r e e i n g a m e m o r y b l o c k r e m o v e s its c o n t e n t s a n d i n v a l i d a t e s t h e h a n d l e to the m e m o r y block by r e m o v i n g the h a n d l e from a table of valid local m e m o r y handles.
285
286
Part I I — A d v a n c e d T o p i c s
D i s c a r d i n g a m e m o r y b l o c k r e a l l o c a t e s its size t o z e r o , b u t d o e s n o t remove the handle from the local m e m o r y handles table. Y o u c a n reuse the h a n d l e , u s i n g t h e LocalRealloc p r o c e d u r e , a n d r e a l l o c a t e a n e w m e m o r y b l o c k o f a different size: var ALocalHandle: THandle; begin { .... Previous allocation and use of block } LocalDiscard(ALocalHandle}; ALocalHandle := LocalReAlloc(ALocalHandle,512,lmem_Moveable); {.... more processing } end; Y o u m i g h t w a n t t o r e u s e a m e m o r y b l o c k t o save t h e u n l o c k i n g - a n d new-handle allocation steps. Y o u a l s o c a n f i n d o u t h o w l a r g e a l o c a l b l o c k is b y u s i n g LocalSize: var ALocalHandle
: THandle;
MemoryBlockSize: Word; begin ALocalHandle := LocalAlloc(lmem_Moveable,512); if ALocalHandle 0 then MemoryBlockSize := LocalSize(ALocalHandle); end; N o t i c e a g a i n that y o u a l l o c a t e a n d a c c e s s t h e m e m o r y b l o c k i n d i r e c t l y t h r o u g h a h a n d l e t o t h e m e m o r y block, n o t directly t h r o u g h a pointer. B e c a u s e y o u a r e a c c e s s i n g m e m o r y i n d i r e c t l y (by h a n d l e ) , W i n d o w s c a n safely m o v e m e m o r y blocks a r o u n d a n d inform y o u w h e r e they are only w h e n y o u n e e d to k n o w . M o s t o f t h e t i m e y o u d o n o t k n o w w h e r e a m e m o r y b l o c k is, a n d that is just fine. T h a n k y o u , W i n d o w s . O n e w a y y o u c a n u s e a l o c a l m e m o r y b l o c k is s i m p l y t o s t o r e a text b u f f e r o n t h e l o c a l h e a p . F o r e x a m p l e , y o u m i g h t w a n t t o s t o r e a l a r g e string f o r u s e b y a s i n g l e m o d u l e , as t h e c o d e i n listing 9.1 illustrates. N o t e that a MessageBox is u s e d t o d i s p l a y t h e status a n d r e s u l t s o f t h e l o c a l m e m o r y a l l o c a t i o n , w h i c h o c c u r s b e f o r e t h e MainWindow is d i s p l a y e d . A l s o n o t e that it is n e c e s s a r y t o c o n v e r t t h e d i s p l a y e d c h a r a c t e r i n t o a string b e f o r e u s i n g MessageBox t o d i s p l a y it. R e m e m b e r : W i n d o w s f u n c t i o n s , s u c h as MessageBox, that d i s p l a y strings r e q u i r e n u l l - t e r m i n a t e d s t r i n g s . F i g u r e 9.4 s h o w s a m e s s a g e b o x i n d i c a t i n g that t h e l o c a l m e m o r y a l l o c a t i o n h a s n o t o c c u r r e d yet. F i g u r e 95 s h o w s t h e MessageBox d i s p l a y i n g t h e first c h a r a c t e r i n t h e l o c a l l y a l l o c a t e d array o f c h a r a c t e r s , after t h e a l l o c a t i o n . F i g u r e 9.6 s h o w s t h e MainWindow d i s p l a y e d after t h e a l l o c a t i o n .
9 — M e m o r y Matters 2 8 7
Figure
9.4.
A message box showing that the local memory allocation occurred.
Figure
9.5. A message box displaying the first character of characters (after allocation).
has not yet
in the locally allocated
array
288
Part I I — A d v a n c e d T o p i c s
Figure 9.6. The MainWindow
Listing
9*1. Storing
a text buffer
displayed after
on the local
allocation.
heap.
program localjnem; uses WObjects, WinTypes, WinProcs, StdDlgs, Strings, WIF5;
{ Basic Interface }
type PLocalArray = "TLocalArray; TLocalArray = array[0..1000] of char; LocalApplication = object(TApplication) { Derive an application object } FirstApplication : boolean; procedure InitMainWindow; virtual; { Init a main window } procedure InitApplication; virtual; end; PLocalWindow = "LocalWindow;
9 — M e m o r y Matters
289
LocalWindow = object(MainWindow) LocalHandle: THandle; PtrLocalData: PBigArray; Value: Char; S : array[0..9] of char; constructor Init(AParent : PWirfdowsObject; ATitle : PChar); procedure AllocateBlock; end;
{ LocalApplication method implementation } procedure LocalApplication.InitMainWindow; begin if FirstApplication then MainWindow := New(PLocalWindow, Init(nil, Local Windows Interface')) else MainWindow := New(PLocalWindow, Init(nil,'Additional Instance of BI')); end; 1
procedure LocalApplication.InitApplication; begin FirstApplication := True; end; constructor LocalWindow.Init(AParent : PWindowsObject; ATitle : PChar); begin MainWindow.Init(AParent, ATitle); { Send message to ancestor's constructor Attr.Menu := LoadMenu(HInstance, PChar(100)); { 100 = menu ID } ButtonDown := False; { Set status flag } MessageBox(HWindow,' Here before Local call', 'Local Status 1', mb_0k); AllocateBlock; { Allocate the block } end; procedure LocalWindow.AllocateBlock; begin LocalHandle := LocalAlloc(gmem_Moveable,1000); if LocalHandle 0 then begin PtrLocalData := LocalLock(LocalHandle); if PtrLocalData nil then begin continues
290
Part II—Advanced Topics
Listing
9.1.
continued
PtrLocalData"[0] := 'L'; Value := PtrLocalData"[0]; { Value = char } S[0] := Value; { Convert to a string for viewing } MessageBox(HWindow,S, 'AllocateBlock , mb_0k); LocalUnlock(LocalHandle); 1
end else MessageBox(HWindow,
1
Local Fail', 'LF', mb_0k);
end else end; var Applicationl: LocalApplication;
{ An instance of BasicApplication } { Run Applicationl }
begin Applicationl.Init( Local Interface'); { Init application instance } Applicationl.Run; { Message loop } Applicationl.Done; { Destroy application instance } end. 1
Global Memory Blocks Working with global m e m o r y blocks is similar. The following segment shows h o w to allocate a moveable, global m e m o r y block of 256K: var AGlobalHandle : THandle; begin AGlobalHandle := GlobalAlloc(gmem_Moveable,1024); { } end; Allocate the global m e m o r y as either fixed, moveable, or moveable or discardable, using the W i n d o w s API function GlobalAlloc. GlobalAlloc returns a m e m o r y block identifier (a number) if it is successful and zero if not successful. This identifier is the handle to the m e m o r y block:
9 — M e m o r y Matters
A G l o b a l H a n d l e i s a T H a n d l e , already declared in O b j e c t W i n d o w s , w h i c h c a n b e a c c e s s e d b y o t h e r f u n c t i o n s n e e d i n g t o find t h e h a n d l e . After y o u h a v e a s k e d that t h e m e m o r y b l o c k b e a l l o c a t e d , c h e c k t o s e e w h e t h e r t h e m e m o r y a l l o c a t i o n h a s b e e n s u c c e s s f u l . If t h e a l l o c a t i o n w a s s u c c e s s f u l , G l o b a l A l l o c r e t u r n s t h e h a n d l e t o t h e m e m o r y b l o c k . If u n s u c c e s s f u l , it r e t u r n s a z e r o : if
AGlobalHandle
0 t h e n
{••••} If t h e a l l o c a t i o n h a s n o t b e e n s u c c e s s f u l , b a i l o u t . If t h e a l l o c a t i o n w a s s u c c e s s f u l , l o c k t h e m e m o r y b l o c k a n d g e t its a d d r e s s : var APtrGlobalData: { Pointer } begin APtrGlobalData {
:=
GlobalLock(AGlobalHandle);
}
end; If t h e l o c k is s u c c e s s f u l , G l o b a l L o c k , like L o c a l L o c k , r e t u r n s a p o i n t e r t o t h e b l o c k (an a d d r e s s ) . If n o t , it r e t u r n s n i l . C h e c k f o r s u c c e s s b e f o r e moving on: if
APtrGlobalData {
n i l
then
}
If s u c c e s s f u l , p r o c e s s t h e d a t a . W h e n y o u are finished w i t h t h e b l o c k , u s e t h e W i n d o w s A P I f u n c t i o n G l o b a l U n l o c k t o u n l o c k it, a n d e i t h e r free o r d i s c a r d it s o that W i n d o w s c a n r e c o v e r t h e m e m o r y if n e c e s s a r y . F r e e t h e m e m o r y b y freeing the handle: GlobalUnlock(AGlobalHandle); GlobalFree(AGlobalHandle): or discard: GlobalUnlock(AGlobalHandle); GlobalDiscard(AGlobalHandle); A g a i n , as w i t h l o c a l m e m o r y a l l o c a t i o n , y o u m u s t u n l o c k t h e b l o c k (setting t h e L o c k C o u n t t o z e r o ) b e f o r e y o u free o r d i s c a r d it. O t h e r w i s e t h e free o r d i s c a r d o p e r a t i o n fails b e c a u s e it a u t o m a t i c a l l y c h e c k s t h e L o c k c o u n t t o s e e w h e t h e r it is z e r o . F r e e i n g a m e m o r y b l o c k r e m o v e s its c o n t e n t s a n d i n v a l i d a t e s t h e h a n d l e to the m e m o r y b l o c k by removing the h a n d l e from a table of valid global memory handles.
291
292
Part I I — A d v a n c e d T o p i c s
D i s c a r d i n g a g l o b a l m e m o r y b l o c k r e a l l o c a t e s its size t o z e r o , b u t d o e s n o t remove the handle from the global m e m o r y handles table. Y o u c a n reuse the h a n d l e , u s i n g t h e GlobalRealloc p r o c e d u r e , a n d r e a l l o c a t e a n e w m e m o r y b l o c k o f a different size:
var AGlobalHandle: THandle; begin { .... Previous allocation and use of block } GlobalDiscard(AGlobalHandle}; AGlobalHandle := GlobalReAlloc(AGlobalHandle,512,gmem_Moveable); {.... more processing } end; Y o u a l s o c a n d e t e r m i n e h o w l a r g e a g l o b a l b l o c k is b y u s i n g GlobalSize:
var AGlobalHandle : THandle; MemoryBlockSize: Word; begin AGlobalHandle := GlobalAlloc(gmem_Moveable,1024); if AGlobalHandle 0 then MemoryBlockSize := GlobalSize(AGlobalHandle); end; W h e n e v e r y o u n e e d t o u s e a large block, u s e g l o b a l m e m o r y . Listing 9 2 s h o w s y o u h o w t o c r e a t e a l a r g e g l o b a l b u f f e r . F i g u r e 9 7 s h o w s a MessageBox d i s p l a y e d b e f o r e t h e g l o b a l a l l o c a t i o n . F i g u r e 9 8 s h o w s t h e v a l u e o f t h e first s i x c h a r a c t e r s o f t h e g l o b a l array. F i g u r e 9 9 s h o w s t h e MainWindow (GlobalWindow) d i s p l a y e d after t h e g l o b a l a l l o c a t i o n . If t h e g l o b a l a l l o c a t i o n d o e s n o t s u c c e e d , a MessageBox i n d i c a t e s t h e global failure. T h e user must a c k n o w l e d g e the failure, a n d t h e n processing continues.
9 — M e m o r y Matters
Figure
9.7. A message box showing that the global allocation
Figure
9.8. A message box displaying the first six characters array after global allocation.
has not
occurred.
in the globally
allocated
293
294
Part I I — A d v a n c e d T o p i c s
Figure
Listing
9-2.
93.
The MainWindow
Creating
(GlobalWindow)
a large global
after the global
allocation.
buffer.
program glob_mem; uses WObjects, WinTypes, WinProcs, StdDlgs, Strings, WIF5; { Basic Interface } type PGlobalArray = "TGlobalArray; TGlobalArray = array[0..1024] of char; GlobalApplication = object(TApplication) { Derive an application object } FirstApplication : boolean; procedure InitMainWindow; virtual; { Init a main window } procedure InitApplication; virtual; end; PGlobalWindow = "GlobalWindow;
9 — M e m o r y Matters
295
GlobalWindow = object(MainWindow) GlobalHandle: THandle; PtrGlobalData: PGlobalArray; Value: Char; S : array[0..9] of char; constructor Init(AParent : PWindowsObject; ATitle : PChar); procedure AllocateBlock; end;
{ BasicApplication method implementation } procedure GlobalApplication.InitMainWindow; begin if FirstApplication then MainWindow := New(PGlobalWindow, Init(nil, 'Global Windows Interface')) else MainWindow := New(PGlobalWindow, Init(nil,'Additional Instance of GI')); end;
procedure GlobalApplication.InitApplication; begin FirstApplication := True; end; constructor GlobalWindow.Init(AParent : PWindowsObject; ATitle : PChar); begin MainWindow.Init(AParent, ATitle); { Send message to ancestor's constructor } Attr.Menu := LoadMenu(HInstance, PChar(100)); { 100 = menu ID } ButtonDown := False; { Set status flag } MessageBox(HWindow, Here before Global call', 'GF', mb_Ok); AllocateBlock; end; 1
procedure GlobalWindow.AllocateBlock; var I : integer; begin GlobalHandle := GlobalAlloc(gmem_Moveable,1024); if GlobalHandle 0 then continues
296
Part I I — A d v a n c e d T o p i c s
Listing
9.2.
continued
begin PtrGlobalData := GlobalLock(GlobalHandle); if PtrGlobalData nil then begin PtrGlobalData"[0] := 'G'; PtrGlobalData"[1] := 'L'; PtrGlobalData"[2] := '0'; PtrGlobalData"[3] := 'B'; PtrGlobalData"[4] := 'A'; PtrGlobalData"[5] := 'L'; For I := 0 to 5 do begin Value := PtrGlobalData"[I]; S[I] := Value; end; MessageBox(HWindow,S, AllocateBlock , mb_0k); GlobalUnlock(GlobalHandle); 1
1
end else MessageBox(HWindow,
1
Global Fail', ' G F , mb_0k); 1
end else end;
var Applicationl: GlobalApplication; { An instance of BasicApplication } { Run Applicationl } begin Applicationl.Init('Global Interface'); { Init application instance } Applicationl.Run; { Message loop } Applicationl.Done; { Destroy application instance } end. W h e t h e r t o u s e g l o b a l o r l o c a l m e m o r y d e p e n d s b o t h o n t h e size o f t h e m e m o r y b l o c k y o u are a l l o c a t i n g a n d w h o n e e d s t o a c c e s s it. I n C h a p t e r 1 1 , y o u use global m e m o r y blocks to exchange data with the clipboard and other applications through D D E (Dynamic Data Exchange).
9 — M e m o r y Matters
A Few Advanced Memory Matters A s a r u l e o f t h u m b , w h e n i n d o u b t , a l l o c a t e m e m o r y as m o v e a b l e r a t h e r t h a n f i x e d . A m e m o r y b l o c k s h o u l d b e a l l o c a t e d as fixed o n l y if y o u m u s t k e e p a m e m o r y b l o c k i n a s i n g l e l o c a t i o n t h r o u g h o u t t h e life o f y o u r a p p l i c a t i o n . If y o u fix a m e m o r y b l o c k , y o u sacrifice m u c h o f t h e s o p h i s t i c a t i o n o f W i n d o w s ' memory-management system. T h e r e are a c o u p l e o f n o t a b l e v a r i a t i o n s o n t h e fixer t h e m e y o u m i g h t w a n t t o b e a w a r e of: • A l l s e g m e n t s are m o v e a b l e i n s t a n d a r d (or 2 8 6 p r o t e c t e d ) m o d e b e c a u s e W i n d o w s can m o v e segments without c h a n g i n g their addresses. W i n d o w s changes the base address in the segment descript o r t a b l e , n o t t h e s e g m e n t a d d r e s s . N o t s o , o f c o u r s e , i n real m o d e . • A l s o , w h e n e v e r y o u r a p p l i c a t i o n g e t s a far p o i n t e r f r o m W i n d o w s , t h e far p o i n t e r r e f e r e n c e s a fixed d a t a s e g m e n t . F o r e x a m p l e , e a c h t i m e y o u r a p p l i c a t i o n starts u p , it g e t s a far p o i n t e r t o a l o c a t i o n i n m e m o r y that h o l d s a c o m m a n d - l i n e a r g u m e n t f o r y o u r a p p l i c a t i o n . For a m o r e in-depth discussion of h o w W i n d o w s manages c o d e and data s e g m e n t s , c h e c k o u t C h a r l e s P e t z o l d ' s e x c e l l e n t Programming Windows, a g u i d e to p r o g r a m m i n g W i n d o w s using C (Microsoft Press). A l t h o u g h Petzold's e x a m p l e s a n d a t t e n t i o n are a l m o s t e n t i r e l y C - o r i e n t e d , h e p r o v i d e s a n i n c r e d ible a m o u n t o f useful a n d general information about W i n d o w s p r o g r a m m i n g .
Direct Memory Access T u r b o P a s c a l f o r W i n d o w s h a s t h r e e p r e d e f i n e d arrays (Mem, MemW, a n d MemL) that e n a b l e y o u t o a c c e s s m e m o r y directly. U s i n g t h e s e arrays, y o u c a n c h a n g e the values o f a byte o f m e m o r y . This b o o k d o e s not detail h o w to manipulate m e m o r y directly, b e c a u s e it is p r o b a b l y n o t a g o o d i d e a t o d o s o . B y d i r e c t l y m a n i p u l a t i n g m e m o r y , y o u interfere with the W i n d o w s m e m o r y - m a n a g e m e n t s y s t e m a n d s e r i o u s l y j e o p a r d i z e t h e life e x p e c t a n c y o f y o u r a p p l i c a t i o n s . U n l e s s y o u h a v e a n o u t s t a n d i n g r e a s o n f o r a c c e s s i n g m e m o r y directly, let W i n d o w s d o it.
Data Segments E a c h a p p l i c a t i o n r u n n i n g i n W i n d o w s h a s its o w n 6 4 K d a t a s e g m e n t . T h i s d a t a s e g m e n t is t h e o n e p o i n t e d t o b y t h e d a t a s e g m e n t ( D S ) register. It c o n s i s t s o f four parts:
297
298
Part I I — A d v a n c e d T o p i c s
1. A l o c a l h e a p ( y o u specify size) 2. A stack (for l o c a l v a r i a b l e s — t h e o n e s a l l o c a t e d i n p r o c e d u r e s a n d functions) 3. A stack d a t a a r e a f o r g l o b a l v a r i a b l e s a n d t y p e d c o n s t a n t s 4. A task h e a d e r that i d e n t i f i e s t h e s e g m e n t E a c h d y n a m i c l i n k library ( D L L ) r u n n i n g i n W i n d o w s h a s its o w n 6 4 K d a t a s e g m e n t as w e l l , w h i c h c o n s i s t s o f a task h e a d e r a n d a l o c a l h e a p , b u t n o t a stack o r stack d a t a a r e a . D L L p r o c e d u r e s a n d f u n c t i o n s u s e t h e stack o f t h e a p p l i c a t i o n that c a l l e d t h e m .
Heap Errors S o m e t h i n g e l s e y o u m i g h t w a n t t o t h i n k a b o u t a r e h e a p e r r o r s . If t h e T u r b o Pascal f o r W i n d o w s h e a p m a n a g e r c a n n o t a l l o c a t e t h e m e m o r y b l o c k y o u r e q u e s t ( u s i n g New o r Get Mem), it g e n e r a t e s a r u n - t i m e e r r o r . A r u n - t i m e e r r o r is p r o b a b l y n o t d e s i r a b l e f o r y o u r a p p l i c a t i o n . M o r e likely, y o u w a n t y o u r a p p l i c a t i o n t o c o n t i n u e p r o c e s s i n g , e v e n if it c a n n o t a l l o c a t e t h e m e m o r y b l o c k . T h e s o l u t i o n i s a H e a p E r r o r v a r i a b l e . U s e t h e H e a p E r r o r v a r i a b l e t o install a h e a p e r r o r f u n c t i o n that is s e n t a m e s s a g e w h e n e v e r t h e h e a p m a n a g e r c a n n o t a l l o c a t e t h e m e m o r y b l o c k y o u r e q u e s t . T h e H e a p E r r o r v a r i a b l e is a p o i n t e r t o a f u n c t i o n (in t h e s y s t e m u n i t ) w i t h a h e a d e r s u c h as t h i s :
function HeapFunc(Size: Word): Integer; far; Install t h e HeapFunc b y a s s i g n i n g its a d d r e s s t o t h e HeapError v a r i a b l e :
HeapError := @HeapFunc; HeapFunc is c a l l e d a u t o m a t i c a l l y w h e n e v e r a New o r GetMem r e q u e s t fails. T h e Size p a r a m e t e r c o n t a i n s t h e size o f t h e m e m o r y b l o c k that c o u l d n o t b e a l l o c a t e d . T h e HeapFunc s h o u l d r e t u r n a z e r o , o n e , o r t w o . A z e r o i n d i c a t e s a m e m o r y - a l l o c a t i o n failure a n d c a u s e s a r u n - t i m e e r r o r . A o n e i n d i c a t e s f a i l u r e , but d o e s n o t generate a run-time error. A t w o indicates success. T o guarantee that y o u r a p p l i c a t i o n d o e s n o t c r a s h after a n u n s u c c e s s f u l m e m o r y - a l l o c a t i o n a t t e m p t , h a v e t h e HeapFunc r e t u r n a o n e :
function HeapFunc(Size: Word): Integer; far; begin HeapFunc := 1; end; W h e n t h e HeapFunc r e t u r n s a o n e , it f o r c e s New o r GetMem t o r e t u r n a n i l pointer rather than crash the p r o g r a m .
9 — M e m o r y Matters
T h e HeapError v a r i a b l e a l s o c a n b e u s e d t o install a c o n s t r u c t o r error-recovery system.
Code Segments E a c h u n i t , library, o r m a i n p r o g r a m h a s its o w n c o d e s e g m e n t . E a c h o f t h e s e c o d e s e g m e n t s c a n b e u p t o 6 4 K i n s i z e , l i m i t e d o n l y b y available m e m o r y . E a c h c o d e s e g m e n t c a n b e m o v e a b l e o r fixed, p r e l o a d e d o r d e m a n d l o a d e d , d i s c a r d a b l e o r p e r m a n e n t . ( T h e d e f a u l t attributes f o r a c o d e s e g m e n t are m o v e a b l e , p r e l o a d e d , a n d p e r m a n e n t . U n l e s s y o u a r e d o i n g s o m e n o n ordinary programming, y o u d o not have to change these defaults. This minid i s c u s s i o n is i n c l u d e d just i n c a s e . ) If a c o d e s e g m e n t is m o v e a b l e it c a n b e m o v e d b y W i n d o w s t o free m e m o r y b l o c k s . I f a c o d e s e g m e n t is fixed, W i n d o w s c a n n o t m o v e it. T o m a k e y o u r a p p l i c a t i o n flexible f o r W i n d o w s , it s h o u l d r e s i d e i n m o v e a b l e c o d e s e g m e n t s . If a c o d e s e g m e n t is p r e l o a d e d , it is a u t o m a t i c a l l y l o a d e d w h e n y o u activate t h e a p p l i c a t i o n . I f a c o d e s e g m e n t is d e m a n d - l o a d e d , it is l o a d e d o n l y w h e n a r o u t i n e that r e s i d e s i n t h e s e g m e n t is c a l l e d . If a c o d e s e g m e n t is d i s c a r d a b l e , it b e h a v e s m u c h like a n o v e r l a i d s e g m e n t . W i n d o w s c a n t e m p o r a r i l y d i s c a r d it a n d free its m e m o r y w h e n it n e e d s t o . Windows then reloads the segment w h e n a procedure or function in the code s e g m e n t is n e e d e d . R e l o a d i n g a s e g m e n t is o b v i o u s l y m o r e t i m e - c o n s u m i n g . T h e trade-off: y o u r a p p l i c a t i o n t a k e s u p less r o o m a n d a g a i n is m o r e flexible a n d c a n b e m o v e d around by Windows.
wm_Compacting O n e o t h e r i m p o r t a n t m a t t e r y o u m i g h t w a n t t o i n f o r m y o u r a p p l i c a t i o n s o f is t h e wm_Compacting m e s s a g e . W i n d o w s b r o a d c a s t s this m e s s a g e t o all h i g h l e v e l w i n d o w s w h e n it b e g i n s t o s p e n d m o r e t h a n 12.5 p e r c e n t o f its t i m e compacting memory. B e c a u s e c o m p a c t i n g m e m o r y is o b v i o u s l y a t i m e - c o n s u m i n g task f o r t h e W i n d o w s m a n a g e m e n t s y s t e m , it s e n d s this m e s s a g e t o i n d i c a t e that it is s p e n d i n g t o o m u c h time "managing" rather than r u n n i n g applications. W h e n a n a p p l i c a t i o n r e c e i v e s this m e s s a g e , it s h o u l d a t t e m p t t o free as m u c h m e m o r y as it c a n . Y o u r a p p l i c a t i o n r e s p o n d s t o this m e s s a g e t h e s a m e w a y it r e s p o n d s t o a n y W i n d o w s m e s s a g e : w i t h a W i n d o w s m e s s a g e - r e s p o n s e method. For example:
299
300
Part I I — A d v a n c e d T o p i c s
AnObjectInstance.WMCompacting(var Msg: TMessage); begin { Handle compaction message by freeing memory here } end;
Wrap-up That discussion covers the general m e m o r y issues y o u n e e d to k n o w in order t o w r i t e s e n s i b l e W i n d o w s a p p l i c a t i o n s . W i n d o w s is a d y n a m i c s y s t e m i n various ways, and object-oriented techniques can help y o u use and appreciate this d y n a m i c quality. I n g e n e r a l , y o u s h o u l d let W i n d o w s h a n d l e a n y t h i n g it c a n h a n d l e f o r y o u b e c a u s e (frankly) it is g o i n g t o b e b e t t e r at it. Y o u a l s o c a n e a s e t h e p r o c e s s f o r W i n d o w s by letting the blocks o f m e m o r y y o u allocate (whether local or global) b e m o v e a b l e a n d d i s c a r d a b l e , if p o s s i b l e . T h i s t a k e s t h e b e s t a d v a n t a g e o f t h e W i n d o w s m e m o r y - m a n a g e m e n t system. Y o u a l s o m u s t c h a n g e y o u r t r a d i t i o n a l t h i n k i n g w h e n y o u refer t o m e m o r y b l o c k s i n t e r m s o f p o i n t e r s a n d a d d r e s s e s . W i t h W i n d o w s , m e m o r y b l o c k s are just a little m o r e i n d i r e c t . Y o u g e t t h e a d d r e s s f r o m a h a n d l e first b e c a u s e W i n d o w s has a built-in system for manipulating m e m o r y t h r o u g h handles. By u s i n g h a n d l e s , o t h e r a p p l i c a t i o n s c a n "get a h a n d l e " o n t h e m e m o r y that a n o t h e r a p p l i c a t i o n is u s i n g . T h i s c r e a t e s t h e u s e f u l p o s s i b i l i t y o f e x c h a n g i n g data b e t w e e n applications, w h i c h y o u learn about in detail in C h a p t e r 11.
10 CHAPTER
DISPLAY CONTEXTS AND DRAWING TOOLS / wanted the audience to know that a computer was making the drawings. People would stand there for a long time watching the computer produce drawings. The pen would pause and people would say, "Gee, it's thinking of what to do next." Aaron C o h e n A l t h o u g h y o u have already u s e d the Graphics Device Interface in most of the p r e v i o u s c h a p t e r s , this c h a p t e r s p e n d s a little t i m e d e s c r i b i n g its f e a t u r e s . T o h e l p t h e G D I m a k e m o r e s e n s e , several e x a m p l e s o f h o w y o u m i g h t u s e it t o c r e a t e c o m p l e x g r a p h i c s - o r i e n t e d a p p l i c a t i o n s are c o v e r e d . T h e W i n d o w s G D I is a r e m a r k a b l e a s p e c t o f W i n d o w s b e c a u s e it a l l o w s y o u t o w r i t e a p p l i c a t i o n s that d i s p l a y a n d m a n i p u l a t e g r a p h i c s , i n d e p e n d e n t o f a s p e c i f i c d i s p l a y d e v i c e . Y o u c a n , f o r e x a m p l e , w r i t e a p p l i c a t i o n s that u s e t h e s a m e c o d e yet c a n b e d i s p l a y e d i n E G A , V G A , o r H e r c u l e s m o d e s . W i n d o w s a c h i e v e s d e v i c e i n d e p e n d e n c e b y u s i n g v a r i o u s d e v i c e drivers that translate G D I f u n c t i o n calls i n t o c o m m a n d s that m a k e s e n s e t o t h e s p e c i f i c o u t p u t d e v i c e b e i n g u s e d . Y o u w r i t e c o d e as t h o u g h t h e o u t p u t d e v i c e d o e s n o t m a t t e r , w h i c h (in g e n e r a l ) is h o w it is.
302
Part I I — A d v a n c e d T o p i c s
Handling a Display Context A d i s p l a y c o n t e x t is the surface of a n a p p l i c a t i o n w i n d o w ' s client area, or m o r e precisely, it represents the surface of a n a p p l i c a t i o n w i n d o w ' s client area. A n y d i s p l a y c o n t e x t has attributes that represent c o l o r s , w i n d o w p o s i t i o n , d r a w i n g t o o l s , a n d s o o n . (These attributes are set t o d e f a u l t v a l u e s b y O b j e c t W i n d o w s , w h i c h is w h y y o u have n o t had t o set a n y o f t h e s e attributes in t h e e x a m p l e s s o far.) A d i s p l a y c o n t e x t u s e s a l o t o f m e m o r y , s o Windows l i m i t s a n y Windows s e s s i o n t o a total o f five c o n c u r r e n t in-use d i s p l a y c o n t e x t s . It is important, therefore, that y o u r a p p l i c a t i o n release a n y d i s p l a y c o n t e x t it is u s i n g as s o o n as it n o l o n g e r n e e d s the d i s p l a y c o n t e x t . This a c t i o n results in a repetitive, s e e m i n g l y inefficient ( b u t necessary) p o s s e s s i n g a n d releasing o f display c o n t e x t s , a n d it d o e s have a d r a w b a c k . It m e a n s f o r e m o s t that y o u r a p p l i c a t i o n d o e s n o t maintain control over a display context. When a n a p p l i c a t i o n releases a d i s p l a y c o n t e x t , it is giving it u p t o a n y other a p p l i c a t i o n that n e e d s it. T h e n e w a p p l i c a t i o n c a n , in t u r n , m a n i p u l a t e its attributes. E a c h t i m e a n a p p l i c a t i o n releases a d i s p l a y c o n t e x t , the d i s p l a y c o n t e x t ' s attributes are reset t o the d e f a u l t s . T h u s , y o u r a p p l i c a t i o n m u s t set a n y d i s p l a y c o n t e x t attributes for c h a n g i n g e a c h t i m e it receives a d i s p l a y c o n t e x t . I n a d d i t i o n , y o u r a p p l i c a t i o n m u s t reselect a n y d r a w i n g t o o l ( p e n , b r u s h , f o n t ) for u s e e a c h t i m e it receives a d i s p l a y c o n t e x t . F o r e x a m p l e , derive a d r a w i n g w i n d o w that resets a specific k i n d o f p e n (a d r a w i n g t o o l ) e a c h t i m e it o b t a i n s a d i s p l a y c o n t e x t . I n a d d i t i o n , let the u s e r m o d i f y b o t h the p e n size (the w i d t h o f the l i n e it draws) a n d the p e n style. This e x a m p l e s h o w s how t o • O b t a i n a n d release
a display context.
• U s e m e n u - c o m m a n d m e s s a g e s t o invoke
a dialog.
• Create, modify, a n d delete drawing tools. B e g i n , as u s u a l , b y deriving a n Application ( o b j e c t ) : type DrawingApplication = object(BasicApplication) procedure InitMainWindow; virtual; end; a n d its MainWindow (a DrawingWindow): type PDrawingWindow = "DrawingWindow; DrawingWindow = object(MainWindow) DragDC: HDC; { A new display context } ThePen: HPen; { A drawing tool }
10—Display Contexts a n d Drawing Tools
PenSize: Integer; { Pen variables } PenStyle: Integer; constructor Init(AParent: PWindowsObject; ATitle: PChar); destructor Done; virtual; function CanClose: Boolean; virtual; { New mouse methods } procedure WMLButtonDown(var Msg: TMessage); virtual wm_First + wm_LButtonDown; procedure WMLButtonUp(var Msg: TMessage); virtual wm_First + wm_LButtonUp; procedure WMMouseMove(var Msg: TMessage); virtual wm_First + wm_MouseMove; { Menu-response methods } procedure CMPenStyle(var Msg: TMessage); virtual cm_First + cm_PenStyle; procedure CMPenSize(var Msg: TMessage); virtual cm_First + cm_PenSize; { Pen modifiers } procedure SetPenSize(NewSize: Integer); procedure SetPenStyle(NewStyle: Integer); end; T h e CMPenSize a n d CMPenStyle m e t h o d s a r e m e n u - r e s p o n s e m e t h o d s , w h i c h r e s p o n d t o t h e m e n u c o m m a n d s cm_PenSize a n d cmPenStyle. D e clare t h e s e t w o c o m m a n d s i n t h e const s e c t i o n :
const cm_PenStyle = 401; cm_PenSize = 402; T h e s e c o n s t a n t s c o r r e s p o n d t o t h e m e n u i t e m s i n t h e r e s o u r c e file, P E N . R E S . F i g u r e 10.1 s h o w s t h e c r e a t i o n a n d t e s t i n g o f P E N . R E S . N o t i c e t h e matching constants. W h e n y o u c o n s t r u c t t h e DrawingWindow: 1. L o a d t h e m e n u ( P E N . R E S ) that c o n t a i n s t h e PenSize a n d PenStyle m e n u items. 2. S e t t h e d e f a u l t p e n size a n d style. 3. C r e a t e t h e p e n , u s i n g CreatePen:
constructor DrawingWindow.Init(AParent: PWindowsObj ect; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, PChar(109));
303
304
Part I I — A d v a n c e d T o p i c s
ButtonDown := False; PenSize := 1; { Size increases with integer value } PenStyle := ps_DashDot; { Refers to a pen constant, an integer } ThePen := CreatePen(PenStyle, PenSize, 0); end;
Figure
10.1. Creation and testing of PEN. RES.
N o t i c e that t h e d r a w i n g t o o l (the p e n ) is n o t a s s o c i a t e d w i t h a d i s p l a y c o n t e x t . Y o u d o n o t o b t a i n a d i s p l a y c o n t e x t u n t i l y o u d e c i d e t o u s e o n e . I n this e x a m p l e , t h e u s e r c a n d r a w i n t h e w i n d o w w h e n s h e p r e s s e s t h e left m o u s e button down:
procedure DrawingWindow.WMLButtonDown(var Msg: TMessage); begin (* InvalidateRect(HWindow, nil, True); if you want the window cleared *) if not ButtonDown then begin ButtonDown := True; SetCapture(HWindow); DragDC := GetDC(HWindow); SelectObject(DragDC, ThePen); { Select the pen created in Init } MoveTo(DragDC, Msg.LParamLo, Msg.LParamHi); { Use the pen } end; end;
10—Display Contexts a n d Drawing Tools
S h e r e l e a s e s t h e d i s p l a y c o n t e x t w h e n s h e is f i n i s h e d d r a w i n g :
procedure DrawingWindow.WMLButtonUp(var Msg: TMessage); begin if ButtonDown then begin ButtonDown := False; ReleaseCapture; ReleaseDC(HWindow, DragDC); end; end; N o t i c e that, a l t h o u g h t h e d i s p l a y c o n t e x t h a s b e e n r e l e a s e d s o that o t h e r a p p l i c a t i o n s c a n u s e t h e i r o w n d i s p l a y c o n t e x t s , t h e DrawingWindow is still o p e n , a n d y o u c a n still d r a w i n t h e w i n d o w . E a c h t i m e y o u c l i c k t h e left m o u s e button, the application grabs a display context for y o u to u s e . N o w w r i t e t h e m e n u - r e s p o n s e m e t h o d s f o r m o d i f y i n g t h e p e n ' s size a n d style. W h e n t h e u s e r s e l e c t s t h e PenSize m e n u i t e m , a d i a l o g w i n d o w a p p e a r s that a l l o w s h e r t o c h a n g e t h e p e n size:
procedure DrawingWindow.CMPenSize(var Msg: TMessage); var InputText: array[0..5] of Char; NewSize, ErrorPos: Integer; begin if not ButtonDown then begin Str(PenSize, InputText); if Application".ExecDialog(New(PInputDialog, Init(@Self, 'Line Thickness', 'Input a new thickness:', InputText, SizeOf(InputText)))) = id_0k then begin Val(InputText, NewSize, ErrorPos); if ErrorPos = 0 then SetPenSize(NewSize); end; end; end; A p r o c e d u r e for actually creating the n e w p e n in t h e n e w size:
procedure DrawingWindow.SetPenSize(NewSize: Integer); begin DeleteObject(ThePen); ThePen := CreatePen(PenStyle, NewSize, 0); PenSize := NewSize; end;
305
306
Part I I — A d v a n c e d T o p i c s
T h e s a m e g o e s for PenStyle. A response a l l o w t h e u s e r t o m o d i f y t h e p e n ' s style is
m e t h o d that u s e s a d i a l o g t o
procedure DrawingWindow.CMPenStyle(var Msg: TMessage); var InputText: array[0..5] of Char; NewStyle, ErrorPos: Integer; begin if not ButtonDown then begin Str(PenStyle, InputText); if Application".ExecDialog(New(PInputDialog, Init(@Self, 'Pen Style', 'New Pen Style: 0 = solid 1 = dash 2 = dot, and so on, InputText, SizeOf(InputText)))) = id_0k then begin Val(InputText, NewStyle, ErrorPos); if ErrorPos = 0 then SetPenStyle(NewStyle); end; end; end; A SetPenStyle m e t h o d to actually create t h e n e w p e n is procedure DrawingWindow.SetPenStyle(NewStyle: begin DeleteObject(ThePen); ThePen := CreatePen(NewStyle, PenSize, 0); PenStyle := NewStyle; end;
Integer);
N o t i c e that t h e DrawingWindow d o e s n o t " o w n " a d i s p l a y c o n t e x t w h i l e the p e n ' s size a n d style are m o d i f i e d . Y o u d o n o t n e e d it t o create a n d m o d i f y d r a w i n g t o o l s (objects) that are u s e d t o d r a w o n t h e display c o n t e x t . A l s o , n o t i c e that b e c a u s e t h e t w o variables PenStyle a n d PenSize m a i n t a i n t h e status of t h e d r a w i n g t o o l s , e a c h t i m e t h e DrawingWindow o b t a i n s a d i s p l a y c o n t e x t it u s e s the current settings for the p e n . T h e p e n (with its current v a l u e s ) is s e l e c t e d just after the d i s p l a y c o n t e x t is o b t a i n e d : DragDC := GetDC(HWindow); SelectObject(DragDC, ThePen);
{ Get a display context } { Select the pen created in Init }
When y o u finish with the DrawingWindow (notthe d i s p l a y context), d e l e t e the drawing tool (the p e n ) u s i n g DeleteObj ect:
10—Display Contexts and Drawing Tools
destructor begin
DrawingWindow.Done;
DeleteObject(ThePen); TWindow.Done; end; B e c a u s e t h e d r a w i n g t o o l ( o b j e c t ) is n o t part o f t h e d i s p l a y c o n t e x t , it is n o t d e l e t e d a u t o m a t i c a l l y w h e n t h e d i s p l a y c o n t e x t is r e l e a s e d . Listing 1 0 . 1 s h o w s t h e c o m p l e t e Pen m o d i f i c a t i o n e x a m p l e , a n d f i g u r e 1 0 . 2 s h o w s t h e D r a w i n g W i n d o w c r e a t e d b y this c o d e .
Figure
Listing
10.2. The DrawingWindow
10.1.
The complete
created by listing 10.1.
pen-modification
example.
program Pen; uses Strings, WinTypes, WinProcs, WObjects, WIF5, StdDlgs;
{ Basic Interface }
{$R Pen.Res } continues
307
308
Part I I — A d v a n c e d T o p i c s
Listing
10.1.
continued
const cm_PenStyle = 401; cm_PenSize = 402; type DrawingApplication = object(BasicApplication) procedure InitMainWindow; virtual; end; PDrawingWindow = "DrawingWindow; DrawingWindow = object(MainWindow) DragDC: HDC; ThePen: HPen; PenSize: Integer; PenStyle: Integer; constructor Init(AParent: PWindowsObject; ATitle: PChar); destructor Done; virtual; function CanClose: Boolean; virtual; procedure WMLButtonDown(var Msg: TMessage); virtual wm_First + wm_LButtonDown; procedure WMLButtonUp(var Msg: TMessage); virtual wm_First + wm_LButtonUp; procedure WMMouseMove(var Msg: TMessage); virtual wm_First + wm_MouseMove; procedure CMPenStyle(var Msg: TMessage); virtual cm_First + cm_PenStyle; procedure CMPenSize(var Msg: TMessage); virtual cm_First + cm_PenSize; procedure SetPenSize(NewSize: Integer); procedure SetPenStyle(NewStyle: Integer); end; { { DrawingWindow's method implementations:
} }
{
}
constructor DrawingWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, PChar(109)); ButtonDown := False; PenSize := 1; PenStyle := ps_DashDot;
10—Display Contexts and Drawing Tools
ThePen := CreatePen(PenStyle, PenSize, 0); end;
destructor DrawingWindow.Done; begin DeleteObject(ThePen); TWindow.Done; end; procedure DrawingWindow.CMPenStyle(var Msg: TMessage); var InputText: array[0..5] of Char; NewStyle, ErrorPos: Integer; begin if not ButtonDown then begin Str(PenStyle, InputText); if Application".ExecDialog(New(PInputDialog, Init(@Self, 'Pen Style', 'New Pen Style: 0 = solid 1 = dash 2 = dot, etc.', InputText, SizeOf(InputText)))) = id_0k then begin Val(InputText, NewStyle, ErrorPos); if ErrorPos = 0 then SetPenStyle(NewStyle); end; end; end; procedure DrawingWindow.SetPenStyle(NewStyle: Integer); begin DeleteObject(ThePen); ThePen := CreatePen(NewStyle, PenSize, 0); PenStyle := NewStyle; end;
function DrawingWindow.CanClose: Boolean; var Reply: Integer; begin CanClose := True; continues
309
310
Part I I — A d v a n c e d T o p i c s
Listing
10.1.
continued
Reply := MessageBox(HWindow, 'Do you want to save?', 'Drawing has changed', mb_YesNo or mb_IconQuestion); if Reply = id_Yes then CanClose := False; end; procedure DrawingWindow.WMLButtonDown(var Msg: TMessage); begin (* InvalidateRect(HWindow, nil, True); *) if not ButtonDown then begin ButtonDown := True; SetCapture(HWindow); DragDC := GetDC(HWindow); SelectObject(DragDC, ThePen); MoveTo(DragDC, Msg.LParamLo, Msg.LParamHi); end; end; procedure DrawingWindow.WMMouseMove(var Msg: TMessage); begin if ButtonDown then LineTo(DragDC, Integer(Msg.LParamLo), Integer(Msg.LParamHi)); end; procedure DrawingWindow.WMLButtonUp(var Msg: TMessage); begin if ButtonDown then begin ButtonDown := False; ReleaseCapture; ReleaseDC(HWindow, DragDC); end; end; procedure DrawingWindow.CMPenSize(var Msg: TMessage); var InputText: array[0..5] of Char; NewSize, ErrorPos: Integer; begin if not ButtonDown then begin Str(PenSize, InputText); if Application".ExecDialog(New(PInputDialog,
10—Display C o n t e x t s a n d D r a w i n g T o o l s
Init(@Self, 'Line Thickness', 'Input a new thickness:', InputText, SizeOf(InputText)))) = id_0k then begin Val(InputText, NewSize, ErrorPos); if ErrorPos = 0 then SetPenSize(NewSize); end; end; end; procedure DrawingWindow.SetPenSize(NewSize: Integer); begin DeleteObject(ThePen); ThePen := CreatePen(PenStyle, NewSize, 0); PenSize := NewSize; end; { { DrawingApplication's
method implementations:
{
} } }
procedure DrawingApplication.InitMainWindow; begin MainWindow := New(PDrawingWindow, Init(nil, end;
'Drawing
{ { Main program:
} }
{
}
Window'));
var App :
DrawingApplication;
begin App.Init('DrawProgram ); App.Run; App.Done; end. 1
Y o u a l s o c a n t h i n k o f a d i s p l a y c o n t e x t ( D C ) as a s t o r a g e o f t h e attributes that d e t e r m i n e h o w W i n d o w s G D I f u n c t i o n s o p e r a t e i n a w i n d o w ' s c l i e n t a r e a . A d i s p l a y c o n t e x t " h o l d s " 19 attributes (a m a p p i n g m o d e , p e n , f o n t , text c o l o r , a n d s o o n ) . E a c h t i m e y o u r a p p l i c a t i o n asks f o r a d i s p l a y c o n t e x t f r o m W i n d o w s , W i n d o w s creates a n e w o n e with a default value for each attribute. Y o u d o not h a v e t o set e a c h o f t h e 19 attributes e a c h t i m e y o u r e c e i v e a D C . T a b l e 10.1 s h o w s t h e d e v i c e c o n t e x t a t t r i b u t e a n d its d e f a u l t .
311
312
Part I I — A d v a n c e d T o p i c s
Table DC
10.1.
Device
context
Attribute
attributes
with their
defaults.
Default
Mapping mode
MMTEXT
Window
0,0
origin
Viewport origin
0,0
Window
1,1
extents
Viewport extents
1,1
Pen
BLACK_PEN
Brush
WHITE
JBRUSH
Font
SYSTEMFONT
Bit m a p
—
Current pen position
0,0
Background mode
Opaque
Background color
White
Text color
Black
Drawing mode
R2COPYPEN
Stretching m o d e
BLACK-ONWHITE
P o l y g o n filling m o d e
Alternate
Intercharacter spacing
0
Brush origin
0,0
C l i p p i n g region
—
Y o u c a n o v e r r i d e a n y o f t h e d i s p l a y c o n t e x t ' s d e f a u l t a t t r i b u t e s if y o u w a n t . W i n d o w s provides a f u n c t i o n for setting o r selecting e a c h attribute a n d for g e t t i n g t h e v a l u e o f a n a t t r i b u t e . F o r e x a m p l e , t o set t h e m a p p i n g m o d e attribute:
var ADCHandle : HDC; AMapMode : Integer; begin
end;
SetMapMode(ADCHandle, AMapMode); {...}
10—Display Contexts and Drawing Tools
T o set t h e Windows
origin:
var ADCHandle : HDC; X, Y : Integer; begin SetWindowOrg(ADCHandle,X,Y); {
}
end; T o g e t t h e text color: var TxtColor : Longlnt; ADCHandle : HDC; begin TxtColor := GetTextColor(ADCHandle); {••-.} end;
T a b l e 10.2 s h o w s t h e f u n c t i o n s t o set o r select e a c h o f t h e d i s p l a y c o n t e x t
attributes. Table
10.2. Functions
to set or select
display
context
attributes.
Set/Select
Get
Mapping mode
SetMapMode
GetMapMode
Window
SetWindowOrg
GetWindowOrg
V i e w p o r t origin
SetViewportOrg
GetViewportOrg
Window
SetWindowExt
GetWindowExt
Viewport extents
SetViewportExt
GetViewportExt
Pen
SelectObject
SelectObject
Brush
SelectObject
SelectObject
Font
SelectObject
SelectObject
Bit m a p
SelectObject
SelectObject
Current p e n position
MoveTo; LineTo
GetCurrentPosition
Background mode
SetBkMode
GetBkMode
Background color
SetBkColor
GetBkColor
DC
Attribute
origin
extents
continues
313
314
Part I I — A d v a n c e d T o p i c s
Table
10.2.
continued Set/Select
Get
Text color
SetTextColor
GetTextColor
Drawing m o d e
SetROP2
GetROP2
Stretching m o d e
SetPolyFiUMode
GetPolyFillMode
P o l y g o n filling m o d e
SetPOlyFillMode
GetPolyFillMode
Intercharacter spacing
SetTextCharacterExtra
GetTextChar..
B r u s h origin
SetBrushOrg
GetBrushOrg
DC
Attribute
C l i p p i n g region
SelectClipRgn
GetClipBox
SelectObject
SelectObject
T h e s u r f a c e o f t h e d i s p l a y c o n t e x t itself is a bit m a p that c o r r e s p o n d s t o s o m e s p e c i f i c d e v i c e . T h u s , a n y d e v i c e c o n t e x t ' s bit m a p is s p e c i f i c t o t h e c u r r e n t d i s p l a y c o n t e x t that r e p r e s e n t s t h e v i d e o a d a p t e r y o u r a p p l i c a t i o n is u s i n g . T h i s s u g g e s t s t h e p r o b l e m o f m a k i n g t h e d e v i c e - c o n t e x t bit m a p u s a b l e by different adapters. T h e s o l u t i o n is f o r y o u r a p p l i c a t i o n t o c r e a t e d e v i c e - i n d e p e n d e n t bit m a p s using the following Windows G D I functions: CreateCompatibleDC, CreateCompatible Bitmap, CreateDIBitmap. For example: procedure var
SomeWindow.SetupWindow;
HandleDC: HDC; begin TNoIconWindow.SetupWindow; HandleDC := GetDC(HWindow); ABitmap := CreateCompatibleBitmap(HandleDC, 80, 80); ABkgnd := CreateCompatibleBitmap(HandleDC, 1000, 1000); ReleaseDC(HWindow, HandleDC); end; Y o u r application c a n decide w h e t h e r drawings are clipped in t h e display context b y modifying t h e clipping-region attribute in t h e display context. Usually, y o u want t o u s e the default clipping region, the client area o f the window.
10—Display Contexts and Drawing Tools
Set the clipping region w h e n you select an object: SelectObj ect(ADCHandle,ARegionHandle); or use SelectClipRgn: SelectClipRgn(ADCHandle,ARegionHandle);
Mapping Modes O n e of the attributes you might find useful to change is the mapping mode. W i n d o w s defines eight mapping m o d e s (the default MM_TEXT, MM_L0METRIC, and so on). Table 10.3 shows these mapping modes. Table
10.3-
Mapping
Windows
Mode
mapping
modes.
Logical
Unit
MMTEXT
pixel
MMLOMETRIC
0.1 m m
MMHIMETRIC
0.01 m m
MMLOENGLISH
0.01
MMHIENGLISH
0.001
MM_TWIPS
1/1440 inch
MMJSOTROPIC
Arbitrary ( x = y )
MM ANISOTROPIC
Arbitrary ( x < > y )
inch inch
The default mapping m o d e is MM_TEXT, which moves X and Y values a pixel at a time. Its origin (0,0) is the upper-left corner of the window's client area. If you have difficulty understanding h o w a screen, window, and window's client areas differ, see figure 10.3. In short, the screen is the entire display. The w i n d o w is an entire window, including the caption bar, scroll bars, w i n d o w frame, and any m e n u . The w i n d o w client area is the part of a w i n d o w excluding the caption bar, m e n u , and so forth. Generally, w h e n you use display contexts, you use the w i n d o w client area (which is what is used in the examples). Y o u should be aware, however, that there are W i n d o w s functions for converting coordinates between client area and screen, screen and window, and so on.
315
316
Part I I — A d v a n c e d T o p i c s
A s s u m i n g that y o u are w o r k i n g i n t h e w i n d o w ' s c l i e n t a r e a (the d e f a u l t ) , a n d a s s u m i n g that y o u are w o r k i n g i n MM_TEXT m a p p i n g m o d e (the d e f a u l t ) , y o u are u s i n g a p i x e l - b a s e d c o o r d i n a t e s y s t e m b e g i n n i n g i n t h e u p p e r - l e f t c o r n e r (see figure 1 0 . 4 ) .
Figure 10.3- A screen, window,
and window's
client
M M _ T E X T Mapping
areas.
Mode
+x
+
y
Figure 10.4. A pixel-based
coordinate
system beginning
in the upper-left
comer.
10—Display Contexts and Drawing Tools
If y o u are u s e d t o w o r k i n g w i t h m a t h e m a t i c a l c o o r d i n a t e s y s t e m s , y o u m i g h t w o n d e r w h y t h e o r i g i n is t h e u p p e r - l e f t c o r n e r . It is t h e r e b e c a u s e text flows f r o m left t o right, f r o m t o p t o b o t t o m . T h u s , a d d i t i o n a l text o n a s c r e e n is s h o w n b y i n c r e a s i n g X a n d Y ( + X , + Y ) c o o r d i n a t e s — c o n v e n i e n t f o r text, b u t backward for most mathematical coordinate systems. If y o u n e e d a m o r e intuitive c o o r d i n a t e s y s t e m f o r p l o t t i n g g r a p h s a n d o t h e r s , h o w e v e r , y o u c a n c h a n g e t h e m a p p i n g m o d e t o o n e o f five d i f f e r e n t m o d e s that h a v e t h e i r o r i g i n (0,0) i n t h e lower-left c o r n e r . T h e s e lower-left m a p p i n g m o d e s are s o m e t i m e s c a l l e d metric mapping modes. T h e y are n o t p i x e l - b a s e d (like M M T E X T ) ; i n s t e a d t h e y i n c r e m e n t t h e i r X a n d Y c o m p o n e n t s b y l o g i c a l u n i t s ( 0 . 2 5 4 m m , 0 . 1 m m , a n d s o f o r t h ) . F i g u r e 10.5 s h o w s a m e t r i c mapping mode.
Metric Mapping
Modes
+x
-y
Figure
10.5. A metric mapping mode.
T o set a M M _ L 0 E N G L I S H m e t r i c m a p p i n g m o d e , f o r e x a m p l e , SetMapMode: SetMapMode(DC,
use
MM_L0ENGLISH)
N o t i c e that if y o u u s e a m e t r i c m a p p i n g m o d e , a n y t h i n g y o u d i s p l a y i n t h e c l i e n t a r e a m u s t b e l o c a t e d u s i n g n e g a t i v e v a l u e s o f Y . N o t spifiy. Y o u p r o b a b l y w a n t t o t h i n k i n b o t h p o s i t i v e X a n d Y . F o r t u n a t e l y , W i n d o w s offers a s o l u t i o n : y o u c a n c h a n g e the "logical" origin o f the client area u s i n g the W i n d o w s function S e t V i e w p o r t O r g and S e l e c t C l i p R g n :
317
318
Part I I — A d v a n c e d T o p i c s
SetView(ADCHandle,ClientX/2,ClientY/2); SelectClipRgn(ADCHandle,AClipregion); w h i c h c h a n g e s the coordinate system t o l o o k like figure 10.6.
Resetting the Viewport Origin
Figure
10.6. The result of changing from the "logical" origin.
Listing 10.2 s h o w s a little a p p l i c a t i o n that shirts t h e o r i g i n f r o m t h e u p p e r left t o t h e u p p e r - r i g h t c o r n e r o f t h e c l i e n t w i n d o w i n r e s p o n s e t o a m e n u i t e m selection. T h e key m e n u - r e s p o n s e m e t h o d s are CMUpperLef t , w h i c h uses the default upper-left origin: procedure MoveOriginWindow.CMUpperLeft(var begin
Msg: TMessage);
DragDC := GetDC(HWindow); SetMapMode(DragDC,MM_TEXT); { U s e MM_TEXT mode } StrLCopy(S,'Hello',Size0f(S) - 1); TextOut(DragDC,10,20,S,SizeOf(S)); ReleaseDC(HWindow,DragDC); end; and CMUpperRight, which moves the origin to the upper-right corner o f the client w i n d o w : procedure MoveOriginWindow.CMUpperRight(var begin DragDC := GetDC(HWindow); SetMapMode(DragDC,MM_TEXT);
Msg: TMessage);
{ S e t map mode }
10—Display Contexts and Drawing Tools
SetViewportOrg(DragDC,Attr.W,0); StrLCopy(S,'Hello',SizeOf(S) - 1); TextOut(DragDC,-60,20,S,SizeOf(S)); ReleaseDC(HWindow,DragDC);
{ Shift origin } { Note -X coordinate }
end; Y o u d o n o t have to e x p l i c i t l y set t h e MM_TEXT m a p p i n g m o d e b e c a u s e it is t h e d e f a u l t . It is d o n e here f o r c o m p l e t e n e s s . Listing
10.2.
Setting
the MM_ TEXT mapping
mode.
program MoveOrigin; uses Strings, WinTypes, WinProcs, WObjects; {$R Pen.Res }{Pen resource is just used for convenience} const cm_Upperl_ef t cmJJpperRight
= 401; = 402;
type MoveOriginApplication = object(TApplication) procedure InitMainWindow; virtual; end; PMoveOriginWindow = "MoveOriginWindow; MoveOriginWindow = object(TWindow) S : array[0..5] of Char; DragDC: HDC; constructor Init(AParent: PWindowsObject; ATitle: PChar); destructor Done; virtual; procedure CMUpperLeft(var Msg: TMessage); virtual cm_First + cm_UpperLeft; procedure CMUpperRight(var Msg: TMessage); virtual cm_First + cmJJpperRight; end; { { MoveOriginWindow's method implementations:
} }
{
} continues
319
320
Part I I — A d v a n c e d T o p i c s
Listing
10.2.
continued
constructor MoveOriginWindow.Init (AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, PChar(109)); DisableAutoCreate; Attr.Style := ws_PopupWindow or ws_Caption or ws_Visible; Attr.X Attr.Y Attr.W Attr.H
:= := := :=
50; 50; 200; 200;
end; destructor MoveOriginWindow.Done; begin TWindow.Done; end; procedure MoveOriginWindow.CMUpperLeft(var Msg: TMessage); begin DragDC := GetDC(HWindow); SetMapMode(DragDC,MM_TEXT); { Use MM_TEXT mode } StrLCopy(S,'Hello',SizeOf(S) - 1); TextOut(DragDC,10,20,S,SizeOf(S)); ReleaseDC(HWindow,DragDC); end; procedure MoveOriginWindow.CMUpperRight(var begin DragDC := GetDC(HWindow); SetMapMode(DragDC,MM_TEXT); { SetViewportOrg(DragDC,Attr.W,0); { StrLCopy(S,'Hello',SizeOf(S) - 1); TextOut(DragDC,-60,20,S,SizeOf(S)); { ReleaseDC(HWindow,DragDC); end;
Msg: TMessage);
Set map mode } Shift origin } Note -X coordinate }
{ { MoveOriginApplication s method implementations:
} }
{
}
1
10—Display Contexts and Drawing Tools
procedure MoveOriginApplication.InitMainWindow; begin MainWindow := New(PMoveOriginWindow, Init(nil, 'Origin Window')); end; { { Main program:
} }
{
}
var App : MoveOriginApplication; begin App.Init('MoveOriginProgram'); App.Run; App.Done; end. F i g u r e 1 0 . 7 s h o w s t h e resulting
Figure
10.7. The result of listing
10.2.
text d i s p l a y .
321
322
Part I I — A d v a n c e d T o p i c s
Drawing Figures W i n d o w s h a s a r i c h , b u i l t - i n set o f t o o l s f o r d r a w i n g l i n e s a n d v a r i o u s s h a p e s ; including lines, circles, ellipses, rectangles, r o u n d rectangles, chords, pies, polygons, and poly polygons. Y o u can draw these figures individually or in c o m b i n a t i o n . T o draw any figure, y o u r application uses a p e n , either the default p e n (BLACKPEN) or a c u s t o m p e n that y o u r a p p l i c a t i o n c r e a t e s . F o r e x a m p l e , t h e little e x a m p l e i n listing 10.3 s h o w s h o w t o c r e a t e a n a p p l i c a t i o n that r e s p o n d s t o u s e r m e n u - i t e m s e l e c t i o n s b y d r a w i n g e i t h e r a r e c t a n g l e , a filled r e c t a n g l e , o r a n e l l i p s e i n a D a s h D o t p e n style. It c r e a t e s t h e p e n , retrieves a d i s p l a y c o n t e x t , selects t h e p e n , d r a w s t h e figure, r e l e a s e s t h e display context, and deletes the object using m e n u - c o m m a n d messageresponse methods. N o t i c e that filling a r e c t a n g l e is s o m e w h a t d i f f e r e n t t h a n s i m p l y d r a w i n g t h e r e c t a n g l e . T h e k e y d i f f e r e n c e lies i n t h e d r a w i n g t o o l y o u u s e t o p r o d u c e t h e r e c t a n g l e . W h e n y o u d r a w a r e c t a n g l e , y o u u s e a p e n . W h e n y o u d r a w a n d fill a r e c t a n g l e , y o u u s e a b r u s h that c a n b e e i t h e r a s t o c k o b j e c t ( s u c h as a GRAY_BRUSH) o r a b r u s h b a s e d o n a bit m a p . T h e C M F i l l e d R e c t a n g l e m e t h o d i n listing 10.3 u s e s a s t o c k b r u s h : procedure FigsWindow.CMGrayFilledRectangle(var begin SetCapture(HWindow); DragDC := GetDC(HWindow);
Msg:
TMessage);
SelectObject(DragDC, GetStockObject(GRAY_BRUSH)); Rectangle(DragDC,20,20,200,200); ReleaseCapture; ReleaseDC(HWindow, DragDC); end; W i n d o w s provides seven stock brushes and three stock pens, which y o u c a n u s e effectively t o c r e a t e filled figures. T a b l e 10.4 s h o w s t h e s t o c k d r a w i n g tools you can use with the G e t S t o c k O b j e c t function. Table
10.4.
Windows
stock
drawing
Constant
Brush/Pen
Type
BlackBrush
Black brush
DkGrayBrush
D a r k gray b r u s h
GrayBrush
Gray brush
HollowBrush
Hollow brush
LtGrayBrush
Light gray b r u s h
tools.
10—Display Contexts and Drawing Tools
Constant
Brush/Pen
NullBrush
Null brush
WhiteBrush
White
BlackPen
Black p e n
NullPen
Null pen
White
White
Pen
Type
brush
pen
T h e f o l l o w i n g r e s p o n s e m e t h o d s h o w s h o w t o c r e a t e a n d select a h a t c h e d b r u s h , w h i c h is t h e n u s e d t o fill a r e c t a n g l e . N o t i c e that t h e b r u s h n e e d s t o b e d e l e t e d w h e n y o u are d o n e w i t h it:
procedure FigsWindow.CMHatchedRectangle(var Msg: TMessage); begin SetCapture(HWindow); DragDC := GetDC(HWindow); TheBrush := CreateHatchBrush(hs_Vertical, RGB(0,255,0)); SelectObject(DragDC,TheBrush); Rectangle(DragDC,20,20,200,200); DeleteObject(TheBrush); ReleaseCapture; ReleaseDC(HWindow, DragDC); end;
Listing
103-
A figure-drawing
and
-filling
program.
program Figs; uses Strings, WinTypes, WinProcs, WObjects, WIF5, { Basic Interface } StdDlgs;
{$R FIGS.RES }
const cm_Rectangle cm_Ellipse
= 401; = 402; continues
323
324
Part I I — A d v a n c e d T o p i c s
Listing
10.3-
continued
cm_GrayFilledRectangle cmJHatchedRectangle
= 403; = 404;
type FigsApplication = object(BasicApplication) procedure InitMainWindow; virtual; end; PFigsWindow = "FigsWindow; FigsWindow = object(MainWindow) DragDC: HDC; TheBrush: HBrush; ThePen: HPen; PenSize: Integer; PenStyle: Integer; constructor Init(AParent: PWindowsObject; ATitle: PChar); destructor Done; virtual; procedure CMRectangle(var Msg: TMessage); virtual cm_First + cm_Rectangle; procedure CMGrayFilledRectangle(var Msg: TMessage); virtual cm_First + cm_GrayFilledRectangle; procedure CMHatchedRectangle(var Msg: TMessage); virtual cm_First + cm_HatchedRectangle; procedure CMEllipse(var Msg: TMessage); virtual cm_First + cm_Ellipse; end; { { FigsWindow s method implementations:
} }
{
}
1
constructor FigsWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin TWindow.Init(AParent, ATitle); Attr.Menu := LoadMenu(HInstance, PChar(109)); PenSize := 1; PenStyle := ps_DashDot; ThePen := CreatePen(PenStyle, PenSize, 0); end; destructor FigsWindow.Done; begin DeleteObject(ThePen);
10—Display Contexts and Drawing Tools
325
TWindow.Done; end; procedure FigsWindow.CMRectangle(var Msg: TMessage); begin SetCapture(HWindow); DragDC := GetDC(HWindow); SelectObject(DragDC, ThePen); Rectangle(DragDC,20,20,200,200); ReleaseCapture; ReleaseDC(HWindow, DragDC); end; procedure FigsWindow.CMGrayFilledRectangle(var Msg: TMessage); begin SetCapture(HWindow); DragDC := GetDC(HWindow); SelectObj ect(DragDC, GetStockObj ect(GRAY_BRUSH)); Rectangle(DragDC,20,20,200,200); ReleaseCapture; ReleaseDC(HWindow, DragDC); end; procedure FigsWindow.CMHatchedRectangle(var Msg: TMessage); begin SetCapture(HWindow); DragDC := GetDC(HWindow); TheBrush := CreateHatchBrush(hs_Vertical, RGB(0,255,0)); SelectObject(DragDC,TheBrush); Rectangle(DragDC,20,20,200,200); DeleteObject(TheBrush); ReleaseCapture; ReleaseDC(HWindow, DragDC); end; procedure FigsWindow.CMEllipse(var Msg: TMessage); begin SetCapture(HWindow); DragDC := GetDC(HWindow); SelectObject(DragDC, ThePen); Ellipse(DragDC,20,20,200,200); ReleaseCapture; ReleaseDC(HWindow, DragDC); end; continues
326
Part I I — A d v a n c e d T o p i c s
Listing
10.3-
continued
{
}
{ FigsApplication s 1
method implementations:
}
{
}
procedure FigsApplication.InitMainWindow; begin MainWindow := New(PFigsWindow, Init(nil, end;
'Drawing
Window'));
{ { Main program:
} }
{
}
var App
: FigsApplication;
begin App.Init('FigsProgram'); App.Run; App.Done; end. Figure 10.8, 10.9 a n d 10.10 s h o w several o f t h e s h a p e s created b y t h e display: a gray-filled rectangle, a gray-filled rectangle w i t h a n e l l i p s e inside it, a n d a hatched rectangle.
Figure
10.8. A gray-filled
rectangle.
10—Display Contexts and Drawing Tools
A Stranger Graphics Function Demo T o illustrate h o w s o m e o f t h e s e f u n c t i o n s w o r k , u s e a m e n u t o s e l e c t v a r i o u s drawing functions (MoveToLineTo, S p l o t c h , S t r a n g e A r c s , S t r a n g e P i e s , a n d R o u n d R e c t ) that u t i l i z e m a n y o f t h e W i n d o w s p r i m i t i v e g r a p h i c s f u n c t i o n s for drawing lines, arcs, pies, a n d so o n .
Figure
10.9. A gray-filled
Figure
10.10. A hatched
rectangle with an
rectangle.
ellipse.
327
328
Part I I — A d v a n c e d T o p i c s
E a c h d r a w i n g f u n c t i o n d i s p l a y s i n its o w n w i n d o w . B y u s i n g o n e w i n d o w per function, y o u can maintain many drawings simultaneously, switching b e t w e e n t h e m . E a c h w i n d o w c o n s t r u c t s itself, m a i n t a i n s d a t a fields s p e c i f i c t o it, a n d h a s its o w n Paint p r o c e d u r e f o r u p d a t i n g its d i s p l a y . T h e splotch w i n d o w l o o k s like this:
type PSplotchWindow = "SplotchWindow; SplotchWindow = object(TWindow) Points: array[0..MaxPoints] of APoint; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; end; A r o u n d r e c t a n g l e w i n d o w l o o k s similar:
type PRRectangleWindow = "RRectangleWindow; RRectangleWindow = object(TWindow) Points: array[0..MaxPoints] of APoint; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; end; N o t i c e that n o n e o f t h e w i n d o w s that m a i n t a i n d r a w i n g s is t h e a p p l i c a t i o n ' s MainWindow. T h e a p p l i c a t i o n ' s MainWindow, as u s u a l , is c o n s t r u c t e d at start-up b y t h e Application ( o b j e c t ) :
type GDIExApp = object(TApplication) procedure InitMainWindow; virtual; end;
procedure GDIExApp.InitMainWindow; begin { Create a main window of type TGDIWindow. } MainWindow := New(PGDIExWindow, Init('GDI Example', LoadMenu(HInstance,MakeIntResource(MenuID)))); end; T h e GDIExApp's MainWindow, i n t u r n , m a i n t a i n s e a c h o f t h e d r a w i n g w i n d o w s as a c h i l d w i n d o w . B e c a u s e t h e MainWindow (GDIExWindow) m a i n tains a g r o u p o f c h i l d w i n d o w s , y o u c a n m a k e it e a s y t o m a i n t a i n t h e c h i l d r e n
by derivingGDIExWindowfrom TMDIWindow, t h e b a s e MDI W i n d o w (TMDIWindow),
10—Display Contexts and Drawing Tools
in O b j e c t W i n d o w s . R e c a l l f r o m C h a p t e r 7, " M a n y Windows: A M u l t i - D o c u m e n t I n t e r f a c e , " that a TMDIWindow a l r e a d y k n o w s how t o m a i n t a i n c h i l d w i n d o w s , w h i c h saves y o u t o n s o f w o r k . GDIExWindow l o o k s like this:
type PGDIExWindow = "GDIExWindow; GDIExWindow = object(TMDIWindow) procedure CMStrangeArcs(var Msg: TMessage); virtual cm_First + cm_StrangeArcs; procedure CMStrangePies(var Msg: TMessage); virtual cm_First + cm_StrangePies; procedure CMRoundRect(var Msg: TMessage); virtual cm_First + cm_RoundRect; procedure CMMoveToLineTo(var Msg: TMessage); virtual cm_First + cm_MoveToLineTo; procedure CMSplotch(var Msg: TMessage); virtual cm_First + cm_Splotch; procedure CMQuit(var Msg: TMessage); virtual cm_First + cm_Quit; procedure WMDestroy(var Msg: TMessage); virtual wm_First + wm_Destroy; end; It c o n s i s t s m o s t l y o f m e s s a g e - r e s p o n s e m e t h o d s f o r handling Windows m e s s a g e s a n d m e n u - c o m m a n d m e s s a g e s , w h i c h indicate that t h e u s e r has s e l e c t e d a d r a w i n g w i n d o w f o r display. H e r e are t h e c o r r e s p o n d i n g m e n u - c o m m a n d m e s s a g e c o n s t a n t s f o r
GDIExWindow: const MenuID cm_Quit cm_MoveToLineTo cm_Splotch cm_StrangeArcs cm_StrangePies cm_Roundrect
= = = = = = =
100; { Resource ID of the menu } 100; { File->Quit ID } 201; { Shapes } 202; 203; 204; 205;
T h e s e c o n s t a n t s c o r r e s p o n d t o t h e m e n u items in t h e resource file, G D I _ E X . R E S . Figure 10.11 shows a n aspect o f t h e creation a n d testing o f GDIJEX.RES. Notice the matching constants. I n response t o e a c h m e n u item s e l e c t i o n , t h e GDIExWindow m e n u response m e t h o d c o n s t r u c t s t h e c o r r e s p o n d i n g w i n d o w .
329
330
Part I I — A d v a n c e d T o p i c s
Figure
10.11.
An aspect of the creation and testing
ofGDI_EX.RES.
For example, a SplotchWindow: p r o c e d u r e G D I E x W i n d o w . C M S p l o t c h ( v a r Msg: T M e s s a g e ) ; begin Application".MakeWindow(New(PSplotchWindow, Init(@Self, 'Splotch Window'))); end; or a RoundRectWindow: procedure GDIExWindow.CMRoundRect(var begin
Msg:
TMessage);
Application".MakeWindow(New(PRRectangleWindow, 'Round R e c t a n g l e W i n d o w ' ) ) ) ; end;
Init(@Self,
T h e same applies for the other drawing w i n d o w s . Listing 10.4 c o n t a i n s t h e c o m p l e t e c o d e f o r t h e G D I e x a m p l e , a n d f i g u r e s 1 0 . 1 2 a n d 1 0 . 1 3 s h o w this MDI a p p l i c a t i o n r u n n i n g i n different s t a g e s .
N o t e : O n e particularly interesting a n d useful aspect o f the M D I o b j e c t s that c o m p o s e t h e M D I i n t e r f a c e is that M D I w i n d o w s are r e p a i n t e d a u t o m a t i c a l l y w h e n t h e y are u n c o v e r e d after b e i n g c o v e r e d , u n l i k e n o n - M D I w i n d o w s ( u n t i l y o u w r i t e Paint m e t h o d s for redisplay).
10—Display Contexts and Drawing Tools
Figure
10.12.
One stage of running the MDI application of listing 10.4.
Figure
10.13- Another stage during the MDI application
execution.
331
332
Part II—Advanced Topics
Listing
10.4.
A GDI
example.
program GDI_EX; uses WinProcs, WinTypes, WObjects, Strings; {$R GDI_EX.RES} { Menu bar constants } const MenuID = 100; { Resource ID of the menu } cm_Quit = 1 0 0 ; { File->Quit ID } cm_MoveToLineTo = 201; { Shapes } cm_Splotch = 202; cm_StrangeArcs = 203; cm_StrangePies = 204; cm_Roundrect = 205;
{ Shape constant } const MaxPoints
=
15; { Number of points to be drawn in MoveToLineToDemo }
{ Global function } function Min(X, Y: Integer): Integer; begin if X > Y then Min := Y else Min := X; end;
type APoint = record X, Y : Real; end; { NoIconWindow } type PNoIconWindow = "NoIconWindow;
10—Display Contexts and Drawing Tools
333
NoIconWindow = object(TWindow) procedure GetWindowClass(var AWndClass: TWndClass); virtual; function GetClassName: PChar; virtual; end; procedure NoIconWindow.GetWindowClass(var AWndClass: TWndClass); begin TWindow.GetWindowClass(AWndClass); AWndClass.hbrBackground := GetStockObject(Black_Brush); AWndClass.hlcon := 0; end; { No need to call the ancestor's method here, because you want to provide an entirely new window class name. } function NoIconWindow.GetClassName: PChar; begin GetClassName := 'NoIconWindow'; end; { Splotch window } type PSplotchWindow = "SplotchWindow; SplotchWindow = object(TWindow) Points: array[0..MaxPoints] of APoint; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; end; constructor SplotchWindow.Init(AParent: PWindowsObject; ATitle: PChar); var I: Integer; StepAngle: Integer; Radians: Real; begin TWindow.Init(AParent, ATitle); StepAngle := 360 div MaxPoints; for I := 0 to MaxPoints - 1 do begin Radians := (StepAngle * I) * PI / 180; Points[I].x := Cos(Radians); continues
334
Part I I — A d v a n c e d T o p i c s
Listing
10.4.
continued
Points[I].y := Sin(Radians); end; end; procedure SplotchWindow.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var TheRect: TRect; I, J: Integer; CenterX, CenterY: Integer; Radius, StepAngle: Word; Radians: real; begin GetClientRect(HWindow,TheRect); { Get the client window's coordinates } CenterX := TheRect.Right div 2; CenterY := TheRect.Bottom div 2; Radius := Min(CenterY, CenterX); Rectangle(PaintDC,CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius); for I := 0 to MaxPoints - 1 do begin for J := I + 1 to MaxPoints - 1 do begin MoveTo(PaintDC, CenterX + Round(Points[I].X / Radius * Radius), CenterY + Round(Points[I].Y / Radius *Radius)); LineTo(PaintDC, CenterX + Round(Points[J].X * Radius), CenterY + Round(Points[J].Y * Radius)); end; end; end; { End splotch window }
{ Round rectangle window } type PRRectangleWindow = "RRectangleWindow; RRectangleWindow = object(TWindow) Points: array[0..MaxPoints] of APoint;
10—Display Contexts and Drawing Tools
335
constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; end; constructor RRectangleWindow.Init(AParent: PWindowsObject; ATitle: PChar); var I: Integer; StepAngle: Integer; Radians: Real; begin TWindow.Init(AParent, ATitle); StepAngle := 360 div MaxPoints; for I := 0 to MaxPoints - 1 do begin Radians := (StepAngle * I) * PI / 180; Points[I].x := Cos(Radians); Points[I].y := Sin(Radians); end; end; procedure RRectangleWindow.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var TheRect: TRect; I, J: Integer; CenterX, CenterY: Integer; Radius, StepAngle: Word; Radians: real; begin GetClientRect(HWindow,TheRect); { Get the client window's coordinates } CenterX := TheRect.Right div 2; CenterY := TheRect.Bottom div 2; Radius := Min(CenterY, CenterX); RoundRect(PaintDC,CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius,9,11); for I := 0 to MaxPoints - 1 do begin for J := I + 1 to MaxPoints - 1 do continues
336
Part I I — A d v a n c e d T o p i c s
Listing
10A.
continued
begin MoveTo(PaintDC, CenterX + Round(Points[I].X / Radius * Radius), CenterY + Round(Points[I].Y / Radius * Radius)); RoundRect(PaintDC, CenterX + Round(Points[J].X * Radius), CenterY + Round(Points[J].Y * Radius),9,11,9,11); end; end; end; { End round rectangle } { Strange arcs window } type PStrangeArcsWindow = "StrangeArcsWindow; StrangeArcsWindow = object(TWindow) procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; end; procedure StrangeArcsWindow.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var X, EndX : integer; begin For X := 1 to 400 do begin EndX := X + 50; Arc(PaintDC, X,15,EndX,250,50,0,0,0); end; end; { End strange arcs } { Strange pie window } type PStrangePiesWindow = "StrangePiesWindow; StrangePiesWindow = object(TWindow) procedure Paint(PaintDC: HDC; var Paintlnfo: end; TPaintStruct); virtual;
10—Display Contexts and Drawing Tools
procedure StrangePiesWindow.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var X, EndX : integer; begin For X := 1 to 400 do begin EndX := X + 50; Pie(PaintDC, X,15,EndX,250,50,0,0,0); end; end; { End strange pies }
{ MoveToLineToWindow
}
type PMoveToLineToWindow = "MoveToLineToWindow; MoveToLineToWindow = object(TWindow) Points: array[0..MaxPoints] of APoint; constructor Init(AParent: PWindowsObject; ATitle: PChar); procedure Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; end; constructor MoveToLineToWindow.Init(AParent: PWindowsObject; ATitle: PChar); var I: Integer; StepAngle: Integer; Radians: Real; begin TWindow.Init(AParent, ATitle); StepAngle := 360 div MaxPoints; for I := 0 to MaxPoints - 1 do begin Radians := (StepAngle * I) * PI / 180; Points[I].x := Cos(Radians); Points[I].y := Sin(Radians); end; end; continues
337
338
Part I I — A d v a n c e d T o p i c s
Listing
10.4.
continued
procedure MoveToLinetoWindow.Paint(PaintDC: HDC; var Paintlnfo: TPaintStruct); var TheRect: TRect; I, J: Integer; CenterX, CenterY: Integer; Radius, StepAngle: Word; Radians: real; begin GetClientRect(HWindow,TheRect); CenterX := TheRect.Right div 2; CenterY := TheRect.Bottom div 2; Radius := Min(CenterY, CenterX); Ellipse(PaintDC,CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius); for I := 0 to MaxPoints - 1 do begin for J := I + 1 to MaxPoints - 1 do begin MoveTo(PaintDC, CenterX + Round(Points[I].X * Radius), CenterY + Round(Points[I].Y * Radius)); LineTo(PaintDC, CenterX + Round(Points[J].X * Radius), CenterY + Round(Points[J],Y * Radius)); end; end; end; { GDIExWindow type PGDIExWindow = "GDIExWindow; GDIExWindow = object(TMDIWindow) procedure CMStrangeArcs(var Msg: TMessage); virtual cm_First + cm_StrangeArcs; procedure CMStrangePies(var Msg: TMessage); virtual cm_First + cm_StrangePies; procedure CMRoundRect(var Msg: TMessage); virtual cm_First + cm_RoundRect; procedure CMMoveToLineTo(var Msg: TMessage); virtual cm_First + cm_MoveToLineTo;
}
10—Display Contexts and Drawing Tools
procedure CMSplotch(var Msg: TMessage); virtual cm_First + cm_Splotch; procedure CMQuit(var Msg: TMessage); virtual cm_First + cm_Quit; procedure WMDestroy(var Msg: TMessage); virtual wm_First + wm_Destroy; end; procedure GDIExWindow.CMMoveToLineTo(var Msg: TMessage); begin Application".MakeWindow(New(PMoveToLineToWindow, Init(@Self, 'MoveTo/LineTo Window'))); end; procedure GDIExWindow.CMSplotch(var Msg: TMessage); begin Application".MakeWindow(New(PSplotchWindow, Init(@Self, 'Splotch Window'))); end; procedure GDIExWindow.CMRoundRect(var Msg: TMessage); begin Application".MakeWindow(New(PRRectangleWindow, Init(@Self, 'Round Rectangle Window ))); end; 1
procedure GDIExWindow.CMStrangeArcs(var Msg: TMessage); begin Application".MakeWindow(New(PStrangeArcsWindow, Init(@Self, 'Strange Arcs Window'))); end; procedure GDIExWindow.CMStrangePies(var Msg: TMessage); begin Application".MakeWindow(New(PStrangePiesWindow, Init(@Self, 'Strange Pie Window'))); end;
procedure GDIExWindow.CMQuit(var Msg: TMessage); begin CloseWindow; end; continues
339
340
Part I I — A d v a n c e d T o p i c s
Listing
10.4.
continued
procedure GDIExWindow.WMDestroy(var begin TMDIWindow.WMDestroy(Msg); end;
Msg: TMessage);
{ GDIExApp
}
type GDIExApp = object(TApplication) procedure InitMainWindow; end;
virtual;
procedure GDIExApp.InitMainWindow; begin { Create a main window of type GDIExWindow. } MainWindow := New(PGDIExWindow, Init('GDI Example , LoadMenu(HInstance,MakeIntResource(MenuID)))); end; 1
var ExApp: GDIExApp; begin ExApp.Init('GDIExample ) ; ExApp.Run; ExApp.Done; end. 1
Wrap-up T h e g r a p h i c s p o s s i b i l i t i e s w i t h t h e W i n d o w s G D I a r e virtually e n d l e s s ( p l e a s e e x c u s e t h e p u n ) . Y o u c a n c r e a t e d r a w i n g s a n d s h a p e s o f a l m o s t every k i n d , a n d , w i t h a bit o f effort, c r e a t e s o p h i s t i c a t e d g r a p h i c s a p p l i c a t i o n s that u t i l i z e v a r i o u s f o n t s , i c o n s , c u r s o r s , bit m a p s , a n d t h e l i k e . Y o u c a n c r e a t e this m y r i a d o f s h a p e s o n a n y d e v i c e s u p p o r t e d b y W i n d o w s without writing c o d e for a specific device. A l t h o u g h y o u might s p e n d s o m e time learning the ins a n d outs o f W i n d o w s functions, y o u are m o r e than c o m p e n s a t e d w h e n y o u d o n o t h a v e t o w r i t e d e v i c e drivers o r d e v i c e - s p e c i f i c c o d e . W i n d o w s is i n d e e d t h e m o s t u n i v e r s a l i n t e r f a c e t o c o m e d o w n t h e D O S p i k e , a n d it b e c o m e s m o r e u s e f u l a n d m o r e p o w e r f u l as y o u l e a r n m o r e a b o u t it.
10—Display Contexts and Drawing Tools
For additional information about G D I definitions, functions, and the ObjectGraphics T o o l b o x (from the Whitewater G r o u p ) , check the reference s e c t i o n i n t h e s e c o n d h a l f o f this b o o k .
341
11 CHAPTER
FROM PROGRAM TO PROGRAM USING DDE (DYNAMIC DATA EXCHANGE) As I look across my desk to the "computer museum" in the corner of my office, I can see the progress hardware has made in the past decade. We 've gone from 64KZ80 CP/M machines like the Osborne I that ran Ron Cain's Small-C and Turbo Pascal 1.0 (and had room to spare!), to my new four-megabyte 386SX that runs Turbo C+ + and Turbo Pascal 6.0. And I'm not at all surprised by the fact that the Osborne cost more than the 386. Zack Urlocker
O n e o f t h e m o s t a m a z i n g a n d u s e f u l f e a t u r e s o f M i c r o s o f t W i n d o w s is its facility f o r l e t t i n g a p p l i c a t i o n s s h a r e d a t a . W i n d o w s a c c o m p l i s h e s this d a t a - s h a r i n g t h r o u g h a p r o t o c o l c a l l e d D D E ( d y n a m i c d a t a e x c h a n g e ) . T u r b o Pascal f o r W i n d o w s compiles D D E b e t w e e n applications—those y o u write a n d even t h o s e y o u d o n ' t w r i t e y o u r s e l f — r e a d i l y a c c e s s i b l e at a h i g h l e v e l . In general, to e x c h a n g e data with other applications a n d programs through D D E , y o u have to learn: • T h e W i n d o w s m e s s a g e s (wm_pref ixed) that u s e D D E • H o w to use global m e m o r y to buffer the data e x c h a n g e
344
Part I I — A d v a n c e d T o p i c s
This chapter explains h o w D D E works with examples, including exchanges with the Clipboard and the Windows Program Manager. Although e x c h a n g e s w i t h t h e c l i p b o a r d a r e n o t " t e c h n i c a l l y " part o f D D E b e c a u s e y o u d o not send D D E messages to access the clipboard, the chapter l u m p s together the e x c h a n g e o f c l i p b o a r d a n d D D E d a t a . C a l l t h e l u m p s o m e t h i n g like " W i n d o w s global data e x c h a n g e " because both the clipboard a n d D D E require the u s e o f global m e m o r y buffers. Y o u a l s o c a n " l u m p " D D E a n d D L L b e c a u s e t h e y are c o n c e p t u a l l y similar. T h e y differ significantly, h o w e v e r , i n that D D E is t h e s h a r i n g o f d a t a b e t w e e n a p p l i c a t i o n s , a n d D L L is t h e s h a r i n g o f c o d e . Y o u r a p p l i c a t i o n s s h a r e c o d e b y s t o r i n g it i n d y n a m i c l i n k a b l e libraries. T h e capability t o share data a n d c o d e has m a n y advantages a n d possibilities. S h a r i n g r e d u c e s m e m o r y u s e ( b e c a u s e a s i n g l e c o p y , r a t h e r t h a n t w o o r m o r e c o p i e s , o f a s e g m e n t o f c o d e o r d a t a saves s p a c e ) . A l s o , b y s h a r i n g d a t a i n real t i m e , y o u r a p p l i c a t i o n s c a n save t i m e a n d interact s e n s i b l y w i t h e a c h o t h e r . Applications using either the clipboard o r D D E c a n r e s p o n d to each other immediately, thus leading to a future o f independently developed programs that d e p e n d o n t h e o u t p u t f r o m e a c h o t h e r . This chapter focuses o n data e x c h a n g e s b e t w e e n T u r b o Pascal for W i n d o w s applications a n d the clipboard a n d between applications using D D E . C h a p t e r 12 c o v e r s D L L .
The Clipboard T h e s i m p l e s t w a y f o r y o u r a p p l i c a t i o n s t o e x c h a n g e d a t a is w i t h t h e c l i p b o a r d . A l t h o u g h y o u m i g h t t h i n k o f t h e c l i p b o a r d as t h e C l i p b o a r d p r o g r a m p a c k a g e d w i t h W i n d o w s , it isn't. T h e C l i p b o a r d is a c l i p b o a r d v i e w e r y o u u s e t o d i s p l a y a n d m a n i p u l a t e t h e c u r r e n t c o n t e n t s o f t h e c l i p b o a r d . T h e c l i p b o a r d , p e r s e , is a f u n c t i o n a l W i n d o w s u n i t y o u u s e t o e x c h a n g e d a t a b e t w e e n p r o g r a m s . It i s , i n fact, invisible u n l e s s y o u c h o o s e t o " v i e w " it. W h e n y o u r applications are using the O p e n , C l o s e , Write t o , a n d Read c o m m a n d s f r o m t h e c l i p b o a r d , t h e y are " c o n v e r s i n g " w i t h t h e c l i p b o a r d u n i t — not t h e C l i p b o a r d p r o g r a m . If y o u w a n t t o see t h e actual e x c h a n g e o f data b e t w e e n y o u r a p p l i c a t i o n s that u s e t h e c l i p b o a r d , o p e n t h e C l i p b o a r d p r o g r a m . Figure 11.1 shows a C l i p b o a r d p r o g r a m "view" o f a data e x c h a n g e b e t w e e n a T u r b o P a s c a l f o r W i n d o w s a p p l i c a t i o n (details a n d c o d e a r e d e s c r i b e d later i n this s e c t i o n ) . M a n y o f the W i n d o w s applications are u s e d t o cut, copy, a n d paste data t o a n d f r o m t h e c l i p b o a r d . T h e O b j e c t W i n d o w s ' E d i t c o n t r o l , EditWindow, a n d FileWindow o b j e c t s , w h i c h y o u h a v e a l r e a d y u s e d , a c c e s s t h e c l i p b o a r d through these m e n u c o m m a n d s .
1 1 — F r o m Program to Program Using D D E
Figure
11.1. "View" of a data exchange.
"Hello" is pasted at various mouse
locations.
T h e C l i p b o a r d c a n a c c e p t a variety o f d a t a f o r m a t s : text, bit m a p s , s y m b o l i c l i n k f o r m a t t e d d a t a , tiff f o r m a t , a n d m e t a f i l e p i c t u r e f o r m a t . T a b l e 11.1 s h o w s the clipboard format a n d the associated data. Table
11.1.
Clipboard
format
and associated
data.
Format
Format
Explanation
cf_Text
N u l l - t e r m i n a t e d array o f c h a r a c t e r s
cfBitmap
W i n d o w s ' bit m a p f o r m a t
cfSylk
Microsoft symbolic link format
cfTiff
T a g i m a g e file f o r m a t
cfMetafilePict
W i n d o w s metafile picture format
T h e s e c l i p b o a r d f o r m a t s are m o r e o r less i n d u s t r y s t a n d a r d s , w h i c h m a n y applications recognize. T h u s , by using o n e or m o r e of these formats to p u t data i n t h e c l i p b o a r d , y o u c a n s e n d d a t a t o a n y a p p l i c a t i o n that c a n interact w i t h t h e clipboard. T o place data in the Clipboard: 1. O p e n t h e c l i p b o a r d ( u s i n g t h e W i n d o w s f u n c t i o n OpenClipboard). 2. E m p t y t h e c l i p b o a r d ( u s i n g EmptyClipboard).
345
346
Part II-—Advanced T o p i c s
3. S e t a d a t a h a n d l e t o t h e c l i p b o a r d (SetClipboardData). 4. C l o s e t h e c l i p b o a r d (CloseClipboard). T o o p e n the clipboard, use OpenClipboard(HWindow); w h e r e HWindow is a w i n d o w h a n d l e a s s o c i a t e d w i t h t h e w i n d o w that w a n t s contact with the clipboard. EmptyClipboard e m p t i e s t h e c l i p b o a r d a n d frees a n y h a n d l e s t o d a t a i n t h e c l i p b o a r d , a s s i g n i n g o w n e r s h i p t o t h e w i n d o w ( d e s i g n a t e d b y HWindow) that o p e n e d t h e c l i p b o a r d : EmptyClipboard;
N o t e : A l l t h e i n f o r m a t i o n r e s e a r c h e d f o r this b o o k that refers t o t h e c l i p b o a r d d e s i g n a t e s that y o u m u s t u s e EmptyClipboard before y o u copy data to the clipboard. Various experiments s u g g e s t that e m p t y i n g t h e c l i p b o a r d isn't a b s o l u t e l y n e c e s s a r y . F o r e x a m p l e , if y o u o m i t EmptyClipboard f r o m t h e c o d e i n listing 1 1 . 1 , t h e d a t a e x c h a n g e b e t w e e n t h e T u r b o Pascal f o r W i n d o w s a p p l i c a t i o n a n d t h e c l i p b o a r d still w o r k s .
SetClipboardData r e q u i r e s t w o p a r a m e t e r s : a cf _ clipboard c o n s t a n t that s p e c i f i e s t h e f o r m a t of t h e d a t a t o b e c o p i e d t o t h e c l i p b o a r d a n d a h a n d l e t o a g l o b a l m e m o r y b l o c k that c o n t a i n s t h e d a t a t o b e c o p i e d . F o r e x a m p l e : SetClipboardData(cf_Text,AStringGlobalHandle); R e c a l l f r o m C h a p t e r 9 , " M e m o r y M a t t e r s , " that a g l o b a l m e m o r y b l o c k is a special kind o f system-wide m e m o r y shared by W i n d o w s applications. Y o u r application c a n create these global m e m o r y blocks in the W i n d o w s global h e a p , and Windows can manage them. In general, an application does not have to use g l o b a l m e m o r y b l o c k s ; u s u a l l y it's a m a t t e r o f c h o i c e ( s e e C h a p t e r 9 f o r a discussion o f global versus local m e m o r y ) . Applications using the clipboard, however, must use global memory. T o a d d c l i p b o a r d - a c c e s s c a p a b i l i t y t o a w i n d o w , you d e r i v e a n e w w i n d o w ( c a l l e d ClipWindow) f r o m MainWindow a n d a d d a CopyText f e a t u r e . First, d e r i v e a n e w application: ClipApp = object(BasicApplication) BasicApplication }
{ ModelApp=a kind of
procedure InitMainWindow; virtual; { Init a specific MainWindow } end;
1 1 — F r o m Program to Program Using D D E
N e x t , a d d a n e w m a i n w i n d o w that c a n interact w i t h t h e C l i p b o a r d :
PClipWindow = "ClipWindow; ClipWindow = object(MainWindow) constructor Init(AParent : PWindowsObject; ATitle : PChar); procedure CMCopyText(var Msg: TMessage); virtual cm_First + cm_CopyText; function CopyText(Txt: PChar): boolean; end; ClipWindow h a s t w o k e y m e t h o d s : 1. CMCopyText r e s p o n d s t o t h e m e n u - c o m m a n d m e s s a g e (cm_CopyText). 2. CopyText a c t u a l l y h a n d l e s t h e c o p y i n g o f text t o t h e c l i p b o a r d .
cm_CopyText is a c o n s t a n t :
const cm_CopyText = 501; is d e f i n e d i n t h e m e n u r e s o u r c e i n W I F 1 0 6 :
{$R ....} CMCopyText r e s p o n d s t o t h e cm_CopyText m e s s a g e b y c o p y i n g a string ( " H e l l o " ) t o a n u l l - t e r m i n a t e d string (S). Recall that w h e n e v e r y o u p a s s strings t o W i n d o w s f u n c t i o n s t h e y m u s t b e a PCh a r t y p e (a p o i n t e r t o a n u l l - t e r m i n a t e d s t r i n g ) . T h e n t h e string s e n d s a m e s s a g e t o CopyText a n d p a s s e s it t o t h e string to copy to the clipboard:
procedure ClipWindow.CMCopyText(var Msg: TMessage); var Stat : boolean; S : array[0..15] of char; begin StrCopy(S,'Hello'); Stat := CopyText(S); end; CopyText t h e n sets a g l o b a l m e m o r y h a n d l e , c o p i e s t h e s t r i n g t o g l o b a l m e m o r y , o p e n s a n d e m p t i e s t h e c l i p b o a r d , sets t h e c l i p b o a r d d a t a , a n d c l o s e s the clipboard:
function ClipWindow.CopyText(Txt: PChar): boolean; var AStrGlobalHandle: THandle; AStrGlobalPtr: PChar;
347
348
Part I I — A d v a n c e d T o p i c s
begin CopyText := False; AStrGlobalHandle := GlobalAlloc(gmem_Moveable,StrLen(Txt) if AStrGlobalHandle 0 then begin AStrGlobalPtr := GlobalLock(AStrGlobalHandle); if AStrGlobalPtr nil then begin StrCopy(AStrGlobalPtr,Txt); GlobalUnlock(AStrGlobalHandle); OpenClipboard(HWindow); EmptyClipboard; SetClipboardData(cf_Text,AStrGlobalHandle); CloseClipboard; CopyText := True; GlobalFree(AStrGlobalHandle); end; end; end;
Pastingfromthe Clipboard P a s t i n g text f r o m t h e c l i p b o a r d i n t o y o u r a p p l i c a t i o n is o n l y slightly m o r e c o m p l i c a t e d t h a n c o p y i n g text t o t h e c l i p b o a r d . Listing
11.1.
Paste
text.
function ClipWindow.PasteText(TxtString: PChar; TxtSize:Integer): Integer; var AStrGlobalHandle: THandle; AStrGlobalPtr: PChar; AStrGlobalSize : Longint; begin PasteText := -1; OpenClipboard(HWindow); IsClipboardFormatAvailable(cf_Text); AStrGlobalHandle := GetClipboardData(cf_Text); if AStrGlobalHandle 0 then begin
+1);
11—From Program to Program Using D D E
AStrGlobalSize := GlobalSize(AStrGlobalHandle); AStrGlobalPtr := GlobalLock(AStrGlobalHandle); if AStrGlobalPtr nil then begin if TxtSize < AStrGlobalSize then AStrGlobalSize := TxtSize; StrLCopy(TxtString,AStrGlobalPtr,AStrGlobalSize); GlobalUnlock(AStrGlobalHandle); PasteText := StrLen(TxtString); end; end; CloseClipboard; end; T h e e x a m p l e p r o g r a m i n listing 11.2 c o p i e s text t o t h e c l i p b o a r d a n d a l l o w s t h e u s e r t o p a s t e text f r o m t h e c l i p b o a r d t o a s p e c i f i c l o c a t i o n i n t h e w i n d o w . T h e l o c a t i o n is d e t e r m i n e d b y c l i c k i n g t h e m o u s e . Listing
11.2.
Pasting
text from
clipboard
to the
window.
unit ClipWnd; interface uses WObjects, WinTypes, WinProcs, strings, WIF5;
{ Basic Interface }
{$R wif106.res} const cm_CopyText = 501; cm_PasteText = 502; type ClipApp = object(BasicApplication)
{ ModelApp=a kind of BasicApplication } procedure InitMainWindow; virtual; { Init a specific MainWindow } end; continues
349
350
Part I I — A d v a n c e d T o p i c s
Listing
11.2.
continued
PClipWindow = "ClipWindow; ClipWindow = object(MainWindow) Lo, Hi : Word; constructor Init(AParent : PWindowsObject; ATitle : PChar); procedure WMLButtonDown(var Msg: TMessage); virtual wm_First + wm_LButtonDown; procedure WMLButtonUp(var Msg: TMessage); virtual wm_First + wm_LButtonllp; procedure CMCopyText(var Msg: TMessage); virtual cm_First + cm_CopyText; procedure CMPasteText(var Msg: TMessage); virtual cm_First + cm_PasteText; function CopyText(Txt: PChar): boolean; function PasteText(TxtString: PChar; TxtSize: Integer): Integer; end;
implementation
procedure ClipApp.InitMainWindow; { Init a model application window } begin if FirstApplication then MainWindow := New(PClipWindow, Init(nil, 'Model Windows Interface')) else MainWindow := New(PClipWindow, Init(nil,'Additional Instance of MI')); end; constructor ClipWindow.Init(AParent : PWindowsObject; begin TWindow.Init(AParent, ATitle); { Send message to Attr.Menu := LoadMenu(HInstance, PChar(106)); { ButtonDown := False; { Set status flag end;
procedure ClipWindow.WMLButtonDown(var Msg: TMessage); begin if not ButtonDown then begin ButtonDown := True; SetCapture(HWindow);
ATitle: PChar); ancestor's constructor } 99 = menu ID } }
1 1 — F r o m Program to Program Using D D E
351
DC := GetDC(HWindow); end; end; procedure ClipWindow.WMLButtonUp(var Msg: TMessage); begin if ButtonDown then begin ButtonDown := False; { Determine mouse location } Lo := Msg.lParamLo; Hi := Msg.lParamHi; TextOut(DC,Lo,Hi, . ,1); { Put a dot at current mouse location } ReleaseCapture; ReleaseDC(HWindow,DC); end; end; 1
1
procedure ClipWindow.CMCopyText(var Msg: TMessage); var Stat : boolean; S : array[0..15] of char; begin StrCopy(S,'Hello'); Stat := CopyText(S); end;
procedure ClipWindow.CMPasteText(var Msg: TMessage); var Stat : integer; TxtStr: PChar; TxtSize: Integer; S : array[0..256] of Char; begin New(TxtStr); TxtSize := 256; Stat := PasteText(TxtStr, TxtSize); DC := GetDC(HWindow); TextOut(DC,Lo,Hi,TxtStr,Stat); { Paste to mouse location } ReleaseDC(HWindow,DC); end; continues
352
Part I I — A d v a n c e d T o p i c s
Listing
11.2.
continued
function ClipWindow.CopyText(Txt: PChar): boolean; var AStrGlobalHandle: THandle; AStrGlobalPtr: PChar; begin CopyText := False; AStrGlobalHandle := GlobalAlloc(gmem_Moveable, StrLen(Txt) + 1 ) ; if AStrGlobalHandle 0 then begin AStrGlobalPtr := GlobalLock(AStrGlobalHandle); if AStrGlobalPtr nil then begin StrCopy(AStrGlobalPtr,Txt); GlobalUnlock(AStrGlobalHandle); OpenClipboard(HWindow); EmptyClipboard; SetClipboardData(cf_Text,AStrGlobalHandle); CloseClipboard; CopyText := True; end; end;
function ClipWindow.PasteText(TxtString: Integer): Integer; var AStrGlobalHandle: THandle; AStrGlobalPtr: PChar; AStrGlobalSize : Longlnt;
PChar; TxtSize:
begin PasteText := -1; OpenClipboard(HWindow); IsClipboardFormatAvailable(cf_Text); AStrGlobalHandle := GetClipboardData(cf_Text); if AStrGlobalHandle 0 then begin AStrGlobalSize := GlobalSize(AStrGlobalHandle);
1 1 — F r o m Program to Program Using D D E
AStrGlobalPtr := GlobalLock(AStrGlobalHandle); if AStrGlobalPtr nil then begin if TxtSize < AStrGlobalSize then AStrGlobalSize := TxtSize; StrLCopy(TxtString,AStrGlobalPtr,AStrGlobalSize); GlobalUnlock(AStrGlobalHandle); PasteText := StrLen(TxtString); end; end; CloseClipboard; end;
end.
{ Unit clipwnd }
program Test_Clip;
{ A generic way to test each phase of interface development }
uses WIF5, clipwnd;
{ Basic Interface unit } { Contains ClipApp }
type App = object(ClipApp) end; var Application: App;
{ An instance of BasicApplication } { Run Applicationl }
begin Application.Init('Cliplnterface'); { Init application instance } Application.Run; { Message loop } Application.Done; { Destroy application instance } end.
Sharing Data Between Applications D y n a m i c d a t a e x c h a n g e ( D D E ) is a p r o t o c o l that e n a b l e s a p p l i c a t i o n s t o s h a r e data. Applications share data by way of a "conversation" in w h i c h they "post" m e s s a g e s t o e a c h o t h e r . T h e t w o a p p l i c a t i o n s s h a r i n g d a t a are c a l l e d t h e client
353
354
Part I I — A d v a n c e d T o p i c s
( w h o initiates t h e c o n v e r s a t i o n b y b r o a d c a s t i n g a D D E m e s s a g e ) a n d t h e server (who responds to the message). D D E l i n k s b e t w e e n a p p l i c a t i o n s a r e e i t h e r very c o l d , c o l d , h o t , o r w a r m , d e p e n d i n g o n t h e c o m p l e x i t y o f t h e link. A very cold l i n k is s i m p l e s t ; a c l i e n t b r o a d c a s t s a WM_DDE_INITIATE m e s s a g e i d e n t i f y i n g t h e a p p l i c a t i o n a n d t o p i c o f interest. A n y a p p l i c a t i o n ( p o t e n t i a l server) c a n r e s p o n d t o this m e s s a g e , a n d it is u p t o t h e c l i e n t w i n d o w t o t e r m i n a t e all servers e x c e p t t h e o n e it w a n t s . {Remember: use one window for each DDE link!) After t h e u n w a n t e d servers are t e r m i n a t e d , t h e c l i e n t s e n d s t h e d a t a t o t h e server. A cold l i n k is n e x t s i m p l e s t : a c l i e n t b r o a d c a s t s a WM_DDE_INITIATE m e s s a g e that i d e n t i f i e s t h e a p p l i c a t i o n a n d t h e a p p l i c a t i o n t o p i c it w a n t s . A n y p o t e n t i a l server w h o c a n r e s p o n d t o this a p p l i c a t i o n t o p i c r e s p o n d s t o t h e c l i e n t b y s e n d i n g a WM_DDE_ACK m e s s a g e . W h e n t h e c l i e n t d e t e r m i n e s a l i n k , it t e r m i n a t e s a n y o t h e r a c k n o w l e d g m e n t s o f its b r o a d c a s t m e s s a g e . It t h e n r e q u e s t s t h e a p p l i c a t i o n w i t h a WM_DDE_REQUEST m e s s a g e (if it w a n t s d a t a ) o r s e n d s d a t a t o t h e server (if it wants to send data). T h e c l i e n t a n d t h e server c a n c o n t i n u e t o " t a l k , " e i t h e r a c k n o w l e d g i n g the other's requests o r not, until o n e o f the linked applications posts a WM_DDE_TERMINATE m e s s a g e . E i t h e r t h e c l i e n t o r t h e server c a n p o s t t h e terminate message. A hot l i n k is m o r e s o p h i s t i c a t e d . After t h e a p p l i c a t i o n s h a v e l i n k e d , a c l i e n t p o s t s a c o n d i t i o n a l m e s s a g e (WM_DDE_ADVISE), a s k i n g t h e server t o i n f o r m t h e c l i e n t w h e n t h e v a l u e o f a d a t a field c h a n g e s . T h a t is w h e n t h e c l i e n t wants the data. This scenario allows the client to b e u p d a t e d regarding the status o f a d a t a f i e l d , a h a n d y s i t u a t i o n i n p a r t i c u l a r if t h e a p p l i c a t i o n is p r o c e s s i n g i n real t i m e . F o r e x a m p l e , y o u r a p p l i c a t i o n m i g h t w a n t t o r e c a l c u l a t e a s p r e a d s h e e t o r d a t a b a s e c o l u m n e a c h t i m e a v a l u e c h a n g e s a n d , i n t u r n , act if t h e n e w c a l c u l a t e d v a l u e e x c e e d s a t h r e s h o l d . D u r i n g a h o t l i n k , a c l i e n t c a n d e c i d e that it n o l o n g e r w a n t s d a t a u p d a t e s a n d " u n a d v i s e " t h e server b y s e n d i n g a n " UNADVISE" m e s s a g e . A n a p p l i c a t i o n also c a n maintain a hot a n d cold link simultaneously by requesting the data f r o m s o m e fields u n c o n d i t i o n a l l y a n d f r o m o t h e r s c o n d i t i o n a l l y . A warm l i n k is a partly h o t , partly c o l d l i n k . I n this s c e n a r i o , t h e c l i e n t m a k e s its c o n n e c t i o n t o a server, s e n d s a WM_DDE_ADVISE m e s s a g e , b u t i n d i c a t e s w i t h a flag c o n t a i n i n g t h e WM_DDE_ADVISE m e s s a g e that it w a n t s t o b e i n f o r m e d o n l y o f c h a n g e s i n a d a t a f i e l d ; it d o e s n ' t w a n t t h e d a t a s e n t . I f t h e c l i e n t d o e s d e c i d e that it w a n t s t h e d a t a , it r e q u e s t s it (WM_DDE_R EQUEST). T h e c l i e n t a l s o c a n c h a n g e this a d v i s e status b y s e n d i n g a n "UNADVISE" m e s s a g e .
Atoms, and So On C l i e n t a n d server a p p l i c a t i o n s identify d a t a w i t h c h a r a c t e r strings r e p r e s e n t i n g the application, topic in the application, a n d data in the application. These
1 1 — F r o m Program to Program Using D D E
c h a r a c t e r strings a r e r e p r e s e n t e d b y " a t o m s , " c a s e - i n s e n s i t i v e w o r d v a l u e s that refer t o t h e character strings. T h e a t o m c h a r a c t e r string is r e c o r d e d i n a n a t o m t a b l e , w h i c h is s t o r e d i n a s h a r e d d a t a s e g m e n t i n a d y n a m i c l i n k library i n W i n d o w s . Y o u d o n ' t h a v e t o k n o w t h e d e t a i l s o f h o w this s h a r e d a t o m t a b l e w o r k s , b u t y o u d o h a v e t o u s e it t o e s t a b l i s h a D D E l i n k . Specifically, w h e n t h e c l i e n t a p p l i c a t i o n w a n t s t o initiate a D D E c o n v e r s a t i o n , it a d d s t h e a p p l i c a t i o n , t o p i c , a n d i t e m n a m e s (if necessary) to the a t o m table: ApplicationAtom TopicAtom
:= GlobalAddAtom('Application
Name');
:= GlobalAddAtom( Topic Name'); 1
T h e D D E applications e n g a g e d in the conversation u s e the a t o m table t o establish their link. W h e n y o u r a p p l i c a t i o n h a s e s t a b l i s h e d t h e l i n k , it d e l e t e s t h e n a m e s f r o m the table: GlobalDeleteAtom(ApplicationAtom); GlobalDeleteAtom(TopicAtom); T h e wm_DDE_Initiate m e s s a g e , which y o u r a p p l i c a t i o n u s e s t o e s t a b l i s h a D D E c o n v e r s a t i o n , is a c t u a l l y b r o a d c a s t ( o r s e n t ) t o all t o p - l e v e l ( o r p a r e n t ) w i n d o w s . A n y a p p l i c a t i o n c a n r e s p o n d t o this DDE_Initiate m e s s a g e , s o it is u p t o t h e c l i e n t a p p l i c a t i o n t o t e r m i n a t e all t h e s e u n w a n t e d l i n k s . Y o u r a p p l i c a t i o n h a n d l e s this d u t y with a WMDDE m e s s a g e - r e s p o n s e m e t h o d , which p o s t s a m e s s a g e t o all u n w a n t e d r e s p o n d e e s , t e r m i n a t i n g t h e l i n k : procedure TDDEWindow.WMDDEAck(var
Msg: TMessage);
begin {
}
PostMessage(Msg.WParam, wm_DDE_Terminate, HWindow, 0); { .... } end; T o initiate a D D E c o n v e r s a t i o n , b r o a d c a s t a m e s s a g e that i d e n t i f i e s t h e a p p l i c a t i o n . I n t h e n e x t e x a m p l e , y o u e s t a b l i s h a very c o l d l i n k t o t h e P r o g r a m M a n a g e r , e v e n t u a l l y u s i n g t h e l i n k t o c r e a t e a p r o g r a m g r o u p that c a n , i n t u r n , b e u s e d b y a n y a p p l i c a t i o n s that a c c e s s t h e P r o g r a m M a n a g e r . T h e InitiateDDE m e t h o d l o o k s like this: procedure var
DDEWindow.InitiateDDE;
AppAtom, TopicAtom: TAtom; lParam : Word; begin PostedMessage := wm_DDE_Initiate;
{ Global atoms } { Message parameter } { Initiate DDE }
355
356
Part I I — A d v a n c e d T o p i c s
AppAtom := GlobalAddAtom( PROGMAN'); { Specify server application TopicAtom := GlobalAddAtom( PROGMAN'); { Specify server topic } SendMessage(HWnd(-1), wm_DDE_Initiate, HWindow, MakeLong(AppAtom, TopicAtom)); GlobalDeleteAtom(AppAtom); { Done with global atoms } GlobalDeleteAtom(TopicAtom); PostedMessage := 0; if ServerWindow = 0 then { DDE failed if ServerWindow = 0 } begin MessageBox(HWindow, 'Cannot establish DDE link to Program Manager.', 'Error', mb_IconExclamation or mb_Ok); EndDDE; { EndDDE if no successful DDE contact } end; end; 1
1
Notice that you cancel the D D E link if the Program Manager is not available. A message is displayed indicating the lack of success, and EndDDE is called, like this: procedure TDDEWindow.EndDDE; var Msg :TMessage; begin WMDestroy(Msg); end; WMDestroy sends messages to TerminateDDE and to TDlgWindow. WMDestroy destroys the additional dialog w i n d o w you created: procedure DDEWindow.WMDestroy(var Msg: TMessage); begin TerminateDDE; TDlgWindow.WMDestroy(Msg); end; WMDDETerminate uses the W i n d o w s function TerminateDDE to break the D D E link, as such: procedure TDDEWindow.WMDDETerminate(var Msg: TMessage); begin if Msg.WParam = ServerWindow then TerminateDDE; end; Listing 11.3 shows the complete procedure of a unit and test program used for linking to the Program Manager and creating a program group. Figure 11.2 shows the dialog w i n d o w in add-an-item-to-the-list m o d e created by the
1 1 — F r o m Program to Program Using D D E
c o d e . F i g u r e 11.3 s h o w s a g r o u p list. F i g u r e 11.4 s h o w s t h e C r e a t e G r o u p m o d e . F i g u r e 11.5 s h o w s a g r o u p c r e a t e d u s i n g this c o d e . Listing
11.3* Linking
to the Program
Manager.
unit MakeGroup; { This unit based on BI's progtalk.pas } interface uses WinTypes, WinProcs, WObjects, Strings; {$R MAKEGROU} const { Resource IDs } id_DDEDialog = 100; id_AddDialog = 101; id_CreateDialog = 102; { DDE dialog item IDs } id_ListBox id_AddItem id_DeleteItem id_ClearItems id_CreateGroup
= 100; =101; = 102; = 103; = 104;
{ Add and Create dialog item IDs } id_InputLine = 100; type { DDEDialog is the object type used to represent the Add Item and Create Group dialogs. } PDDEDialog = "DDEDialog; DDEDialog = object(TDialog) Buffer: PChar; continues
357
358
Part I I — A d v a n c e d T o p i c s
Listing
11.3>
continued
BufferSize: Word; constructor Init(AParent: PWindowsObject; AName, EditBuffer: PChar; EditBufferSize: Word); procedure SetupWindow; virtual; function CanClose: Boolean; virtual; procedure Inputl_ine(var Msg: TMessage); virtual id_First + id_Inputl_ine; end; { DDEWindow is the Application's MainWindow. It maintains a DDE conversation with the Program Manager, and allows a user to create program groups containing a user-specified list of program items. } PDDEWindow = "DDEWindow; DDEWindow = object(TDlgWindow) { DDEWindow is a kind of TDlgWindow } ListBox: PListBox; { List box for setting up group } ServerWindow: HWnd; { The server's handle } ContactMessage: Word; constructor Init; procedure SetupWindow; virtual; function GetClassName: PChar; virtual; procedure InitiateDDE; { DDE contact messages } procedure TerminateDDE; procedure EndDDE; procedure virtual procedure virtual procedure virtual procedure virtual procedure virtual procedure virtual procedure virtual end;
Addltem(var Msg: TMessage); { Make group messages } id_First + id_AddItem; Deleteltem(var Msg: TMessage); id_First + id_DeleteItem; Clearltems(var Msg: TMessage); id_First + id_ClearItems; CreateGroup(var Msg: TMessage); id_First + id_CreateGroup; WMDDEAck(var Msg: TMessage); { Windows messages } wm_First + wm_DDE_Ack; WMDDETerminate(var Msg: TMessage); wm_First + wm_DDE_Terminate; WMDestroy(var Msg: TMessage); wm_First + wm_Destroy;
1 1 — F r o m Program to Program Using D D E
{ DDEApp is the application object. It constructs a DDEWindow (its MainWindow) } DDEApp = object(TApplication) procedure InitMainWindow; virtual; end;
implementation
{ DDEDialog } { Input dialog constructor. Save the input buffer pointer and size for copying the contents of the EditControl } constructor DDEDialog.Init(AParent: PWindowsObject; AName, EditBuffer: PChar; EditBufferSize: Word); begin TDialog.Init(AParent, AName); Buffer := EditBuffer; BufferSize := EditBufferSize; end; { SetupWindow is called right after the dialog is created. The Edit control is limited to the maximum length of the input buffer. Disable the Ok button by setting EnableWindow to false. } procedure DDEDialog.SetupWindow; begin SendDlgltemMessage(HWindow, id_InputLine, em_LimitText, BufferSize - 1, 0); EnableWindow(GetDlgItem(HWindow, id_Ok), False); end; { Copy the contents of the edit control to the input buffer and return True, which allows the dialog to close. } function DDEDialog.CanClose: Boolean; begin GetDlgltemText(HWindow, id_Inputl_ine, Buffer, BufferSize); CanClose := True; end; continues
359
360
Part I I — A d v a n c e d T o p i c s
Listing
11.3'
continued
{ Edit control response method. Enable the Ok button if the edit control contains text, else disable the Ok button. } procedure DDEDialog.InputLine(var Msg: TMessage); begin if Msg.LParamHi = en_Change then EnableWindow(GetDlgItem(HWindow, id_0k), SendMessage(Msg.LParamLo, wm_GetTextLength, 0, 0) 0); end; { DDEWindow } { DDE window constructor. Create a TListBox object to represent the dialog's list box. Clear the DDE server window handle and the pending DDE message ID. } constructor DDEWindow.Init; begin TDlgWindow.Init(nil, PChar(id_DDEDialog)); ListBox := New(PListBox, InitResource(@Self, id_ListBox)); ServerWindow := 0; { No server yet. } ContactMessage := 0; end; { SetupWindow is called right after the DDE window is created. Initiate the DDE conversation. }
procedure DDEWindow.SetupWindow; begin TDlgWindow.SetupWindow; InitiateDDE; end;
{ Return window class name. This name corresponds to the class name specified for the DDE dialog in the resource file. } function DDEWindow.GetClassName: PChar; begin GetClassName := 'DDEWindow'; end;
1 1 — F r o m Program to Program Using D D E
{ Initiate a DDE conversation with the Program Manager. Bring up a message box if the Program Manager doesn't respond to the wm_DDE_Initiate message. } procedure DDEWindow.InitiateDDE; var AppAtom, TopicAtom: TAtom; lParam : Word; begin ContactMessage := wm_DDE_Initiate; AppAtom := GlobalAddAtom('PROGMAN'); TopicAtom := GlobalAddAtom('PROGMAN'); lParam := AppAtom or (TopicAtom shl 16); (* Either of the following SendMessage procedures works, but don't use both. SendMessage(HWnd(-1), wm_DDE_Initiate, HWindow, MakeLong(AppAtom, TopicAtom)); *)
SendMessage(HWnd(-1), wm_DDE_Initiate,HWindow,lParam); GlobalDeleteAtom(AppAtom); GlobalDeleteAtom(TopicAtom); ContactMessage := 0; if ServerWindow = 0 then begin MessageBox(HWindow, 'Cannot establish DDE link to Program Manager.', 'Error', mb_IconExclamation or mb_Ok); EndDDE; { Bail out if no DDE } end; end;
procedure DDEWindow.EndDDE; var Msg :TMessage; begin WMDestroy(Msg); end; continues
3
61
362
Part I I — A d v a n c e d T o p i c s
Listing
11.3>
continued
{ Terminate the DDE conversation. Send the wm_DDE_Terminate message only if the server window still exists. } procedure DDEWindow.TerminateDDE; var W: HWnd; begin W := ServerWindow; ServerWindow := 0; if IsWindow(W) then PostMessage(W, wm_DDE_Terminate, HWindow, 0); end; { Add item button response method. Bring up the Add item dialog to input a program item string, and add that item to the list box. } procedure DDEWindow.AddItem(var Msg: TMessage); var Name: array[0..63] of Char; begin if Application".ExecDialog(New(PDDEDialog, Init(@Self, PChar(id_AddDialog), Name, SizeOf(Name)))) id_Cancel then ListBox".AddString(Name); end; { Delete item button response method. Delete the currently selected item in the list box. } procedure DDEWindow.DeleteItem(var Msg: TMessage); begin ListBox".DeleteString(ListBox .GetSellndex); end; A
{ Clear items button response method. Clear the list box. } procedure DDEWindow.ClearItems(var Msg: TMessage); begin ListBox".ClearList; end; { Create group button response method. Initiate the Create Group dialog to input the program group name. Then, if a DDE link has been established (ServerWindow 0) and there is no DDE message currently pending (ContactMessage = 0), build
1 1 — F r o m Program to Program Using D D E
363
a list of Program Manager commands, and submit the commands using a wm_DDE_Execute message. To build the command list, first calculate the total length of the list, then allocate a global memory block of that size, and finally store the command list as a null-terminated string in the memory block. } procedure DDEWindow.CreateGroup(var Msg: TMessage); const sCreateGroup = [CreateGroup(%s)]'; sAddltem = '[Addltem(%s)] ; var Executed: Boolean; I, L: Integer; HCommands: THandle; PName, PCommands: PChar; Name: array[0..63] of Char; begin if Application".ExecDialog(New(PDDEDialog, Init(@Self, PChar(id_CreateDialog), Name, SizeOf(Name)))) id_Cancel then begin Executed := False; if (ServerWindow 0) and (ContactMessage = 0) then begin L := StrLen(Name) + (Length(sCreateGroup) - 1); for I := 0 to ListBox".GetCount - 1 do Inc(L, ListBox".GetStringLen(I) + (Length(sAddltem) - 2)); HCommands := GlobalAlloc(gmem_Moveable or gmemJDDEShare, L); { Must be DDEShare memory } if HCommands 0 then begin PName := Name; PCommands := GlobalLock(HCommands); WVSPrintF(PCommands, sCreateGroup, PName); for I := 0 to ListBox".GetCount - 1 do begin ListBox".GetString(Name, I); PCommands := StrEnd(PCommands); WVSPrintF(PCommands, sAddltem, PName); end; GlobalUnlock(HCommands); if PostMessage(ServerWindow, wm_DDE_Execute, HWindow, Makel_ong(0, HCommands)) then 1
1
continues
364
Part I I — A d v a n c e d T o p i c s
Listing
11.3'
continued
begin ContactMessage := wm_DDE_Execute; Executed := True; end else GlobalFree(HCommands); end; end; if not Executed then MessageBox(HWindow, 'Program Manager DDE execute failed.', 'Error , mb_IconExclamation or mb_0k); end; end; 1
{ wm_DDE_Ack message response method. If the current DDE message is a wm_DDE_Initiate, store off the window handle of the window that responded. If more than one window responds, terminate all conversations but the first. If the current DDE message is a wm_DDE_Execute, free the command string memory block, focus the window, and clear the list box. } procedure DDEWindow.WMDDEAck(var Msg: TMessage); begin case ContactMessage of wm_DDE_Initiate: begin if ServerWindow = 0 then ServerWindow := Msg.WParam else PostMessage(Msg.WParam, wm_DDE_Terminate, HWindow, 0); GlobalDeleteAtom(Msg.LParamLo); GlobalDeleteAtom(Msg.LParamHi); end; wm_DDE_Execute: begin GlobalFree(Msg.LParamHi); ContactMessage := 0; SetFocus(HWindow); ListBox".ClearList; end; end; end;
1 1 — F r o m Program to Program Using D D E
{ wm_DDE_Terminate message response method. If the window signaling termination is the server window (the Program Manager), terminate the DDE conversation. Otherwise ignore the wm_DDE_Terminate. } procedure DDEWindow.WMDDETerminate(var Msg: TMessage); begin if Msg.WParam = ServerWindow then TerminateDDE; end; { wm_Destroy message response method. Terminate the DDE link and call the inherited WMDestroy. } procedure DDEWindow.WMDestroy(var Msg: TMessage); begin TerminateDDE; TDlgWindow.WMDestroy(Msg); end; { TDDEApp } { Create a DDE window as the application's main window. } procedure DDEApp.InitMainWindow; begin MainWindow := New(PDDEWindow, Init); end; end.
{ end MakeGrou unit }
program Test_Interface;
{ A generic way to test each phase of interface development }
uses WIF5, makegrou;
{ Basic Interface unit } { Contains DDEApp } continues
365
366
Part I I — A d v a n c e d T o p i c s
Listing
11.3>
continued
type App = object(DDEApp) end; var Application: App;
{ An instance of BasicApplication }
{ Run Applicationl } begin Application.Init('Basiclnterface'); { Init application instance } Application.Run; { Message loop } Application.Done; { Destroy application instance } end.
Figure
11.2. The dialog window listing 11.3.
in add-an-item-to-the-list
mode created
by
1 1 — F r o m Program to Program Using D D E
Figure
11.3- A group list.
Figure
11.4. The Create Group
mode.
367
368
Part I I — A d v a n c e d T o p i c s
Figure
11.5. A group created using listing
113.
Wrap-up D D E is o n e o f t h e m a n y f e a t u r e s that m a k e s W i n d o w s s i n g . If y o u r a p p l i c a t i o n k n o w s h o w t o l i n k t o t h e D D E , it c a n act a n d react t o t h e b e h a v i o r o f m a n y o t h e r programs. A l t h o u g h this c h a p t e r h a s f o c u s e d o n t h e a p p l i c a t i o n - c l i p b o a r d c o n n e c tion a n d the very c o l d link b e t w e e n a n application a n d the Program M a n a g e r , t h e p o s s i b i l i t i e s f o r m a k i n g m o r e d r a m a t i c c o n n e c t i o n s are virtually e n d l e s s . Y o u r applications can 1. M o d i f y t h e d a t a fields i n o t h e r p r o g r a m s . 2. H a v e t h e i r o w n d a t a fields m o d i f i e d o r b e h a v i o r m a n i p u l a t e d i n response to the behavior of another program. 3. D i r e c t l y c o m m a n d a n o t h e r p r o g r a m t h r o u g h t h e u s e o f a p r o g r a m ' s M A C R O language. For e x a m p l e , y o u can access Microsoft W o r d , Excel, a n d other sophisticated programs t h r o u g h their M A C R O languages. For advanced information about D D E contacts, check the Reference s e c t i o n i n Part III o f this b o o k .
12 CHAPTER
SHARING LIBRARIES: USING DLL (DYNAMIC LINK LIBRARIES) When a child draws shape were like a
a tree, a green Popsicle.
mass sits atop a brown
trunk,
as if the
basic
James Gleick
D y n a m i c l i n k libraries are e x e c u t a b l e m o d u l e s o f c o d e l i n k e d i n t o a n a p p l i c a t i o n at r u n - t i m e . D L L s a l l o w a p p l i c a t i o n d e v e l o p e r s t o c r e a t e a n d m a i n t a i n i n d e p e n d e n t application c o m p o n e n t s . Similar to units in their modularity, D L L s are m o r e p o w e r f u l b e c a u s e t h e y 1. C a n b e l i n k e d i n t o a n a p p l i c a t i o n at r u n - t i m e . 2. C a n b e s h a r e d b y m a n y c o n c u r r e n t l y e x e c u t i n g a p p l i c a t i o n s . 3. C a n b e w r i t t e n i n a variety o f l a n g u a g e s , r e g a r d l e s s o f t h e l a n g u a g e u s e d to access the D L L .
370
Part I I — A d v a n c e d T o p i c s
D y n a m i c a l l y l i n k e d libraries ( D L L s ) p e r m i t several a p p l i c a t i o n s t o s h a r e c o d e a n d r e s o u r c e s . T h e s e a p p l i c a t i o n s (also c a l l e d clients) s h a r e a s i n g l e c o p y o f a p r o c e d u r e o r f u n c t i o n . T h e D L L file h a s t o b e p r e s e n t w h e n t h e c l i e n t application executes. D L L s are s i m i l a r t o u n i t s , e x c e p t t h e p r o c e d u r e s a n d f u n c t i o n s i n u n i t s are l i n k e d i n t o a p p l i c a t i o n s at l i n k t i m e (in o t h e r w o r d s , t h e y are statically linked), a n d t h e p r o c e d u r e s a n d f u n c t i o n s i n D L L s are a c c e s s i b l e t o t h e a p p l i c a t i o n at r u n - t i m e (in o t h e r w o r d s , t h e y are dynamically linked). T h e W i n d o w s p r o g r a m l o a d e r d y n a m i c a l l y l i n k s t h e p r o c e d u r e a n d f u n c t i o n calls i n t h e a p p l i c a t i o n t o t h e i r e n t r y p o i n t s i n t h e D L L s , w h i c h t h e n are u s e d b y t h e a p p l i c a t i o n . D L L s are e s p e c i a l l y p o w e r f u l b e c a u s e a T u r b o P a s c a l f o r W i n d o w s a p p l i c a t i o n c a n u s e D L L s that w e r e n o t w r i t t e n u s i n g T u r b o Pascal f o r W i n d o w s , a n d applications written in o t h e r l a n g u a g e s c a n u s e D L L s written with T u r b o Pascal for W i n d o w s . A D L L c o n s i s t s o f i n d e x e d f u n c t i o n s a n d p r o c e d u r e s , a n d is a m o r e o r less straightforward aspect of W i n d o w s ' application d e v e l o p m e n t . This chapter briefly s h o w s y o u h o w t o c r e a t e a n d a c c e s s a D L L i n T u r b o P a s c a l f o r W i n d o w s . F o r m o r e e x t e n s i v e details a b o u t D L L s , s e e t h e M i c r o s o f t S o f t w a r e D e v e l o p e r s Kit ( S D K ) .
DLL Details First, a f e w D L L r u l e s : • For an application to u s e a p r o c e d u r e or f u n c t i o n c o n t a i n e d in a D L L , the application must import the procedure or function using an external declaration. • I n i m p o r t e d p r o c e d u r e s a n d functions, the external directive replaces t h e d e c l a r a t i o n a n d s t a t e m e n t p a r t s that o t h e r w i s e w o u l d b e p r e s e n t i n the application. • I m p o r t e d p r o c e d u r e s a n d f u n c t i o n s b e h a v e similarly t o n o r m a l o n e s , e x c e p t t h e y m u s t u s e far calls (either a far p r o c e d u r e d i r e c t i v e o r a { $ F+} compiler directive). T u r b o Pascal lets y o u i m p o r t p r o c e d u r e s a n d f u n c t i o n s i n D L L s i n t h r e e different ways: • By name • By new name • By ordinal
1 2 — S h a r i n g Libraries: U s i n g D L L
A l t h o u g h a D L L c a n have variables, y o u cannot import t h e m into other m o d u l e s . A n y access t o a DLL's variables m u s t o c c u r t h r o u g h a p r o c e d u r a l interface. For example, the following external declaration imports the function GlobalAlloc f r o m t h e D L L c a l l e d K E R N E L ( t h e W i n d o w s k e r n e l ) : function GlobalAlloc(Flags: Word; Bytes: Longint): THandle; far; external 'KERNEL' index 15; N o t i c e that t h e D L L n a m e y o u specify after t h e e x t e r n a l k e y w o r d a n d t h e n e w n a m e y o u specify i n a n a m e c l a u s e d o n o t h a v e t o b e string literals. A n y c o n s t a n t string e x p r e s s i o n w i l l d o . A l s o , t h e o r d i n a l n u m b e r s p e c i f i e d i n a n index clause can b e any constant integer expression. For example: const ALib = 'ALIB'; Ordinal = 8;
procedure ImportByName; external ALib; procedure ImportByNewName; external ALib name 'REALNAME'; procedure ImportByOrdinal; external ALib index Ordinal;
Using DLLs U s i n g a D L L is basically a t w o - s t e p p r o c e s s : 1. C r e a t e t h e d y n a m i c l i n k library o f f u n c t i o n s a n d p r o c e d u r e s , w h i c h includes an export procedure a n d function section. 2. C r e a t e t h e a p p l i c a t i o n that u s e s t h e library. F o r e x a m p l e , d e s i g n a t e a library w i t h t h e library identifier: library BitBtn; or library DLLStuff; A n y f u n c t i o n y o u w a n t t o e x p o r t i n t h e library h a s t o b e s p e c i f i e d b y a n export identifier. F o r e x a m p l e : function BitButWinFn(HWindow:
HWnd; Message: Word; wParam:
Word; lParam: Longint): Longint; export; A n d at t h e e n d o f t h e library, y o u h a v e t o s p e c i f y t h e f u n c t i o n s that c a n b e exported. For example:
371
372
Part I I — A d v a n c e d T o p i c s
exports BitButWinFn; T h e a p p l i c a t i o n t h e n u s e s t h e f u n c t i o n s i n t h e library m o r e o r less n o r m a l l y , w i t h a c o u p l e o f e x c e p t i o n s . First, t h e a p p l i c a t i o n h a s t o l o a d t h e library b e f o r e it u s e s it. F o r e x a m p l e : constructor ABitApp.Init(AName: begin
PChar);
L i b := LoadLibrary(DLLName); i f L i b < 32 t h e n S t a t u s : = em_DLLNotFound; TApplication.Init(AName); end; A n d it h a s t o free t h e library w h e n it is f i n i s h e d w i t h it. F o r e x a m p l e : destructor begin
ABitApp.Done;
TApplication.Done; FreeLibrary(Lib); end; T h e e x a m p l e i n listing 12.1 d e m o n s t r a t e s a u s e o f D L L s . I n this e x a m p l e , a n a p p l i c a t i o n i m p o r t s c u s t o m c o n t r o l s f r o m a D L L . F i g u r e 12.1 s h o w s t h e w i n d o w and custom controls created by the c o d e .
Figure
12.1. A window and its custom controls created by listing 12.1.
1 2 — S h a r i n g Libraries: U s i n g D L L
Listing
12.1.
A dynamic
link
library
(DLL)
example.
{ A DLL library example that accesses Borland International's BitBtn.DLL. }
library ABitBtn; uses WinTypes, WinProcs; {$R ABITBTN.RES} const ofState ofDownBits ofUpBits ofFocUpBits ofSize
= = = = =
0; 2; 4; 6; 8; { Amount of window extra bytes to use }
= = = = = =
$0001; $0002; $0004; $0008; $0010; $0020;
const bdBorderWidth = 1; const bsDisabled bsFocus bsKeyDown bsMouseDown bsMouseUpDown bsDefault
function BitButtonWinFn(HWindow: HWnd; Message: Word; wParam: Word; lParam: Longint): Longint; export; var DC: HDC; BitsNumber: Integer; Bitmap: TBitmap; Rect: TRect; Pt: TPoint; PS: TPaintStruct; continues
373
374
Part I I — A d v a n c e d T o p i c s
Listing
12.1.
continued
function Get(Ofs: Integer): Word; begin Get := GetWindowWord(HWindow, Ofs); end; procedure SetWinWord(Ofs: Integer; Val: Word); begin SetWindowWord(HWindow, Ofs, Val); end; function State: Word; begin State := Get(ofState); end; function DownBits: Word; begin DownBits := Get(ofDownBits); end; function UpBits: Word; begin UpBits := Get(ofUpBits); end; function FocUpBits: Word; begin FocUpBits := Get(ofFocUpBits); end; function GetState(AState: Word): Boolean; begin GetState := (State and AState) = AState; end; procedure Paint(DC: HDC); var MemDC: HDC; Bits, Oldbitmap: HBitmap; BorderBrush, OldBrush: HBrush; Frame: TRect; Height, Width: Integer;
1 2 — S h a r i n g Libraries: U s i n g D L L
375
begin if (State and (bsMouseDown + bsKeyDown) 0) and not GetState(bsMouseUpDown) then Bits := DownBits else if GetState(bsFocus) then Bits := FocUpBits else Bits := UpBits; { Draw a border } GetClientRect(HWindow, Frame); Height := Frame.bottom - Frame.top; Width := Frame.right - Frame.left; if GetState(bsDefault) then BorderBrush := GetStockObject(Black_Brush) else BorderBrush := GetStockObject(White_Brush); OldBrush := SelectObject(DC, BorderBrush); PatBlt(DC, Frame.left, Frame.top, Width, bdBorderWidth, PatCopy); PatBlt(DC, Frame.left, Frame.top, bdBorderWidth, Height, PatCopy); PatBlt(DC, Frame.left, Frame.bottom - bdBorderWidth, Width, bdBorderWidth, PatCopy); PatBlt(DC, Frame.right - bdBorderWidth, Frame.top, bdBorderWidth, Height, PatCopy); SelectObject(DC, OldBrush); { Draw a bit map } MemDC := CreateCompatibleDC(DC); OldBitmap := SelectObject(MemDC, Bits); GetObject(Bits, Sizeof(Bitmap), ^Bitmap); BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth, Bitmap.bmHeight, MemDC, 0, 0, srcCopy); SelectObject(MemDC, OldBitmap); DeleteDC(MemDC); end; procedure Repaint; var DC: HDC; begin DC := GetDC(HWindow); Paint(DC); ReleaseDC(HWindow, DC); end; continues
376
Part I I — A d v a n c e d T o p i c s
Listing
12.1.
continued
procedure SetState(AState: Word; Enable: Boolean); var OldState: Word; begin OldState := State; if Enable then SetWinWord(ofState, State or AState) else SetWinWord(ofState, State and not AState); if State OldState then Repaint; end; function InMe(lPoint: Longint): Boolean; var R: TRect; Point: TPoint absolute lPoint; begin GetClientRect(HWindow, R); InflateRect(R, -bdBorderWidth, -bdBorderWidth); InMe := PtInRect(R, Point); end; procedure ButtonPressed; begin SetState(bsMouseDown + bsMouseUpDown + bsKeyDown, False); SendMessage(GetParent(HWindow), wm_Command, GetDlgCtrllD(HWindow), Longint(HWindow)); end; begin BitButtonWinFn := 0; case Message of { Message responses } wm_Create: begin DC := GetDC(0); if (GetSystemMetrics(sm_CYScreen) < 480) or (GetDeviceCaps(DC, numColors) < 16) then BitsNumber := 2000 + Get(gww_ID) else BitsNumber := 1000 + Get(gww_ID); ReleaseDC(0, DC); SetWinWord(ofUpBits, LoadBitmap(hlnstance, PChar(BitsNumber)));
12—Sharing Libraries: Using DLL
377
SetWinWord(ofDownBits, LoadBitmap(hInstance, pChar(BitsNumber + 2000))); SetWinWord(ofFocUpBits, LoadBitmap(hinstance, pChar(BitsNumber + 4000))); GetObject(DownBits, SizeOf(Bitmap), ^Bitmap); GetWindowRect(HWindow, Rect); Pt.X := Rect.Left; Pt.Y := Rect.Top; ScreenToClient(PCreateStruct (lParam) .hwndParent, Pt); MoveWindow(HWindow, Pt.X, Pt.Y, Bitmap.bmWidth + bdBorderWidth * 2, Bitmap.bmHeight + bdBorderWidth * 2, False); if (PCreateStruct(lParam)".style and $1F) = bs_DefPushButton then SetState(bsDefault, True); end; wm_NCDestroy: begin BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam); DeleteObject(UpBits); DeleteObject(DownBits); DeleteObject(FocUpBits); end; wm_Paint: begin BeginPaint(HWindow, PS); Paint(PS.hDC); EndPaint(HWindow, PS); end; wm_EraseBkGnd: begin end; wm_Enable: SetState(bsDisabled, wParam 0); wm_SetFocus: SetState(bsFocus, True); wm_KillFocus: SetState(bsFocus, False); wm_KeyDown: if (wParam = $20) and not GetState(bsKeyDown) and not GetState(bsMouseDown) then SetState(bsKeyDown, True); wm_KeyUP: if (wParam = $20) and GetState(bsKeyDown) then ButtonPressed; A
continues
378
Part I I — A d v a n c e d T o p i c s
Listing
12.1.
continued
wm_LButtonDblClk, wm_LButtonDown: if InMe(lParam) and not GetState(bsKeyDown) then begin if GetFocus HWindow then SetFocus(HWindow); SetState(bsMouseDown, True); SetCapture(HWindow); end; wm__MouseMove: if GetState(bsMouseDown) then SetState(bsMouseUpDown, not InMe(lParam)); wm_LButtonUp: if GetState(bsMouseDown) then begin ReleaseCapture; if not GetState(bsMouseUpDown) then ButtonPressed else SetState(bsMouseDown + bsMouseUpDown, False); end; wm_GetDlgCode: if GetState(bsDefault) then BitButtonWinFn:= dlgc_DefPushButton else BitButtonWinFn := dlgcJJndefPushButton; bm_SetStyle: SetState(bsDefault, wParam = bs_DefPushButton); else BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam); end; end; exports BitButtonWinFn;
{ Export qualifier }
var Class: TWndClass; begin with Class do begin IpszClassName hCursor IpszMenuName style lpfnWndProc
:= := := :=
'ABitButton'; LoadCursor(0, idc_Arrow); nil; cs_HRedraw or cs_VRedraw or csJDblClks or cs_GlobalClass; := TFarProc(@BitButtonWinFn);
1 2 — S h a r i n g Libraries: U s i n g D L L
hlnstance := System.hlnstance; hlcon := 0; cbWndExtra := ofSize; cbClsExtra := 0; hbrBackground := 0; end; RegisterClass(Class); end. { End DLL }
{ Main application uses the custom controls in the DLL: ABITBTN.PAS. }
program BitBnApp; {$R BitBnApp.RES} uses WinTypes, WinProcs, WObjects; const DLLName = ABITBTN.DLL'; 1
{ The DLL }
const em_DLLNotFound = 1; type PABitWindow = "ABitWindow; ABitWindow = object(TDlgWindow) { A dialog window } { Button response methods } procedure Yes(var Msg: TMessage); virtual id_First + id_Yes; procedure No(var Msg: TMessage); virtual id_First + id_No; procedure Ok(var Msg: TMessage); virtual id_First + id_0K; procedure Cancel(var Msg: TMessage); virtual id_First + id_Cancel; end; continues
379
380
Part I I — A d v a n c e d T o p i c s
Listing
12.1.
continued
PABitApp = ABitApp; ABitApp = object(TApplication) Lib: THandle; { A library handle } constructor Init(AName: PChar); destructor Done; virtual; procedure InitMainWindow; virtual; procedure Error(ErrorCode: Integer); virtual; end; A
{ ABitApp } constructor ABitApp.Init(AName: PChar); begin Lib := LoadLibrary(DLLName); { Load the DLL } if Lib < 32 then Status := em_DLLNotFound; TApplication.Init(AName); end; destructor ABitApp.Done; begin TApplication.Done; FreeLibrary(Lib); end;
{ Release the DLL }
procedure ABitApp.InitMainWindow; begin MainWindow := New(PABitWindow, Init(nil, MakeIntResource(100))); { Use resource } end; procedure ABitApp.Error(ErrorCode: Integer); begin case ErrorCode of em_DLLNotFound: MessageBox(0, DLLName + not found. ', 'Fatal error', mb_0k or mb_IconStop); else TApplication.Error(ErrorCode); end; end; 1
{ ABitWindow methods }
1 2 — S h a r i n g Libraries: U s i n g D L L
procedure ABitWindow.Yes(var Msg: TMessage); begin CloseWindow; end; procedure ABitWindow.No(var Msg: TMessage); begin { Cancel close } end; procedure ABitWindow.Ok(var Msg: TMessage); begin CloseWindow; end; procedure ABitWindow.Cancel(var Msg: TMessage); begin { Cancel close } end; var App: ABitApp; { Main loop } begin App.Init('Uses ABITBTN.DDL'); App.Run; App.Done; end.
381
13 CHAPTER
DESIGNING WINDOWS APPLICATIONS My roads will not be exactly the same as yours, but, with our separate maps, we can each get from a particular place to another. D o u g l a s R. H o f s t a d t e r T u r b o Pascal f o r W i n d o w s offers a p p l i c a t i o n d e v e l o p e r s a n e x c e p t i o n a l w a y t o d e s i g n a p p l i c a t i o n s f o r W i n d o w s that c a n e v o l v e as t h e n e e d s o f u s e r s e v o l v e . If y o u b u i l d y o u r W i n d o w s a p p l i c a t i o n s o u t o f o b j e c t s ( u s i n g t h e O b j e c t W i n d o w s library): 1. Y o u r a p p l i c a t i o n d o e s n o t h a v e t o b o t h e r w i t h t h e d e t a i l s o f i n t e r a c t i n g w i t h W i n d o w s at a l o w l e v e l . 2. Y o u r a p p l i c a t i o n c o n s i s t s o f easily m o d i f i a b l e o b j e c t s . T h e n e t result is easily m o d i f i a b l e a n d e x t e n d a b l e W i n d o w s a p p l i c a t i o n s . O n e i m p o r t a n t w a y o f e x t e n d i n g o b j e c t s , as this b o o k h a s s h o w n , is t h r o u g h i n h e r i t a n c e . W h e n y o u w a n t a n e w o b j e c t s i m i l a r t o o n e that O b j e c t W i n d o w s (or y o u r o b j e c t library) a l r e a d y c o n t a i n s , y o u c a n d e r i v e a n e w object from the o n e y o u have, a n d create n e w behavior or override s o m e existing behavior y o u must c h a n g e . W h y is this i m p o r t a n t ? B e c a u s e p r o b l e m s a n d t h e n e e d s o f c o m p u t e r u s e r s c h a n g e , a n d g o o d a p p l i c a t i o n s always c h a n g e i n r e s p o n s e t o u s e r s . W i n d o w s is a g e n e r a l - p u r p o s e , f l e x i b l e i n t e r f a c e ; u s e r - f r i e n d l y a n d (with t h e h e l p o f T u r b o Pascal f o r W i n d o w s ) d e v e l o p e r - f r i e n d l y .
384
Part I I — A d v a n c e d T o p i c s
T h i s c h a p t e r r e s h a p e s t h e i d e a s d i s c u s s e d s o far i n t o a m o r e o r less g e n e r a l W i n d o w s design philosophy. This philosophy emphasizes two primary themes f o r d e s i g n i n g efficient, e x p a n d a b l e W i n d o w s a p p l i c a t i o n s : 1. M a k e n e w a p p l i c a t i o n s c o n s i s t e n t w i t h e x i s t i n g W i n d o w s a p p l i c a t i o n s . I n o t h e r w o r d s , if y o u are g o i n g t o u s e W i n d o w s as y o u r u s e r i n t e r f a c e , t a k e full a d v a n t a g e o f it b y u s i n g its s t r e n g t h s ; f o r e x a m p l e , t h e c o n s i s t e n c y o f its i n t e r f a c e . I B M h a s p u b l i s h e d g u i d e l i n e s that a d d r e s s this i s s u e , c a l l e d t h e C o m m o n U s e r A c c e s s ( C U A ) , w h i c h this b o o k u s e s as a basis. 2 . T a k e a d v a n t a g e o f o b j e c t - o r i e n t e d t e c h n i q u e s that are flexible e n o u g h t o let y o u e x t e n d a n d m o d i f y t h e m as p a i n l e s s l y as p o s s i b l e . T h e object-oriented t e c h n i q u e s built t h o r o u g h l y into T u r b o Pascal for W i n d o w s (that is, O b j e c t W i n d o w s ) c a n save y o u a n e n o r m o u s a m o u n t o f t i m e a n d effort, as t h e p r e v i o u s 12 c h a p t e r s h a v e d e m o n s t r a t e d . T h e s e c o n d part o f this c h a p t e r d e s c r i b e s m o r e a b o u t d i s c o v e r i n g a n d e x t e n d i n g o b j e c t s as a p r i m a r y s t e p i n a p p l i c a t i o n d e s i g n . Discussing consistency in the l o o k and feel of applications a n d highlighti n g s o m e o f t h e i m p o r t a n t a s p e c t s o f t h e C o m m o n U s e r A c c e s s is a g o o d w a y t o start.
Common User Access T h e C o m m o n U s e r A c c e s s ( C U A ) is a set o f g u i d e l i n e s that h e l p y o u d e v e l o p applications consistent with IBM's (and probably Microsoft's) ideas about h o w a W i n d o w s application s h o u l d l o o k a n d feel. T h e C U A emphasizes two primary ideas: 1. U s e r s s h o u l d f e e l c o m f o r t a b l e w i t h a n a p p l i c a t i o n a n d c o n f i d e n t i n t h e results o f an action. 2. U s e r s s h o u l d c o n t r o l t h e flow o f e v e n t s . L o o k i n g o u t f o r u s e r s ' c o m f o r t a n d b u i l d i n g t h e i r c o n f i d e n c e is a b i g j o b . Making your application consistent with other W i n d o w s applications they m i g h t h a v e u s e d , a n d m a k i n g it c o n s i s t e n t w i t h its o w n b e h a v i o r c a n d o t h e j o b . E a c h o p e n i n g o f a w i n d o w s h o u l d b e less m y s t e r i o u s a n d m o r e familiar. S i m i l a r tasks s h o u l d r u n i n s i m i l a r - l o o k i n g w i n d o w s . I n a d d i t i o n , if p o s s i b l e , try t o u s e m e t a p h o r s w i t h w h i c h t h e u s e r is familiar. A classic e x a m p l e is a card-filing a p p l i c a t i o n o n a c o m p u t e r that r e s e m b l e s a card-filing s y s t e m u s e d i n b u s i n e s s e s .
13—Designing W i n d o w s Applications
Also, avoid limiting users whenever y o u can. I n other words, avoid restricting u s e r s ' a c c e s s t o parts o f a n a p p l i c a t i o n . U s e r s s h o u l d b e a b l e t o m o v e anywhere they want w h e n they want. Y o u c a n t h i n k o f this p r o c e s s as e v e n t - f l o w . I n o t h e r w o r d s , let t h e u s e r s c o n t r o l as m u c h o f t h e flow o f t h e a p p l i c a t i o n as p o s s i b l e . T h i s b u i l d s u s e r s ' c o n f i d e n c e a n d lets t h e m o v e r c o m e t h e all-too-typical fear o f a p p l i c a t i o n s a n d thus, of the computer. W h e n y o u c a n , let u s e r s d e c i d e t h i n g s f o r t h e m s e l v e s u s i n g v i s u a l c u e s ( i c o n s , s h a p e s , m e n u s , lists, a n d s o o n ) . E n c o u r a g e t h e m t o e x p l o r e t h e application. D o not m a k e t h e m pay t o o dearly for mistakes. Provide a n U n d o , B a c k o u t , Feedback, a n d H e l p . T h e best application includes a context- a n d situation-sensitive H e l p system that p r o v i d e s n o t o n l y g e n e r a l b u t also s p e cific h e l p . E a c h a p p l i c a t i o n s h o u l d h a v e t h e s t a n d a r d a p p e a r a n c e o f a MainWindow, m e n u , a n d event-driven object-action cycle. Users' d o u b l e o r single m o u s e clicks s h o u l d d o similar t h i n g s i n a p p l i c a t i o n s . T h e s a m e r u l e a p p l i e s t o t h e k e y b o a r d : if t h e a p p l i c a t i o n s y o u u s e a l r e a d y specify F l , S h i f t - F l , o r C o n t r o l - F l t o call u p c e r t a i n k i n d s o f H e l p , c o n s i d e r u s i n g t h o s e k e y s y o u r s e l f . M a k e t h e a p p l i c a t i o n f e e l as familiar as y o u c a n . U s e w i n d o w s s p a r i n g l y , b u t w e l l . D o n o t m a k e a w i n d o w b i g g e r t h a n it h a s t o b e , a n d k e e p i n m i n d that t h e MainWindow r e p r e s e n t s t h e a p p l i c a t i o n . W h e n it is m i n i m i z e d t h e a p p l i c a t i o n virtually d i s a p p e a r s . W h e n y o u c a n , n o t i c e t h e s e l e c t i o n o f a n o b j e c t visually. S h o w that a n object has b e e n selected o r deselected. A n excellent u s e o f visual selection a n d d e s e l e c t i o n is t h e i c o n d i s p l a y u s e d b y m a n y d r a w i n g a p p l i c a t i o n s t o r e p r e s e n t pens, brushes, and so o n . D o n o t restrict t h e m o u s e p o i n t e r . I n o t h e r w o r d s , always m a k e s u r e that it is free t o m o v e f r o m w i n d o w t o w i n d o w o r f r o m a p p l i c a t i o n t o a p p l i c a t i o n . U s e t h e k e y b o a r d s e l e c t i o n c u r s o r , a n d m a r k t h e i n p u t f o c u s w h e r e i n p u t is occurring o n the screen. M a k e t h e m e n u s ' styles c o n f o r m t o t h e k i n d o f m e n u s typically u s e d b y a p p l i c a t i o n s s u c h as t h e P r o g r a m M a n a g e r . T h e P r o g r a m M a n a g e r , b y t h e w a y , is a n e x c e l l e n t e x a m p l e t o c o m p a r e t o y o u r a p p l i c a t i o n s w h e n y o u try t o m a k e them conform to the C o m m o n User Access. C U A a l s o r e c o m m e n d s specific m e n u i t e m s f o r c o m m o n l y u s e d t o p i c s , s u c h as F i l e , Edit, V i e w , H e l p , a n d s o o n . I n a d d i t i o n , t h e C U A r e c o m m e n d s specific keyboard accelerators for u s e with m a n y c o m m o n l y u s e d topics. S e e the I B M C U A specification for m o r e details. M a k e d i a l o g a n d file b o x e s , list v i e w e r s , e n t r y w i n d o w s , a n d o t h e r s as c o n s i s t e n t as p o s s i b l e . D o n o t m i x t o o m a n y e l e m e n t s i n o n e a p p l i c a t i o n . R e m e m b e r : y o u w a n t y o u r a p p l i c a t i o n t o b e as easy t o k n o w a n d u s e as p o s s i b l e .
385
386
Part I I — A d v a n c e d T o p i c s
Objects and Windows P r o g r a m s (that is, a p p l i c a t i o n s ) b e c o m e m o r e p o w e r f u l a n d m o r e difficult t o d e s i g n a n d c o d e a l m o s t daily, it s e e m s . W a s n o t t h e r e a n early m y t h that s o f t w a r e w o u l d e v e n t u a l l y b e e a s y t o u s e , p o w e r f u l , and easy t o d e v e l o p ? ( H a , h a . ) Application ease of use and p o w e r might be keeping pace with each other, b u t e a s e o f d e v e l o p m e n t is still d e s p e r a t e l y s t r u g g l i n g t o k e e p u p . T h e W i n d o w s - O O P c o n n e c t i o n is a s t e p i n t h e right d i r e c t i o n . E v e n t s a n d o b j e c t s ; objects a n d actions. Point, click, a n d a n object r e s p o n d s to an event by carrying o u t a n a c t i o n . W i n d o w s is b o t h p o w e r f u l a n d e a s y t o u s e . O O P a l s o m a k e s it easier to create a n d , in particular, to maintain applications. W h y is m a i n t e n a n c e s o i m p o r t a n t ? C o n s i d e r h o w o n e g o e s a b o u t d e s i g n ing an application. B e f o r e o b j e c t - o r i e n t e d d e s i g n , first-rate a p p l i c a t i o n d e v e l o p e r s p r i m a r i l y u s e d something called "structured programming" or "structured design," a p h i l o s o p h y w h i c h a d v o c a t e s that y o u d e t e r m i n e all t h e d e t a i l s o f a n a p p l i c a t i o n (in o t h e r w o r d s , its s t r u c t u r e ) b e f o r e y o u b e g i n c o d i n g it. M o s t d e v e l o p e r s , i n fact, still u s e s o m e s t r u c t u r e d p h i l o s o p h y as t h e i r d e s i g n m o d e l . Y o u s t r u c t u r e t h e a p p l i c a t i o n b y b r e a k i n g it i n t o s m a l l e r s t r u c t u r e s o f i n f o r m a t i o n , o r g a n i z e d b y levels o f c o m p l e x i t y . T h e m o s t s p e c i f i c a s p e c t s o f t h e s t r u c t u r e are i n c o r p o r a t e d i n t o l a r g e r , less s p e c i f i c s t r u c t u r e s . In addition to "structuring" aspects of the application, y o u describe the a p p l i c a t i o n i n t e r m s o f " d a t a - f l o w d i a g r a m s . " A data-flow diagram is a c o l l e c t i o n o f b l o c k s (the s t r u c t u r e d , u s u a l l y f u n c t i o n a l , parts) a n d a r r o w s . E a c h b l o c k represents a process for accepting, using, a n d often transforming data items, w i t h a r r o w s r e p r e s e n t i n g t h e flows f r o m b l o c k t o b l o c k . F i g u r e 13.1 illustrates this s c e n a r i o . A c o m p l e t e s y s t e m (or a p p l i c a t i o n ) o r s u b s e t o f a n a p p l i c a t i o n c a n b e represented by a single block. Arranging an application into a hierarchy o f dataflow d i a g r a m s is c a l l e d leveling ( b e c a u s e t h e a p p l i c a t i o n is o r g a n i z e d i n t o levels o f c o m p l e x i t y ) . T h e d a t a - f l o w d i a g r a m m o d e l i n g p r o c e s s l e a d s t o a c o m p l e t e set o f d i a g r a m s that r e p r e s e n t t h e s y s t e m a n d its flow t h r o u g h v a r i o u s levels o f complexity. Using these structured blocks, y o u can view, use, or analyze an application from m a n y perspectives—from overview (represented by a single diagram with a s i n g l e b l o c k , a n d n o t m u c h d e t a i l ) , t o fine d e t a i l ( r e p r e s e n t e d b y m a n y different diagrams, each with multiple b l o c k s ) . After y o u h a v e g e n e r a t e d , c h e c k e d , a n d a g r e e d o n t h e d e t a i l e d d a t a - f l o w d i a g r a m s , y o u o f t e n g e n e r a t e a h i e r a r c h i c a l s t r u c t u r e chart f r o m t h e m (see figure 1 3 2 ) .
13—Designing W i n d o w s Applications
Processes & Transformations
Input P r o c e s s block
Output
Input
Figure
13.1. A data-flow
diagram.
Hierarchical structure chart
Executive
Input
Figure
13.2. A hierarchical
P r o c e s s block
structure
Output
chart.
T h e h i e r a r c h i c a l chart s h o w s t h e f l o w o f d a t a i n a n d o u t o f t h e b l o c k s . T h e blocks either transform the data or don't, and then return t h e m (represented b y t h e o u t g o i n g a r r o w ) . T h e chart s h o w s h o w b l o c k s interact w i t h o t h e r b l o c k s .
387
388
Part I I — A d v a n c e d T o p i c s
F r o m this h i e r a r c h i c a l chart a n d f r o m i n f o r m a t i o n a b o u t t h e d a t a structures a n d transformations, y o u c a n c o d e the specific c o m p o n e n t s o f the a p p l i c a t i o n o n e b l o c k at a t i m e , i n d e p e n d e n t o f o t h e r b l o c k s . F r o m a c o d i n g perspective, each block represents a function or procedure, and m o v i n g data f r o m in a n d out o f the b l o c k represents the function's or p r o c e d u r e ' s parameters a n d r e t u r n v a l u e s . This structured design has b e e n a r o u n d a l o n g time, and makes m u c h s e n s e b e c a u s e it s e e m s t o c a p t u r e t h e e l e m e n t s o f t h e a p p l i c a t i o n i n o n e s w o o p . A n a p p l i c a t i o n s t r u c t u r e d i n this w a y is p o w e r f u l a n d relatively easy t o understand. Y e t , t h e s t r u c t u r e d a p p r o a c h is n o t a p e r f e c t d e s i g n s o l u t i o n f o r at least o n e i m p o r t a n t r e a s o n — a r e a s o n that s e e m s t o g r o w i n i m p o r t a n c e w i t h t i m e . Applications change, usually in response to the changing needs of users. A s t r u c t u r e that m a d e m u c h s e n s e i n t h e b e g i n n i n g m i g h t n o t m a k e s e n s e further d o w n the line. Structured design supplies m u c h - n e e d e d organization at t h e b e g i n n i n g o f a n a p p l i c a t i o n ' s life, b u t t h e s t r u c t u r e itself m i g h t resist c h a n g e . M o s t a p p l i c a t i o n d e v e l o p e r s h a v e s t r u g g l e d w i t h t h e "difficult t o c h a n g e " p r o b l e m , e v e n w h e n t h e i r initial d e s i g n s s e e m e d c o r r e c t o r e v e n exceptional. T h e d e s i g n o f a n a p p l i c a t i o n m i g h t b e c l e a r . It m i g h t b e c l e a r , i n part, b e c a u s e it is b a s e d o n a s i n g l e s o l u t i o n t o a s i n g l e p r o b l e m . A h a r d - c o d e d s i n g l e s o l u t i o n t o a s i n g l e p r o b l e m is a l m o s t always c l e a r e r t h a n a g e n e r a l - s o l u t i o n o r a g e n e r a l - p r o b l e m s o l u t i o n . T h e g e n e r a l s o l u t i o n , b y n a t u r e , is m o r e c o m p l e x b e c a u s e it c o n s i d e r s m o r e t h a n o n e p r o b l e m a n d s o l u t i o n . O b j e c t - o r i e n t e d t e c h n i q u e s s u g g e s t a d e s i g n a p p r o a c h that a d d r e s s e s b o t h t h e s p e c i f i c a n d g e n e r a l n a t u r e o f p r o b l e m s . T h e a p p r o a c h is s p e c i f i c i n that a n o b j e c t c a n b e d e s i g n e d t o s o l v e s p e c i f i c a s p e c t s o f a p r o b l e m o r a s p e c i f i c p r o b l e m a n d yet b e derivative o f a b a s e o b j e c t that c o n t a i n s t h e g e n e r a l b e h a v i o r for handling general problems of a type. In an object-oriented design, the idea of the "flow of data" between blocks is d i m i n i s h e d . M e s s a g e s m o v e a b o u t t h e a p p l i c a t i o n , b u t o b j e c t s k e e p d a t a t o themselves a n d operate o n their o w n data. T h e potential c o n f u s i o n o f the w r o n g p r o c e d u r e s a n d f u n c t i o n s a c t i n g o n t h e right d a t a a n d v i c e v e r s a is virtually e l i m i n a t e d . M e t h o d s c a n o p e r a t e o n l y o n t h e d a t a s p e c i f i e d f o r t h e m b y t h e o b j e c t d e f i n i t i o n . A l s o , t h e p o t e n t i a l c o m p l e x i t y that arises f r o m t h e c o n n e c t i o n s o f b l o c k s t r a n s f o r m i n g d a t a is d i m i n i s h e d . Objects have the n o t i o n o f c h a n g e built into t h e m . Extension, modificat i o n , a n d a s e n s e o f g e n e r a l p u r p o s e are f e a t u r e s i n O O P . T h u s , a p p l i c a t i o n s that u s e o b j e c t s as t h e " s t r u c t u r e d b l o c k s " c a n i n c o r p o r a t e t h e n o t i o n o f c h a n g e i n their "structures" from the b e g i n n i n g .
13—Designing Windows Applications
Note: Object-oriented programming techniques d o not attempt to eliminate structure; instead they attempt to incorporate c h a n g e in structure. T h e best o f b o t h worlds? Perhaps.
Designing for Change Object-oriented design anticipates the evolution o f real-world systems a n d applications. Object-oriented W i n d o w s d e s i g n utilizes the consistency o f the W i n d o w s G U I . T h e interface remains similar a l t h o u g h the application e n c a p s u lates its r e s p o n s e t o b o t h t h e r e a l w o r l d a n d W i n d o w s i n m o d i f i a b l e o b j e c t s . A n y a p p l i c a t i o n o f e v e n m o d e s t c o m p l e x i t y c h a n g e s , s o a n t i c i p a t i n g c h a n g e is o n l y natural. In general, change c o m e s in o n e of two forms: external or internal to the a p p l i c a t i o n . A n e x t e r n a l c h a n g e is a c h a n g e i n t h e o u t s i d e w o r l d that r e q u i r e s a change in the application's behavior, so the application can continue to accurately represent the outside w o r l d . Simple e x a m p l e s include: 1. A d d i n g n e w p r i n t e r s o r g r a p h i c s t e r m i n a l s t o a n a p p l i c a t i o n ' s c a p a bility t o c o m m u n i c a t e w i t h d e v i c e s . 2. A d d i n g d e s k t o p p u b l i s h i n g b e h a v i o r t o a w o r d - p r o c e s s i n g a p p l i c a t i o n . S t r u c t u r e d d e s i g n t e c h n i q u e s , e v e n w i t h o u t O O P , are e x p e r t at f o c u s i n g o n t h e s e k i n d s o f c h a n g e s . N o t i c e that W i n d o w s a l r e a d y s p e c i a l i z e s i n t h e s e k i n d s o f p r o b l e m s f o r a n a p p l i c a t i o n . D e v i c e - i n d e p e n d e n c e is a c e n t r a l t e n e t o f Windows. A n i n t e r n a l c h a n g e is a c h a n g e i n t h e w a y y o u ( a n d s u b s e q u e n t l y t h e application) handle a p r o b l e m . N o t h i n g has to c h a n g e in the outside w o r l d for y o u to have a better idea h o w an application works or handles the p r o b l e m . This c h a n g e is b e t w e e n y o u a n d t h e a p p l i c a t i o n , s e p a r a t e f r o m t h e p r o b l e m itself. Y o u r r e a l i z a t i o n o f a p r o b l e m m i g h t s i m p l y arise f r o m y o u r u s i n g t h e a p p l i c a t i o n , f r o m r e s e a r c h , o r (in v e r y s p e c i a l c a s e s ) f r o m a s t r o k e o f d e s i g n g e n i u s . F o r e x a m p l e , y o u m i g h t r e w r i t e a sort a l g o r i t h m t o i n c r e a s e its s o r t i n g speed w h e n the n u m b e r of items exceeds s o m e threshold. Y o u also might r e o r g a n i z e y o u r c o d e s o that it m a k e s m o r e s e n s e t o a n o t h e r p r o g r a m m e r . Finally, y o u m i g h t d e c i d e that a n e n t i r e l y d i f f e r e n t d e s i g n a p p r o a c h is b e t t e r . Y o u m i g h t d i s c o v e r (by r e u s i n g a n a p p l i c a t i o n i n a n e w s i t u a t i o n ) that a t y p e y o u c r e a t e d f o r a n a p p l i c a t i o n c a n b e i m p r o v e d b y r e d e s i g n i n g it o r b y r e c o m p o s i n g it i n t o a d i f f e r e n t g r o u p o f o b j e c t s . S t r u c t u r e d t e c h n i q u e s (witho u t O O P ) i m p l i c i t l y a s s u m e that y o u h a v e a c o m p l e t e u n d e r s t a n d i n g o f t h e a p p l i c a t i o n a n d t h e w o r l d it r e p r e s e n t s b e f o r e y o u b e g i n c o d i n g it, a n d that t h e
389
390
Part I I — A d v a n c e d T o p i c s
p r o g r a m m e r or designer either d o e s not m a k e mistakes or learns from those mistakes. I n short, structured techniques d o not l e n d themselves well to internal changes. O b j e c t - o r i e n t e d p r o g r a m m i n g l a n g u a g e s s u c h as T u r b o P a s c a l f o r W i n d o w s a t t e m p t t o offer t h e b e s t o f b o t h w o r l d s , w i t h t e c h n i q u e s f o r c r e a t i n g a p p l i c a t i o n s that c a n a d a p t easily t o e x t e r n a l o r i n t e r n a l c h a n g e s . If y o u ' r e u s i n g O O P f o r y o u r a p p l i c a t i o n d e s i g n , y o u a n d y o u r i d e a s c a n g r o w easily as t h e needs of the users of your application grows. Y o u d o not p r e s u m e to k n o w e v e r y t h i n g a b o u t t h e a p p l i c a t i o n a n d its " u n k n o w n " u s e r s b e f o r e y o u b e g i n t o c o d e . Y o u c a n n o t k n o w e v e r y t h i n g a b o u t a n y t h i n g that is t h e least bit c o m p l e x . Y e t that is e x a c t l y w h a t m a n y a p p l i c a t i o n d e s i g n p h i l o s o p h i e s h a v e a s s u m e d all a l o n g . A p p l i c a t i o n p r o j e c t s d o n o t u s u a l l y b e c o m e disasters d u r i n g a p p l i c a t i o n development. Afterward, w h e n the worlds, the users, or the designers' and programmers' understanding of the application changes, they can b e c o m e d i s a s t e r s . T y p i c a l l y , a p p l i c a t i o n s d o n o t e v o l v e ; t h e y drift t o w a r d o b s o l e s c e n c e as t h e y b e c o m e less a n d less a p p r o p r i a t e f o r t h e n e w v e r s i o n o f t h e p r o b l e m s t h e y w e r e s u p p o s e d t o s o l v e . If a p p l i c a t i o n s are a p p r o p r i a t e l y d e s i g n e d a r o u n d objects, they have a g o o d c h a n c e to survive. F o r e x a m p l e , c o n s i d e r y o u r s e l f a n d h o w y o u interact w i t h t h e w o r l d . Y o u b e g i n by collecting the best information y o u can, a n d t h e n y o u create (suppose d l y i n y o u r b r a i n ) a m o d e l o f t h e w o r l d b a s e d o n that i n f o r m a t i o n . (This p r o c e s s is h a p p e n i n g , o f c o u r s e , at b r a i n - w a v e s p e e d . T h e n y o u b e h a v e b a s e d o n the m o d e l . Y o u r m o d e l is n o d o u b t f l a w e d ; m o r e o r less a p p r o p r i a t e o r g o o d e n o u g h for y o u t o survive ( s o u n d s i m p e r f e c t , scary, b u t a l m o s t a s s u r e d l y t r u e ) . A s y o u p r o c e e d t h r o u g h y o u r life, y o u g a i n e x p e r i e n c e ( e x t e r n a l factors) a n d h a v e n e w t h o u g h t s ( i n t e r n a l factors) that l e a d y o u t o c h a n g e y o u r c a r e f u l l y b u i l t , f l a w e d m o d e l . Y o u might even develop multiple models to represent the world's various aspects a n d complexities. M a n y of these m o d e l s y o u regularly update in response to n e w technology, n e w programming techniques. For example, y o u r perception of h o w a compiler works or the ways y o u c o m m u n i c a t e can l e a d y o u t o c h a n g e y o u r m o d e l . O t h e r m o d e l s , p e r h a p s less d e p e n d e n t o n n e w t e c h n i q u e s , m i g h t c o n t i n u e t o w o r k , a n d y o u m i g h t s e l d o m (if ever) u p d a t e them. I n this s c e n a r i o , y o u r life c o n s i s t s o f m o d i f y i n g p a r t s o f y o u r m o d e l (in response to n e w external and internal information), a n d not modifying other p a r t s . Y o u are c o n t i n u a l l y l e a r n i n g f r o m y o u r m o d e l , a n d y o u c h a n g e t h e m o d e l a c c o r d i n g l y . T y p i c a l l y , if a n y m o d e l s t o p s c h a n g i n g , c h a n c e s are that it n o l o n g e r is i n s t e p w i t h t h e w o r l d . I n o n e s e n s e , a m o d e l is a n i n d i c a t o r o f l e a r n i n g and process.
1 3 — D e s i g n i n g W i n d o w s Applications
A n a p p l i c a t i o n is a n e x p r e s s i o n o f y o u r c u r r e n t u n d e r s t a n d i n g o f a n e x t e r n a l p r o b l e m a n d y o u r ability t o r e p r e s e n t it w i t h its s o l u t i o n s . T h u s , t h e d e s i g n a n d t h e e x p r e s s i o n o f t h e d e s i g n are i n e x o r a b l y c o n n e c t e d . T h e p r o b l e m c h a n g e s ; y o u r v i e w o f t h e p r o b l e m c h a n g e s ; a n d y o u r ability t o d e s i g n a n d develop an application changes. A g o o d design philosophy (whether for W i n d o w s or not) must support a v i e w that a n t i c i p a t e s c h a n g e . H e r e are a f e w i d e a s t o k e e p i n m i n d w h e n y o u are d e s i g n i n g a p p l i c a t i o n s : 1. A c k n o w l e d g e that y o u c a n n o t k n o w e v e r y t h i n g a b o u t a p r o b l e m o r a n a p p l i c a t i o n b e f o r e y o u d e s i g n it. D o n o t e v e n try. A c c e p t that t h e r e are s o m e t h i n g s a b o u t a n a p p l i c a t i o n that y o u c a n l e a r n o n l y b y d e s i g n i n g a n d u s i n g it. 2. T r y t o g e t s o m e f o r m o f t h e a p p l i c a t i o n w o r k i n g as s o o n as p o s s i b l e , and use each application forerunner to improve your understanding of the p r o b l e m and application. Y o u r early v e r s i o n s o f t h e a p p l i c a t i o n m i g h t b e o n l y v a g u e i m i t a t o r s o f f u t u r e — m o r e p e r f e c t — v e r s i o n s . Let y o u r a p p l i c a t i o n s reflect t h e e v o l u t i o n o f y o u r i d e a s . R e f i n e a n d m o d i f y as y o u l e a r n m o r e . O b j e c t oriented programming encourages change. Use objects to explore. A n a d d i t i o n a l , a n d p e r h a p s s u b t l e , a s p e c t o f o b j e c t - o r i e n t e d d e s i g n is that it e n c o u r a g e s y o u n o t t o s p e n d t o o m u c h t i m e c r e a t i n g a n a p p l i c a t i o n . It e n c o u r a g e s y o u n o t t o try t o s o l v e p r o b l e m s that n e v e r arise. A l s o , o b j e c t - o r i e n t e d d e s i g n t e n d s t o i s o l a t e t h e effects o f o n e part o f a s y s t e m f r o m o t h e r s s o that c h a n g i n g o n e part o f a n a p p l i c a t i o n s h o u l d not disrupt other parts. 3. P l a n t o c h a n g e t h e d e s i g n , n o t just t h e a p p l i c a t i o n , as y o u g o . T h i s d o e s n o t m e a n " t h r o w a w a y parts r e c k l e s s l y , " b u t r a t h e r "start s o m e p l a c e r e a s o n a b l e , a n d let t h e d e s i g n g r o w as y o u l e a r n a b o u t t h e p r o b l e m a n d t h e a p p l i c a t i o n . " I n o t h e r w o r d s , a v o i d static d e s i g n s . A s s u m e f r o m t h e b e g i n n i n g that t h e a p p l i c a t i o n h a s t o c h a n g e . 4. E x p e c t t o m a k e m i s t a k e s . T h e b e s t w a y t o f i n d o u t w h e t h e r y o u h a v e m a d e a m i s t a k e is t o u s e t h e a p p l i c a t i o n . C h a n c e s are that y o u r m i s t a k e s c a n b e i s o l a t e d i n s i n g l e o b j e c t s , a n d t h u s y o u d o n o t h a v e t o t h r o w e v e r y t h i n g a w a y at o n c e . I n s t e a d , y o u m o d i f y t h e a p p l i c a t i o n , part b y part, t o reflect t h e e v o l u t i o n o f y o u r l e a r n i n g a b o u t t h e a p p l i c a t i o n a n d its u s e r s .
391
392
Part I I — A d v a n c e d T o p i c s
Object-Oriented Application Design It w o u l d b e s o - o - o n i c e , b u t u n f o r t u n a t e l y s o - o - o u n e x p e c t e d , if p r o g r a m m e r s a n d users h a d perfect k n o w l e d g e about a n application o r the p r o b l e m the a p p l i c a t i o n a d d r e s s e s . U n f o r t u n a t e l y , this is s e l d o m t h e c a s e . First, y o u p r o b a b l y c a n n o t d e l u d e y o u r s e l f i n t o b e l i e v i n g that y o u k n o w everything about a n application o r p r o b l e m . S e c o n d , the application y o u are developing a n d the techniques (the compilers, the languages, the hardware) y o u a r e u s i n g t o d e s i g n t h e a p p l i c a t i o n a r e e v o l v i n g as w e l l . Y o u a p p r o x i m a t e , a n t i c i p a t e , s p e c u l a t e , a n d a d d n e w t o o l s t o y o u r t o o l b o x at e v e r y t u r n . N a t u r a l l y , y o u w a n t y o u r a p p l i c a t i o n s t o reflect y o u r n e w p o w e r t o o l s . O n the m o r e personal side, y o u often make two convenient (and probably erroneous) approximations: 1. Y o u , t h e d e s i g n e r , c o m p l e t e l y u n d e r s t a n d t h e p r o b l e m b e f o r e b e g i n ning the design. 2. U s e r s r e a d w h a t e v e r i n f o r m a t i o n y o u g i v e t h e m b e f o r e u s i n g t h e a p p l i c a t i o n , a n d t h u s k n o w t h e a p p l i c a t i o n w e l l b e f o r e firing it u p . ( D e m a n d i n g this k i n d o f p e r f e c t i o n f r o m yourself, t h e a p p l i c a t i o n , o r t h e u s e r s s i m p l y is n o t s e n s i b l e . ) During development, object-oriented design encourages y o u to a d d , c h a n g e , a n d d e l e t e o b j e c t s at a n y t i m e — w h e n e v e r t h e m o o d m o v e s y o u . It's a s s u m e d t h a t , b e c a u s e e v e r y p r o b l e m is i n p r o g r e s s , e v e r y a p p l i c a t i o n a d d r e s s i n g a p r o b l e m is i n p r o g r e s s ; it's d y n a m i c . F o r e x a m p l e , s u p p o s e that y o u a r e d e s i g n i n g a n e d i t o r . Y o u b e g a n ( s e n s i b l y e n o u g h ) b y c r e a t i n g a w i n d o w e d i t o r t y p e , w h i c h c a n p r o c e s s text t h r o u g h a b u f f e r , m o v e a c u r s o r a r o u n d i n t h e b u f f e r , f i n d text, insert a n d d e l e t e text, a n d s o o n . A s t h e a p p l i c a t i o n p r o g r e s s e s ( a n d t h e t y p e d e f i n i t i o n d e v e l o p s ) , s o d o e s t h e n e e d t o test it. Y o u d e c i d e that t h e s i m p l e s t w a y t o test t h e a p p l i c a t i o n is t o w r i t e t h e text i n t h e b u f f e r t o a file a n d r e a d it b a c k f r o m t h e file t o t h e b u f f e r . T o m a k e a w i n d o w e d i t o r file a w a r e , y o u m u s t g i v e it s o m e k n o w l e d g e o f i n s e r t i n g a n d r e t r i e v i n g text f r o m files. T h e file h a s t o u n d e r s t a n d h o w t o o p e n a n d c l o s e files, h o w t o r e c o g n i z e t h e e n d o f l i n e s a n d t h e e n d o f files, a n d so o n . Y o u c a n a d d streams a n d whatever else y o u want t o t h e editor. T h e n y o u s h o u l d b e g i n t e s t i n g t h e f e a t u r e s o f t h e f ile_editor, o n e b y o n e . S e v e r a l t h i n g s o c c u r . First, b y u s i n g t h e a p p l i c a t i o n (as a file e d i t o r ) , y o u (the d e s i g n e r " t u r n e d " u s e r ) b e g i n t o s e e p o s s i b i l i t i e s y o u h a d n o t i m a g i n e d b e f o r e . Y o u m i g h t d e c i d e that m o r e t h a n o n e file c a n b e o p e n e d at a t i m e , that t h e files c a n e x c h a n g e i n f o r m a t i o n , a n d that t h e size o f t h e files is i m p o r t a n t . I n s h o r t , t h e f i l e e d i t o r t y p e is u n d e r g o i n g a " r e u s e test."
13—Designing Windows Applications
I n a r e u s e test, y o u a s k , " D o e s t h e a p p l i c a t i o n a d a p t easily t o n e w s i t u a t i o n s ? " If y o u d e c i d e that it d o e s n o t , y o u b e g i n m o d i f y i n g t h e t y p e t o m a k e it m o r e g e n e r a l . I n this s c e n a r i o , t h e a p p l i c a t i o n b e c o m e s t o o g e n e r a l a n d fails t h e " c o m p l e x i t y test." Y o u h a v e e x p a n d e d t h e a p p l i c a t i o n t o o m u c h ; it is t o o c o m p l e x . S u d d e n l y , b e c a u s e y o u a r e r u n n i n g o u t o f m e m o r y , y o u h a v e t o k e e p b e t t e r tabs o n m e m o r y u s e . K e e p i n g tabs m e a n s that y o u h a v e t o c h a n g e s o m e t h i n g e l s e , w h i c h c a u s e s a f e w m o r e p r o b l e m s that affect o t h e r p a r t s o f t h e a p p l i c a t i o n . T h e f ile_editor t y p e n o w is failing t h e " o v e r a m b i t i o u s o b j e c t test." It tries t o d o t o o m u c h , a n d as a result c a n n o t b e r e u s e d . A n e v o l v e d t y p e , e s p e c i a l l y o n e that h a s s u r v i v e d several r e d e s i g n s , o f t e n b e c o m e s t o o c o m p l e x f o r f u r t h e r e v o l u t i o n . I f t h e o b j e c t b e g i n s t o c o n f u s e y o u , it p r o b a b l y h a s a d e s i g n p r o b l e m . C h e c k it o u t a n d r e d e s i g n it, if y o u h a v e t o . I n this e x a m p l e , y o u d i s c o v e r t h e s i m p l e , t i g h t e r d e s i g n that y o u s h o u l d h a v e c r e a t e d ; a t e x t b u f f er t y p e that c a n h a n d l e b i g c h u n k s o f text a n d k e e p track o f t h e m e m o r y safety p o o l . F o r e x a m p l e , it c h e c k s f o r l o w m e m o r y c o n d i t i o n s b e f o r e it r e a d s t h e e n t i r e file. Y o u d e c i d e t o m a k e this l o w - l e v e l m e m o r y a w a r e n e s s a part o f t h e b a s e file e d i t o r . N o w y o u d e r i v e a m u l t i p l e file e d i t o r f r o m this s m a r t e r , still single-file e d i t o r that c a n k e e p track o f m e m o r y u s e . T h i s t y p e n o w c a n b e u s e d as a b a s e t y p e f o r o t h e r k i n d s o f file e d i t o r s . T h e p o i n t o f this h y p o t h e t i c a l r a m b l e is t h i s : y o u d e s i g n , e x p e r i m e n t , a n d c r e a t e every t i m e y o u interact w i t h t h e a p p l i c a t i o n o r p r o b l e m . O n l y i n t h e simplest cases are y o u able to u n d e r s t a n d the p r o b l e m completely a n d get t h e d e s i g n right t h e first t i m e .
A Tao of Windows Y o u m i g h t n o t k n o w h o w t o p u t a p a r t i c u l a r d a t a field o r m e t h o d i n a t y p e . Y o u m i g h t t h i n k that it t a k e s y e a r s o f e x p e r i e n c e t o d e s i g n t y p e s p r o p e r l y . T o h e l p d i s p e l this m y t h a n d t o k e e p y o u f r o m w a s t i n g t o o m u c h t i m e o n early d e s i g n d e c i s i o n s , t h e b o o k c o v e r s a relatively s i m p l e , b u t g o o d b e g i n n i n g t e c h n i q u e f o r describing the creation and d e v e l o p m e n t of types. This technique (based o n the d e s i g n p h i l o s o p h y r e c o m m e n d e d i n The Tao of Objects, m y first b o o k ) r e c o g n i z e s five s t a g e s o f o b j e c t d e s i g n : 1. Object discovery. Try t o determine w h i c h objects solve the p r o b l e m s your application addresses. B e m o r e concerned with the boundaries and the gross interactions b e t w e e n objects than with h o w the objects work. 2. Object construction. A s y o u start c r e a t i n g o b j e c t s , y o u d i s c o v e r that y o u w a n t d a t a fields a n d m e t h o d s t o m a k e t h e o b j e c t w o r k p r o p e r l y . Y o u a l s o m i g h t d i s c o v e r that y o u w a n t o t h e r o b j e c t s e i t h e r as s u b j e c t s
393
394
Part I I — A d v a n c e d T o p i c s
(object m e m b e r s o f y o u r object), or to w o r k with s o m e object in y o u r a p p l i c a t i o n . A n e x c e l l e n t t e c h n i q u e d u r i n g o b j e c t c r e a t i o n is t o d e v e l o p test a p p l i c a t i o n s ( m i n i - a p p l i c a t i o n s ) for e a c h t y p e y o u c r e a t e . A s y o u w r i t e t h e test a p p l i c a t i o n s , y o u m i g h t u n c o v e r f u r t h e r t y p e r e q u i r e ments. 3. Application construction. As y o u collect objects in the application, the needs o f the application might require n e w behavior in existing objects, or entirely n e w objects. 4. Application extension. A p p l i c a t i o n e x t e n s i o n is a n i n t e g r a l part o f a p p l i c a t i o n d e v e l o p m e n t . B e h a v i o r is f o c u s e d i n o b j e c t s . O b j e c t s c h a n g e in order to c h a n g e applications. 5. Object reuse. W h e n y o u u s e o l d o b j e c t t y p e s t o b u i l d n e w a p p l i c a t i o n s , n e w n e e d s b e n d a n d s t r e t c h t h e d e s i g n o f y o u r o l d o b j e c t t y p e s . If a n o l d t y p e d o e s n o t fit easily i n t o a n e w s i t u a t i o n , it s h o w s u p i n t h e s e p r o s p e c t i v e n e w a p p l i c a t i o n s , a n d y o u s e e t h e p a r t s that h a v e t o b e c h a n g e d . T h e m o s t u s e f u l o b j e c t s are u s u a l l y t h e " e v o l v e d " o n e s that h a v e g o n e t h r o u g h several p r o j e c t s . N o t i c e that at e a c h s t a g e o f a p p l i c a t i o n d e v e l o p m e n t y o u g e t n e w i n f o r m a t i o n t o g u i d e y o u t h r o u g h t y p e d e s i g n . A l t h o u g h it w o u l d b e difficult a n d t i m e - c o n s u m i n g t o a n t i c i p a t e this i n f o r m a t i o n i n a " p r e - p r e e m p t i v e " d e s i g n , it c o m e s t o y o u n a t u r a l l y as y o u p a s s t h r o u g h t h e a p p r o p r i a t e s t a g e . A l t h o u g h this style o f O O P d e s i g n u s e s a d i f f e r e n t p h i l o s o p h y t h a n p a s t s t r u c t u r e d m e t h o d o l o g i e s , it is n o t a b i g d e a l t o i m p l e m e n t . ( M a n y p r o g r a m m e r s t e n d t o w o r k this w a y r e g a r d l e s s o f w h a t m e t h o d o l o g y t h e y are s u p p o s e d t o b e f o l l o w i n g . ) A s a g u i d e l i n e : d o n ' t f o r c e y o u r s e l f t o k n o w e v e r y t h i n g at t h e b e g i n n i n g . I n s t e a d , a l l o w y o u r s e l f t o l e a r n as y o u g o a l o n g .
Object Discovery T h e first o f t h e five s t a g e s , t h e i c e b r e a k e r , d e s e r v e s a c l o s e r l o o k . W h a t m e t h o d s s h o u l d y o u u s e t o d i s c o v e r o b j e c t s ? H e r e are a f e w g u i d e l i n e s : • L o o k for t h e " e x t e r n a l f a c t o r s " that are n e c e s s a r y for i n t e r a c t i o n s between objects and the world outside the application. Y o u might d i s c o v e r s o m e d a t a f i e l d s a n d m e t h o d s at this p o i n t , b u t y o u m o s t l y just d i s c o v e r t h e o b j e c t s t h e m s e l v e s . • F i n d n a t u r a l b o u n d a r i e s . If y o u t h i n k o f s o m e t h i n g w i t h b o u n d a r i e s i n t h e w o r l d , c h a n c e s are that it s h o u l d b e a b o u n d a r y i n a n o b j e c t as w e l l . F o r e x a m p l e , t h e b o u n d a r y b e t w e e n m e m o r y a n d d i s k is o f t e n r e f l e c t e d as a b o u n d a r y i n y o u r a p p l i c a t i o n .
13—Designing Windows Applications
• S e e k t h e b e h a v i o r a n d d a t a that are d u p l i c a t e d i n t h e a p p l i c a t i o n . F o r e x a m p l e , a k e y b o a r d is a c o l l e c t i o n o f b u t t o n s , s o " b u t t o n " is a n obvious object. A simulation m i g h t consist o f customers a n d b a n k tellers. A t r u c k has f o u r w h e e l s , a s p a r e , f o u r d o o r s , a n d s o o n . • F l e s h o u t t h e least c o m m o n d e n o m i n a t o r s o f a n a p p l i c a t i o n (its s m a l l e s t u n i t s ) . F o r e x a m p l e , if y o u are m a n i p u l a t i n g text, t h e s m a l l e s t u n i t is e i t h e r a character, a w o r d , a l i n e , o r a g r o u p o f text w i t h t h e s a m e a t t r i b u t e s ; d e p e n d i n g o n how y o u i n t e n d t o u s e t h e text. • Try t o i m a g i n e n e w s i t u a t i o n s i n w h i c h y o u m i g h t u s e t h e t y p e . D o y o u t h i n k it w o r k s t h e r e a n d a d a p t s easily? F o r e x a m p l e , c o n s i d e r a b i g g e r v e r s i o n o f y o u r a p p l i c a t i o n . D o e s it w o r k ? • S e p a r a t e t h e a s p e c t s o f t h e a p p l i c a t i o n that c h a n g e f r o m t h o s e that probably will not c h a n g e . • M a k e a list o f t h e d a t a that y o u r a p p l i c a t i o n has t o k n o w a b o u t . L o o k f o r d a t a that s e e m s t o b e l o n g t o g e t h e r . C o l l e c t t h e s e d a t a e l e m e n t s into an object. • L o o k for b e h a v i o r y o u w a n t t o hide o r d a t a y o u w a n t t o p r o t e c t f r o m careless m a n i p u l a t i o n . This k i n d o f behavior a n d data usually b e l o n g s inside an object. • L o o k for t h e c o m m o n i n t e r f a c e s b e t w e e n o b j e c t s . F i n d o u t w h a t o b j e c t s have i n c o m m o n . P u t c o m m o n a s p e c t s i n t o a n abstract b a s e type. • L o o k for i n i t i a l i z a t i o n a n d c l e a n u p activities. T h e s e activities s h o u l d b e handled b y c o n s t r u c t o r s a n d d e s t r u c t o r s . I n i t i a l i z a t i o n a n d c l e a n u p m i g h t help y o u d i s c o v e r t y p e s .
Star Wars and Dances: The Sequel As a n e x a m p l e , c o n s i d e r a v i d e o - s t o r e m a n a g e m e n t a p p l i c a t i o n that w a s d i s c u s s e d i n The Tao of Objects. C o n s i d e r this v e r s i o n a s e q u e l t o that o n e , b e c a u s e t h e r e has b e e n a l o n g t i m e t o reconsider t h e p r o b l e m a n d g i v e it a n e w Windows f a c e . If y o u have n o t read t h e b o o k , d o n ' t w o r r y , this c h a p t e r w i l l b r i n g y o u u p t o snuff. T h e v i d e o - s t o r e m a n a g e m e n t a p p l i c a t i o n tries t o s o l v e t h e p r o b l e m s i n h e r e n t i n s e t t i n g u p a u s e r - d r i v e n v i d e o s t o r e . T h e v i d e o b u f f (that is, t h e user) c o m e s i n t o t h e store w i t h a t y p e o f v i d e o i n m i n d , b u t he d o e s n o t k n o w t h e title o f any specific v i d e o .
395
396
Part I I — A d v a n c e d T o p i c s
T y p i c a l l y i n this s c e n a r i o , t h e u s e r w a l k s a r o u n d t h e s t o r e a n d c h e c k s t h e various video boxes, w h i c h contain a three- or four-paragraph description of w h a t t h e m o v i e d i s t r i b u t o r w a n t s t h e u s e r t o t h i n k . (MovieMagic, Part3 is a Star Wars c l o n e , w i t h o v e r t o n e s o f Lawrence of Arabia a n d Dances with Wolves r o l l e d i n t o o n e fine p i c t u r e . E v e r y s i n g l e r e v i e w e r , at least all t h e o n e s m e n t i o n e d o n t h e b o x , l o v e d it.) W h a t t h e u s e r u n f o r t u n a t e l y d o e s n o t l e a r n f r o m t h e b o x is w h a t t h e v i d e o is a b o u t , t h e l e v e l o f v i o l e n c e , w h e t h e r o t h e r f o l k s h a v e e n j o y e d t h e v i d e o , a n d n o t just w h a t a f e w c a r e f u l l y s e l e c t e d , a n d c a r e f u l l y q u o t e d , critics t h o u g h t . N o w c o n s i d e r a n alternative s c e n a r i o . S u p p o s e that t h e u s e r c a n w a l k i n t o a v i d e o s t o r e i n w h i c h t h e r e are n o s h e l v e s filled w i t h v i d e o b o x e s . I n s t e a d , s h e s t e p s u p t o a c o m p u t e r (or t o a p e r s o n o p e r a t i n g a c o m p u t e r ) a n d says, " T o d a y I a m i n t h e m o o d f o r a m o v i e w i t h a r o m a n t i c t h e m e set i n t h e n e a r f u t u r e , w h i c h m y favorite r e v i e w e r l i k e d , a n d w h i c h h a s n o v i o l e n c e , a n d w h i c h h a s a s o c i a l t h e m e w i t h m o d e r a t e levels o f n u d i t y . " T h e c o m p u t e r t h e n c h e c k s t h e u s e r ' s file t o s e e w h a t s h e h a s v i e w e d o r l i k e d i n t h e past a n d retrieves t h e v i d e o titles that s h e h a s n o t c h e c k e d o u t b e f o r e , m i n u s t h e o n e s that are a l r e a d y c h e c k e d o u t . T h e c o m p u t e r n u m b e r s t h e m corresponding to her personal profile. S h e c a n g e t e v e n m o r e i n f o r m a t i o n a b o u t e a c h o f t h e titles; i n c l u d i n g t h e actors, directors, a n d so o n ; reviews o f the videos; biographies o f the p e o p l e i n v o l v e d i n m a k i n g t h e m o v i e ; a n d e v e n g r a p h i c d e s c r i p t i o n s (bit m a p s , a n d s o on) depicting s o m e aspect of the video. In other words, the user gets a m o r e detailed view o f the videos in the store based o n the information users supply. (It m i g h t e v e n b e s o m u c h f u n t o p l a y a r o u n d w i t h t h e v i d e o l o o k - u p s y s t e m that v i d e o l o o k - u p b e c o m e s an arcade fad.) W h e n t h e u s e r d e c i d e s o n a v i d e o , t h e c l e r k g e t s it f r o m a stack ( n o t i c e that t h e s h e l f s p a c e r e q u i r e d f o r a s t o r e like this is s m a l l e r ) a n d u s e s a b a r - c o d e reader to enter the n u m b e r into the computer, w h i c h generates a receipt a n d d o e s all t h e n e c e s s a r y b o o k k e e p i n g . Part o f this is o b v i o u s l y a n e l a b o r a t e d a t a b a s e s y s t e m ( w h i c h h a s t o b e easily u p d a t e d at r e g u l a r i n t e r v a l s , f r o m v a r i o u s s o u r c e s i n c l u d i n g t h e c u s t o m ers t h e m s e l v e s ) . Part o f it is t h e u s e r i n t e r f a c e , part t h e b a r - c o d e i n t e r f a c e , a n d part t h e b o o k k e e p i n g s y s t e m . Try t o d e s c r i b e this a p p l i c a t i o n u s i n g O O P . First, m a k e f o u r lists that r e p r e s e n t : 1.
Data
2.
Events
3.
Behavior
4. O b v i o u s o b j e c t s
13—Designing Windows Applications
T h e d a t a list c o n s i s t s o f i n f o r m a t i o n t h e a p p l i c a t i o n h a s t o k n o w o r r e m e m b e r . T h e e v e n t list c o n s i s t s o f e v e n t s that t h e a p p l i c a t i o n h a s t o r e s p o n d t o . T h e b e h a v i o r list is w h a t t h e a p p l i c a t i o n h a s t o d o . T h e o b v i o u s - o b j e c t s list i n c l u d e s a n y t h i n g that i m m e d i a t e l y s p r i n g s t o m i n d . F o r e x a m p l e , y o u k n o w f r o m t h e start y o u w a n t t o u s e a s t a n d a r d W i n d o w s a p p l i c a t i o n i n t e r f a c e that u s e s m e n u s a n d s t a n d a r d m o u s e clicks t o s e l e c t i t e m s f r o m t h e m e n u s . D o n o t try t o p e r f e c t t h e s e lists i n t h e b e g i n n i n g ; just w r i t e d o w n w h a t y o u c a n t h i n k of. R e m e m b e r that t h e act o f c r e a t i n g t h e a p p l i c a t i o n ( n o t t h e c r e a t i o n o f lists) e n s u r e s that t h e a p p l i c a t i o n is c o m p l e t e . T h e lists o n l y act as "instigators" to h e l p y o u discover the objects for y o u r application. By l o o k i n g at t h e lists, y o u s e e p a t t e r n s that s u g g e s t o b j e c t s . W h e n y o u d i s c o v e r e n o u g h o b j e c t s t o d e s c r i b e t h e a p p l i c a t i o n w i t h o u t t h e lists, t h r o w t h e lists away. F o r s o m e a p p l i c a t i o n s , t h e d a t a list g i v e s y o u t h e m o s t i n f o r m a t i o n , a n d it is easiest t o t h i n k o f i n f o r m a t i o n f o r that list. B e c a u s e W i n d o w s a p p l i c a t i o n s are p r i m a r i l y e v e n t - d r i v e n , y o u s h o u l d a n t i c i p a t e e v e n t s a n d r e s p o n s e s t o e v e n t s i n t h e s e lists. H o w y o u d e f i n e t h e s e lists d e p e n d s o n h o w y o u t h i n k a b o u t a p r o b l e m . I n g e n e r a l , h o w e v e r , it d o e s n o t m a t t e r m u c h h o w y o u o r d e r o r a s s e m b l e t h e s e lists, b e c a u s e all y o u are trying t o d o is d i s c o v e r t h e o b j e c t s f o r y o u r a p p l i c a t i o n s . S o m e o f t h e i t e m s o n t h e list m i g h t n o t e v e n h e l p y o u d i s c o v e r a n y objects, so y o u discard t h e m mercifully. A g a i n , r e m e m b e r : it is O K t o m a k e m i s t a k e s , a n d it is O K t o o m i t t h i n g s y o u m i g h t w a n t later. A n o b j e c t - o r i e n t e d a p p l i c a t i o n a l l o w s y o u t o easily m o d i f y t h e application w h e n y o u discover inconsistencies. B e c a u s e objects k e e p their data a n d behaviors to themselves, changes in the application tend to localize t h e m s e l v e s — a m a j o r p l u s as t h e a p p l i c a t i o n e v o l v e s . W h e n y o u m a k e t h e d a t a list, g r o u p t o g e t h e r d a t a i t e m s that y o u are fairly sure s h o u l d b e an object. For e x a m p l e , a "person" object probably contains data f i e l d s f o r n a m e , a d d r e s s , a g e , s e x , m e m b e r s h i p n u m b e r , a n d a list o f v i d e o s this p e r s o n h a s c h e c k e d o u t . It m i g h t m a k e s e n s e t o c o l l e c t all t h e s e f i e l d s i n a n object. W i n d o w s e v e n t s are a l m o s t as o b v i o u s as d a t a o r b e h a v i o r . A m o u s e , f o r e x a m p l e , g e n e r a t e s a n e v e n t that W i n d o w s r o u t e s t o t h e c o r r e c t w i n d o w . A m e n u s e l e c t i o n is a n e v e n t , a n d s o o n . B e c a u s e W i n d o w s a p p l i c a t i o n s d e p e n d s o m u c h o n e v e n t s s u c h as t h e m o u s e a n d m e n u s , it m a k e s s e n s e t o always k e e p events in the forefront. Behavior s h o u l d be responses to events. For e x a m p l e , y o u can i m p l e m e n t a context-sensitive h e l p system d e p e n d i n g o n t h e a p p l i c a t i o n ' s c u r r e n t c o n t e x t (or s t a t e ) . Every t i m e t h e u s e r c h a n g e s c o n t e x t (by m a k i n g a s e l e c t i o n f r o m a m e n u , f o r e x a m p l e ) , t h e " h e l p state c o n t e x t " c h a n g e s . W h e n t h e u s e r asks f o r h e l p , t h e t y p e o f h e l p g i v e n d e p e n d s o n t h e state (that is, t h e c o n t e x t ) . L o o k i n g at a c o l l e c t i o n o f e v e n t s o f t e n h e l p s y o u discover appropriate objects.
397
398
Part I I — A d v a n c e d T o p i c s
R e m e m b e r that this is a n p r o c e s s o f i t e r a t i o n ; a n a p p r o a c h i n t e n d e d o n l y to give y o u a f r a m e w o r k — s t e p s to f o l l o w to get y o u started. T h e framework m i g h t c h a n g e as y o u s k e t c h o u t t h e a p p l i c a t i o n , b u t i n t h e e n d it is u n i m p o r t a n t . Y o u r g o a l is t o d e t e r m i n e w h a t y o u r o b j e c t s s h o u l d b e a n d w h a t y o u w a n t . A s y o u fill i n t h e d e t a i l s , y o u d i s c o v e r n e w o b j e c t s a n d n e w r e l a t i o n s h i p s b e t w e e n o b j e c t s . T h a t ' s fine; that is h o w it is s u p p o s e d t o w o r k . For example, the video-store application might begin with the following f o u r lists:
Data List:
User Name Address User ID Video List (videos checked out in the past) User's Video Preference List
Video Name Quantity Price Structure Video Evaluation List
Rental Transaction Date User Video List
Business Report Date Range Data List Data Format Calculations
Event List:
User asks for some specific range of videos
13—Designing W i n d o w s Applications
User asks for further data on a specific video's Reviews Local opinions Box description/pictures Personnel: actors, directors, and so on. Theater runs and receipts User checks out video(s). User asks for computer-generated video selection based on the user's profile. User asks for best selling selection based on some level of popularity. User returns some or all checked out videos; possibly checks out more. User 'reviews' video just viewed. New videos arrive. New video data arrives. Old videos are discarded/replaced.
Behavior List:
Create new user profile. Create new video profile. Create video request profile; combine with user profile and search for appropriate videos. Create management report. Check out video. Check in video. Update profiles.
399
400
Part I I — A d v a n c e d T o p i c s
Obvious Objects:
Objects for connecting to Windows Database
(use collections)
Error Handler Time & Date Menus
(use ObjectWindows for these)
(use Error)
(use System)
(use ObjectWindows)
Dialogs
(use ObjectWindows)
File Dialogs
(use ObjectWindows)
Other controls, list boxes, buttons, and so on (use ObjectWindows)
Begin Discovering Objects B y this j u n c t u r e , y o u m i g h t h a v e g l i m p s e d s o m e o b j e c t s ; f o r e x a m p l e , i n t h e D a t a List w h e r e s o m e d a t a o b v i o u s l y b e l o n g s t o g e t h e r . I n t h e v i d e o e x a m p l e , User, V i d e o , R e n t a l T r a n s a c t i o n , B u s i n e s s R e p o r t , a n d s o o n , s u g g e s t o b j e c t s . B e h a v i o r u s u a l l y requires m o r e w o r k . T o h e l p y o u v i s u a l i z e , y o u m i g h t w a n t t o p u t t h e b e h a v i o r i n a " b l o c k c h a r t " as s h o w n i n f i g u r e 1 3 . 3 . N o w c o n s i d e r a n i n d i v i d u a l p a r t a n d b e g i n a n a l y z i n g it f o r o b j e c t s . T h i n k about: • What y o u w a n t that part t o p r o d u c e . (Will t h e b e h a v i o r l e a d t o t h e p r o d u c t i o n o f a n object; will the p r o d u c e r b e a n object?) • What parts d o y o u w a n t t o b e p o r t a b l e , o r at least retargetable (for e x a m p l e , u s e r i n t e r f a c e , o t h e r h a r d w a r e , o p e r a t i n g s y s t e m interface)? Put these in a n object. • D o e s t h e b l o c k d i a g r a m s u g g e s t a n y n e w b o u n d a r i e s that m i g h t reveal n e w o b j e c t s ? F o r e x a m p l e , i n a n e t w o r k i n g s y s t e m , t h e n e t w o r k is a boundary. Y o u might want t o create "transaction objects" t o s e n d across the network. • As y o u discover objects, consider what those objects have to know. S h o u l d t h e y m a i n t a i n this i n f o r m a t i o n t h e m s e l v e s , o r g e t it f r o m a n o t h e r o b j e c t ? T a k e n o t e o f a n y o b j e c t that g i v e s i n f o r m a t i o n , e v e n if it b e l o n g s i n a n o t h e r part.
13—Designing Windows Applications
Block D i a g r a m
Create
user
profile Check
Create video
out
profile C h e c k in
Create
Figure
video
video
video
request
13-3. A block chart.
Y o u don't want your objects to b e c o m e too complex. Just because you w a n t a p a r t i c u l a r o b j e c t d o e s n o t m e a n that t h e o b j e c t s h o u l d b e part o f a s i n g l e t y p e rather t h a n part o f a t y p e hierarchy. If y o u r o b j e c t s are t o o c o m p l e x , y o u w i l l n o t i c e this p r o b l e m d u r i n g t h e o b j e c t - c r e a t i o n p h a s e . A s y o u a d d a n d test f u n c t i o n s , t h i n g s s e e m t o " g o haywire" a n d "get o u t o f hand." It b e c o m e s difficult t o a d d n e w b e h a v i o r b e c a u s e t h e t y p e is m a n a g i n g t o o m u c h itself. T h i s is a n indication that t h e t y p e has t o b e f a c t o r e d into s m a l l e r s e c t i o n s a n d a s s e m b l e d t h r o u g h e i t h e r inheritance or composition. B y f a c t o r i n g t h e t y p e , y o u e n d u p w i t h several t y p e s , a n y o f w h i c h is e a s i e r t o implement b e c a u s e it is e a s i e r t o t h i n k a b o u t .
Wrap-up B y n o w y o u s h o u l d b e t h i n k i n g that d e s i g n i n g Windows a p p l i c a t i o n s is b o t h a n art a n d a s c i e n c e . C r e a t i n g a p p l i c a t i o n s , like art, requires m u c h interpretation o n t h e part o f t h e d e s i g n e r a n d artist. F i n d i n g , c r e a t i n g , a n d recasting objects requires b o t h artistic a n d e n g i n e e r i n g skills. O n t o p o f that, Windows is a G U I : ready-to-roll graphics. Y o u c r e a t e y o u r o b j e c t s f r o m t h e t i m e y o u start t h i n k i n g a b o u t t h e m . Writing t h e m is o n l y t h e o b v i o u s p h a s e o f c r e a t i o n . Y o u start w i t h t h e t y p e f r a m e w o r k , a n d t h e n a d d a n d test b e h a v i o r . D u r i n g a p p l i c a t i o n c o n s t r u c t i o n and extension, y o u may add more to t h e type.
401
402
Part I I — A d v a n c e d T o p i c s
T h u s , object design occurs t h r o u g h o u t the lifetime o f an application in all five p h a s e s o f a p p l i c a t i o n d e v e l o p m e n t : 1. O b j e c t d i s c o v e r y 2. O b j e c t c r e a t i o n 3. A p p l i c a t i o n c o n s t r u c t i o n 4. A p p l i c a t i o n e x t e n s i o n 5. O b j e c t r e u s e U s e r s o n l y p r e t e n d that t h e y c a n f o r c e d e s i g n t o o c c u r w h e n it is c o n v e n i e n t — i n t h e first p h a s e s o f a p r o j e c t — a n d n o t later. T h a t w r a p s u p this part o f t h e i n t r o d u c t o r y s t u d y o f W i n d o w s a p p l i c a t i o n d e v e l o p m e n t u s i n g t h e o b j e c t - o r i e n t e d t e c h n i q u e s o f T u r b o Pascal for W i n d o w s . I h o p e that y o u h a v e l e a r n e d at least this s m a l l p o i n t : t h e s o p h i s t i c a t e d t e c h n i q u e s i n T u r b o Pascal for W i n d o w s c a n h e l p y o u c r e a t e p r o d u c t i v e , c r e a t i v e , a n d flexible W i n d o w s a p p l i c a t i o n s that h a v e t h e b u i l t - i n c a p a c i t y t o e v o l v e as t h e p r o b l e m s t h e y a t t e m p t t o s o l v e i n e v i t a b l y e v o l v e . O b j e c t - o r i e n t e d p r o g r a m m i n g is b o t h a m e t h o d a n d a p h i l o s o p h y , a n d a n i m p o r t a n t t e c h n i q u e for d e v e l o p i n g e v e n t - d r i v e n W i n d o w s a p p l i c a t i o n s . W i n d o w s a n d o b j e c t s ( T u r b o Pascal style) a r e , s o m e say, a d r a m a t i c o n e two punch.
PART T H R E E
REFERENCES
A
REFERENCE
OBJECTWINDOWS OBJECTS T h i s r e f e r e n c e c h a p t e r is a n a l p h a b e t i c a l listing o f t h e O b j e c t W i n d o w s o b j e c t s :
TApplication TBufStream TButton TCheckBox TCollection TComboBox TControl TDialog TDlgWindow TDosStream TEdit TEmsStream TGroupBox
TListBox TMDIClient TMDIWindow TObject TRadioButton TScrollBar TScroller TSortedCollection TStatic TStrCollection TStream TWindow TWindowsObject
406
Part I I I — R e f e r e n c e s
TApplication TApplication is t h e b a s e a p p l i c a t i o n o b j e c t f o r all O b j e c t W i n d o w s a p p l i c a tions. E a c h O b j e c t W i n d o w s application derives a n application object type f r o m TAp plication i n o r d e r t o c o n s t r u c t a s p e c i f i c m a i n w i n d o w f o r t h e a p p l i c a t i o n .
Fields HAccTable KBHandlerWnd MainWindow Name Status
Methods Init CanClose Error ExecDialog InitApplication Initlnstance InitMainWindow MakeWindow MessageLoop ProcessAccels ProcessAppMsg ProcessDlgMsg ProcessMDIAccels Run SetKBHandler ValidWindow
Fields TApplication.HAccTable HAccTable: THandle; (read/write) HAccTable h o l d s a h a n d l e t o a W i n d o w s a c c e l e r a t o r - t a b l e r e s o u r c e ify o u d e f i n e o n e for t h e a p p l i c a t i o n .
A—ObjectWindows Objects
TApplication.KBHandlerWnd KBHandlerWnd: PWindowsOb j e c t ; ( r e a d o n l y ) KBHandle rWnd p o i n t s t o t h e c u r r e n t l y active w i n d o w if t h e w i n d o w ' s k e y b o a r d h a n d l e r m e c h a n i s m is e n a b l e d . ( T h e k e y b o a r d h a n d l e r m e c h a n i s m lets a w i n d o w c o n t a i n i n g controls process keyboard input in dialog fashion. If the k e y b o a r d h a n d l e r m e c h a n i s m is d i s a b l e d f o r t h e active w i n d o w , KBHandler is n i l .
TAppUcation.MainWindow MainWindow: PWindowsOb j e c t ;
(read/write)
MainWindow p o i n t s t o t h e a p p l i c a t i o n ' s m a i n w i n d o w , w h i c h s h o u l d b e i n s t a n t i a t e d b y y o u r a p p l i c a t i o n t y p e ' s InitMainWindow m e t h o d .
TApplication.Name Name h o l d s t h e a p p l i c a t i o n ' s n a m e .
TApplication.Status Status: Integer; Status i n d i c a t e s t h e c u r r e n t state o f a n a p p l i c a t i o n . If Status is g r e a t e r t h a n or e q u a l t o 0 , t h e n t h e a p p l i c a t i o n is o p e r a t i n g s u c c e s s f u l l y .
Methods TApplication.Init constructor Init(AName: PChar); (Override: sometimes) Constructs the application object. • C a l l s TOb j ect. Init • S e t s t h e g l o b a l v a r i a b l e Application t o @Self • S e t s t h e Name field t o AName • S e t s t h e HAccTable field a n d t h e Status field t o 0 • Initializes t h e MainWindow a n d t h e KBHandlerWnd fields t o n i l
407
408
Part I I I — R e f e r e n c e s
If t h e c u r r e n t i n s t a n c e is t h e first i n s t a n c e o f a n a p p l i c a t i o n , Init s e n d s a m e s s a g e t o InitApplication. I f InitApplication s u c c e e d s , Init s e n d s a m e s s a g e t o Initlnstance.
TApplication.CanClose function CanClose: Boolean; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s T r u e if it's O K f o r t h e a p p l i c a t i o n t o close. B y d e f a u l t , CanClose s e n d s a m e s s a g e t o t h e CanClose m e t h o d o f its m a i n w i n d o w a n d returns that m e t h o d ' s return v a l u e . Rather t h a n override TApplication. CanClose, o v e r r i d e y o u r a p p l i c a t i o n ' s m a i n w i n d o w ' s CanClose method.
TApplication.Error procedure Error(ErrorCode: Integer); virtual; ( O v e r r i d e : s o m e t i m e s ) TApplication.Error p r o c e s s e s t h e e r r o r s i d e n t i f i e d b y t h e e r r o r v a l u e p a s s e d i n ErrorCode. T h e s e e r r o r s a r e g e n e r a t e d b y t h e a p p l i c a t i o n o b j e c t , a w i n d o w , o r a d i a l o g o b j e c t . E r r o rCod e c a n b e a n e r r o r y o u define o r o n e o f t h e following errors, w h i c h are detected a n d reported b y ObjectWindows: em_0ut0fMemory em_InvalidClient em_InvalidChild em_InvalidMainWindow em_InvalidWindow If t h e r e ' s a n e r r o r , TApplication.Error d i s p l a y s t h e e r r o r c o d e i n a m e s s a g e b o x a n d asks t h e u s e r w h e t h e r it's O K t o p r o c e e d . I f n o t , a p p l i c a t i o n e x e c u t i o n halts.
TApplication.ExecDialog function ExecDialog(ADialog: PWindowsObject): Integer; virtual ( O v e r r i d e : n e v e r ) After c h e c k i n g ValidWindow, ExecDialog e x e c u t e s t h e m o d a l d i a l o g o b j e c t p a s s e d i n ADialog b y s e n d i n g a m e s s a g e t o t h e d i a l o g o b j e c t ' s Execute m e t h o d . If m e m o r y is l o w o r t h e d i a l o g c a n n o t b e e x e c u t e d , ExecDialog d i s p o s e s o f the object a n d returns a negative error status.
A—ObjectWindows Objects
TApplication.InitApplication procedure
InitApplication;
virtual;
( O v e r r i d e : s o m e t i m e s ) H a n d l e s i n i t i a l i z a t i o n f o r t h e first i n s t a n c e o f a n application. Because T A p p l i c a t i o n . I n i t A p p l i c a t i o n doesn't d o anything, your a p p l i c a t i o n o b j e c t t y p e o v e r r i d e s T A p p l i c a t i o n . I n i t A p p l i c a t i o n if it n e e d s t o initialize a n y a p p l i c a t i o n - s p e c i f i c b e h a v i o r .
TAppUcation.InitMainWindow procedure
InitMainWindow;
virtual;
( O v e r r i d e : always) Y o u r a p p l i c a t i o n always o v e r r i d e s I n i t M a i n W i n d o w construct a main w i n d o w object. For example: procedure
to
MyApplication.InitMainWindow;
begin MainWindow end;
: = New(PMainWindow,
Init('Window
Caption'));
B y d e f a u l t , I n i t M a i n W i n d o w c r e a t e s a TWindow o b j e c t w i t h o u t a title.
TApplication.MakeWindow f u n c t i o n MakeWindow(AWindowsObject: PWindowsObj e c t ; v i r t u a l ;
PWindowsObject):
( O v e r r i d e : n e v e r ) After c h e c k i n g t h e safety p o o l , T A p p l i c a t i o n . MakeWindow tries t o c r e a t e a w i n d o w o r m o d e l e s s d i a l o g e l e m e n t a s s o c i a t e d w i t h t h e o b j e c t p a s s e d i n AWindowsOb j e c t . If m e m o r y is l o w , o r if t h e w i n d o w o r d i a l o g c a n n o t b e c r e a t e d , MakeWindow d i s p o s e s o f t h e o b j e c t a n d r e t u r n s n i l . If s u c c e s s f u l , it r e t u r n s AWindowsOb j e c t .
TApplication.MessageLoop procedure
MessageLoop;
virtual;
( O v e r r i d e : n e v e r ) C o n t r o l s a n a p p l i c a t i o n ' s g e n e r a l m e s s a g e l o o p that r u n s t h r o u g h o u t the lifetime of the application. T A p p l i c a t i o n . M e s s a g e L o o p sends a message to P r o c e s s A p p M s g , which handles the special messages required for modeless dialogs, accelerators, and M D I accelerators.
409
410
Part I I I — R e f e r e n c e s
TApplication.ProcessAccels function
ProcessAccels(var
Message:
TMsg):
Boolean;
virtual;
( O v e r r i d e : s o m e t i m e s ) H a n d l e s s p e c i a l a c c e l e r a t o r m e s s a g e p r o c e s s i n g . If a n application doesn't use accelerator resources, y o u can improve performance by o v e r r i d i n g this m e t h o d t o r e t u r n F a l s e .
TApplication.ProcessAppMsg function
ProcessAppMsg(var
Message:
TMsg):
Boolean;
virtual;
(Override: sometimes) C h e c k s for special processing for modeless dialog, accelerator, and M D I accelerator messages. Sends messages to P r o c e s s D l g M s g , P r o c e s s M D I A c c e l s , and P r o c e s s A c e e l s , a n d r e t u r n s T r u e if it e n c o u n t e r s a n y o f t h e s e s p e c i a l p r o c e s s ing messages. If y o u r a p p l i c a t i o n d o e s n ' t c r e a t e m o d e l e s s d i a l o g s , d o e s n ' t r e s p o n d t o a c c e l e r a t o r s , a n d isn't a n M D I a p p l i c a t i o n , y o u c a n i m p r o v e p e r f o r m a n c e b y o v e r r i d i n g this m e t h o d t o r e t u r n F a l s e .
TApplication.ProcessDlgMsg function
ProcessDlgMsg(var
Message:
TMsg): Boolean;
virtual;
(Override: sometimes) Handles special modeless dialog and w i n d o w message processing for keyboard input for controls. If y o u r a p p l i c a t i o n d o e s n ' t c r e a t e m o d e l e s s d i a l o g s o r w i n d o w s w i t h c o n t r o l s , y o u c a n i m p r o v e p e r f o r m a n c e b y o v e r r i d i n g this m e t h o d t o r e t u r n False.
TApplication.ProcessMDIAccels function
ProcessMDIAccels(var
Message:
TMsg): Boolean;
virtual;
H a n d l e s special accelerator message processing for M D I - c o m p l i a n t applications. If y o u r a p p l i c a t i o n isn't a n M D I a p p l i c a t i o n , y o u c a n i m p r o v e p e r f o r m a n c e b y o v e r r i d i n g this m e t h o d t o r e t u r n F a l s e .
TApplication.Run procedure
Run;
virtual;
( O v e r r i d e : s e l d o m ) If a n a p p l i c a t i o n i n i t i a l i z a t i o n is s u c c e s s f u l , Run sets t h e application in m o t i o n by sending a message t o M e s s a g e L o o p .
A—ObjectWindows Objects
TApplication.SetKBHandler procedure SetKBHandler(AWindowsObject: PWindowsObject); ( O v e r r i d e : n e v e r ) Activates k e y b o a r d h a n d l i n g b y s e t t i n g KBHandlerWnd t o AWindowsObject.
TApplication.ValidWindow function ValidWindow(AWindowsObj ect: PWindowsObj ect):PWindowsObj ect; D e t e r m i n e s w h e t h e r AWindowsOb j ect is a v a l i d o b j e c t . I f AWindowsOb j ect is v a l i d , ValidWindow r e t u r n s a p o i n t e r t o it. O t h e r w i s e , it r e t u r n s n i l . AWindowsOb j ect is i n v a l i d if • A l l o c a t i o n o f t h e o b j e c t d i s t u r b e d t h e safety p o o l • T h e status field o f AWindowsOb j ect is n o n z e r o
TBufStream TBuf St ream i m p l e m e n t s a b u f f e r e d v e r s i o n o f TDosSt ream. Its a d d i t i o n a l fields specify t h e size a n d l o c a t i o n o f t h e b u f f e r a n d t h e c u r r e n t a n d last p o s i t i o n s within the buffer. TBufStream o v e r r i d e s t h e e i g h t m e t h o d s o f TDosStream a n d d e f i n e s t h e abstract TStreamFlush m e t h o d . T h e TBufStream c o n s t r u c t o r c r e a t e s a n d o p e n s a file b y s e n d i n g a m e s s a g e t o TDosSt ream. I n it (the c o n s t r u c t o r ) . T h e n it c r e a t e s t h e b u f f e r w i t h Get Mem. TBufStream is m o r e efficient t h a n TDosStream w h e n a l a r g e n u m b e r o f s m a l l d a t a transfers o c c u r o n a s t r e a m ; f o r e x a m p l e , if y o u ' r e l o a d i n g a n d s t o r i n g o b j e c t s u s i n g TStream. Get a n d TStream. Put u s e TBufStream t o i m p r o v e p e r f o r m a n c e .
Fields Buffer BufSize BufPtr BufEnd
411
412
Part I I I — R e f e r e n c e s
Methods Init Done Flush GetPos GetSize Read Seek Truncate Write
Fields TBufStream.Buflfer Buffer: Pointer; ( r e a d o n l y ) A p o i n t e r t o t h e start o f a s t r e a m ' s b u f f e r .
TBufStream.BufSize BufSize: W o r d ; ( r e a d o n l y ) H o l d s t h e b u f f e r size i n b y t e s .
TBufStream.BufPtr BufPtr: W o r d ; ( r e a d o n l y ) A n offset f r o m t h e Buffer p o i n t e r that i n d i c a t e s t h e c u r r e n t p o s i t i o n w i t h i n t h e buffer.
TBufStream.BufEnd BufEnd: W o r d ; ( r e a d o n l y ) I f t h e b u f f e r isn't f u l l , BufEnd h o l d s a n offset f r o m t h e Buffer p o i n t e r t o t h e last u s e d byte in the buffer.
A—ObjectWindows Objects
Methods TBufStream.Init constructor Init(FileName: FNameStr; Mode, Size: Word); C r e a t e s a n d o p e n s a file w i t h a c c e s s Mode b y c a l l i n g TDosStream. Init. Init c r e a t e s a b u f f e r of Size b y t e s u s i n g Get Mem a n d initializes t h e Handle, Buffer, a n d Buf Size f i e l d s . A l t h o u g h b u f f e r s i z e s u s u a l l y r a n g e f r o m 512 t o 2,048 b y t e s , larger buffers are s o m e t i m e s useful.
TBufStream.Done destructor Done; virtual; ( O v e r r i d e : n e v e r ) C l o s e s a n d d i s p o s e s o f t h e file s t r e a m a n d f l u s h e s a n d d i s p o s e s o f its b u f f e r .
TBufStream.Hush procedure Flush; virtual; ( O v e r r i d e : n e v e r ) If t h e s t r e a m is stOK, Flush f l u s h e s t h e c a l l i n g file s t r e a m ' s buffer.
TBufStream.GetPos function GetPos: Longint; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e v a l u e of t h e c a l l i n g s t r e a m ' s c u r r e n t p o s i t i o n .
TBufStream.GetSi2e function GetSize: Longint; virtual; ( O v e r r i d e : n e v e r ) F l u s h e s t h e b u f f e r a n d t h e n r e t u r n s t h e t o t a l size i n b y t e s of the calling stream.
TBufStream.Read procedure Read(var Buf; Count: Word); virtual; ( O v e r r i d e : n e v e r ) If stOK, r e a d s Count b y t e s i n t o t h e Buf b u f f e r starting at t h e c a l l i n g s t r e a m ' s c u r r e n t p o s i t i o n . N o t e that Buf isn't t h e s t r e a m ' s b u f f e r b u t a n e x t e r n a l b u f f e r that h o l d s t h e d a t a r e a d i n f r o m t h e s t r e a m .
413
414
Part I I I — R e f e r e n c e s
TBufStream.Seek procedure Seek(Pos: Longint); virtual; ( O v e r r i d e : n e v e r ) F l u s h e s t h e b u f f e r a n d t h e n resets t h e c u r r e n t p o s i t i o n t o Pos b y t e s f r o m t h e start o f t h e c a l l i n g s t r e a m . T h e start o f a s t r e a m is p o s i t i o n 0 .
TBufStream.Thincate procedure Truncate; virtual; ( O v e r r i d e : n e v e r ) F l u s h e s t h e b u f f e r a n d t h e n d e l e t e s all d a t a o n t h e c a l l i n g s t r e a m f r o m t h e c u r r e n t p o s i t i o n t o t h e e n d . T h e c u r r e n t p o s i t i o n is set t o t h e n e w e n d o f the stream.
TBufitream.Write procedure Write(var But; Count: Word); virtual; ( O v e r r i d e : n e v e r ) I f stOK, w r i t e s Count b y t e s f r o m t h e Buf b u f f e r t o t h e c a l l i n g s t r e a m , starting at t h e c u r r e n t p o s i t i o n . N o t e that Buf isn't t h e s t r e a m ' s b u f f e r b u t a n e x t e r n a l b u f f e r that h o l d s t h e d a t a b e i n g w r i t t e n t o t h e s t r e a m . W h e n Write is c a l l e d , Buf p o i n t s t o t h e v a r i a b l e w h o s e v a l u e is b e i n g w r i t t e n .
TButton TButton is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a p u s h - b u t t o n e l e m e n t i n Windows. Y o u u s u a l l y d o n ' t u s e TButton o b j e c t s i n d i a l o g b o x e s (TDialog) o r d i a l o g w i n d o w s (TDlgWindow). R a t h e r , u s e t h e m w h e n y o u w a n t t o d i s p l a y a s t a n d - a l o n e b u t t o n as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a . There are t w o types o f p u s h buttons: • A regular button appears with a thin border. • A default b u t t o n appears with a thick border a n d represents the default action o f the window. E a c h w i n d o w is a l l o w e d o n l y o n e d e f a u l t p u s h b u t t o n .
Fields None.
A—ObjectWindows Objects
415
Methods Init InitResource GetClassName
Methods TButton.Init constructor Init(AParent: PWindowsObject; Anld: Integer; AText: PChar; X,Y,W,H: Integer; IsDefault: Boolean); Constructs a button object with the • P a s s e d p a r e n t w i n d o w (AParent)
• C o n t r o l ID (Anld) • A s s o c i a t e d text (AText) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) S e n d s a m e s s a g e toTControl.Init a n d t h e n a d d s b s_De f PushButton to t h e Attr. S t y l e field if IsDefault is T r u e . If not, it a d d s bs_PushButton.
TButton.InitResource constructor InitResource(AParent:
PWindowsObject,
ResourcelD: Word);
C o n s t r u c t s a n O b j e c t W i n d o w s o b j e c t that c o r r e s p o n d s t o a b u t t o n e l e m e n t created by a dialog resource definition. S e n d s m e s s a g e s t o TControl. InitResource a n d TWindowsObject. B e c a u s e b u t t o n s h a v e n o d a t a t o transfer, y o u c a n u s e DisableTransf er t o e x c l u d e t h e b u t t o n f r o m t h e transfer m e c h a n i s m .
TButton.GetClassName function GetClassName:
PChar;
virtual;
( O v e r r i d e : n e v e r ) R e t u r n s t h e n a m e o f TButton's w i n d o w c l a s s , Button.
416
Part I I I — R e f e r e n c e s
TCheckBox TCheckBox is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a c h e c k - b o x e l e m e n t i n W i n d o w s . Y o u u s u a l l y d o n ' t u s e TCheckBox o b j e c t s i n d i a l o g b o x e s (TDialog) o r d i a l o g w i n d o w s (TDlgWindow). R a t h e r , u s e t h e m t o d i s p l a y a s t a n d - a l o n e c h e c k b o x as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a . C h e c k b o x e s h a v e t w o states: c h e c k e d a n d u n c h e c k e d . TCheckBox m e t h o d s p r i m a r i l y m a n a g e t h e c h e c k b o x ' s state. O p t i o n a l l y , a c h e c k b o x c a n b e part o f a g r o u p (TGroupBox) that v i s u a l l y a n d f u n c t i o n a l l y " g r o u p s " its c o n t r o l s .
Fields Group
Methods Init InitResource Load BNClicked Check GetCheck SetCheck Store Toggle Transfer Uncheck
Fields TCheckBox.Group Group: PGroupBox; ( r e a d o n l y ) Group p o i n t s t o t h e TGroupBox c o n t r o l o b j e c t that u n i f i e s t h e c h e c k b o x w i t h o t h e r c h e c k b o x e s a n d r a d i o b u t t o n s (TRadioButton). Group is e q u a l t o n i l if t h e c h e c k b o x isn't part o f a g r o u p .
A—ObjectWindows Objects
417
Methods TCheckBox.Init constructor Init(AParent: PWindowsObject; AnID: Integer; ATitle: PChar; X,Y,W,H: Integer; AGroup: PGroupBox); (Override: sometimes) Constructs a check b o x object with the • P a s s e d p a r e n t w i n d o w (AParent)
• C o n t r o l I D (AnId) • A s s o c i a t e d text (ATitle) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) • A s s o c i a t e d g r o u p b o x (AGroup)
Init sets t h e c h e c k b o x ' s Att r .Style field to ws_Child o r ws_Visible
o r ws_TabStop o r bs_AutoCheckBox.
TCheckBox.InitResource constructor InitResource(AParent: PWindowsObject; ResourcelD: Word); A s s o c i a t e s aTCheckBox o b j ect w i t h t h e r e s o u r c e n a m e d b y ResourcelD. It t h e n e n a b l e s t h e transfer m e c h a n i s m b y s e n d i n g a m e s s a g e toEnableTransfer.
TCheckBoxIoad constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a c h e c k b o x f r o m t h e s t r e a m S b y first s e n d i n g a m e s s a g e to TButton. Load a n d t h e n r e a d i n g t h e a d d i t i o n a l field (Group) i n t r o d u c e d b y
TCheckBox.
TCheckBox.BNCUcked procedure BNClicked(var Msg: TMessage); virtual nf_First + bn_Clicked; ( O v e r r i d e : s o m e t i m e s ) A u t o m a t i c a l l y r e s p o n d s to t h e notification m e s s a g e s ( w h i c h i n d i c a t e that t h e c h e c k b o x w a s c l i c k e d ) b y t o g g l i n g its state. If t h e c h e c k b o x ' s Group isn't n i l , BNClicked n o t i f i e s t h e TGroupBox b y s e n d i n g a m e s s a g e
to its SelectionChanged m e t h o d .
418
Part I I I — R e f e r e n c e s
TCheckBox.Check procedure Check; virtual; ( O v e r r i d e : s e l d o m ) F o r c e s t h e c h e c k box i n t o t h e c h e c k e d state by s e n d i n g a m e s s a g e t o SetCheck.
TCheckBox.GetCheck function GetCheck: Word; virtual; (Override: seldom) Returns o n e o f the following: bfJJnchecked bf_Checked bf _Grayed
(0) if t h e c h e c k box is u n c h e c k e d
(1) if t h e c h e c k box is c h e c k e d (2) if t h e c h e c k box is g r a y e d
TCheckBox.SetCheck procedure SetCheck(CheckFlag: Word); virtual; ( O v e r r i d e : s e l d o m ) F o r c e s t h e c h e c k b o x i n t o t h e state s p e c i f i e d byCheckFlag. • I f CheckFlag is 0 , t h e state is u n c h e c k e d . • I f CheckFlag is 1, t h e state is c h e c k e d . • If CheckFlag is 2, t h e state is g r a y e d . SetCheck a l s o i n f o r m s t h e c h e c k box's g r o u p that t h e s e l e c t i o n h a s c h a n g e d .
TCheckBox.Store procedure Store(var S: TStream); S t o r e s t h e c h e c k box o n t h e s t r e a m , S, by first s e n d i n g a m e s s a g e t o TControl. Store a n d t h e n w r i t i n g t h e a d d i t i o n a l field (Group) i n t r o d u c e d by TCheckBox.
TCheckBox.Toggle procedure Toggle; virtual; ( O v e r r i d e : s e l d o m ) T o g g l e s t h e state o f t h e c h e c k b o x by c a l l i n g Check o r Uncheck. F o r a 3-state c h e c k b o x , it t o g g l e s t h r o u g h all t h r e e states: u n c h e c k e d , checked, a n d grayed.
A — O b j e c t W i n d o w s Objects
419
TCheckBox.Transfer function Transfer(DataPtr: Pointer; TransferFlag: Word): Word; virtual; ( O v e r r i d e : s o m e t i m e s ) T r a n s f e r s t h e state o f a c h e c k b o x i n a Word t y p e v a l u e to or from the m e m o r y location pointed to by D a t a P t r . • I f Transf erFlag is tf_GetData, t h e c h e c k b o x ' s state d a t a is transferred to the m e m o r y location. • If Transf erFlag is tf_SetData, t h e c h e c k b o x is set t o t h e state indicated in the m e m o r y location. Transfer returns the n u m b e r o f bytes stored in o r retrieved f r o m the m e m o r y l o c a t i o n . I f y o u p a s s tf_SizeData, Transfer r e t u r n s t h e size o f t h e transfer d a t a .
TCheckBox.Uncheck procedure Uncheck; virtual; ( O v e r r i d e : s e l d o m ) F o r c e s t h e c h e c k b o x i n t o t h e u n c h e c k e d state b y s e n d i n g a m e s s a g e t o SetCheck.
TCollection TCollection is a n abstract t y p e f o r i m p l e m e n t i n g a c o l l e c t i o n o f i t e m s . T h e c o l l e c t i o n c a n c o n t a i n v a r i o u s d a t a t y p e s , i n c l u d i n g o b j e c t s . B e c a u s e it c a n i n c l u d e m i x e d d a t a t y p e s , TCollection is a m o r e g e n e r a l w a y o f h a n d l i n g d a t a t h a n t h e t r a d i t i o n a l array, set, o r list t y p e s . TCollection o b j e c t s size t h e m s e l v e s d y n a m i c a l l y at r u n - t i m e a n d c a n b e a b a s e t y p e f o r m a n y s p e c i a l i z e d t y p e s , s u c h as TSortedCollection a n d TStrCollection. I n a d d i t i o n t o m e t h o d s f o r a d d i n g a n d d e l e t i n g i t e m s , TCollection offers several u s e f u l iterator r o u t i n e s that call a p r o c e d u r e o r f u n c t i o n f o r e a c h i t e m in the collection.
Fields Count Delta Items Limit
420
Part I I I — R e f e r e n c e s
Methods Init Load Done AtDelete AtFree Atlnsert AtPut At Delete DeleteAll Error FirstThat ForEach FreeAll Freeltem Free Getltem IndexOf Insert LastThat Pack Putltem SetLimit Store
Fields TCollection.Count Count: Integer; ( r e a d o n l y ) T h e current n u m b e r o f items in the collection, u p to (and including)
MaxCollectionSize.
TCollection.Delta Delta: Integer; ( r e a d o n l y ) T h e n u m b e r o f i t e m s t o i n c r e a s e t h e Items list b y w h e n e v e r t h e list b e c o m e s f u l l . I f Delta is 0, t h e c o l l e c t i o n c a n n o t g r o w b e y o n d t h e size set b y Limit.
A — O b j e c t W i n d o w s Objects
I n c r e a s i n g t h e size o f a c o l l e c t i o n r e d u c e s p e r f o r m a n c e . T o m i n i m i z e t h e n u m b e r o f t i m e s t h e c o l l e c t i o n i n c r e a s e s its s i z e , set t h e initial Limit t o a v a l u e that a c c o m m o d a t e s all t h e i t e m s y o u m i g h t w a n t t o c o l l e c t , a n d set Delta t o a v a l u e that a l l o w s a r e a s o n a b l e a m o u n t o f e x p a n s i o n .
TCollectionJtems Items: PItemList; ( r e a d o n l y ) A p o i n t e r t o a n array o f i t e m p o i n t e r s .
TCollection.Iimit Limit: Integer; ( r e a d o n l y ) T h e c u r r e n t l y a l l o c a t e d size (in e l e m e n t s ) o f t h e Items list.
Methods TCollection.Init constructor Init(ALimit, ADelta: Integer); C r e a t e s a c o l l e c t i o n w i t h Limit set t o ALimit a n d Delta set t o ADelta. T h e initial n u m b e r o f i t e m s is l i m i t e d t o ALimit, b u t t h e c o l l e c t i o n c a n g r o w i n i n c r e m e n t s o f ADelta u n t i l m e m o r y r u n s o u t o r t h e n u m b e r o f i t e m s r e a c h e s MaxCollectionSize.
TCollectionload constructor Load(var S: TStream); C r e a t e s a n d l o a d s a c o l l e c t i o n f r o m a s t r e a m . Load s e n d s a m e s s a g e t o Get It em for e a c h i t e m i n t h e c o l l e c t i o n .
TCollection.Done destructor Done; virtual; ( O v e r r i d e : o f t e n ) D e l e t e s a n d d i s p o s e s o f all i t e m s i n a c o l l e c t i o n b y s e n d i n g a m e s s a g e t o FreeAll a n d s e t t i n g Limit t o 0.
421
422
Part III—References
TCoUectionAtDelete procedure AtDelete(Index: Integer); Deletes the item at the Index'th position and moves the ensuing items u p by one position. Co u n t is decremented by 1, but the m e m o r y allocated to the collection (as specified by Limit) isn't reduced. If I n d e x is less than 0 or greater than or equal to Co u n t, the Error method is sent a message with an argument of eolndexError.
TCollectionAtFree procedure AtFree(Index: Integer); Disposes of and deletes the item at the Index'th position.
TCoUectionAtlnsert procedure Atlnsert(lndex: Integer; Item: Pointer); Inserts Item at the Index'th position and moves the following items d o w n by one position: • If Index is less than 0 or greater than Count, the Error method is sent a message with an argument of eolndexError and the n e w Item isn't inserted. • If Count is equal to Limit before the call to Atlnsert, the allocated size of the collection is expanded by Delta items via a message sent to SetLimit. • If the SetLimit call fails to expand the collection, the Error method is sent a message with an argument of coOverf low, and the n e w Item isn't inserted.
TCoUectionAtPut procedure AtPut(Index: Integer; Item: Pointer); Replaces the item at Index position with the item specified by Item. If Index is less than 0 or greater than or equal to Count, the Error method is sent a message with an argument of eolndexError.
A—ObjectWindows Objects
TCollectionAt function At(Index: Integer): Pointer; R e t u r n s a p o i n t e r t o t h e i t e m i n d e x e d b y Index i n t h e c o l l e c t i o n . T h i s m e t h o d lets y o u m a n i p u l a t e a c o l l e c t i o n as t h o u g h it w e r e a n i n d e x e d array. I f I ndex is less t h a n 0 o r g r e a t e r t h a n o r e q u a l t o Count, t h e Error m e t h o d is s e n t a m e s s a g e w i t h a n a r g u m e n t ofcoIndexError, a n d a v a l u e o f n i l is r e t u r n e d .
TCollection.Delete procedure Delete(Item: Pointer); D e l e t e s t h e i t e m s p e c i f i e d b y Item f r o m t h e c o l l e c t i o n . E q u i v a l e n t t o AtDelete(IndexOf(Item)).
TCollection.DeleteAll procedure DeleteAll; D e l e t e s all i t e m s f r o m t h e c o l l e c t i o n b y s e t t i n g Count t o 0.
TCollection.Eiror procedure Error(Code, Info: Integer); virtual; ( O v e r r i d e : s o m e t i m e s ) Receives a m e s s a g e w h e n e v e r a c o l l e c t i o n error is e n c o u n t e r e d . B y default, this m e t h o d p r o d u c e s a r u n - t i m e error o f 212 - C o d e ) .
TCollection.FirstThat function FirstThat(Test: Pointer): Pointer; FirstThat a p p l i e s a B o o l e a n f u n c t i o n ( s u p p l i e d b y t h e f u n c t i o n p o i n t e r T e s t ) t o e a c h i t e m i n t h e c o l l e c t i o n u n t i l T e s t r e t u r n s T r u e . T h e result is t h e i t e m p o i n t e r u s e d w h e n T e s t r e t u r n e d T r u e , o r n i l if t h e T e s t f u n c t i o n r e t u r n e d F a l s e f o r all i t e m s . T e s t m u s t p o i n t t o a far l o c a l f u n c t i o n t a k i n g o n e P o i n t e r p a r a m e t e r a n d returning a Boolean value. For example: function Matches(Item: Pointer): Boolean; far; T h e Test f u n c t i o n c a n n o t b e a g l o b a l f u n c t i o n .
423
424
Part I I I — R e f e r e n c e s
A s s u m i n g that List is a TCollection, t h e s t a t e m e n t
P :=
List.FirstThat(@Matches);
corresponds to I
: = 0;
while
(I < List.Count)
and not Matches(List.At(I))
do
Inc(I);
if I < List.Count
then P := List.At(I)
else P := nil;
TCollection.ForEach procedure
ForEach(Action:
Pointer);
For Each a p p l i e s a n a c t i o n ( s u p p l i e d b y t h e p r o c e d u r e p o i n t e r Action) t o e a c h i t e m i n t h e c o l l e c t i o n . Action m u s t p o i n t t o a far l o c a l p r o c e d u r e t a k i n g o n e Pointer p a r a m e t e r ; f o r e x a m p l e :
function
Printltem(ltem:
Pointer); far;
T h e Action p r o c e d u r e c a n n o t b e a g l o b a l p r o c e d u r e . A s s u m i n g that List is a TCollection, t h e s t a t e m e n t
List.ForEach(@PrintItem); corresponds to
for I := 0 to List.Count
- 1 do
PrintItem(List.At(I));
TCollection.FreeAll procedure
FreeAll;
D e l e t e s a n d d i s p o s e s o f all i t e m s i n t h e c o l l e c t i o n .
TCollection.FreeItem procedure
Freeltem(ltem:
Pointer);
virtual;
( O v e r r i d e : s o m e t i m e s ) T h e Freeltem m e t h o d m u s t d i s p o s e o f t h e Item. T h e d e f a u l t Freeltem a s s u m e s that Item is a p o i n t e r t o a d e s c e n d a n t o f TOb j ect a n d s e n d s a m e s s a g e t o t h e Done d e s t r u c t o r :
if Item nil then Dispose(PObject(Item),
Done);
Freeltem r e c e i v e s m e s s a g e s f r o m Free a n d FreeAll, b u t s h o u l d n e v e r b e s e n t m e s s a g e s directly.
A — O b j e c t W i n d o w s Objects
TCollection.Free procedure Free(Item: Pointer); D e l e t e s a n d d i s p o s e s o f a s p e c i f i e d Item. E q u i v a l e n t t o Delete(Item); Freeltem(Item);
TCollection.GetItem function TCollection.Getltem(var
S: TStream): Pointer; virtual;
( O v e r r i d e : s o m e t i m e s ) S e n t a m e s s a g e b y Load f o r e a c h i t e m i n t h e c o l l e c t i o n . Y o u c a n o v e r r i d e this m e t h o d , b u t y o u s h o u l d n ' t s e n d it m e s s a g e s directly. T h e d e f a u l t Get I tern a s s u m e s that t h e i t e m s i n t h e c o l l e c t i o n a r e d e s c e n d a n t s o f TObject a n d s e n d s a m e s s a g e t o TStream.Get t o l o a d t h e i t e m : Getltem
:= S.Get;
TCollection.IndexOf function IndexOf(Item: Pointer): Integer; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e i n d e x o f a s p e c i f i e d Item. T h e c o n v e r s e o p e r a t i o n o f At. I f Item isn't i n t h e c o l l e c t i o n , IndexOf r e t u r n s - 1 .
TCollection.Insert procedure Insert(Item: Pointer); virtual; ( O v e r r i d e : n e v e r ) I n s e r t s Item i n t o t h e c o l l e c t i o n a n d a d j u s t s o t h e r i n d i c e s if n e c e s s a r y . B y d e f a u l t , i n s e r t i o n s a r e m a d e at t h e e n d o f t h e c o l l e c t i o n b y w a y of a message to Atlnsert(Count,
Item);
TCollectionlastThat function LastThat(Test: Pointer): Pointer; LastThat a p p l i e s a B o o l e a n f u n c t i o n ( s p e c i f i e d b y t h e f u n c t i o n p o i n t e r Test) t o e a c h i t e m i n t h e c o l l e c t i o n i n r e v e r s e o r d e r u n t i l Test r e t u r n s T r u e . T h e result is t h e i t e m p o i n t e r u s e d w h e n Test r e t u r n e d T r u e , o r n i l if t h e Test f u n c t i o n r e t u r n e d F a l s e f o r all i t e m s .
425
426
Part III—References
Test must point to a far local function that takes aPointer parameter and returns a Boolean; for example: function Matches(Item: Pointer): Boolean; far; The Test function cannot be a global function. Assuming that List is a TCollection, the statement: P := List.LastThat(@Matches); corresponds to: I := List.Count - 1; while (I >= 0) and not Matches(List.At(I)) do Dec(I); if I >= 0 then P := List.At(I) else P := nil;
TCollection.Pack procedure Pack; Deletes all nil pointers in the collection.
TCollection.PutItem procedure Putltem(var S: TStream; Item: Pointer); virtual; (Override: sometimes) Put Item receives a message from Store for each item in the collection. Y o u can override this method, but you shouldn't send it a message directly. The default Put Item assumes that the items in the collection are descendants ofTObj ect, and thus sends a message to TStream. Put to store the item: S.Put(Item);
TCollection.SetLimit procedure SetLimit(ALimit: Integer); virtual; (Override: seldom) Expands or shrinks the collection by changing the allocated size to ALimit. If ALimit is less than Count, ALimit is set to Count. If ALimit is greater than MaxCollectionSize, ALimit is set to MaxCollectionSize. Then, if ALimit is different from the current Limit, a n e w Items array of ALimit elements is allocated. The old Items array then is copied into the n e w array, and the old array is disposed.
A — O b j e c t W i n d o w s Objects
TCollection.Store procedure Stbre(var S: TStream); S t o r e s t h e c o l l e c t i o n a n d all its i t e m s o n t h e s t r e a m S. Store s e n d s a m e s s a g e t o Put I tern f o r e a c h i t e m i n t h e c o l l e c t i o n .
TComboBox TComboBox is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a c o m b o b o x e l e m e n t i n W i n d o w s . U s u a l l y y o u d o n ' t u s e TComboBox o b j e c t s i n d i a l o g b o x e s (TDialog) o r d i a l o g w i n d o w s (TDlgWindow). R a t h e r , u s e a c o m b o b o x o b j e c t t o d i s p l a y a s t a n d - a l o n e c o m b o b o x as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a . C o m b o b o x o b j e c t s i n h e r i t m o s t o f t h e i r f u n c t i o n a l i t y f r o m TListBox. T h e t h r e e styles o f c o m b o b o x e s a r e •
Simple
• Drop down • D r o p d o w n list T h e s e styles a r e c o n t r o l l e d b y t h e W i n d o w s style c o n s t a n t s c b s S i m p l e , cbs_DropDown, a n d cbs DropDownList. T h e s e c o n s t a n t s a r e p a s s e d t o t h e Init c o n s t r u c t o r , which i n t u r n tells W i n d o w s which t y p e o f c o m b o b o x element to create.
Fields TextLen
Methods Init InitResource Load GetClassName GetMsgID (private) HideList SetupWindow ShowList Store Transfer
427
428
Part I I I — R e f e r e n c e s
Fields TComboBox.TextLen TextLen: W o r d ; (read o n l y ) Text Len c o n t a i n s t h e l e n g t h o f t h e c h a r a c t e r b u f f e r i n t h e e d i t p a r t o f t h e c o m b o b o x . T h e c h a r a c t e r b u f f e r is e q u a l t o t h e n u m b e r o f b y t e s t r a n s f e r r e d b y
Transfer. TextLen is set b y Init.
Methods TComboBox.Init constructor Init(AParent: PWindowsObject; AnID: Integer; X,Y,W,H: Integer; CanDropList: Boolean; HasStaticControl: Boolean); ( O v e r r i d e : s o m e t i m e s ) S e n d s a m e s s a g e t o TListBox. Init a n d c o n s t r u c t s a c o m b o b o x object with the following parameters: • P a s s e d p a r e n t w i n d o w (AParent)
• C o n t r o l I D (Anld) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H)
Sets TextLen t o ATextLen. Sets Attr .Style t o (Attr.Style and not lbs_Notify) or AStyle or cbs_Sort or ws_VScroll or ws_HScroll.
TComboBox.InitResource constructor InitResource(AParent: PWindowsObj ect; ResourcelD: Integer; ATextLen: Word); A s s o c i a t e s a TComboBox o b j e c t w i t h t h e r e s o u r c e i n d i c a t e d b y ResourcelD w i t h a m a x i m u m text l e n g t h o f ATextLen -1.
TComboBoxload constructor Load(var S: TStream);
A—ObjectWindows Objects
C o n s t r u c t s a n d l o a d s a c o m b o b o x f r o m t h e s t r e a m , S, b y first s e n d i n g a m e s s a g e toTListBox. Load a n d t h e n r e a d i n g t h e a d d i t i o n a l fields (I sDropDown, IsList) i n t r o d u c e d b y TComboBox.
TComboBox.GetClassName function GetClassName:
PChar;
virtual;
( O v e r r i d e : n e v e r ) R e t u r n s t h e n a m e o f TComboBox's w i n d o w class, ComboBox.
TComboBox.GetMsgID function GetMsgID(AMsg : TMsgName): word; virtual; Private m e t h o d ; u s e d i n t e r n a l l y b y TComboBox.
TComboBox.HideList procedure HideList;
virtual;
( O v e r r i d e : s e l d o m ) H i d e s t h e d r o p d o w n list o f a d r o p d o w n o r d r o p - d o w n list combo box.
TComboBox.SetUpWindow H a n d l e s s o m e o f t h e TComboBox w i n d o w s e t u p ,
procedure SetupWindow; virtual;
TComboBox.ShowIist procedure ShowList;
virtual;
( O v e r r i d e : s e l d o m ) D i s p l a y s t h e d r o p d o w n list o f a d r o p d o w n o r d r o p - d o w n list c o m b o b o x .
TComboBox.Store procedure Store(var S: TStream); S t o r e s t h e c o m b o b o x o n t h e s t r e a m , S, b y first s e n d i n g a m e s s a g e t o TListBox. Store a n d t h e n w r i t i n g t h e a d d i t i o n a l field (TextLen) i n t r o d u c e d
b y TComboBox.
429
430
Part III—References
TComboBox.Transfer function
Transfer(DataPtr:
Pointer;
TransferFlag:
Word);virtual
Transfers data to or from the record p o i n t e d to by D a t a P t r . T h e r e c o r d s h o u l d first b e a p o i n t e r t o a string c o l l e c t i o n that h o l d s t h e e n t r i e s o f t h e c o m b o b o x ' s list. T h e n a n array o f c h a r a c t e r s h o l d i n g t h e c u r r e n t l y s e l e c t e d e n t r y is t r a n s f e r r e d . • If T r a n s f e r F l a g is t f G e t D a t a , t h e c o m b o b o x ' s d a t a is t r a n s f e r r e d t o t h e D a t a P t r r e c o r d . T r a n s f e r r e t u r n s t h e size o f t h e d a t a t r a n s f e r r e d . • If T r a n s f e r F l a g is t f _ S e t D a t a , t h e d a t a is t r a n s f e r r e d t o t h e c o m b o b o x f r o m t h e r e c o r d . T r a n s f e r r e t u r n s t h e size o f t h e d a t a t r a n s f e r r e d . • If T r a n s f e r F l a g is t f _ S i z e D a t a , T r a n s f e r r e t u r n s t h e size o f t h e transfer d a t a .
TControl T C o n t r o l is a n abstract o b j e c t t y p e that u n i f i e s all c o n t r o l o b j e c t t y p e s , s u c h as T S c r o l l B a r a n d T B u t t o n . It's a l s o t h e a n c e s t o r t o T M D I C l i e n t , a s p e c i a l i z e d control for MDI-compliant applications. Y o u generally w o n ' t use control objects in dialog b o x e s ( T D i a l o g ) or d i a l o g w i n d o w s ( T D l g W i n d o w ) , o n l y as s t a n d - a l o n e c o n t r o l s i n t h e c l i e n t a r e a of other windows.
Methods Init GetClassName InitResource Register WMPaint
Methods TControLMt constructor Init(AParent: A T i t l e : PChar; X,Y,W,H:
PWindowsObject; Integer);
Anld:
Integer;
A—ObjectWindows Objects
431
Constructs a control object with the following parameters: • A s s o c i a t e d p a r e n t w i n d o w (AParent) • C o n t r o l ID (AnId) • A s s o c i a t e d text (ATitle) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t area • W i d t h (W) • H e i g h t (H) U s i n g t h e s e p a r a m e t e r s , Init fills t h e c o n t r o l ' s Att r field i n h e r i t e d f r o m TWindow. B y d e f a u l t , Init sets Attr.Style t o ws_Child o r ws_Visible o r ws_Group o r w s T a b S t o p ; t h u s , all c o n t r o l o b j e c t s a r e visible c h i l d w i n d o w s .
TControLGetClassName function GetClassName: PChar; virtual; ( O v e r r i d e : always) A b s t r a c t m e t h o d always o v e r r i d d e n b y d e s c e n d a n t o b j e c t s .
TControLlnitResource constructor InitResource(AParent:
PWindowsObject;
ResourcelD: Word); Associates a control object with the control element in the resource specified b y ResourcelD. S e n d s a m e s s a g e t o TWindow. InitResource a n d EnableTransf er t o e n a b l e t h e transfer m e c h a n i s m .
TControLRegister function Register: Boolean; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s T r u e t o i n d i c a t e that TControl d e s c e n d a n t s u s e preregistered w i n d o w classes.
TControLWMPaint procedure WMPaint(var Msg: TMessage); virtual; wm_First + wm_Paint; ( O v e r r i d e : s e l d o m ) S e n d s a m e s s a g e t o Def WndProc e n a b l i n g s t a n d a r d r e p a i n t i n g of c o n t r o l o b j e c t s .
432
Part I I I — R e f e r e n c e s
TDialog T D i a l o g d e f i n e s o b j e c t s t o serve as t h e m o d a l a n d m o d e l e s s d i a l o g b o x e s u s e d in W i n d o w s applications. A T D i a l o g object has a n associated dialog resource that d e s c r i b e s t h e a p p e a r a n c e a n d p l a c e m e n t o f its c o n t r o l s . S p e c i f y t h e d i a l o g resource in the message to I n i t . Y o u c a n associate dialog b o x objects with either m o d a l o r m o d e l e s s dialog e l e m e n t s b y w a y o f m e s s a g e s t o E x e c u t e (for m o d a l d i a l o g s ) o r C r e a t e (for m o d e l e s s d i a l o g s ) . Note: W h e n y o u c r e a t e a m o d a l d i a l o g , y o u d i s a b l e t h e o p e r a t i o n o f its p a r e n t w i n d o w u n t i l t h e m o d a l d i a l o g is f i n i s h e d .
Fields Attr DialogProc IsModal
Methods Init Load Done Cancel Create DefWndProc EndDlg Execute GetltemHandle Ok SendDlgltemMsg Store WMClose WMInitDialog WMQueryEndSession
A — O b j e c t W i n d o w s Objects
Fields TDialogAttr Attr: TDialogAttr; Attr h o l d s t h e d i a l o g b o x ' s c r e a t i o n a t t r i b u t e s . Attr is d e f i n e d as f o l l o w s : TDialogAttr = record Name: PChar; Param: Longint; end; T h e Name field c o n t a i n s t h e n a m e o r I D o f t h e d i a l o g r e s o u r c e . T h e Param f i e l d c o n t a i n s a p a r a m e t e r s e n t t o t h e d i a l o g p r o c e d u r e w h e n t h e d i a l o g is created.
TDialog.DialogProc DialogProc: TFarProc; (read o n l y ) DialogProc p o i n t s t o t h e p r o c e d u r e - i n s t a n c e a d d r e s s o f t h e d i a l o g f u n c t i o n .
TDialog.IsModal IsModal: Boolean; ( r e a d o n l y ) IsModal is T r u e if t h e d i a l o g is m o d a l a n d F a l s e if t h e d i a l o g is m o d e l e s s .
Methods TDialog.Init constructor Init(AParent: PWindowsObject; AName: PChar); (Override: sometimes) Constructs the dialog object by sending a message to TWindowsOb j ect. Init, p a s s i n g it t h e p a r e n t w i n d o w , AParent. N e x t , Init sets t h e Att r. Name f i e l d t o AName. AName c a n b e t h e s y m b o l i c n a m e o f t h e d i a l o g r e s o u r c e o r a n i n t e g e r I D cast t o t y p e PChar. Init a l s o s e n d s a m e s s a g e t o TWindowsOb j ect. DisableAutoCreate t o prevent dialogs from being created a n d displayed automatically along with their parent w i n d o w s .
433
434
Part III—References
TDialogload constructor
Load(var S:
TStream);
C o n s t r u c t s a n d l o a d s a d i a l o g b o x f r o m t h e s t r e a m , S, b y first s e n d i n g a m e s s a g e t o T W i n d o w s O b j e c t . L o a d a n d t h e n r e a d i n g t h e a d d i t i o n a l fields ( A t t r a n d I s M o d a l ) introduced by T D i a l o g .
TDialog.Done destructor
Done;
virtual;
(Override: sometimes) Disposes of the dialog b o x object. Sends a message to TWindowsObj e c t . D o n e .
TDialog.Cancel p r o c e d u r e C a n c e l ( v a r Msg: T M e s s a g e ) ; v i r t u a l ;
id_First
+
id_Cancel
(Override: sometimes) Automatically responds to a dialog's Cancel button (when pressed) by sending a message to EndDlg with the value i d C a n c e l .
TDialog.Create function
Create:
Boolean;
virtual;
(Override: never) Creates a modeless dialog object's corresponding dialog e l e m e n t . C r e a t e r e t u r n s T r u e if t h e c r e a t i o n w a s s u c c e s s f u l . If u n s u c c e s s f u l , it sends a message to E r r o r with the error c o d e e m _ I n v a l i d W i n d o w .
TDialog.DefWndProc procedure DefWndProc(var
Msg:
TMessage);
virtual;
(Override: never) Forces W i n d o w s default-message processing by setting the result o f t h e p a s s e d m e s s a g e e q u a l t o 0.
TDialog.EndDlg procedure EndDlg(ARetValue:
Integer);
virtual;
( O v e r r i d e : n e v e r ) D e s t r o y s m o d a l a n d m o d e l e s s d i a l o g b o x e s . A R e t V a l u e is p a s s e d b a c k as t h e r e t u r n v a l u e f r o m E x e c u t e f o r m o d a l d i a l o g b o x e s .
A—ObjectWindows Objects
TDialog-Execute function Execute: Integer; virtual; (Override: never) Creates a n d displays a m o d a l dialog object's c o r r e s p o n d i n g d i a l o g e l e m e n t . T h i s m e t h o d e x e c u t e s w h i l e t h e d i a l o g b o x is o n - s c r e e n , u n t i l its EndDlg m e t h o d is s e n t a m e s s a g e . B e f o r e t h e m e t h o d f i n i s h e s , it resets HWindow t o 0. Execute r e t u r n s t h e i n t e g e r v a l u e r e t u r n e d b y EndDlg if s u c c e s s f u l . If u n s u c c e s s f u l , Execute s e n d s Error a m e s s a g e w i t h t h e e r r o r c o d e em_InvalidWindow.
TDialog-GetltemHandle function GetItemHandle(DlgItemID:
Integer): HWnd;
(Override: never) Returns the handle to the dialog's control identified by the p a s s e d I D , DlgltemlD.
TDialog.Ok procedure 0k(var Msg: TMessage); virtual; id_First + id_0K; (Override: sometimes) Automatically responds to a dialog's O K button (when p r e s s e d ) b y s e n d i n g m e s s a g e s t o CanClose a n d EndDlg w i t h t h e v a l u e id_0K. A l s o s e n d s a m e s s a g e t o Transf e rDat a t o transfer d a t a f r o m t h e c o n t r o l s t o t h e transfer b u f f e r .
TDialog.SendDlgltemMsg function SendDlgItemMsg(DlgItemID:
Integer; AMsg, WParam: Word;
LParam: Longint): Longint; ( O v e r r i d e : n e v e r ) S e n d s a W i n d o w s c o n t r o l m e s s a g e , i d e n t i f i e d b y AMsg, t o t h e d i a l o g ' s c o n t r o l i d e n t i f i e d b y DlgltemlD. WParam a n d LParam b e c o m e p a r a m e t e r s i n t h e W i n d o w s m e s s a g e . SendDlgltemMsg r e t u r n s t h e v a l u e r e t u r n e d b y t h e c o n t r o l o r 0 if t h e c o n t r o l I D is i n v a l i d .
TDialog.Store procedure Store(var S: TStream); S t o r e s t h e d i a l o g b o x o n t h e s t r e a m , S, b y first s e n d i n g a m e s s a g e t o TWindowsObject .Store a n d t h e n w r i t i n g t h e a d d i t i o n a l fields (Attr a n d IsModal) i n t r o d u c e d b y TDialog.
435
436
Part I I I — R e f e r e n c e s
TDialog.WMClose p r o c e d u r e WMClose(var Msg:
TMessage);
virtual;
wm_First
+ wm_Close
If t h e d i a l o g b o x is m o d a l , WMClose s e n d s a m e s s a g e t o E n d D l g t o c l o s e t h e dialog box. If t h e d i a l o g b o x is m o d e l e s s , WMClose s e n d s a m e s s a g e t o its WMClose m e t h o d inherited f r o m TWindowsObj e c t .
TDialog.WMInitDialog procedure WMInitDialog(var wm_First
+
Msg:
TMessage);
virtual;
wm_InitDialog;
( O v e r r i d e : n e v e r ) W M I n i t D i a l o g a u t o m a t i c a l l y r e c e i v e s a m e s s a g e just b e f o r e t h e d i a l o g is d i s p l a y e d . It s e n d s a m e s s a g e t o S e t u p W i n d o w t o h a n d l e a n y i n i t i a l i z a t i o n n e e d e d f o r t h e d i a l o g o r its c o n t r o l s .
TDialog.WMQueryEndSession p r o c e d u r e W M Q u e r y E n d S e s s i o n ( v a r Msg wm_First + wm_QueryEndSession
: TMessage);
virtual;
T h i s p r o c e d u r e e n d s t h e q u e r y s e s s i o n b y first a s k i n g e a c h a p p l i c a t i o n w h e t h e r the query session should e n d . Uses the W i n d o w s API.
TDlgWindow D i a l o g w i n d o w s d e f i n e d b y T D l g W i n d o w c o m b i n e s o m e o f t h e characteristics o f dialogs a n d s o m e characteristics o f w i n d o w s . A d i a l o g w i n d o w h a s a n a s s o c i a t e d d i a l o g r e s o u r c e that d e s c r i b e s t h e a p p e a r a n c e a n d p o s i t i o n o f its c o n t r o l s . It a l s o h a s a w i n d o w class that c a n specify i c o n s a n d c u r s o r s . T o create a n d display dialog w i n d o w s , use the m o d e l e s s dialog C r e a t e m e t h o d s . D o n ' t use the E x e c u t e m e t h o d .
Fields None.
A — O b j e c t W i n d o w s Objects
Methods Init Create GetWindowClass
Methods TDlgWindow.Init constructor Init(AParent: PWindowsObject; AName: PChar); C o n s t r u c t s a n e w TDlgWindow o b j e c t b y s e n d i n g TDialog. Init a m e s s a g e . Init a l s o s e n d s a m e s s a g e t o EnableAutoCreate t o e n s u r e that t h e TDlgWindow o b j e c t a u t o m a t i c a l l y is c r e a t e d a n d d i s p l a y e d a l o n g w i t h its p a r e n t window.
TDlgWindow.Create function Create: Boolean; virtual; ( O v e r r i d e : n e v e r ) R e g i s t e r s t h e d i a l o g w i n d o w ' s class a n d s e n d s a m e s s a g e t o
TDialog.Create. Create r e t u r n s T r u e if s u c c e s s f u l .
TDlgWindow.GetWindowClass procedure GetWindowClass(var AWndClass: TWndClass); virtual; ( O v e r r i d e : o f t e n ) D e f i n e s t h e d e f a u l t w i n d o w class r e c o r d a n d p a s s e s it b a c k i n AWndClass. T h i s w i n d o w class s p e c i f i e s a s t a n d a r d i c o n a n d c u r s o r .
R e d e f i n e GetWindowClass ( a n d GetClassName) f o r a n y TDlgWindow descendants. A l s o , m a k e s u r e that y o u r GetWindowClass m e t h o d s e n d s a m e s s a g e t o GetWindowClass b e f o r e m o d i f y i n g a n y TWndClass f i e l d s .
TDosStream TDosStream is a s p e c i a l i z e d TStream i m p l e m e n t i n g u n b u f f e r e d D O S file s t r e a m s . Its c o n s t r u c t o r , Init, lets y o u c r e a t e o r o p e n a D O S file b y s p e c i f y i n g its n a m e a n d a c c e s s m o d e : e i t h e r stCreate, stOpenRead, stOpenWrite, o r
stOpen.
437
438
Part I I I — R e f e r e n c e s
T D o s S t r e a m h a s o n e f i e l d n e w f i e l d , Handle, w h i c h r e p r e s e n t s t h e D O S file h a n d l e u s e d t o a c c e s s a n o p e n file. M o s t a p p l i c a t i o n s u s e t h e b u f f e r e d derivative o f T D o s S t r e a m c a l l e d TBuf S t r e a m . T D o s S t r e a m o v e r r i d e s all t h e abstract m e t h o d s o f T S t r e a m e x c e p t f o r T S t r e a m . Flush.
Fields Handle
Methods Init Done GetPos GetSize Read Seek Truncate Write
Fields TDosStream.Handle Handle: Word (read o n l y ) Handle is t h e D O S file h a n d l e u s e d to a c c e s s a n o p e n file s t r e a m .
Methods TDosStream.Init constructor Init(FileName: FNameStr; Mode: Word); C r e a t e s a D O S file s t r e a m w i t h FileName a n d a c c e s s Mode. I f s u c c e s s f u l , t h e Handle is set w i t h t h e D O S file h a n d l e . F a i l u r e is i n d i c a t e d b y a m e s s a g e t o Error w i t h a n a r g u m e n t of stlnitError. T h e Mode a r g u m e n t m u s t b e s e t e i t h e r : stCreate, stOpenRead, stOpenWrite, or stOpen.
A—ObjectWindows Objects
TDosStream.Done destructor Done; virtual; ( O v e r r i d e : n e v e r ) C l o s e s a n d d i s p o s e s o f t h e D O S file s t r e a m .
TDosStream.GetPos function GetPos: Longint; virtual; (Override: never) Returns the value o f the calling stream's current position.
TDosStream.GetSize function GetSize: Longint; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e size i n b y t e s o f t h e c a l l i n g s t r e a m .
TDosStream.Read procedure Read(var Buf; Count: Word); virtual; ( O v e r r i d e : n e v e r ) R e a d s Count bytes i n t o t h e Buf b u f f e r starting at t h e c a l l i n g stream's current position.
TDosStream.Seek procedure Seek(Pos: Longint); virtual; ( O v e r r i d e : n e v e r ) R e s e t s t h e c u r r e n t p o s i t i o n t o Pos b y t e s f r o m t h e b e g i n n i n g o f the calling stream.
TDosStream.Thincate procedure Truncate; virtual; ( O v e r r i d e : n e v e r ) D e l e t e s all d a t a o n t h e c a l l i n g s t r e a m f r o m t h e c u r r e n t position to the e n d o f the stream.
TDosStream.Write procedure Write(var Buf; Count: Word); virtual; W r i t e s Count b y t e s f r o m t h e Buf b u f f e r t o t h e c a l l i n g s t r e a m , starting at t h e current position.
439
440
Part I I I — R e f e r e n c e s
TEdit TEdit is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a n e d i t c o n t r o l e l e m e n t i n Windows. Y o u u s u a l l y d o n ' t u s e TEdit o b j e c t s i n d i a l o g b o x e s (TDialog) o r d i a l o g w i n d o w s (TDlgWindow). R a t h e r , y o u u s e t h e m t o d i s p l a y a s t a n d - a l o n e e d i t c o n t r o l as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a . T h e r e are t w o styles o f e d i t c o n t r o l o b j e c t s : s i n g l e - a n d m u l t i l i n e . M u l t i l i n e e d i t c o n t r o l s c a n u s e vertical s c r o l l b a r s a n d a l l o w t h e e d i t i n g o f m u l t i p l e l i n e s . M o s t o f TEdit's m e t h o d s m a n a g e t h e e d i t c o n t r o l ' s text. TEdit i n c l u d e s several c o m m a n d - b a s e d m e s s a g e - r e s p o n s e m e t h o d s f o r r e s p o n d i n g a u t o m a t i c a l l y t o C u t , C o p y , Paste, D e l e t e , C l e a r , a n d U n d o m e n u selections f r o m the edit control's parent w i n d o w . GetText a n d SetText a r e i n h e r i t e d f r o m TEdit's a n c e s t o r , TStatic.
Fields None.
Methods Init CanUndo ClearModify CMEditClear CMEditCopy CMEditCut CMEditDelete CMEditPaste CMEditUndo Copy Cut DeleteLine DeleteSelection DeleteSubText GetClassName GetLine GetLineFromPos GetLinelndex GetLineLength GetNumLines
A—ObjectWindows Objects
GetSelection GetSubText Insert IsModified Paste Scroll Search SetSelection SetupWindow Transfer Undo
Methods TEditlnit constructor Init(AParent: A T i t l e : PChar; X,Y,W,H:
PWindowsObject; A n l d : I n t e g e r ; Integer; Multiline : Boolean);
( O v e r r i d e : s o m e t i m e s ) C o n s t r u c t s a n edit c o n t r o l o b j e c t w i t h a p a r e n t w i n d o w (AParent). It fills its A t t r f i e l d s w i t h t h e f o l l o w i n g i n f o r m a t i o n : • Passed control I D (Anld) • Initial text ( A T i t l e ) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) If M u l t i l i n e is T r u e , t h e edit c o n t r o l is a m u l t i l i n e e d i t c o n t r o l w i t h h o r i z o n t a l a n d vertical s c r o l l b a r s . I n this c a s e , t h e A t t r . S t y l e field i n c l u d e s the Windows s t y l e c o n s t a n t s e s _ M u l t i l i n e , e s _ A u t o V S c r o l l , e s _ A u t o H S c r o l l , e s _ L e f t, w s _ V S c r o l l , and w s _ H S c r o l l . If M u l t i l i n e is F a l s e , t h e edit c o n t r o l h a s a s i n g l e l i n e o f text a n d a b o r d e r ( w s _ B o r d e r ) , a n d is left-justified ( e s _ L e f t ) .
TEditCanUndo function
CanUndo:
Boolean;
virtual;
( O v e r r i d e : s e l d o m ) R e t u r n s T r u e if it's p o s s i b l e t o u n d o t h e last edit.
441
442
Part I I I — R e f e r e n c e s
TEdit.ClearModify procedure ClearModify; virtual; ( O v e r r i d e : s e l d o m ) R e s e t s t h e c h a n g e s flag f o r t h e edit c o n t r o l .
TEdit.CMEditClear procedure CMEditClear(var Msg: TMessage); virtual; cm_First + cm_EditClear; (Override: never) Automatically responds to a m e n u selection with a m e n u I D o f cm_EditClear b y s e n d i n g a m e s s a g e t o t h e Clear m e t h o d .
TEdit.CMEditCopy procedure CMEditCopy(var Msg: TMessage); virtual; cm_First + cm_EditCopy; (Override: never) Automatically responds to a m e n u selection with a m e n u I D o f cm_EditCopy b y s e n d i n g a m e s s a g e t o t h e Copy m e t h o d .
TEdit.CMEditCut procedure CMEditCut(var Msg: TMessage); virtual; cm_First + cm_EditCut; (Override: never) Automatically responds to a m e n u selection with a m e n u I D o f cm_EditCut b y s e n d i n g a m e s s a g e t o t h e Cut m e t h o d .
TEdit.CMEditDelete procedure CMEditDelete(var Msg: TMessage); virtual; cm_First + cm_EditDelete; (Override: never) Automatically responds t o a m e n u selection with a m e n u I D o f c m E d i t D e l e t e b y s e n d i n g a m e s s a g e t o t h e DeleteSelection m e t h o d .
TEdit.CMEditPaste procedure CMEditPaste(var Msg: TMessage); virtual; cm_First + cm_EditPaste; ( O v e r r i d e : n e v e r ) A u t o m a t i c a l l y r e s p o n d s t o a m e n u s e l e c t i o n w i t h a m e n u ID o f cm_EditPaste b y s e n d i n g a m e s s a g e t o t h e Paste m e t h o d .
A—ObjectWindows Objects
443
TEdit.CMEditUndo procedure CMEditUndo(var cm_First
Msg:
TMessage);
virtual;
+ cm_EditUndo;
(Override: never) Automatically responds to a m e n u selection with a m e n u I D o f c m E d i t U n d o b y s e n d i n g a m e s s a g e t o t h e Undo m e t h o d .
TEditCopy procedure Copy;
virtual;
( O v e r r i d e : s e l d o m ) C o p i e s a n y c u r r e n t l y s e l e c t e d text i n t o t h e c l i p b o a r d .
TEditCut procedure Cut;
virtual;
( O v e r r i d e : s e l d o m ) C u t s (that is, c o p i e s a n d d e l e t e s ) a n y c u r r e n t l y s e l e c t e d text into the clipboard.
TCditDeleteline function
DeleteLine{LineNumber:
Integer):
Boolean;
virtual;
( O v e r r i d e : s o m e t i m e s ) D e l e t e s t h e text i n t h e l i n e s p e c i f i e d b y L i n e N u m b e r i n a m u l t i l i n e edit c o n t r o l . D e l e t e L i n e d o e s n ' t d e l e t e t h e l i n e b r e a k a n d h a s n o effect o n o t h e r l i n e s . D e l e t e L i n e r e t u r n s T r u e if s u c c e s s f u l .
TEdit.DeleteSelection function
DeleteSelection:
Boolean;
virtual;
( O v e r r i d e : s e l d o m ) C l e a r s t h e c u r r e n t l y s e l e c t e d text a n d r e t u r n s F a l s e if n o text is s e l e c t e d .
TEdit.DeleteSubText function
DeleteSubText(StartPos,
EndPos:
Integer):
Boolean;
virtual;
( O v e r r i d e : s e l d o m ) D e l e t e s t h e text b e t w e e n t h e starting a n d e n d i n g p o s i t i o n s specified by S t a r t P o s and EndPos. T h e first c h a r a c t e r is at p o s i t i o n 0 , a n d t h e p o s i t i o n n u m b e r s c o n t i n u e s e q u e n t i a l l y t h r o u g h o u t all l i n e s i n a m u l t i l i n e e d i t c o n t r o l . L i n e b r e a k s are c o u n t e d as t w o c h a r a c t e r s . D e l e t e S u b T e x t r e t u r n s T r u e if s u c c e s s f u l .
444
Part I I I — R e f e r e n c e s
TEdit.GetClassName function GetClassName: PChar; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e n a m e o f TEdit's w i n d o w c l a s s , Edit.
TEditGetLine function GetLine(ATextString: PChar; StrSize, LineNumber: Integer): Boolean; virtual; ( O v e r r i d e : s e l d o m ) G e t s a m u l t i l i n e edit c o n t r o l ' s text f r o m t h e l i n e s p e c i f i e d b y LineNumber a n d r e t u r n s it i n ATextString. StrSize i n d i c a t e s t h e n u m b e r o f c h a r a c t e r s t o retrieve. GetLine r e t u r n s False if it's u n a b l e t o retrieve t h e text o r if t h e text is t o o long.
TEdit.GetIineFromPos function GetLineFromPos(CharPos: Integer): Integer; virtual; (Override: s e l d o m ) Returns f r o m a multiline edit control the line n u m b e r w h e r e t h e c h a r a c t e r p o s i t i o n s p e c i f i e d byCharPos o c c u r s . T h e p o s i t i o n o f t h e first c h a r a c t e r is 0 a n d t h e n u m b e r s c o n t i n u e s e q u e n t i a l l y t h r o u g h o u t all t h e l i n e s . L i n e b r e a k s are c o u n t e d as t w o c h a r a c t e r s .
TEdit.GetIineIndex function GetLineIndex(LineNumber: Integer): Integer; virtual; (Override: s e l d o m ) Returns f r o m a multiline edit control the n u m b e r o f c h a r a c t e r s that a p p e a r b e f o r e t h e l i n e n u m b e r s p e c i f i e d b y LineNumber. L i n e b r e a k s a r e c o u n t e d as t w o c h a r a c t e r s . If t h e l i n e d o e s n ' t exist, GetLinelndex r e t u r n s t h e n u m b e r o f c h a r a c t e r s in t h e edit control.
TEdit.GetIineLength function GetLineLength(LineNumber: Integer): Integer; virtual; (Override: s e l d o m ) Returns f r o m a multiline edit control the n u m b e r o f c h a r a c t e r s i n t h e l i n e s p e c i f i e d b y LineNumber. Note: S e n d GetLine a m e s s a g e b e f o r e y o u s e n d GetLineLength a m e s s a g e .
A — O b j e c t W i n d o w s Objects
445
TEdit.GetNumIines function GetNumLines: Integer; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s t h e n u m b e r of l i n e s that h a v e b e e n e n t e r e d i n a multiline edit control. ( S e n d GetNumLines a m e s s a g e b e f o r e y o u s e n d GetLinea m e s s a g e . )
TEdit.GetSelection procedure GetSelection(var StartPos, EndPos: Integer); virtual; ( O v e r r i d e : s e l d o m ) G e t s t h e starting a n d e n d i n g p o s i t i o n s of t h e c u r r e n t l y s e l e c t e d text a n d r e t u r n s t h e m i n t h e StartPos a n d EndPos a r g u m e n t s . T h e first c h a r a c t e r is at p o s i t i o n 0. I n a m u l t i l i n e edit c o n t r o l , t h e p o s i t i o n s are c o u n t e d s e q u e n t i a l l y t h r o u g h all l i n e s , a n d l i n e b r e a k s a r e c o u n t e d as t w o c h a r a c t e r s . U s e GetSelection w i t h GetSubText t o g e t t h e c u r r e n t l y s e l e c t e d text.
TEditGetSubText procedure GetSubText(ATextString:
PChar; StartPos, EndPos: Integer); virtual;
( O v e r r i d e : s e l d o m ) G e t s (in ATextString) t h e text i n a n e d i t c o n t r o l f r o m t h e i n d i c e s StartPos t o EndPos. T h e first c h a r a c t e r is at i n d e x 0. I n a multiline edit control, the characters are c o u n t e d sequentially t h r o u g h all t h e l i n e s , a n d l i n e b r e a k s a r e c o u n t e d as t w o c h a r a c t e r s .
TEditlnsert procedure Insert(ATextString: PChar); virtual; ( O v e r r i d e : s e l d o m ) I n s e r t s t h e text p a s s e d i n AText St r ing i n t o t h e e d i t c o n t r o l at t h e c u r r e n t t e x t - i n s e r t i o n p o i n t , r e p l a c i n g a n y c u r r e n t l y s e l e c t e d text. Insert is s i m i l a r t o Paste, b u t d o e s n ' t affect t h e c l i p b o a r d .
TEditJsModified function IsModified: Boolean; virtual; ( O v e r r i d e : s e l d o m ) I f t h e u s e r h a s c h a n g e d t h e text i n t h e e d i t c o n t r o l , IsModified r e t u r n s T r u e .
446
Part III—References
TEditPaste procedure Paste;
virtual;
( O v e r r i d e : s e l d o m ) Inserts text f r o m t h e c l i p b o a r d i n t o t h e e d i t c o n t r o l at t h e current insertion point.
TEdit.Scroll procedure S c r o l l ( H o r i z o n t a l U n i t ,
VerticalUnit:
Integer);
virtual;
( O v e r r i d e : s e l d o m ) S c r o l l s a m u l t i l i n e e d i t c o n t r o l h o r i z o n t a l l y a n d vertically b y the n u m b e r s of characters specified by H o r i z o n t a l U n i t a n d V e r t i c a l U n i t . Positive v a l u e s s c r o l l t o t h e right o r d o w n , a n d n e g a t i v e v a l u e s s c r o l l t o t h e left o r u p .
TEditSearch procedure S e a r c h ( S t a r t P o s : I n t e g e r ; AText: CaseSensitive: Boolean): Integer;
PChar;
S e a r c h s e a r c h e s t h e e d i t c o n t r o l ' s text ( b e g i n n i n g w i t h t h e c h a r a c t e r at S t a r t P o s ) u n t i l it f i n d s a m a t c h f o r A T e x t . • If t h e text is f o u n d , t h e m a t c h i n g text is s e l e c t e d , a n d S e a r c h r e t u r n s t h e p o s i t i o n o f t h e start o f t h e m a t c h e d text. • If A T e x t isn't f o u n d , S e a r c h r e t u r n s - 1 . Pass - 1 i n S t a r t P o s t o b e g i n t h e s e a r c h at t h e c u r r e n t p o s i t i o n .
TEditSetSelection function
SetSelection(StartPos,
EndPos:
Integer):
Boolean;
virtual
( O v e r r i d e : s e l d o m ) F o r c e s s e l e c t i o n o f t h e text b e t w e e n t h e p o s i t i o n s s p e c i f i e d b y S t a r t P o s a n d E n d P o s , b u t n o t i n c l u d i n g t h e c h a r a c t e r at E n d P o s . T h e first c h a r a c t e r is at p o s i t i o n 0, a n d t h e p o s i t i o n n u m b e r s c o n t i n u e s e q u e n t i a l l y t h r o u g h all l i n e s i n a m u l t i l i n e edit c o n t r o l . L i n e b r e a k s are c o u n t e d as t w o c h a r a c t e r s .
A—ObjectWindows Objects
447
TEdit.SetupWindow procedure SetupWindow;
virtual;
L i m i t s t h e n u m b e r o f c h a r c t e r s that c a n b e e n t e r e d i n t o t h e edit c o n t r o l b y sending a message to T S t a t i c . SetupWindow. I f t h e T e x t L e n f i e l d is n o n z e r o , t h e v a l u e T e x t L e n -1 is s e n t t o W i n d o w s though an e m _ L i m i t T e x t message.
TEdit.Transfer function
Transfer(DataPtr:
Pointer;
TransferFlag:
W o r d ) : Word;
( O v e r r i d e : s o m e t i m e s ) T r a n s f e r s T e x t L e n c h a r a c t e r s o f t h e c u r r e n t text o f t h e edit control to or f r o m the m e m o r y location p o i n t e d to by D a t a P t r . • If T r a n s f e r F l a g is t f _ G e t D a t a , t h e text is t r a n s f e r r e d t o t h e m e m o r y location. • If T r a n s f e r F l a g is t f _ S e t D a t a , t h e edit c o n t r o l ' s text is set t o t h e text at t h e m e m o r y l o c a t i o n . T r a n s f e r r e t u r n s T e x t L e n (the n u m b e r o f bytes stored in o r retrieved f r o m the m e m o r y location). • If T r a n s f e r F l a g is t f _ S i z e D a t a , T r a n s f e r r e t u r n s t h e size o f t h e transfer d a t a .
TEditUndo procedure
Undo;
virtual;
( O v e r r i d e : s e l d o m ) U n d o e s t h e last edit.
TEmsStream TEmsSt rearn is a s p e c i a l i z e d T S t ream f o r i m p l e m e n t i n g s t r e a m s i n E M S m e m o r y . T E m s S t ream's n e w fields set u p a n E M S h a n d l e , a p a g e c o u n t , s t r e a m s i z e , a n d c u r r e n t p o s i t i o n . T E m s S t r e a m o v e r r i d e s t h e six abstract m e t h o d s o f T S t r e a m a n d i m p l e m e n t s its o w n s p e c i a l i z e d c o n s t r u c t o r a n d d e s t r u c t o r . W h e n y o u d e b u g an application using E M S streams, the I D E cannot r e c o v e r E M S m e m o r y a l l o c a t e d b y a p p l i c a t i o n s if a n a p p l i c a t i o n t e r m i n a t e s p r e m a t u r e l y o r if y o u d o n ' t s e n d a m e s s a g e t o t h e (Done) d e s t r u c t o r f o r a n E M S s t r e a m . O n l y t h e Done m e t h o d ( o r r e b o o t i n g ) c a n r e l e a s e t h e E M S p a g e s o w n e d by the stream.
virtual;
448
Part I I I — R e f e r e n c e s
Fields Handle PageCount Size Position
Methods Init Done GetPos GetSize Read Seek Truncate Write
Fields TEmsStream.Handle Handle: Word; ( r e a d o n l y ) T h e E M S handle for the stream.
TEmsStream.PageCount PageCount: W o r d ; (read o n l y ) T h e n u m b e r o f allocated pages for the stream: 16K p e r page.
TEmsStream.Size Size: Longint; ( r e a d o n l y ) T h e size o f t h e s t r e a m i n b y t e s .
TEmsStream.Position Position: Longint; (read o n l y ) T h e c u r r e n t p o s i t i o n w i t h i n t h e s t r e a m . T h e first p o s i t i o n is 0.
A—ObjectWindows Objects
Methods TEmsStream.Init constructor Init(MinSize: Longint); C r e a t e s a n E M S s t r e a m w i t h t h e MinSize ( i n b y t e s ) . S e n d s a m e s s a g e t o Init a n d t h e n sets Handle, Size a n d PageCount. S e n d s a m e s s a g e t o Error w i t h a n a r g u m e n t of st I nit Error if i n i t i a l i z a t i o n fails.
TEmsStream.Done destructor Done; virtual; (Override: never) Disposes o f the E M S stream a n d releases E M S pages u s e d .
TEmsStream.GetPos function GetPos: Longint; virtual; (Override: never) Returns the value o f the calling stream's current position.
TEmsStream.GetSize function GetSize: Longint; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e size o f t h e c a l l i n g s t r e a m .
TEmsStream.Read procedure Read(var Buf; Count: Word); virtual; ( O v e r r i d e : n e v e r ) R e a d s Count b y t e s i n t o t h e Buf b u f f e r starting at t h e c a l l i n g stream's current position.
TEmsStream.Seek procedure Seek(Pos: Longint); virtual; ( O v e r r i d e : n e v e r ) R e s e t s t h e c u r r e n t p o s i t i o n t o Pos bytes f r o m t h e start of t h e calling stream.
449
450
Part I I I — R e f e r e n c e s
TEmsStream.Truncate procedure Truncate; virtual; ( O v e r r i d e : n e v e r ) D e l e t e s all d a t a o n t h e c a l l i n g s t r e a m f r o m t h e c u r r e n t p o s i t i o n t o t h e e n d . T h e c u r r e n t p o s i t i o n is set t o t h e n e w e n d o f t h e s t r e a m .
TEmsStream.Write procedure Write(var Buf; Count: Word); virtual; ( O v e r r i d e : n e v e r ) W r i t e s Count b y t e s from t h e Buf b u f f e r t o t h e c a l l i n g s t r e a m , starting at t h e c u r r e n t p o s i t i o n .
TGroupBox TGroupBox is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a g r o u p b o x e l e m e n t i n Windows. N o r m a l l y , y o u d o n ' t u s e TGroupBox o b j e c t s i n d i a l o g b o x e s (TDialog) o r d i a l o g w i n d o w s (TDlgWindow). R a t h e r , y o u u s e t h e m w h e n y o u w a n t t o d i s p l a y a s t a n d - a l o n e g r o u p b o x as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a . G r o u p b o x e s unify a g r o u p o f selection boxes (check b o x e s a n d radio b u t t o n s ) a n d m a n a g e t h e states o f t h e i r s e l e c t i o n b o x e s .
Fields NotifyParent
Methods Init Load GetClassName InitResource SelectionChanged Store
A—ObjectWindows Objects
Fields TGroupBox.NotifyParent NotifyParent: Boolean;
(read/write)
I n d i c a t e s w h e t h e r t h e p a r e n t w i l l b e n o t i f i e d w h e n t h e state o f t h e g r o u p b o x ' s selection boxes has changed.
Methods TGroupBox.Init constructor Init(AParent: PWindowsObject; AnID: Integer; AText: PChar; X,Y,W,H: Integer); (Override: sometimes) Constructs a g r o u p b o x object with the following information: • P a s s e d p a r e n t w i n d o w (AParent) • C o n t r o l ID (AnId) • A s s o c i a t e d text (AText) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) S e n d s a m e s s a g e t o TControl. Init a n d t h e n a d d s t h e W i n d o w s style bs_Grou pBox t o t h e g r o u p b o x ' s At t r. Style field. R e m o v e s t h e style ws_TabSt op f r o m t h e g r o u p b o x ' s Attr. Style field. S e t s Notif yParent t o T r u e . B y d e f a u l t , t h e g r o u p b o x ' s p a r e n t is n o t i f i e d w h e n t h e state o f its s e l e c t i o n b o x e s c h a n g e .
TGroupBoxIoad constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a g r o u p b o x f r o m t h e s t r e a m , S, b y s e n d i n g a m e s s a g e t o TControl. Load a n d r e a d i n g t h e a d d i t i o n a l field (Notif yParent) i n t r o d u c e d b y TGroupBox.
451
452
Part I I I — R e f e r e n c e s
TGroupBox.GetClassName function GetClassName: PChar; virtual; ( O v e r r i d e : s o m e t i m e s ) R e t u r n s t h e n a m e o f TGroupBox's w i n d o w class, Button.
TGroupBox.InitResource constructor InitResource(AParent: PWindowsObject; ResourcelD: Word); Subclasses the g r o u p b o x by constructing an ObjectWindows object to corres p o n d to a g r o u p b o x element created by a dialog resource definition. S e n d s a m e s s a g e t o T C o n t r o l . I n i t R e s o u r c e as w e l l as TWindowsObject.DisableTransferto e x c l u d e g r o u p b o x e s f r o m t h e transfer m e c h a n i s m because they have n o data to b e transferred.
TGroupBox.SelectionChanged procedure SelectionChanged(ControlId: Integer); virtual; ( O v e r r i d e : s o m e t i m e s ) If Notif yParent is T r u e , SelectionChanged notifies t h e p a r e n t w i n d o w o f t h e g r o u p b o x that o n e o f its s e l e c t i o n s h a s c h a n g e d b y s e n d i n g it a c h i l d - I D - b a s e d m e s s a g e . Y o u c a n o v e r r i d e this m e t h o d t o let t h e g r o u p b o x r e s p o n d t o its s e l e c t i o n s .
TGroupBox.Store procedure Store(var S: TStream); S t o r e s t h e g r o u p b o x o n t h e s t r e a m , S, b y first s e n d i n g a m e s s a g e t o TControl. Store a n d t h e n w r i t i n g t h e a d d i t i o n a l field (Notif yParent) i n t r o d u c e d b y TGroupBox.
TlistBox TListBox is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a list b o x e l e m e n t i n Windows. U s u a l l y , y o u d o n ' t u s e TListBox o b j e c t s i n d i a l o g b o x e s (TDialog) or d i a l o g w i n d o w s (TDlgWindow). R a t h e r , y o u d i s p l a y a s t a n d - a l o n e list b o x as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t area. TListBox's m e t h o d s a l s o serve o b j e c t i n s t a n c e s o f its d e s c e n d a n t , TComboBox.
A—ObjectWindows Objects
453
Fields None.
Methods Init AddString ClearList DeleteString GetClassName GetCount GetMsgID GetSellndex GetSelString GetStringLen GetString InsertString SetSellndex SetSelString Transfer
Methods TIistBox.Init constructor Init(AParent: PWindowsObject; Anld: Integer; X,Y, W,H: Integer); ( O v e r r i d e : s o m e t i m e s ) C o n s t r u c t s a list b o x o b j e c t w i t h t h e f o l l o w i n g parameters: • P a s s e d p a r e n t w i n d o w (AParent) • Control I D (Anld) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) I nit s e n d s a m e s s a g e t o TCont rol. I nit a n d a d d s t o t h e list b o x o b j e c t ' s Att r. Style field t h e W i n d o w s style c o n s t a n t lbs_Standard, w h i c h s u p p l i e s the scroll b a r with the following
454
Part I I I — R e f e r e n c e s
• A b o r d e r (ws_Border) • A vertical s c r o l l b a r (ws_VScroll) • A u t o m a t i c a l p h a b e t i c s o r t i n g o f list i t e m s (lbs_Sort) • P a r e n t w i n d o w n o t i f i c a t i o n u p o n s e l e c t i o n (lbsNotif y) Y o u c a n o v e r r i d e t h e s e styles i n a d e s c e n d a n t c l a s s , o r i n t h e Init c o n s t r u c t o r o f t h e list b o x ' s p a r e n t w i n d o w o b j e c t .
TlistBoxAddString function AddString(AString: PChar): Integer; virtual; ( O v e r r i d e : s o m e t i m e s ) A d d s AString as a list i t e m i n t h e list b o x o b j e c t , a n d r e t u r n s t h e i t e m ' s p o s i t i o n i n d e x (starting at 0) o r a n e g a t i v e v a l u e i n c a s e o f an error. List i t e m s a r e s o r t e d a u t o m a t i c a l l y u n l e s s t h e style l b s S o r t is r e m o v e d f r o m t h e list b o x o b j e c t ' s Attr. Style field b e f o r e t h e list b o x is c r e a t e d .
TIistBox.ClearList procedure ClearList; virtual; ( O v e r r i d e : s o m e t i m e s ) R e m o v e s all (list) i t e m s f r o m t h e list b o x .
TIistBox.DeleteString function DeleteString(Index:
Integer): Integer; virtual;
( O v e r r i d e : s o m e t i m e s ) R e m o v e s t h e list i t e m at t h e p o s i t i o n i n d e x (starting at 0) p a s s e d i n Index. DeleteString r e t u r n s t h e n u m b e r o f r e m a i n i n g list i t e m s , or a negative value in case o f a n error.
TListBox.GetClassName function GetClassName: PChar; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e n a m e o f t h e TListBox w i n d o w class, List Box.
TListBox.GetCount function GetCount: Integer; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s t h e n u m b e r o f list i t e m s i n t h e list b o x , o r a n e g a t i v e value in case o f a n error.
A—ObjectWindows Objects
455
TListBox.GetMsgID function GetMsgID(AMsg: TMsgName): virtual; T r a n s l a t e s list b o x m e s s a g e s f o r TComboBox o b j e c t s . T h i s m e t h o d is private available t o t h e p r o g r a m m e r ) .
(not
TListBox.SelIndex function GetSellndex: Integer; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s t h e p o s i t i o n i n d e x (starting at 0) o f t h e c u r r e n t l y s e l e c t e d list i t e m , o r a n e g a t i v e v a l u e i n c a s e n o i t e m is s e l e c t e d .
TListBox.GetSelString function GetSelString(AString:
PChar; MaxChars: Integer):
Integer; virtual; ( O v e r r i d e : s e l d o m ) G e t s t h e c u r r e n t l y s e l e c t e d list i t e m (in AString), if it's s h o r t e r t h a n MaxChars. GetSelString r e t u r n s t h e string l e n g t h o r a n e g a t i v e v a l u e i n c a s e o f a n error.
TListBox.GetStringLen function GetStringLen(Index:
Integer): Integer; virtual;
( O v e r r i d e : s e l d o m ) R e t u r n s t h e l e n g t h o f t h e list i t e m (a string) at t h e p o s i t i o n Index, o r a n e g a t i v e v a l u e i n c a s e o f a n e r r o r .
TListBox.GetString function GetString(AString: PChar; Index: Integer): Integer; virtual; ( O v e r r i d e : s e l d o m ) G e t s i n AString t h e list i t e m at t h e p o s i t i o n Index, a n d returns t h e string length o r a negative value in case o f a n error.
TListBox.InsertString function InsertString(AString:
PChar; Index: Integer): Integer; virtual;
( O v e r r i d e : s o m e t i m e s ) I n s e r t s AString as a list i t e m i n t h e list b o x at t h e p o s i t i o n I n d e x , a n d r e t u r n s t h e i t e m ' s p o s i t i o n (starting at 0) o r a n e g a t i v e v a l u e i n c a s e o f a n e r r o r . T h e list b o x i t e m s a r e n ' t r e s o r t e d . I f Index is - 1 , t h e string is a d d e d t o t h e e n d o f t h e list.
456
Part I I I — R e f e r e n c e s
TListBox.SetSelIndex function
SetSelIndex(Index:
Integer):
Integer;
virtual;
( O v e r r i d e : s e l d o m ) F o r c e s s e l e c t i o n o f t h e list i t e m at t h e p o s i t i o n I n d e x . If I n d e x is - 1 , t h e list b o x is c l e a r e d o f a n y s e l e c t i o n . S e t S e l l n d e x returns a negative n u m b e r in case o f an error.
TIistBox.SetSelString function
SetSelString(AString:
PChar;
AIndex:
Integer):
Integer;
virtual;
( O v e r r i d e : s e l d o m ) F o r c e s s e l e c t i o n o f t h e first list i t e m m a t c h i n g A S t r i n g that a p p e a r s after t h e p o s i t i o n i n d e x ( b e g i n n i n g at 0) p a s s e d i n A I n d e x . If A I n d e x i s - 1 , t h e e n t i r e list is s e a r c h e d from t h e b e g i n n i n g . S e t S e l S t r i n g returns the position index of the newly selected item, or a negative value in case o f an error.
TIistBox.Thnsfef function
Transfer(DataPtr:
Pointer;
TransferFlag:
W o r d ) : Word;
T r a n s f e r s t h e list o f e n t r i e s a n d s e l e c t e d i t e m ( s ) t o o r f r o m t h e transfer r e c o r d pointed to by D a t a P t r . • If T r a n s f e r F l a g is t f _ G e t D a t a , t h e list b o x ' s d a t a is t r a n s f e r r e d t o t h e m e m o r y l o c a t i o n . T h e n u m b e r o f b y t e s t r a n s f e r r e d is r e t u r n e d . • If T r a n s f e r F l a g is t f _ S e t D a t a , t h e list b o x is l o a d e d w i t h t h e data from the m e m o r y location. T h e n u m b e r o f bytes transferred is r e t u r n e d . • If T r a n s f e r F l a g is t f _ S i z e D a t a , T r a n s f e r r e t u r n s t h e size o f t h e transfer d a t a . D e p e n d i n g o n where the b o x allows multiple items to be selected, the transfer r e c o r d v a r i e s . T h e first i t e m t r a n s f e r r e d is always a p o i n t e r t o a collection o f strings. • F o r s i n g l e - s e l e c t i o n list b o x e s , t h e p o i n t e r is f o l l o w e d b y a n i n t e g e r index to the selected item. • F o r m u l t i p l e - s e l e c t i o n list b o x e s , t h e c o l l e c t i o n is f o l l o w e d b y a p o i n t e r t o a T M u l t i S e l R e c r e c o r d , w h i c h c o n t a i n s a n array o f i n t e g e r s , e a c h indicating a selected item.
virtual;
A — O b j e c t W i n d o w s Objects
TMDIClient Multiple D o c u m e n t Interface ( M D I ) client w i n d o w s (represented by TMDIClient) a r e c o n t r o l s that m a n a g e t h e M D I c h i l d w i n d o w s o f a n M D I a p p l i c a t i o n . TMDIClient's m e t h o d s m a n a g e M D I c h i l d w i n d o w s .
Fields ClientAttr
Methods Init Load Arrangelcons CascadeChildren GetClassName Store TileChildren
Fields TMDIClient.ClientAttr ClientAttr:
TClientCreateStruct;
ClientAttr m a i n t a i n s a r e c o r d o f t h e M D I c l i e n t w i n d o w ' s a t t r i b u t e s . T h e r e c o r d (TClientCreateStruct) is d e f i n e d as f o l l o w s :
type PClientCreateStruct = "TClientCreateStruct; TClientCreateStruct = record hWindowMenu: THandle; idFirstChild: Word; end;
457
458
Part I I I — R e f e r e n c e s
Methods TMDICUent.Init constructor Init(AParent: PMDIWindow); ( O v e r r i d e : s e l d o m ) C o n s t r u c t s t h e M D I c l i e n t w i n d o w o b j e c t w i t h AParent as t h e p a r e n t w i n d o w . Init s e t s t h e f i e l d s o f ClientAttr. T h e n s e n d s TControl. Init a m e s s a g e a n d a d d s t h e W i n d o w s style ws_ClipChildren t o t h e w i n d o w o b j e c t ' s Attr. Style field. Init a l s o r e m o v e s t h e c l i e n t w i n d o w f r o m its p a r e n t ' s c h i l d w i n d o w list s o that t h e c l i e n t w i n d o w isn't t r e a t e d like o t h e r c h i l d w i n d o w s , s u c h as list boxes and buttons.
TMDIClient.Load constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a n M D I c l i e n t w i n d o w f r o m t h e s t r e a m , S, b y first s e n d i n g TControl. Load a m e s s a g e a n d t h e n r e a d i n g t h e a d d i t i o n a l f i e l d (ClientAttr) i n t r o d u c e d b y TMDIClient.
TMDIClient.ArrangeIcons procedure Arrangelcons; virtual; (Override: seldom) Arranges the m i n i m i z e d M D I child w i n d o w s into a neat r o w at t h e b o t t o m o f t h e M D I c l i e n t w i n d o w .
TMDIClient.CascadeChildren procedure CascadeChildren; virtual; ( O v e r r i d e : s e l d o m ) S i z e s a n d a r r a n g e s all o f t h e n o n m i n i m i z e d MDI c h i l d w i n d o w s w i t h i n t h e MDI c l i e n t w i n d o w .
TMDIClient.GetClassName function GetClassName: PChar; virtual; R e t u r n s TControl's w i n d o w class n a m e , MDIClient.
A — O b j e c t W i n d o w s Objects
TMDIClientStore procedure Store(var S: TStream); S t o r e s t h e M D I c l i e n t w i n d o w o n t h e s t r e a m , S, b y s e n d i n g TControl. Store a m e s s a g e a n d t h e n w r i t i n g t h e a d d i t i o n a l field (ClientAttr) i n t r o d u c e d b y TMDIClient.
TMDIClientTileChildren procedure TileChildren; virtual; ( O v e r r i d e : s e l d o m ) S i z e s a n d a r r a n g e s all t h e n o n m i n i m i z e d MDI c h i l d w i n d o w s w i t h i n t h e M D I c l i e n t w i n d o w u s i n g all available s p a c e w i t h o u t l e t t i n g t h e windows overlap.
TMDIWindow Multiple D o c u m e n t Interface (MDI) frame w i n d o w (defined by TMDIWindow)— the main w i n d o w o f MDI-compliant applications. TMDIWindow o b j e c t s ownaTMDIClient o b j e c t a n d store it i n t h e ClientWnd field. T h e c h i l d w i n d o w m e n u p r e s e n t s m a n i p u l a t i o n o p t i o n s f o r t h e a p p l i c a t i o n ' s M D I c h i l d w i n d o w s . T h i s w i n d o w is m o d i f i e d a u t o m a t i c a l l y t o reflect all displayed M D I child windows.
Fields ChildMenuPos ClientWnd
Methods Init Load Done Arrangelcons CascadeChildren CMCloseChildren CMCreateChild CMTileChildren
459
460
Part I I I — R e f e r e n c e s
CreateChild DefWndProc GetClassName GetClient GetWindowClass InitChild InitClientWindow SetupWindow Store TileChildren
Fields TMDIWindow.ChildMenuPos ChildMenuPos:
Integer;
(read/write)
C h i l d M e n u P o s specifies an i n d e x identifying the position o f the child-window m a n a g e m e n t m e n u . T h e i n d e x c o u n t s o n l y t o p - l e v e l m e n u i t e m s . T h e top-left i t e m is at p o s i t i o n 0.
TMDIWindow.ClientWnd ClientWnd:
PMDIClient;
(read
only)
C l i e n t W n d points to the M D I frame w i n d o w ' s M D I client w i n d o w , an object instance of T M D I C l i e n t .
Methods TMDIWindow.Init constructor
Init(ATitle:
PChar;
AMenu:
HMenu);
(Override: often) Constructs an M D I frame w i n d o w object using the caption p a s s e d i n A T i t l e a n d t h e m e n u p a s s e d i n AMenu. M D I frame w i n d o w s must have m e n u s . A n M D I frame w i n d o w has n o parent w i n d o w , a n d must b e the m a i n w i n d o w of the application. By default, I n i t sets C h i l d M e n u P o s t o 0, i n d i c a t i n g that t h e c h i l d w i n d o w m e n u is t h e t o p left m e n u . T o modify C h i l d M e n u P o s , override I n i t in y o u r descendant types. For example:
A—ObjectWindows Objects
constructor NewMDIWindow.Init(ATitle: PChar; AMenu: HMenu); begin TMDIWindow.Init(ATitle, AMenu); ChildMenuPos := 3; end;
TMDIWindow.Load constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a n M D I frame w i n d o w from t h e s t r e a m , S, b y c a l l i n g TWindow.Load a n d t h e n g e t t i n g a n d r e a d i n g t h e fields (ClientWnd a n d
ChildMenuPos) d e f i n e d b y TMDIWindow.
TMDIWindow.Done destructor Done; virtual; (Override: sometimes) Disposes o f the M D I client w i n d o w object stored in ClientWnd b e f o r e s e n d i n g a m e s s a g e t o TWindow. Done t o d i s p o s e o f t h e M D I frame w i n d o w object.
TMDIWindow.ArrangeIcons procedure Arrangelcons; (Override: seldom) Arranges the minimized M D I child windows into a n e a t r o w at t h e b o t t o m o f t h e M D I c l i e n t w i n d o w . S e n d s a m e s s a g e t o
ClientWnd".Arrangelcons.
TMDIWindow.CascadeChildren procedure CascadeChildren; ( O v e r r i d e : s e l d o m ) S i z e s a n d a r r a n g e s all o f t h e n o n m i n i m i z e d M D I c h i l d w i n d o w s w i t h i n t h e M D I c l i e n t w i n d o w m a k i n g t h e m o v e r l a p . D i s p l a y s t h e title b a r o f e a c h o n e . S e n d s a m e s s a g e t o ClientWnd" .CascadeChildren.
mDIWindow.CMCloseChildren procedure CMCloseChildren(var Msg: TMessage); virtual cm_First + cm_CloseChildren; (Override:
seldom)
Responds
to a menu
selection
with
cm_CloseChildren b y s e n d i n g a m e s s a g e t o CloseChildren.
an ID of
461
462
Part I I I — R e f e r e n c e s
mDIWindow.CMCreateCWld procedure CMCreateChild(var Msg: TMessage); virtual cm_First + cm_CreateChild; (Override: never) Responds to a m e n u selection with a m e n u I D of cm_CreateChild b y s e n d i n g a m e s s a g e t o CreateChild t o c r e a t e a n e w c h i l d window.
TMDIWindow.CMTileChildren procedure CMTileChildren(var Msg: TMessage); virtual cm_First + cm_TileChildren; ( O v e r r i d e : s e l d o m ) R e s p o n d s t o a m e n u s e l e c t i o n w i t h a n I D o f cmTileChild ren b y s e n d i n g a m e s s a g e t o TileChildren.
TMDIWindow.CreateChild function CreateChild:
PWindowsObject;
virtual;
Constructs a n d creates a n e w M D I child w i n d o w by s e n d i n g messages t o InitChild a n d MakeWindow. Y o u d o n ' t h a v e t o o v e r r i d e CreateChild t o handle descendant M D I child w i n d o w types. CreateChild r e t u r n s a p o i n t e r t o t h e n e w M D I c h i l d w i n d o w .
TMDIWindow.DefWndProc procedure DefWndProc(var Msg: TMessage);
virtual;
O v e r r i d e s TWindow's d e f a u l t W i n d o w s m e s s a g e p r o c e s s i n g b y s e n d i n g a m e s s a g e t o t h e W i n d o w s f u n c t i o n Def FrameProc r a t h e r t h a n DefWindowProc.
TMDIWindow.GetClassName function GetClassName:
PChar;
virtual;
( O v e r r i d e : s o m e t i m e s ) R e t u r n s t h e n a m e o f TMDI Window's w i n d o w class n a m e ,
TurboMDIWindow.
TMDIWindow.GetClient function GetClient: PMDIClient;
virtual;
(Override: never) Returns a pointer t o the M D I client w i n d o w stored in
ClientWnd.
A — O b j e c t W i n d o w s Objects
TMDIWindow.GetWindowClass procedure GetWindowClass(var AWndClass: TWndClass); virtual; ( O v e r r i d e : s o m e t i m e s ) M o d i f i e s t h e d e f a u l t w i n d o w class r e c o r d a n d s e n d s it b a c k i n AWndClass. GetWindowClass sets t h e style f i e l d t o 0 t o r e m o v e t h e
styles set b y TWindow.GetWindowClass.
TMDIWindow.InitChad function InitChild: PWindowsObject; virtual; ( O v e r r i d e : o f t e n ) C o n s t r u c t s a n M D I c h i l d w i n d o w o b j e c t (TWindow) w i t h a d e f a u l t c a p t i o n of " M D I C h i l d " a n d r e t u r n s a p o i n t e r t o it. If y o u d e f i n e a n M D I c h i l d w i n d o w t y p e d e s c e n d i n g f r o m TWindow, o v e r r i d e InitChild t o c o n s t r u c t a w i n d o w u s i n g t h e n e w d e f i n e d M D I c h i l d w i n d o w type. For example:
function NewMDIWindow.InitChild: PWindowsObject; begin InitChild := New(PNewMDIChild, Init(@Self, 'New MDI Child Window')); end;
TMDIWindow.InitClientWindow procedure InitClientWindow; virtual; ( O v e r r i d e : s o m e t i m e s ) C o n s t r u c t s t h e M D I c l i e n t w i n d o w as a TMDIClient o b j e c t a n d s t o r e s it i n ClientWnd.
TMDIWindow.SetupWindow procedure SetupWindow; virtual; ( O v e r r i d e : o f t e n ) C o n s t r u c t s t h e M D I c l i e n t w i n d o w (ClientWnd) o b j e c t ' s c o r r e s p o n d i n g w i n d o w e l e m e n t b y s e n d i n g a m e s s a g e t o I nitClientWindow. SetupWindow s e n d s MakeWindow a m e s s a g e t o c r e a t e t h e M D I c l i e n t w i n d o w . If y o u o v e r r i d e SetupWindow i n a d e s c e n d a n t t y p e , s e n d a m e s s a g e t o TMDIWindow.SetupWindow e x p l i c i t l y b e f o r e i m p l e m e n t i n g y o u r a p p l i c a t i o n window's n e w behavior.
463
464
Part I I I — R e f e r e n c e s
TMDIWindow.Store procedure Store(var S: TStream); S t o r e s t h e M D I f r a m e w i n d o w o n t h e s t r e a m , S, b y s e n d i n g a m e s s a g e t o TWindow.Store. It t h e n w r i t e s t h e a d d i t i o n a l f i e l d s (ClientWnd a n d ChildMenuPos) d e f i n e d b y TMDIWindow.
mDIWindowTileCMdren procedure TileChildren; ( O v e r r i d e : s e l d o m ) S i z e s a n d a r r a n g e s all t h e n o n m i n i m i z e d M D I c h i l d w i n d o w s w i t h i n t h e M D I c l i e n t w i n d o w , u s i n g all available w i n d o w s p a c e w i t h o u t o v e r l a p p i n g t h e w i n d o w s . S e n d s a m e s s a g e t o ClientWnd" .TileChildren.
TObject TOb j ect is t h e starting p o i n t o f t h e O b j e c t W i n d o w s o b j e c t h i e r a r c h y . W i t h t h e e x c e p t i o n o f TPoint a n d TRect, all O b j e c t W i n d o w s s t a n d a r d o b j e c t s a r e d e r i v e d (directly o r indirectly) from TOb j ect. A n y o b j e c t that u s e s O b j e c t W i n d o w s s t r e a m s m u s t trace its a n c e s t r y b a c k t o TOb j ect.
Fields None.
Methods Init Free Done
Methods TObjectlnit constructor Init; Allocates space o n the heap for an object. R e c e i v e s a m e s s a g e f r o m all its d e s c e n d a n t o b j e c t s ' c o n s t r u c t o r s .
A — O b j e c t W i n d o w s Objects
TObjectFree procedure Free; D i s p o s e s o f t h e o b j e c t a n d s e n d s a m e s s a g e t o t h e Done d e s t r u c t o r .
TObjectDone destructor Done; virtual; Handles cleanup a n d disposal for dynamic objects.
TRadioButton TRadioButtonisan i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a r a d i o b u t t o n e l e m e n t in W i n d o w s . Y o u n o r m a l l y d o n ' t u s e TRadioButton o b j e c t s i n d i a l o g b o x e s (TDialog) o r d i a l o g w i n d o w s (TDlgWindow). I n s t e a d , u s e t h e m w h e n y o u w a n t t o d i s p l a y a s t a n d - a l o n e r a d i o b u t t o n as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a . A r a d i o b u t t o n is i n o n e o f t w o states: c h e c k e d o r u n c h e c k e d . TRadioButton i n h e r i t s its s t a t e - m a n a g e m e n t m e t h o d s f r o m its a n c e s t o r , TCheckBox. A c h e c k b o x c a n a l s o b e part o f a g r o u p (TGroupBox), w h i c h v i s u a l l y a n d c o n c e p t u a l l y g r o u p s its c o n t r o l s .
Fields None.
Methods Init
Methods TRadioButton.Init constructor Init(AParent: PWindowsObject; AnID: Integer; ATitle: PChar; X,Y,W,H: Integer; AGroup: PGroupBox);
465
466
Part I I I — R e f e r e n c e s
(Override: sometimes) Constructs a radio button object with the following arguments: • P a s s e d p a r e n t w i n d o w (AParent) • C o n t r o l I D (Anld) • A s s o c i a t e d text (ATitle) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) • A s s o c i a t e d g r o u p b o x (AGroup) Init sets t h e c h e c k b o x ' s Att r. Style field t o ws_Child or ws_Visible or bs_RadioButton.
TScrollBar T S c r o l l B a r o b j e c t s r e p r e s e n t s t a n d - a l o n e s c r o l l b a r c o n t r o l s . {Note: T h e s e d o n o t i n c l u d e t h e s c r o l l b a r s that a r e a t t a c h e d t o w i n d o w s . ) S c r o l l b a r s c a n b e vertical ( s c r o l l i n g u p a n d d o w n ) o r h o r i z o n t a l ( s c r o l l i n g right a n d left). M o s t o f T S c r o l l B a r ' s m e t h o d s m a n a g e t h e s c r o l l b a r ' s t h u m b position a n d range. TSc rollBa r m a i n t a i n s a set of m e t h o d s that r e s p o n d a u t o m a t i c a l l y t o t h e W i n d o w s s c r o l l b a r m e s s a g e s wm_HScroll a n d w m V S c r o l l . T h e m e t h o d s , s u c h as SBLineUp a n d SBPageDown, a r e d e f i n e d as notifybased m e t h o d s . T h e y automatically adjust the scroll bar's t h u m b position.
Fields LineMagnitude PageMagnitude
Methods Init Load DeltaPos GetClassName GetPosition GetRange
A—ObjectWindows Objects
SBBottom SBLineDown SBLineUp SBPageDown SBPageUp SBThumbPosition SBThumbTrack SBTop SetPosition SetRange SetupWindow Store Transfer
Fields TScrollBar.IineMagnitude LineMagnitude: Integer; (read/write) LineMagnitude is t h e n u m b e r o f r a n g e u n i t s t o s c r o l l t h e s c r o l l b a r w h e n t h e u s e r clicks o n a s c r o l l b a r ' s a r r o w s t o r e q u e s t a s m a l l (that is, l i n e ) m o v e m e n t . B y d e f a u l t , Init sets LineMagnitude t o 1. A l s o , b y d e f a u l t , SetupWindow sets t h e s c r o l l r a n g e f r o m 0 t o 1 0 0 .
TScrollBar.PageMagnitude PageMagnitude: Integer; (read/write) PageMagnitude is t h e n u m b e r o f r a n g e u n i t s t o s c r o l l t h e s c r o l l b a r w h e n t h e u s e r r e q u e s t s a l a r g e (that i s , p a g e ) m o v e m e n t b y c l i c k i n g i n t h e s c r o l l b a r ' s scrolling area. B y d e f a u l t , Init sets PageMagnitude t o 1 0 . ( B y d e f a u l t , t h e s c r o l l r a n g e is set t o f r o m 0 t o 1 0 0 . )
Methods TScrollBar.Init constructor Init(AParent: PWindowsObject; AnID: Integer; X,Y,W,H: Integer; IsHScrollBar: Boolean);
467
468
Part I I I — R e f e r e n c e s
C o n s t r u c t s a n d initializes a TScrollBar o b j e c t w i t h t h e f o l l o w i n g i n f o r m a t i o n : • Parent w i n d o w (AParent) • An ID as a c o n t r o l I D • A p o s i t i o n o f (X, Y) • A width of W • A height of H T h e s c r o l l b a r is h o r i z o n t a l (style sbs_Horz) if IsHScrollBar is T r u e a n d vertical (style sbs_Vert) if IsHScrollBar is F a l s e . If t h e r e q u e s t e d h e i g h t f o r a h o r i z o n t a l s c r o l l b a r o r t h e r e q u e s t e d w i d t h f o r a vertical s c r o l l b a r is 0, d e f a u l t v a l u e s are set. LineMagnitude is initialized t o 1 a n d PageMagnitude t o 1 0 .
TScrollBar.Load constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a s c r o l l b a r c o n t r o l f r o m t h e s t r e a m , S, b y first s e n d i n g TControl. Load a m e s s a g e a n d t h e n r e a d i n g t h e a d d i t i o n a l fields (LineMagnitude a n d PageMagnitude) d e f i n e d b y TScrollBar.
TScrollBar.DeltaPos function DeltaPos(Delta: Integer): Integer; virtual; ( O v e r r i d e : s e l d o m ) C h a n g e s t h e s c r o l l bar's t h u m b p o s i t i o n b y t h e Delta v a l u e . It s e n d s SetPosition a m e s s a g e . A n e g a t i v e v a l u e m o v e s t h e t h u m b u p o r left. T h e n e w t h u m b p o s i t i o n is returned.
TScrollBar.GetClassName function GetClassName: PChar; virtual; ( O v e r r i d e : n e v e r ) R e t u r n s t h e n a m e ofTScrollBar's w i n d o w class, Scrollbar.
TScrollBar.GetPosition function GetPosition: Integer; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s t h e s c r o l l bar's c u r r e n t t h u m b p o s i t i o n .
A—ObjectWindows Objects
469
TScrollBar.GetRange procedure GetRange(var LoVal, HiVal: Integer); virtual; (Override: s e l d o m ) G e t s the allowed range o f scroll bar t h u m b positions in
LoVal a n d HiVal.
TScrollBar.SBBottom procedure SBBottom(var Msg: TMessage); virtual nf_First + sb_Bottom; ( O v e r r i d e : s e l d o m ) I n r e s p o n s e t o a u s e r r e q u e s t , SBBottom sets t h e t h u m b position to the highest allowable value. This m e t h o d receives a message in response to a scroll-based message
carrying t h e c o d e sb_Bottom. S e n d s a m e s s a g e t o SetPosition.
TScrollBar.SBIineDown procedure SBLineDown(var Msg: TMessage); virtual; nf__First + sb_LineDown; ( O v e r r i d e : s e l d o m ) M o v e s t h e t h u m b p o s i t i o n d o w n o r right byLineMagnitude. SBLineDown r e c e i v e s a m e s s a g e automatically i n r e s p o n s e t o a scrollb a s e d m e s s a g e carrying t h e c o d e sbLineDown. S e n d s SetPositiona m e s s a g e .
TScrollBar.SBLineUp procedure SBLineUp(var Msg: TMessage); virtual; nf_First + sb_Line(Jp; ( O v e r r i d e : s e l d o m ) M o v e s t h e t h u m b p o s i t i o n u p o r left b y t h e LineMagnitude. s b L i n e U p r e c e i v e s a m e s s a g e automatically i n r e s p o n s e t o a s c r o l l - b a s e d m e s s a g e carrying t h e c o d e s b L i n e U p . S e n d s a m e s s a g e t o SetPosition.
TScrollBar.SBPageDown procedure SBPageDown(var Msg: TMessage); virtual; nf_First + sb_PageDown; ( O v e r r i d e : s e l d o m ) M o v e s t h e t h u m b p o s i t i o n d o w n o r right b y Pag eMag n i t u d e. SBPageDown r e c e i v e s a m e s s a g e automatically i n r e s p o n s e t o a s c r o l l b a s e d m e s s a g e carrying t h e c o d e sb_PageDown. S e n d s a m e s s a g e t o SetPosition.
TScrollBar.SBPageUp procedure SBPageUp(var Msg: TMessage); virtual; nf_First + sb_PageUp; ( O v e r r i d e : s e l d o m ) M o v e s t h e t h u m b p o s i t i o n u p o r left byPageMagnitude. SBPageUp r e c e i v e s a m e s s a g e automatically i n r e s p o n s e t o a s c r o l l - b a s e d m e s s a g e carrying t h e c o d e sb_Pagelip. S e n d s a m e s s a g e t o SetPosition.
470
Part I I I — R e f e r e n c e s
TScrollBar.SBThumbPosition procedure SBThumbPosition(var Msg: TMessage); virtual; nf_First + sb_ThumbPosition; (Override: seldom) C h a n g e s the t h u m b position to position chosen by the user a n d p a s s e d i n a scroll-based m e s s a g e c a r r y i n g t h e c o d e sb_ThumbPosition. S e n d s SetPosition a m e s s a g e .
TScrollBar.SBThumbTrack procedure SBThumbTrack(var Msg: TMessage); virtual; nf__First + sb_ThumbTrack; ( O v e r r i d e : s o m e t i m e s ) C h a n g e s t h e t h u m b p o s i t i o n as t h e u s e r d r a g s t h e t h u m b . S e n d s a m e s s a g e t o SetPosition. SBThumbTrack r e c e i v e s a m e s s a g e i n r e s p o n s e t o a scroll-based m e s s a g e c a r r y i n g t h e c o d e sb_ThumbTrack.
TScrollBar.SBTop procedure SBTop(var Msg: TMessage); virtual; nf_First + sb_Top; ( O v e r r i d e : s e l d o m ) I n r e s p o n s e t o a u s e r r e q u e s t , SBTop sets t h e t h u m b position to the lowest allowable value. SBTop r e c e i v e s a m e s s a g e i n r e s p o n s e t o a scroll-based m e s s a g e c a r r y i n g t h e c o d e s b T o p . S e n d s a m e s s a g e t o SetPosition.
TScrollBar.SetPosition procedure SetPosition(ThumbPos: Integer); virtual; ( O v e r r i d e : s o m e t i m e s ) S e t s t h e scroll bar's t h u m b p o s i t i o n t o ThumbPos. • If ThumbPos is h i g h e r t h a n t h e a l l o w a b l e r a n g e , t h e t h u m b p o s i t i o n is set t o t h e h i g h e s t p o s s i b l v a l u e . • If ThumbPos is l o w e r t h a n t h e a l l o w a b l e r a n g e , t h e t h u m b is set t o t h e lowest possible value.
TScroIlBar.SetRange procedure SetRange(LoVal, HiVal: Integer); virtual; ( O v e r r i d e : s e l d o m ) S e t s t h e s c r o l l bar's a l l o w a b l e r a n g e o f t h u m b p o s i t i o n s f r o m LoVal t o HiVal.
A — O b j e c t W i n d o w s Objects
471
TScrollBar.SetupWindow procedure SetupWindow;
virtual;
( O v e r r i d e : s o m e t i m e s ) Initializes t h e s c r o l l b a r ' s r a n g e f r o m 0 to 1 0 0 . T o o v e r r i d e this r a n g e , s e n d a m e s s a g e toSetRange.
TScrollBar.Store procedure Store(var S: TStream); S t o r e s t h e s c r o l l b a r c o n t r o l o n t h e s t r e a m , S, b y s e n d i n g a m e s s a g e to TControl. Store a n d t h e n w r i t i n g t h e fields (LineMagnitude a n d PageMagnitude) d e f i n e d b y TScrollBar.
TScrollBar.Transfer function Transfer(DataPtr: Pointer; TransferFlag: Word): Word; virtual; ( O v e r r i d e : s o m e t i m e s ) T r a n s f e r s t h e s c r o l l b a r ' s r a n g e a n d c u r r e n t p o s i t i o n to o r f r o m t h e m e m o r y l o c a t i o n p o i n t e d to b y DataPtr. • I f Transf erFlag is tf _GetData, a transfer r e c o r d h o l d i n g t h e r a n g e a n d p o s i t i o n is t r a n s f e r r e d to t h e m e m o r y l o c a t i o n . • If Transf erFlag is tf_SetData, t h e transfer r e c o r d at t h e m e m o r y l o c a t i o n c o n t a i n s v a l u e s that a r e u s e d to set t h e r a n g e a n d p o s i t i o n o f the scroll bar. I n b o t h c a s e s , Transfer r e t u r n s t h e n u m b e r o f b y t e s i n t h e m e m o r y location. T h e transfer r e c o r d is d e f i n e d as f o l l o w s : ScrollBarTransferRec = record LowValue: Integer; HighValue: Integer; Position: Integer; end;
TScroller TScroller o b j e c t s a r e part o f t h e Scroller field o f TWindow a n d d e s c e n d a n t objects. A TScroller o b j e c t a d d s a n a u t o m a t i c w i n d o w s c r o l l i n g m e c h a n i s m t o a window. U s u a l l y , y o u c o n s t r u c t a n d m a n i p u l a t e TScroller o b j e c t s f r o m t h e m e t h o d s o f their o w n e r w i n d o w objects.
472
Part I I I — R e f e r e n c e s
Fields AutoMode AutoOrg HasHScrollBar HasVScrollBar TrackMode Window XLine XPage XPos XRange XUnit YLine YPage YPos YRange YUnit
Methods AutoScroll BeginView EndView HScroll Init IsVisibleRect Load ScrollBy ScrollTo SetPageSize SetRange SetSBarRange SetUnits Store VScroll XRangeValue (private) XScrollValue (private) YRangeValue (private) YScrollValue (private)
A—ObjectWindows Objects
Fields TScrollerAutoMode AutoMode:
Boolean;
(read/write)
A u t o M o d e is T r u e if t h e s c r o l l e r is i n a u t o - s c r o l l i n g m o d e . B y d e f a u l t , A u t o M o d e is T r u e .
TScrollerAutoOrg AutoOrg:
Boolean;
A u t o O r g controls the automatic adjustment of the origin of the display context u s e d for painting the w i n d o w . • If A u t o O r g is T r u e (the d e f a u l t ) , t h e o r i g i n o f t h e P a i n t m e t h o d ' s d i s p l a y c o n t e x t is set t o t h e o r i g i n o f t h e s c r o l l e r . • If F a l s e , t h e d i s p l a y c o n t e x t ' s o r i g i n is (0,0) a n d P a i n t m u s t r e a d t h e s c r o l l b a r offsets t o d e t e r m i n e h o w t o p o s i t i o n o b j e c t s o n t h e d i s p l a y context.
TScfoller.HasHScrollBar HasHScrollBar:
Boolean;
(read/Write)
If t h e o w n e r w i n d o w h a s a h o r i z o n t a l w i n d o w s c r o l l b a r , H a s H S c r o l l B a r is True.
TScroller.HasVScrollBar HasVScrollBar:
Boolean;
(read/write)
If t h e o w n e r w i n d o w h a s a vertical w i n d o w s c r o l l b a r , H a s V S c r o l l B a r i s F a l s e .
TScroller.ThckMode TrackMode:
Boolean;
(read/write)
T r a c k M o d e is T r u e if t h e s c r o l l e r a u t o m a t i c a l l y tracks scroll-bar t h u m b m o v e ments by scrolling the w i n d o w . B y d e f a u l t , T r a c k M o d e is T r u e .
473
474
Part I I I — R e f e r e n c e s
TScroller.Window Window: PWindow; ( r e a d o n l y ) W i n d o w p o i n t s t o t h e TScroller's o w n e r w i n d o w .
TScroller.XLine XLine: Integer; (readAvrite) XLine is t h e n u m b e r o f XUnit u n i t s t o s c r o l l h o r i z o n t a l l y i n r e s p o n s e t o a c l i c k o n the scroll bar arrow. T h e d e f a u l t is 1.
TScroller.XPage XPage: Integer; (read/write) XPage is t h e n u m b e r o f XUnit u n i t s t o s c r o l l h o r i z o n t a l l y i n r e s p o n s e t o a c l i c k o n t h e s c r o l l bar's t h u m b a r e a . B y d e f a u l t , XPage is e q u a l t o t h e c u r r e n t w i d t h o f t h e w i n d o w i n XUnit u n i t s . R e s i z i n g t h e w i n d o w u p d a t e s this v a l u e .
TScroller.XPos XPos: Longint; ( r e a d o n l y ) XPos is t h e scroller's c u r r e n t h o r i z o n t a l p o s i t i o n i n t e r m s o f XUnit u n i t s .
TScroUer.XRange XRange: Longint; (read o n l y ) XRange is t h e t o t a l n u m b e r o f h o r i z o n t a l XUnit u n i t s y o u c a n s c r o l l a w i n d o w . A l t h o u g h y o u specify XRange v a l u e s i n t h e Init c o n s t r u c t o r , y o u c a n m o d i f y t h e m later.
TScroller.XUnit XUnit: Integer; ( r e a d o n l y ) XUnit is t h e s m a l l e s t n u m b e r o f d e v i c e u n i t s (pixels) that t h e w i n d o w c a n b e scrolled horizontally. A l t h o u g h y o u specify XUnit v a l u e s i n t h e Init c o n s t r u c t o r , y o u c a n m o d i f y t h e m later.
A — O b j e c t W i n d o w s Objects
TScrollef.YIine YLine: Integer; (read/write) YLine is t h e n u m b e r o f YUnit u n i t s t o s c r o l l vertically i n r e s p o n s e t o a c l i c k o n the scroll bar arrow. T h e d e f a u l t is 1.
TScroller.YPage YPage: Integer; (read/write) YPage is t h e n u m b e r o f YUnit u n i t s t o s c r o l l vertically i n r e s p o n s e t o a c l i c k o n the scroll bar's t h u m b area. B y d e f a u l t , YPage is e q u a l t o t h e c u r r e n t h e i g h t o f t h e w i n d o w i n YUnit u n i t s . R e s i z i n g t h e w i n d o w u p d a t e s this v a l u e .
TScroller.YPos YPos: Longint; ( r e a d o n l y ) Y P o s is t h e s c r o l l e r ' s c u r r e n t vertical p o s i t i o n i n t e r m s o f Y U n i t u n i t s .
TScroller.YRange YRange: Longint; ( r e a d o n l y ) YRange is t h e total n u m b e r o f vertical YUnit u n i t s t h e w i n d o w c a n b e s c r o l l e d . A l t h o u g h y o u specify YRange v a l u e s i n t h e Init c o n s t r u c t o r , y o u c a n m o d i f y t h e m later.
TScroller.YUnit YUnit: Integer; ( r e a d o n l y ) YUnit is t h e s m a l l e s t n u m b e r o f d e v i c e u n i t s (pixels) that t h e w i n d o w c a n b e vertically s c r o l l e d . A l t h o u g h y o u specify YUnit v a l u e s i n t h e Init c o n s t r u c t o r , y o u c a n m o d i f y t h e m later.
475
476
Part I I I — R e f e r e n c e s
Methods TScroller.Init constructor Init(TheWindow: PWindow; TheXUnit, TheYUnit: Integer; TheXRange, TheYRange: Longint); C o n s t r u c t s a n e w TScroller o b j e c t w i t h TheWindow as t h e o w n e r w i n d o w ,
a n d TheXUnit, TheYUnit, TheXRange, a n d TheYRange fields u s i n g XUnit,
YUnit, XRange a n d YRange. Sets AutoMode a n d TrackMode t o T r u e a n d sets HasHScrollBar a n d HasVSc rollBa r, d e p e n d i n g o n t h e scroll b a r a t t r i b u t e s o f t h e o w n e r w i n d o w .
TScrollerload constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a s c r o l l e r f r o m t h e s t r e a m , S, b y s e n d i n g a m e s s a g e t o TOb j ect. Init a n d t h e n r e a d i n g t h e TScroller f i e l d s , w i t h t h e e x c e p t i o n o f
XPage, YPage, XPos, a n d YPos.
TScroUerAutoScroll procedure AutoScroll; virtual; (Override: sometimes) D e p e n d i n g o n the position o f the m o u s e performs auto-scrolling.
cursor,
TScroller.BeginView procedure BeginView(PaintDC: HDC; var Paintlnfo: TPaintStruct); virtual; (Override: sometimes) Sets the origin o f the o w n e r w i n d o w ' s paint display c o n t e x t (PaintDC) a c c o r d i n g t o t h e c u r r e n t s c r o l l e r p o s i t i o n .
TScroller.EndView procedure EndView; virtual; ( O v e r r i d e : s o m e t i m e s ) U p d a t e s t h e p o s i t i o n o f t h e o w n e r w i n d o w ' s scroll b a r s s y n c h r o n i z i n g t h e m w i t h t h e p o s i t i o n o f t h e TScroller.
A—ObjectWindows Objects
477
TScroller.HScroll procedure HScroll(ScrollRequest: Word; ThumbPos: Integer); virtual; (Override: never) R e s p o n d s t o horizontal scroll bar events b y c h a n g i n g the position o f the scroller a n d t h e horizontal scroll bar.
TScrollerisVisibleRect function IsVisibleRect(X, Y: Longint; XExt, YExt: Integer): Boolean; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s T r u e if a n y part o f t h e r e c t a n g l e s p e c i f i e d b y t h e p a s s e d a r g u m e n t s is c u r r e n t l y v i s i b l e i n t h e o w n e r w i n d o w .
TScroller.ScrollBy procedure ScrollBy(Dx, Dy: Longint); virtual; ( O v e r r i d e : s e l d o m ) S c r o l l s b y t h e a m o u n t s s p e c i f i e d b y Dx a n d Dy. A l s o u p d a t e s the w i n d o w ' s display.
TScroller.ScrollTo procedure ScrollTo(X, Y: Longint); virtual; ( O v e r r i d e : s o m e t i m e s ) S c r o l l s t o t h e p o s i t i o n s p e c i f i e d b y X a n d Y. A l s o u p d a t e s the w i n d o w ' s display.
TScroller.SetPageSize procedure SetPageSize; virtual; ( O v e r r i d e : s o m e t i m e s ) S e t s t h e XPage a n d YPage fields t o b e t h e o w n e r window's current width a n d height.
TScroller.SetRange procedure SetRange(TheXRange, TheYRange: Longint); virtual; ( O v e r r i d e : n e v e r ) O v e r r i d e s t h e XRange a n d YRange v a l u e s s e n t i n t h e m e s s a g e t o Init b y s e t t i n g t h e m t o TheXRange a n d TheYRange. SetRange t h e n s e n d s a m e s s a g e t o SetSBarRange t o set t h e r a n g e of t h e o w n e r w i n d o w ' s scroll bars.
478
Part I I I — R e f e r e n c e s
TScroller.SetSBarRange procedure SetSBarRange; virtual; (Override: never) Sets t h e range o f the o w n e r w i n d o w ' s scroll bars b y putting t h e m i n s y n c w i t h t h e r a n g e o f t h e TScroller.
TScroller.SetUnits procedure SetUnits(TheXUnit, TheYUnit: Longint);virtual; Sets t h e XUnit a n d YUnit fields t o TheXUnit a n d TheYUnit.
TScroller.Store procedure Store(var S: TStream); S t o r e s t h e s c r o l l e r o n t h e s t r e a m S b y w r i t i n g t h e TScroller fields, w i t h t h e
e x c e p t i o n o f XPage, YPage, XPos a n d YPos.
TScroller.VScroll procedure VScroll(ScrollRequest: Word; ThumbPos: Integer); virtual; ( O v e r r i d e : n e v e r ) R e s p o n d s t o vertical s c r o l l b a r e v e n t s b y c h a n g i n g t h e p o s i t i o n o f t h e s c r o l l e r a n d t h e vertical s c r o l l b a r .
TScroller.XRangeValue Function XRangeValue (AScrollUnit : Integer) : Longint; Private m e t h o d ; u s e d i n t e r n a l l y b y TScroller O b j e c t .
TScroller.XScrollValue function XScrollValue(ARangeUnit
: LongUnit) : Integer;
Private m e t h o d ; u s e d i n t e r n a l l y b y TScroller
Object.
TScroller.YRangeValue function YRangeValue(AScrollUnit
: Integer): Longint;
Private m e t h o d ; u s e d i n t e r n a l l y b y TScroller O b j e c t .
A—ObjectWindows Objects
TScroller.YScrollValue function YScrollValue(ARangeUnit
: Longint): Integer;
Private m e t h o d ; u s e d i n t e r n a l l y b y TScroller O b j e c t .
TSortedCollection TSortedCollection is a d e s c e n d a n t o f TCollection f o r i m p l e m e n t i n g collections sorted by key without duplicates. S o r t i n g is i m p l i e d b y a virtual TSortedCollection. Compare m e t h o d that y o u override in order to define your o w n element-ordering behavior. N e w i t e m s a r e i n s e r t e d a u t o m a t i c a l l y i n t h e o r d e r d e f i n e d b y t h e Compare method. Y o u c a n locate Items using the binary search method, TSortedCollection.Search. Y o u c a n a l s o o v e r r i d e t h e virtual KeyOf m e t h o d that r e t u r n s a p o i n t e r f o r Compare if Compare n e e d s a d d i t i o n a l i n f o r m a t i o n .
Fields Duplicates
Methods Init Load Compare IndexOf Insert KeyOf Search Store
Fields TSortedCollection.Duplicates Duplicates: Boolean; T h e Duplicates field d e t e r m i n e s w h e t h e r i t e m s w i t h d u p l i c a t e s k e y s a r e accepted by the stream.
479
480
Part I I I — R e f e r e n c e s
• I f Duplicates is T r u e , d u p l i c a t e - k e y e n t r i e s a r e i n s e r t e d i n t o t h e collection. • I f Duplicates is F a l s e , a n e w d u p l i c a t e - k e y i t e m r e p l a c e s t h e e x i s t i n g i t e m w i t h that k e y . T h e d e f a u l t v a l u e is false.
Methods TSortedCollection.Init constructor Init(ALimit, ADelta: Integer); C o n s t r u c t s t h e TSortedCollection b a s e d o n ALimit a n d ADelta.
TSortedCollection.Load constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a s o r t e d c o l l e c t i o n f r o m t h e s t r e a m , S, b y first s e n d i n g a m e s s a g e t o TCollection. Load. It t h e n r e a d s t h e Duplicates f i e l d .
TSortedCollection.Compare function Compare(Key1, Key2: Pointer): Integer; virtual; ( O v e r r i d e : always) Compare is a n abstract m e t h o d that y o u m u s t o v e r r i d e i n all descendant types. Compare s h o u l d c o m p a r e t h e t w o k e y v a l u e s a n d r e t u r n o n e o f t h e following results: -1 if Key 1 < Key2 Oif Key1 = Key2 1 if Key1 > Key2 Key1 a n d Key2 a r e p o i n t e r v a l u e s , e x t r a c t e d f r o m t h e i r c o r r e s p o n d i n g c o l l e c t i o n i t e m s b y t h e KeyOf m e t h o d . T h e Search m e t h o d i m p l e m e n t s a b i n a r y s e a r c h t h r o u g h t h e c o l l e c t i o n ' s i t e m s u s i n g Compare t o c o m p a r e t h e items.
A — O b j e c t W i n d o w s Objects
481
TSortedCollection.IndexOf function IndexOf(Item: Pointer): Integer; virtual; ( O v e r r i d e : n e v e r ) IndexOf u s e s TSortedCollection.Search t o find t h e i n d e x of Item. I f Item isn't i n t h e c o l l e c t i o n , IndexOf r e t u r n s - 1 . F o r e x a m p l e :
if Search(KeyOf(Item), I) then IndexOf := I else IndexOf := -1;
TSortedCollection.Insert procedure Insert(Item: Pointer); virtual; ( O v e r r i d e : n e v e r ) I f t h e target i t e m isn't f o u n d i n t h e s o r t e d c o l l e c t i o n , it's i n s e r t e d at t h e c o r r e c t i n d e x p o s i t i o n . Insert s e n d s a m e s s a g e t o Search t o d e t e r m i n e w h e t h e r t h e i t e m e x i s t s , a n d if n o t , w h e r e t o insert it. F o r e x a m p l e :
if not Search(KeyOf(Item), I) then AtInsert(I, Item);
TSortedCollection.KeyOf function KeyOf(Item: Pointer): Pointer; virtual; ( O v e r r i d e : s o m e t i m e s ) I f it g e t s a n Item f r o m t h e c o l l e c t i o n , KeyOf s h o u l d r e t u r n t h e c o r r e s p o n d i n g k e y of t h e i t e m . T h e d e f a u l t KeyOf r e t u r n s Item. O v e r r i d e KeyOf w h e n t h e k e y of t h e i t e m isn't t h e i t e m itself.
TSortedCollection.Search function Search(Key: Pointer; var Index: Integer): Boolean; virtual; ( O v e r r i d e : s e l d o m ) R e t u r n s T r u e if Item ( i d e n t i f i e d b y Key) is f o u n d i n t h e sorted collection.
If Search finds Item, Index is set t o t h e f o u n d i n d e x ; o t h e r w i s e , Index is set t o t h e i n d e x w h e r e t h e i t e m w o u l d b e p l a c e d if i n s e r t e d .
TSortedCollection.Store procedure Store(var S: TStream); S t o r e s t h e s o r t e d c o l l e c t i o n a n d all its i t e m s o n t h e s t r e a m , S, b y s e n d i n g TCollection.Store a m e s s a g e t o w r i t e t h e c o l l e c t i o n . It t h e n w r i t e s t h e Duplicates field t o t h e s t r e a m .
482
Part I I I — R e f e r e n c e s
TStatic T S t a t i c is a n i n t e r f a c e o b j e c t that c o r r e s p o n d s t o a static c o n t r o l e l e m e n t i n W i n d o w s . Usually, y o u don't use T S t a t i c objects in dialog b o x e s ( T D i a l o g ) o r dialog w i n d o w s (TDlgWindow). Instead, y o u u s e t h e m to display a stand-alone static c o n t r o l as a c h i l d w i n d o w i n a n o t h e r w i n d o w ' s c l i e n t a r e a .
Fields TextLen
Methods Init InitResorce Load Clear GetClassName GetText SetText Store Transfer
Fields TStaticTextLen TextLen: Word; TextLen h o l d s t h e size o f t h e text b u f f e r f o r static c o n t r o l s . B e c a u s e o f t h e n u l l t e r m i n a t o r at t h e e n d o f t h e string, t h e n u m b e r o f c h a r a c t e r s that c a n b e s t o r e d i n t h e static c o n t r o l is o n e less t h a n TextLen. TextLen is a l s o t h e n u m b e r o f b y t e s t r a n s f e r r e d b y t h e Transf er m e t h o d .
Methods TStaticInit constructor Init(AParent: PWindowsObject; AnID: Integer; ATitle: PChar; X,Y,W,H: Integer);
A — O b j e c t W i n d o w s Objects
( O v e r r i d e : s e l d o m ) C o n s t r u c t s a static c o n t r o l o b j e c t w i t h t h e f o l l o w i n g information: • P a r e n t w i n d o w (AParent) • C o n t r o l ID (AnID) • T e x t (ATitle) • P o s i t i o n (X, Y) relative t o t h e o r i g i n o f t h e p a r e n t w i n d o w ' s c l i e n t a r e a • W i d t h (W) • H e i g h t (H) • T e x t l e n g t h (ATextLen) T h e static c o n t r o l is left-justified b e c a u s e Init a d d s t h e W i n d o w s style ss_Lef t t o t h e o b j e c t ' s Attr. Style field. Init a l s o r e m o v e s t h e wsJTabStop style. Init t h e n s e n d s a m e s s a g e t o DisableTransf er t o e x c l u d e TStatic o b j e c t s f r o m t h e transfer m e c h a n i s m .
TStaticInitResource constructor InitResource(AParent: PWindowsObject; ATextLen: Word);
ResourcelD,
A s s o c i a t e s a TStatic o b j e c t w i t h t h e static c o n t r o l r e s o u r c e s p e c i f i e d b y ResourcelD a n d sets t h e TextLen field t o ATextLen. S e n d s a m e s s a g e t o TControl. InitResource t o c o n s t r u c t a n d a s s o c i a t e t h e o b j e c t w i t h its static c o n t r o l r e s o u r c e .
TStatic.Load constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a static c o n t r o l f r o m t h e s t r e a m , S, b y s e n d i n g a m e s s a g e t o TControl. Load a n d t h e n r e a d i n g t h e TextLen
TStaticClear procedure Clear; virtual; ( O v e r r i d e : s e l d o m ) C l e a r s t h e static c o n t r o l ' s text.
field.
483
484
Part I I I — R e f e r e n c e s
TStaticGetText function GetText(ATextString: PChar; MaxChars: Integer): Integer; virtual; ( O v e r r i d e : s e l d o m ) G e t s t h e static c o n t r o l ' s text a n d stores it i n ATextString. MaxChars s p e c i f i e s t h e m a x i m u m size o f ATextString. GetText r e t u r n s t h e size o f t h e r e t r i e v e d string.
TStaticSetText procedure SetText(ATextString: PChar); virtual; ( O v e r r i d e : s e l d o m ) Sets t h e static c o n t r o l ' s text t o t h e string p a s s e d i n
ATextString.
TStaticStore procedure Store(var S: TStream); Stores t h e static c o n t r o l o n t h e s t r e a m , S, b y s e n d i n g a m e s s a g e t o TCont rol. St o re a n d t h e n w r i t i n g t h e TextLen f i e l d .
TStaticTransfer function Transfer(DataPtr: Pointer; TransferFlag: Word): Word; virtual; ( O v e r r i d e : s o m e t i m e s ) T r a n s f e r s TextLen c h a r a c t e r s o f t h e c u r r e n t text o f t h e static c o n t r o l t o o r f r o m t h e m e m o r y l o c a t i o n p o i n t e r t o b y D a t a P t r .
• If Transf erFlag is tf_GetData, t h e text is transferred t o t h e m e m o r y location.
• I f Transf erFlag is tf_SetData, t h e static c o n t r o l ' s text is set t o t h e text at t h e m e m o r y l o c a t i o n . Transfer r e t u r n s TextLen ( t h e n u m b e r o f bytes stored in o r retrieved f r o m the m e m o r y location).
• I f Transf erFlag is tf_SizeData, Transfer r e t u r n s t h e size o f t h e transfer d a t a .
TStrCoUection TStrCollection is a d e s c e n d a n t o f TSortedCollection f o r i m p l e m e n t i n g a s o r t e d list o f A S C I I s t r i n g s .
A—ObjectWindows Objects
O v e r r i d e t h e Compare m e t h o d t o p r o v i d e c o n v e n t i o n a l l e x i c o g r a p h i c A S C I I string o r d e r i n g . Y o u c a n o v e r r i d e Compare t o a l l o w f o r o t h e r o r d e r i n g s , s u c h as those for n o n - E n g l i s h character sets.
Fields None.
Methods Compare Freeltem Getltem Putltem
Methods TStrCollection.Compare function Compare(Key1, Key2: Pointer): Integer; virtual; ( O v e r r i d e : s o m e t i m e s ) C o m p a r e s t h e strings Key1" a n d Key2" as f o l l o w s : Return Return Return
-1 if Key 1 < Key2 0 if Key 1 = Key2 + lifKey1 > Key2
TStrCollection.FreeItem procedure Freeltem(ltem: Pointer); virtual; ( O v e r r i d e : s e l d o m ) R e m o v e s t h e string I t e n T f r o m t h e s o r t e d c o l l e c t i o n a n d d i s p o s e s o f t h e string.
TStrCollection.GetItem function Getltem(var S: TStream): Pointer; virtual; ( O v e r r i d e : s e l d o m ) B y d e f a u l t , r e a d s a string from t h e TStream b y s e n d i n g S.ReadStr a m e s s a g e .
485
486
Part I I I — R e f e r e n c e s
TStrCollection.PutItem procedure Putltem(var S: TStream; Item: Pointer); virtual; ( O v e r r i d e : s e l d o m ) B y d e f a u l t , w r i t e s t h e string Item" o n t o t h e TStream b y s e n d i n g S. WriteStr a m e s s a g e .
TStream TStream is a n abstract o b j e c t that h a n d l e s p o l y m o r p h i c I/O t o a n d f r o m a storage device. T o c r e a t e y o u r o w n d e r i v e d s t r e a m o b j e c t s , o v e r r i d e t h e virtual m e t h o d s :
GetPos, GetSize, Read, Seek, Truncate, a n d Write. For example, ObjectWindows
overrides these m e t h o d s to derive
TDosStream a n d TEmsStream. F o r b u f f e r e d d e r i v e d s t r e a m s , y o u m u s t a l s o o v e r r i d e Flush.
Fields Errorlnfo Status
Methods CopyFrom Error Flush Get GetPos GetSize Init Put Read ReadStr Reset Seek StrRead StrWrite Truncate Write WriteStr
A — O b j e c t W i n d o w s Objects
Fields TStream.EfforInfo Errorlnfo: Integer; (read/write) Errorlnf o c o n t a i n s a d d i t i o n a l i n f o r m a t i o n w h e n Status isn't stOk: Status
Error
Values
stError stlnitError stReadError stWriteError stGetError stPutError
Information
D O S o r E M S e r r o r c o d e ; if available D O S o r E M S e r r o r c o d e ; if available D O S o r E M S e r r o r c o d e ; if available D O S o r E M S e r r o r c o d e ; if a v a i l a b l e object type I D o f unregistered object type V M T d a t a s e g m e n t offset o f u n r e g i s t e r e d object type
TStream.Status Status: Integer; (read/write) I n d i c a t e s t h e c u r r e n t status o f t h e s t r e a m u s i n g t h e f o l l o w i n g e r r o r c o d e s : TStream
error
codes:
stOk
N o error
stError stlnitError stReadError
Access error C a n n o t initialize s t r e a m Read b e y o n d e n d o f stream
stWriteError stGetError stPutError
C a n n o t e x p a n d stream G e t o f unregistered object type Put o f unregistered object type
If Status isn't stOk, all o p e r a t i o n s o n t h e s t r e a m a r e s u s p e n d e d u n t i l Reset is s e n t a m e s s a g e .
Methods TStream.CopyFrom procedure CopyFrom(var S: TStream; Count: Longint); C o p y Count bytes from s t r e a m , S, t o t h e c a l l i n g s t r e a m o b j e c t . F o r e x a m p l e :
487
488
Part I I I — R e f e r e n c e s
{Create a copy of entire stream} ANewStream := New(TEmsStream, Init(AnOldStreanT .GetSize)); AnOldStreanT .Seek(0); ANewStream".CopyFrom(An01dStream, AnOldStreanT .GetSize);
TStfeam.Error procedure Error(Code, Info: Integer); virtual; (Override: sometimes) Receives a message w h e n e v e r a stream error occurs. T h e d e f a u l t Error s t o r e s Code a n d Info i n t h e Status a n d Errorlnf o f i e l d s . T h e n , if t h e g l o b a l v a r i a b l e St reamE r r o r isn't n i l , it s e n d s a m e s s a g e t o t h e p r o c e d u r e p o i n t e d t o b y StreamError. A f t e r a n e r r o r h a s o c c u r r e d , all s t r e a m o p e r a t i o n s o n t h e s t r e a m a r e s u s p e n d e d u n t i l a m e s s a g e is s e n t t o Reset.
TStream.Fhish procedure Flush; virtual; ( O v e r r i d e : s o m e t i m e s ) A n abstract m e t h o d y o u m u s t o v e r r i d e if y o u r d e s c e n d a n t i m p l e m e n t s a b u f f e r . T h i s m e t h o d c a n flush a n y b u f f e r s b y c l e a r i n g t h e r e a d buffer, by writing the write buffer, o r b o t h . T h e d e f a u l t Flush d o e s n ' t d o a n y t h i n g .
TStream.Get function Get: PObject; Reads an object from the stream. T h e object must have b e e n written previously t o t h e s t r e a m b y Put. • Get first r e a d s a n o b j e c t t y p e I D (a word) f r o m t h e s t r e a m . • T h e n it finds t h e c o r r e s p o n d i n g o b j e c t t y p e b y c o m p a r i n g t h e I D t o t h e Ob j Type field of all r e g i s t e r e d o b j e c t t y p e s . • Finally, it s e n d s t h e Load c o n s t r u c t o r of that o b j e c t t y p e a m e s s a g e t o create a n d load the object. If t h e o b j e c t t y p e I D r e a d f r o m t h e s t r e a m is 0, Get r e t u r n s a n i l p o i n t e r . If t h e o b j e c t t y p e I D h a s n ' t b e e n r e g i s t e r e d ( u s i n g RegisterType), Get s e n d s a m e s s a g e t o Error a n d r e t u r n s a n i l p o i n t e r . O t h e r w i s e , Get r e t u r n s a p o i n t e r to the newly created object.
A — O b j e c t W i n d o w s Objects
TStream.GetPos function GetPos: Longint; virtual; ( O v e r r i d e : always) R e t u r n s t h e v a l u e o f t h e c a l l i n g s t r e a m ' s c u r r e n t p o s i t i o n . Y o u m u s t o v e r r i d e this abstract m e t h o d .
TStream.GetSize function GetSize: Longint; virtual; ( O v e r r i d e : always) R e t u r n s t h e total size o f t h e c a l l i n g s t r e a m . Y o u m u s t o v e r r i d e this abstract m e t h o d .
TStream.Init constructor Init; C r e a t e s a TStream.
TStream.Put procedure Put(P: PObject); W r i t e s a n o b j e c t t o t h e s t r e a m . Y o u c a n later r e a d t h e o b j e c t f r o m t h e s t r e a m u s i n g Get. • First Put finds t h e t y p e - r e g i s t r a t i o n r e c o r d o f t h e o b j e c t b y c o m p a r i n g t h e o b j e c t ' s V M T offset t o t h e VmtLink field o f all r e g i s t e r e d o b j e c t t y p e s ( s e e t h e TStreamRec t y p e ) . • T h e n it w r i t e s t h e o b j e c t t y p e I D ( t h e Ob j Type field o f t h e r e g i s t r a t i o n record) to the stream. • F i n a l l y it s e n d s a m e s s a g e t o t h e Store m e t h o d o f that o b j e c t t y p e i n order t o write the object. If t h e P a r g u m e n t s e n t t o Put is n i l , Put w r i t e s a w o r d c o n t a i n i n g 0 t o t h e s t r e a m . If t h e o b j e c t t y p e o f P h a s n ' t b e e n r e g i s t e r e d ( u s i n g R e g i s t e r T y p e ) , Put s e n d s a m e s s a g e t o Error a n d d o e s n ' t w r i t e a n y t h i n g t o t h e s t r e a m .
TStream.Read procedure Read(var Buf; Count: Word); virtual; ( O v e r r i d e : always) Y o u m u s t o v e r r i d e this abstract m e t h o d i n all d e s c e n d a n t types.
489
490
Part I I I — R e f e r e n c e s
Read s h o u l d r e a d Count b y t e s f r o m t h e s t r e a m i n t o Buf a n d a d v a n c e t h e c u r r e n t p o s i t i o n o f t h e s t r e a m b y Count b y t e s . If a n e r r o r o c c u r s , Read s h o u l d s e n d Error a m e s s a g e , a n d fill Buf w i t h Count b y t e s o f 0.
TStream.ReadStr function ReadStr: PString; R e a d s a string f r o m t h e c u r r e n t p o s i t i o n o f t h e c a l l i n g s t r e a m , r e t u r n i n g a PString p o i n t e r . ReadStr s e n d s a m e s s a g e t o GetMem t o a l l o c a t e (Length+1) b y t e s f o r t h e string.
TStream.Reset procedure Reset; R e s e t s a n y s t r e a m e r r o r c o n d i t i o n b y s e t t i n g Status a n d Errorlnf o t o 0. T h i s m e t h o d lets y o u c o n t i n u e s t r e a m p r o c e s s i n g f o l l o w i n g a n e r r o r c o n d i t i o n that you've corrected.
TStream.Seek procedure Seek(Pos: Longint); virtual; ( O v e r r i d e : always) Y o u m u s t o v e r r i d e this abstract m e t h o d i n all d e s c e n d a n t s . Seek sets t h e c u r r e n t p o s i t i o n t o Pos b y t e s f r o m t h e start o f t h e c a l l i n g s t r e a m . T h e b e g i n n i n g o f a s t r e a m is p o s i t i o n 0.
TStream.StrRead function StrRead: PChar; R e a d s a n u l l - t e r m i n a t e d string f r o m t h e s t r e a m b y first r e a d i n g t h e l e n g t h o f t h e string a n d t h e n r e a d i n g that n u m b e r o f c h a r a c t e r s . R e t u r n s a p o i n t e r t o t h e n u l l t e r m i n a t e d string r e a d .
TStream.StfWrite function StrWrite(P: PChar); W r i t e s t h e n u l l - t e r m i n a t e d string, P, t o t h e s t r e a m b y first w r i t i n g t h e l e n g t h o f t h e string a n d t h e n w r i t i n g t h e n u m b e r o f c h a r a c t e r s .
A — O b j e c t W i n d o w s Objects
TStream.Thincate procedure Truncate; virtual; ( O v e r r i d e : always) Y o u m u s t o v e r r i d e this abstract m e t h o d i n all d e s c e n d a n t s . Truncate d e l e t e s all d a t a o n t h e c a l l i n g s t r e a m f r o m t h e c u r r e n t p o s i t i o n to the e n d .
TStream.Write procedure Write(var Buf; Count: Word); virtual; ( O v e r r i d e : always) Y o u m u s t o v e r r i d e this abstract m e t h o d i n all d e s c e n d a n t types. W r i t e s h o u l d w r i t e Count b y t e s f r o m Buf o n t o t h e s t r e a m a n d a d v a n c e t h e c u r r e n t p o s i t i o n o f t h e s t r e a m b y Count b y t e s . If a n e r r o r o c c u r s , Write s h o u l d s e n d Error a m e s s a g e .
TStream.WriteStr procedure WriteStr(P: PString); W r i t e s t h e string P" t o t h e c a l l i n g s t r e a m , b e g i n n i n g at t h e c u r r e n t p o s i t i o n .
TWindow TWindow d e f i n e s f u n d a m e n t a l b e h a v i o r f o r all w i n d o w a n d c o n t r o l o b j e c t s . O b j e c t i n s t a n c e s o f TWindow a r e e m p t y g e n e r i c w i n d o w s , w h i c h c a n define m e n u s , cursors, a n d icons.
Fields Attr DefaultProc FocusChildHandle Scroller
491
492
Part I I I — R e f e r e n c e s
Methods Init InitResource Load Done Create DefWndProc GetID GetWindowClass Paint SetCaption SetupWindow Store WMActivate WMCreate WMHScroll WMLButtonDown WMMove WMPaint WMSize WMVScroll
Fields TWindow Attr Attn
TWindowAttr;
Attr h o l d s a TWindowAttr r e c o r d , w h i c h d e f i n e s a w i n d o w ' s attributes. T h e s e attributes i n c l u d e :
creation
• T h e w i n d o w ' s a s s o c i a t e d text, style, e x t e n d e d style, p o s i t i o n , a n d size • The window handle • T h e control I D T h e s e attributes t r a d i t i o n a l l y a r e set t o d e f a u l t s i n t h e o b j e c t ' s Init c o n s t r u c t o r , b u t c a n b e o v e r r i d d e n i n a d e s c e n d a n t t y p e ' s Init c o n s t r u c t o r . H e r e ' s t h e r e c o r d d e f i n i t i o n f o r TWindowAttr:
A—ObjectWindows Objects
TWindowAttr = record Title: PChar; Style: Longint; ExStyle: Longint; X, Y, W, H: Integer; Param: Pointer; case Integer of 0: (Menu: HMenu); { window menu's handle or... } 1: (Id: Integer); { control's child identifier } end;
TWindow.DefaultProc DefaultProc: TFarProc; ( r e a d o n l y ) Def aultProc h o l d s t h e a d d r e s s o f t h e d e f a u l t w i n d o w p r o c e d u r e , w h i c h defines the W i n d o w s default processing for W i n d o w s messages.
TWindow.FocusChildHandle FocusChildHandle: THandle; ( r e a d o n l y ) FocusChildHandle s t o r e s t h e W i n d o w s h a n d l e t o t h e w i n d o w ' s c h i l d w i n d o w that h a d t h e f o c u s t h e last t i m e t h e w i n d o w w a s a c t i v a t e d .
TWindow.Scroller Scroller: PScroller; (read/write) Scroller h o l d s a p o i n t e r t o a TScroller o b j e c t , w h i c h is t h e w i n d o w ' s scroller, if it h a s a s c r o l l e r . Y o u s h o u l d c o n s t r u c t a scroller i n t h e w i n d o w ' s Init constructor.
Methods TWindow.Init constructor Init(AParent: PWindowsObject; ATitle: PChar); (Override: often) Constructs a w i n d o w object with the parent w i n d o w sent in AParent a n d t h e a s s o c i a t e d text ( c a p t i o n f o r w i n d o w s ) s e n t i n ATitle. AParent s h o u l d b e n i l f o r m a i n w i n d o w s b e c a u s e t h e y h a v e n o p a r e n t .
493
494
Part I I I — R e f e r e n c e s
T h e object's Attr.Style field is set to ws_OverlappedWindow u n l e s s t h e w i n d o w is a n MDI c h i l d w i n d o w , w h e n t h e Attr.Style field is set to ws_ClipSiblings. T h e p o s i t i o n a n d e x t e n t fields i n t h e Attr r e c o r d a r e set to d e f a u l t s s u i t a b l e f o r o v e r l a p p e d a n d p o p - u p w i n d o w s . Y o u c a n o v e r r i d e Init i n y o u r d e s c e n d a n t t y p e s as l o n g as y o u first e x p l i c i t l y s e n t Init a m e s s a g e . T h e n y o u c a n reset t h e Attr f i e l d s . B y d e f a u l t , Scroller is set to n i l .
T\Wndow.InitResource constructor InitResource(AParent: PWindowsObject; ResourcelD: Word); C o n s t r u c t s a n O b j e c t W i n d o w s o b j e c t that is a s s o c i a t e d w i t h a n i n t e r f a c e e l e m e n t (usually a c o n t r o l ) c r e a t e d by a r e s o u r c e d e f i n i t i o n . S e n d s a m e s s a g e to TWindowsOb j ect. Init.
TWindowIoad constructor Load(var S: TStream); C o n s t r u c t s a n d l o a d s a w i n d o w f r o m t h e s t r e a m , S, by first s e n d i n g TWindowsOb j ect. Load a m e s s a g e . T h e n it r e a d s a n d g e t s t h e a d d i t i o n a l fields (Attr a n d Scroller) c r e a t e d b y TWindow.
TWindow.Done destructor Done; virtual; ( O v e r r i d e : o f t e n ) D i s p o s e s o f t h e TScroller object i n Scroller, if a n y , b e f o r e s e n d i n g a m e s s a g e to TWindowsOb j ect. Done to d i s p o s e o f t h e object.
TWindow.Create function Create: Boolean; virtual; Creates the w i n d o w object's c o r r e s p o n d i n g interface e l e m e n t unless the object w a s c o n s t r u c t e d w i t h InitResource. I f t h e o b j e c t w a s c r e a t e d w i t h InitResource, t h e i n t e r f a c e e l e m e n t a l r e a d y e x i s t s . Create first s e n d s a m e s s a g e to Register to r e g i s t e r t h e w i n d o w class if it's n o t a l r e a d y r e g i s t e r e d .
A—ObjectWindows Objects
495
C r e a t e t h e n creates the w i n d o w a n d sends a message to SetupWindow, w h i c h y o u c a n d e f i n e t o initialize t h e n e w l y c r e a t e d w i n d o w . If s u c c e s s f u l , C r e a t e r e t u r n s T r u e . If u n s u c c e s s f u l , it r e t u r n s F a l s e a n d calls E r r o r .
TWindow.DelWndProc procedure
DefWndProc(var
Msg:
TMessage);
virtual;
(Override: never) Sends a message to the w i n d o w ' s default procedure, w h i c h h a n d l e s d e f a u l t p r o c e s s i n g f o r i n c o m i n g W i n d o w s m e s s a g e s . It s t o r e s t h e result o f this m e s s a g e i n t h e R e s u l t field o f t h e m e s s a g e r e c o r d , Msg.
TWindow.GetID function
Getld:
Integer;
virtual;
( O v e r r i d e : s e l d o m ) R e t u r n s t h e w i n d o w i d e n t i f i e r , s u c h as a c o n t r o l I D .
TWindow.GetWindowClass procedure GetWindowClass(var
AWndClass:
TWndClass);virtual;
( O v e r r i d e : o f t e n ) Fills a w i n d o w class r e c o r d , p a s s e d i n A W n d C l a s s , w i t h d e f a u l t v a l u e s f o r its r e g i s t r a t i o n a t t r i b u t e s . T h e r e g i s t r a t i o n a t t r i b u t e s a n d d e f a u l t v a l u e s are s h o w n i n t h e f o l l o w i n g table: Attribute
Default
Value
Style f i e l d Icon Cursor Background
c s H R e d r a w or c s V R e d r a w Generic icon Stock arrow cursor C o l o r system's w i n d o w b a c k g r o u n d color
R e t r i e v e t h e n a m e o f t h e class t o b e r e g i s t e r e d b y s e n d i n g a m e s s a g e GetClassName.
TWindow.Paint procedure virtual;
Paint(PaintDC:
HDC; v a r P a i n t l n f o :
TPaintStruct);
to
496
Part I I I — R e f e r e n c e s
( O v e r r i d e : o f t e n ) A c t s as a p l a c e h o l d e r f o r d e s c e n d a n t t y p e s that d e f i n e Paint m e t h o d s . Paint r e c e i v e s a m e s s a g e a u t o m a t i c a l l y i n r e s p o n s e t o a r e q u e s t (wm_Paint) f r o m W i n d o w s t o r e d i s p l a y t h e w i n d o w ' s c o n t e n t s . U s e PaintDC as t h e d i s p l a y c o n t e x t b e c a u s e it's o b t a i n e d b e f o r e t h e m e s s a g e is s e n t t o Paint, a n d r e l e a s e d after Paint. T h e Paintlnfo p a i n t structure sent contains information about the paint request.
TWindow.SetCaption procedure SetCaption
(ATitle
: PChar);
S e t s a TWindow c a p t i o n .
TWindow.SetupWindow procedure SetupWindow;
virtual;
( O v e r r i d e : o f t e n ) Sets u p t h e n e w l y c r e a t e d w i n d o w . I f t h e w i n d o w is a n MDI c h i l d w i n d o w , SetupWindow s e n d s a m e s s a g e t o SetFocus t o g i v e t h e n e w w i n d o w t h e f o c u s . I f t h e w i n d o w h a s a s c r o l l e r o b j e c t , SetupWindow s e n d s a m e s s a g e t o SetSBarRange t o set t h e r a n g e o f its s c r o l l b a r s .
TWindow.Store procedure Store(var S: TStream); S t o r e s t h e w i n d o w o n t h e s t r e a m , S, b y s e n d i n g a m e s s a g e t o TWindowsOb j ect .Store a n d t h e n w r i t i n g a n d p u t t i n g t h e a d d i t i o n a l fields (Attr a n d Scroller) i n t r o d u c e d b y TWindow.
TWindow.WMActivate procedure WMActivate(var Msg: TMessage); virtual wm_First + wm_Activate; ( O v e r r i d e : s o m e t i m e s ) F o r w i n d o w s that i n t e r c e p t k e y b o a r d m e s s a g e s f o r its c o n t r o l s , WMAc t i vat e r e s p o n d s t o t h e w i n d o w that l o s e s a n d r e c e i v e s t h e f o c u s b y s a v i n g t h e h a n d l e o f t h e c h i l d c o n t r o l that c u r r e n t l y h a s t h e f o c u s i n FocusChildHandle a n d r e s t o r i n g t h e f o c u s .
A—ObjectWindows Objects
497
TWindow.WMCreate p r o c e d u r e WMCreate(var Msg:
TMessage);
virtual;
wm_First
+ wm_Create;
R e s p o n d s t o t h e w m C r e a t e m e s s a g e b y s e n d i n g m e s s a g e s first t o S e t u p W i n d o w a n d t h e n D e f W n d P r o c . B e c a u s e w i n d o w c r e a t i o n is h a n d l e d differently u n d e r ObjectWindows than u n d e r W i n d o w s , the w m C r e a t e message needs to b e t r a p p e d a n d u s e d t o set u p w i n d o w o b j e c t a t t r i b u t e s .
TWindow.WMHScroll procedure WMHScroll(var wm_First
Msg:
TMessage);
virtual;
+ wm_HScroll;
(Sometimes) For w i n d o w s with scrollers, WMHScroll r e s p o n d s to horizontalw i n d o w s c r o l l b a r e v e n t s b y s e n d i n g m e s s a g e s t o t h e s c r o l l e r ' s HSc r o l l m e t h o d and DefWndProc.
TWindow.WMLButtonDown p r o c e d u r e WMLButtonDown(var Msg: w m _ F i r s t + wm_LButtonDown;
TMessage);
virtual;
( O v e r r i d e : s o m e t i m e s ) F o r w i n d o w s w i t h auto-scrolling scrollers, WMLButtonDown r e s p o n d s t o a left m o u s e - b u t t o n c l i c k b y c a p t u r i n g all f u t u r e m o u s e i n p u t u n t i l t h e m o u s e b u t t o n is r e l e a s e d . It a l s o instructs W i n d o w s t o s e n d w m T i m e r m e s s a g e s w h i l e t h e m o u s e b u t t o n is d o w n . If y o u p l a n t o o v e r r i d e this m e t h o d t o p r o c e s s m o u s e c l i c k s , b u t still p l a n t o u s e a u t o - s c r o l l i n g , b e s u r e t o s e n d a m e s s a g e t o this m e t h o d f r o m y o u r WMLButtonDown m e t h o d .
TWindow.WMMove p r o c e d u r e WMMove(var M s g :
TMsg);
virtual;
wm_First
+ wm_Move;
U p d a t e s A t t r . X a n d A t t r . Y w h e n t h e wm_Move m e s s a g e is r e c e i v e d . If t h e w i n d o w is i c o n i c o r z o o m e d , t h e m e s s a g e is i g n o r e d .
498
Part III—References
TWindow.WMPaint p r o c e d u r e W M P a i n t ( v a r Msg:
TMessage);
virtual;
wm_First
+ wm_Paint
(Override: seldom) R e s p o n d s to the W i n d o w s wm_Paint message by sending a message to the w i n d o w object's P a i n t m e t h o d . If the w i n d o w has a scroller, WMPaint sends a message t o B e g i n V i e w before sending messages to P a i n t a n d EndView after sending P a i n t a message.
TWindow.WMSize p r o c e d u r e W M S i z e ( v a r Msg:
TMessage);
virtual;
wm_First
+
wm_Size; (Override: sometimes) For w i n d o w s with scrollers, WMSize responds to a window-sizing event by sending a message to S e t P a g e S i z e to adjust in response to the n e w w i n d o w size.
TWindow.WMVScroll p r o c e d u r e W M V S c r o l l ( v a r Msg: wm_VScroll;
TMessage);
virtual;
wm_First
+
(Override: sometimes) For w i n d o w s with scrollers, W M V S c r o l l responds to vertical-window scroll bar events by sending messages to the scroller's V S c r o l l m e t h o d and DefWndProc.
B REFERENCE
OBJECTWINDOWS CONSTANTS
bfXXXX Constants Buttons, check boxes, and radio-button objects use bf _ constants to define t h e i r t h r e e p o s s i b l e states. ObjectWindows defines the following button-flag constants: Constant
Value
bfJUnchecked bf_Checked bf_Grayed
0 1 2
Meaning I t e m is u n c h e c k e d I t e m is c h e c k e d I t e m is g r a y e d
cmXXXX Constants O b j e c t W i n d o w s c o n t a i n s several c o n s t a n t s that d e f i n e t h e r a n g e s o f c o m m a n d message constants:
500
Part I I I — R e f e r e n c e s
Constant
Value
Meaning
cmJFirst
$A000
Beginning of c o m m a n d
cm_Count
$6000
messages Number of command
cmlnternal
$FF00
messages Beginning of c o m m a n d messages reserved for internal use. cm_Internal - c m F i r s t
cmJReserved
O b j e c t W i n d o w s defines cm_ constants for three standard m e n u s ; File, Edit, a n d W i n d o w : Constant
Value
cmReserved cmEditCut cmEditCopy cmEditPaste cm_EditDelete cmEditClear cmEditUndo cm_EditFind cmEditReplace cmEditFindNext cmFileNew cm_FileOpen cmMDIFileNew cmMDIFileOpen cm_FileSave cm_FileSaveAs cm_ArrangeIcons
cmlnternal cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cmReserved cm_Reserved cmReserved
Menu cmFirst; + 0 4- 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 +11 + 12 +13 + 14 +15
Equivalent
cm_TileChildren
c m R e s e r v e d + 16
None Edit | C u t Edit | C o p y Edit | Paste Edit | D e l e t e Edit | C l e a r Edit | U n d o Search | Find Search | Replace Search | Search Again File | N e w File | O p e n File | N e w File | O p e n File | S a v e File | S a v e A s Window | A r r a n g e Icons Window | T i l e
cmCascadeChildren cmCloseChildren cmCreateChild c m Exit
cmReserved cmReserved cmReserved c m Reserved
Window | C a s c a d e Window | C l o s e A l l Window | O p e n File I Exit
+ + + +
17 18 19 20
B — ObjectWindows Constants
coXXXX Constants c o X X X X c o n s t a n t s are s e n t as t h e C o d e p a r a m e t e r t o t h e T C o l l e c t i o n . E r r o r m e t h o d w h e n a T C o l l e c t i o n object detects an error during an operation. O b j e c t W i n d o w s d e f i n e s t h e f o l l o w i n g s t a n d a r d e r r o r c o d e s f o r all ObjectWindows collections: Error
Code
Value
Meaning
Error
Origin
eolndexError
-1
Index out of range
coOverflow
-2
Collection overflow
The I n f o parameter passed to the E r r o r m e t h o d contains the invalid index. S e t L i m i t failed to expand the collection to the requested size.
The I n f o parameter passed to the E r r o r m e t h o d contains the requested size.
emXXXX Constants S e v e r a l s t a n d a r d e r r o r c o n d i t i o n s are f l a g g e d b y O b j e c t W i n d o w s c o n s t a n t s starting w i t h e m _ . O b j e c t W i n d o w s d e f i n e s t h e f o l l o w i n g e r r o r flags: Constant
Value
em_OutOfMemory
-2
em_InvalidClient
-3
emlnvalidChild
-4
em_InvalidWindow
-1
emlnvalidMainWindow
-5
Meaning A memory allocation used the safety p o o l . A n M D I client w i n d o w c o u l d not be created. O n e or more of the window's c h i l d r e n is n o t v a l i d . Window is invalid b e c a u s e C r e a t e did not succeed. Main w i n d o w could not be created.
501
502
Part I I I — R e f e r e n c e s
id XXXX Constants O b j e c t W i n d o w s has several c o n s t a n t s that d e f i n e t h e ranges
o f child I D
messages: Constant
Value
Meaning
id_First
$8000
Start o f c h i l d I D m e s s a g e s
id_Count
$ 1000
idReserved idlnternalOffset idFirstMDIChild id_MDIClient
$8F00 idlnternal - idFirst; id_InternalOffset + 1 id J n t e r n a l O f f s e t + 2
N u m b e r o f child I D messages R e s e r v e d f o r internal u s e I n t e r n a l offset Base for child I D numbers Child I D number of the M D I client w i n d o w
nf XXXX Constants O b j e c t W i n d o w s h a s several c o n s t a n t s that d e f i n e t h e r a n g e s o f n o t i f i c a t i o n messages: Constant
Value
nfFirst nfCount nflnternal
$9000 $1000 $9F00
Meaning Beginning o f notification messages N u m b e r o f notification messages Beginning o f notification messages reserved for internal u s e
stXXXX Constants T w o sets o f c o n s t a n t s b e g i n w i t h S t . T h e s e are u s e d b y t h e O b j e c t W i n d o w s streams system. TDosStream a n d TBufStream u s e t h e f o l l o w i n g s t r e a m - a c c e s s - m o d e c o n s t a n t s t o d e t e r m i n e t h e file-access m o d e f o r a file that is o p e n e d f o r a n ObjectWindows stream: Constant
Value
stCreate stOpenRead stOpenWrite stOpen
$3C00 $3D00 $3D01 $3D02
Meaning C r e a t e n e w file O p e n a file f o r reading o n l y O p e n a file for w r i t i n g o n l y O p e n a file for reading a n d w r i t i n g
B — ObjectWindows Constants
T h e f o l l o w i n g v a l u e s are returned b y T S t r e a m . E r r o r in t h e T S t r e a m . E r r o r l n f o field w h e n a s t r e a m error o c c u r s : Error
Code
Value
stOk
0
Meaning N o error
stError
-1
A c c e s s error
stlnitError stReadError stWriteError stGetError stPutError
-2 -3 -4 -5 -6
C a n n o t initialize t h e s t r e a m Read b e y o n d e n d of stream C a n n o t e x p a n d the stream G e t unregistered object type Put unregistered object type
tfXXXX Constants T h e T r a n s f e r m e t h o d u s e s flag c o n s t a n t s b e g i n n i n g w i t h t f _ . O b j e c t W i n d o w s d e f i n e s t h e f o l l o w i n g transfer f u n c t i o n c o n s t a n t s : Constant
Value
tfSizeData
0
tfGetData tf_SetData
1 2
Meaning D e t e r m i n e t h e size o f d a t a t r a n s f e r r e d b y t h e object G e t data from the object S e n d d a t a t o set t h e v a l u e o f t h e o b j e c t
wb_XXXX Constants T h e F l a g s field in TWindowsOb j e c t is a b i t - m a p p e d field. Y o u c a n a c c e s s t h e s e bits w i t h c o n s t a n t s b e g i n n i n g w i t h wb_. ObjectWindows defines the following values: Constant
Value
Meaning
wbKeyboardHandler
$01
Window
wbFromResource wbAutoCreate
$02 $04
wb_MDIChild wbTransfer
$08 $10
If
Set
handles
k e y e v e n t s like a
dialog. Dialog was loaded from a resource. Window is c r e a t e d w h e n p a r e n t w i n d o w is c r e a t e d . Window is a n M D I c h i l d w i n d o w . Window participates in t h e T r a n s f e r m e c h a n i s m . B y d e f a u l t , this bit is set b y I n i t R e s o u r c e a n d c l e a r e d b y Init.
503
504
Part I I I — R e f e r e n c e s
wmXXXX Constants O b j e c t W i n d o w s h a s several c o n s t a n t s related to s t a n d a r d Windows messages. T h e s e d e f i n e the ranges o f m e s s a g e s that are reserved f o r Windows. O b j e c t W i n d o w s d e f i n e s the f o l l o w i n g w i n d o w m e s s a g e c o n s t a n t s : Constant
Value
wmFirst wm_Count
$0000 $8000
Meaning B e g i n n i n g o f Windows messages N u m b e r o f Windows messages
c
REFERENCE
OBJECTWINDOWS PROCEDURES AND FUNCTIONS
O b j e c t W i n d o w s h a s a n u m b e r o f p r o c e d u r e s a n d f u n c t i o n s that are separate f r o m t h e O b j e c t W i n d o w s o b j e c t s . T h e s e p r o c e d u r e s a n d f u n c t i o n s are d e f i n e d in this r e f e r e n c e c h a p t e r . Abstract AllocMultiSel DisposeStr FreeMultiSel GetObj ectPtr LongDiv LongMul LowMemory MemAlloc NewStr RegisterType RegisterWObj ects RestoreMemory
procedure function procedure procedure function function function function function function procedure procedure procedure
506
Part I I I — R e f e r e n c e s
Abstract C a l l i n g this p r o c e d u r e t e r m i n a t e s t h e p r o g r a m w i t h r u n - t i m e e r r o r 2 1 1 . procedure Abstract; U s e t h e Abstract p r o c e d u r e w h e n y o u i m p l e m e n t abstract o b j e c t t y p e s t o e n s u r e that d e s c e n d a n t t y p e s o v e r r i d e virtual a n c e s t o r b e h a v i o r .
AllocMultiSel A l l o c a t e s a TMultiSelRec w i t h Count s e l e c t i o n s a n d sufficient s p a c e i n t h e Selections f i e l d t o h o l d Count s e l e c t i o n s (O..Count-l). function AllocMultiSel(Count:
Integer): PMultiSelRec;
R e t u r n s n i l if t h e r e is n o t e n o u g h m e m o r y t o a l l o c a t e t h e e n t i r e r e c o r d .
DisposeStr A m e m o r y - m a n a g e m e n t p r o c e d u r e ; d e s t r o y s t h e string p o i n t e d t o b y P. procedure DisposeStr(P: PString);
FreeMultiSel F r e e s a TMultiSelRec r e c o r d a l l o c a t e d b y AllocMultiSel. procedure FreeMultiSel(P: PMultiSelRec);
GetObjectPtr A memory-management function. Returns a pointer to the Windows object specified by H W i n d o w . function GetObjectPtr(HWindow:
HWnd): PWindowsObject;
C — O b j e c t W i n d o w s Procedures a n d Functions
LongDiv A n optimized inline assembly-coded function for handling integer division. R e t u r n s t h e i n t e g e r v a l u e X/Y. function LongDiv(X: Longint; Y: Integer): Integer; inline($59/$58/$5A/$F7/$F9);
LongMul A n o p t i m i z e d , in-line assembly-coded multiplication f u n c t i o n . Returns the l o n g i n t e g e r v a l u e X * Y. function longmul(X, Y: Integer): Longint; inline($5A/$58/$f7/$EA);
LowMemory If a m e m o r y a l l o c a t i o n u s e s m e m o r y i n t h e safety p o o l at t h e e n d o f t h e h e a p , LowMemory r e t u r n s T r u e . T h e safety p o o l size is d e t e r m i n e d b y t h e Saf etyPoolSize v a r i a b l e . R e s o u r c e s a n d a p p l i c a t i o n s that u s e m u c h m e m o r y ( s u c h as c o m p l e x d i a l o g b o x e s ) s h o u l d b e p r o g r a m m e d t o c h e c k LowMemory t o e n s u r e that t h e i r m e m o r y d e m a n d d o e s n o t e x c e e d available m e m o r y . function LowMemory: Boolean;
MemAlloc A l l o c a t e s Size b y t e s o f m e m o r y o n t h e h e a p a n d r e t u r n s a p o i n t e r t o t h e a l l o c a t e d b l o c k . I f t h e r e q u e s t e d b l o c k c a n n o t b e a l l o c a t e d , MemAlloc r e t u r n s nil. function MemAlloc(Size: Word): Pointer; MemAlloc d o e s n o t a l l o w t h e a l l o c a t i o n t o u s e t h e safety p o o l . Y o u c a n d i s p o s e o f a b l o c k a l l o c a t e d b y MemAlloc u s i n g t h e s t a n d a r d p r o c e d u r e FreeMem.
507
508
Part I I I — R e f e r e n c e s
NewStr A m e m o r y - m a n a g e m e n t f u n c t i o n . C r e a t e s s p a c e f o r a n e w string a n d r e t u r n s a p o i n t e r t o it. function Newstr(S: String): PString;
RegisterType If a n O b j e c t W i n d o w s t y p e is u s e d i n s t r e a m i n p u t a n d o u t p u t , y o u m u s t r e g i s t e r t h e o b j e c t t y p e u s i n g this m e t h o d . procedure RegisterType(var S: TStreamRec); S t a n d a r d object t y p e s a r e p r e r e g i s t e r e d w i t h Ob j Type v a l u e s i n t h e reserved range 0..99. RegisterType c r e a t e s a n e n t r y i n a l i n k e d list o f TStreamRec r e c o r d s .
RegisterWObjects A stream p r o c e d u r e u s e d t o register W O b j e c t s . procedure
RegisterWObjects;
RestoreMemory A m e m o r y - m a n a g e m e n t p r o c e d u r e . R e - e s t a b l i s h e s t h e m e m o r y state that existed before a n attempt to execute another program (using W i n E x e c ) . procedure
RestoreMemory;
D
REFERENCE
OBJECTWINDOWS RECORDS
LongRec PtrRec TDialogAttr TMessage TMultiSelRec TScrollBarTransferRec TStreamRec TWindowAttr WordRec
LongRec L o n g R e c i s a record
type f o r h a n d l i n g d o u b l e - w o r d - l e n g t h v a r i a b l e s .
LongRec = record Lo, Hi: Word; end;
510
Part III—References
PtrRec PtrRec holds the offset and segment values of a pointer. PtrRec = record Ofs, Seg: Word; end;
TDialogAttr TDialogAttr holds attribute values for TDialog objects. TDialogAttr = record Name: PChar; Param: Longint; end;
TMessage T h e m e s s a g e - p r o c e s s i n g l o o p in TApplication stores Windows message information in TMessage records. This information is p a s s e d to t h e a p p r o p r i a t e message-response method. TMessage = record Receiver: HWnd; Message: Word; case Integer of 0: (WParam: Word; LParam: Longint; Result: Longint); 1: (WParamLo: Byte; WParamHi: Byte; LParamLo: Word; LParamHi: Word; ResultLo: Word; ResultHi: Word); end;
D — O b j e c t W i n d o w s Records
TMultiSelRec TMultiSelRec h o l d s a list o f s e l e c t e d i t e m s for transfer t o or f r o m a m u l t i p l e s e l e c t i o n list box.
TMultiSelRec = record Count: Integer; Selections: array[0..0] of Integer; end; • Count i n d i c a t e s t h e n u m b e r o f s e l e c t e d i t e m s .
• Selections is a n o p e n - e n d e d array o f i n t e g e r s . U s i n g AllocMultiSel, y o u c a n a l l o c a t e a r e c o r d w i t h e n o u g h s e l e c t i o n i t e m s t o a c c o m m o d a t e all list-box i t e m s .
TSaollBarHransferRec B e f o r e y o u c a n l o a d or s t o r e o b j e c t s o n a TStream, y o u m u s t r e g i s t e r a n y O b j e c t W i n d o w s o b j e c t t y p e s u s i n g a TStreamRec.
{ TScrollBar transfer record } TScrollBarTransferRec = record LowValue: Integer; HighValue: Integer; Position: Integer; end;
TStreamRec T h e Regist erType p r o c e d u r e registers a n o b j e c t t y p e b y s e t t i n g a TSt reamRec r e c o r d for it.
TStreamRec = record ObjType: Word; VmtLink: Word; Load: Pointer; Store: Pointer; Next: Word; end;
511
512
Part III—References
T h e fields i n t h e s t r e a m - r e g i s t r a t i o n r e c o r d are d e f i n e d as f o l l o w s : Field
Contents
ObjType
U n i q u e n u m e r i c a l ID f o r t h e o b j e c t t y p e
VmtLink
Link to the object type's virtual-method table entry
Load
Pointer to the object type's Load constructor
Store
P o i n t e r t o t h e o b j e c t t y p e ' s Store m e t h o d
Next
P o i n t e r t o t h e n e x t TSt reamRec
O b j e c t W i n d o w s reserves o b j e c t - t y p e I D s ( O b j T y p e ) w i t h v a l u e s f r o m 0 t o 9 9 9 for its o w n u s e . Y o u c a n d e f i n e y o u r o w n o b j e c t - t y p e I D s i n t h e r a n g e 1,000 to 65,535. B y c o n v e n t i o n , a TSt reamRec f o r a Txxxx o b j e c t t y p e is c a l l e d Rxxxx. F o r e x a m p l e , t h e TStreamRec f o r a TCalculator t y p e is c a l l e d RCalculator:
type TCalculator = object(TDialog) constructor Load(var S: TStream); procedure Store(var S: TStream); end; const RCalculator: TStreamRec = ( ObjType: 2099; VmtLink: Ofs(TypeOf(TCalculator) ); Load: @TCalculator.Load; Store: @TCalculator.Store); begin A
RegisterType(RCalculator); end;
TWindowAttr TWindow o b j e c t s d e f i n e t h e i r attributes i n TWindowAttr r e c o r d s .
TWindowAttr = record Title: PChar; Style: Longint; ExStyle: Longint; X, Y, W, H: Integer;
D—ObjectWindows Records
Param: Pointer; case Integer of 0: (Menu: HMenu); 1: (Id: Integer); end;
{ window menu's handle or... } { control's child identifier }
WordRec WordRec is a utility record that lets you access the Lo and Hi bytes of a word. WordRec = record Lo, Hi: Byte; end;
513
E REFERENCE
THE
WINCRT UNIT
T h e T u r b o Pascal f o r Windows W i n C r t u n i t implements a t e r m i n a l - l i k e text s c r e e n in a w i n d o w . If y o u r a p p l i c a t i o n u s e s W i n C r t , it d o e s n o t have t o c o n t a i n a n y Windows-specific c o d e . T h i s u n i t is u s e f u l f o r reimplementing existing T u r b o Pascal t e x t - b a s e d a p p l i c a t i o n s i n Windows, w i t h o u t a d d i n g m u c h extra code. T o u s e t h e W i n C r t u n i t , i n c l u d e it i n y o u r a p p l i c a t i o n ' s u s e s c l a u s e : uses
WinCrt;
Table
E.l.
WinCrt procedures
Procedure
or Function
and
functions.
Value
AssignCrt
A s s o c i a t e s a text file w i t h t h e C R T window
ClrEol
C l e a r s all c h a r a c t e r s f r o m t h e c u r r e n t cursor position to t h e e n d of t h e line
ClrScr
C l e a r s t h e s c r e e n a n d returns c u r s o r t o t h e u p p e r - l e f t c o r n e r o f the s c r e e n
CursorTo
M o v e s the c u r s o r to the s p e c i f i e d c o o r d i n a t e s i n a virtual s c r e e n
DoneWinCrt
D e s t r o y s the C R T w i n d o w continues
516
Part I I I — R e f e r e n c e s
Table
E.l.
Procedure
continued or
Function
GotoXY
Value Moves t h e cursor to t h e specified c o o r d i n a t e s in a virtual s c r e e n
InitWinCrt
Creates the C R T w i n d o w
KeyPressed
Returns True w h e n t h e user presses a key
ReadBuf
Inputs o n e line from t h e C R T w i n d o w
ReadKey
Reads o n e character from t h e keyboard
ScrollTo
Scrolls t h e C R T w i n d o w to a specific screen location Scrolls t h e C R T w i n d o w to k e e p cursor visible
TrackCursor WhereX
Returns t h e X coordinate o f t h e current cursor location
WhereY
Returns the Y coordinate of t h e current cursor location
WriteBuf
Writes a b l o c k o f c h a r a c t e r s t o t h e C R T window
WriteChar
Writes
o n e character to t h e C R T w i n d o w
AssignCrt A s s o c i a t e s a text file w i t h t h e C R T w i n d o w .
procedure AssignCrt(var F: Text); For example:
program sample; uses WinCrt; var AScreenFile: Text; begin AssignCRT(AScreenFile);
E — T h e WinCrt Unit
Rewrite(AScreenFile); Writeln(AScreenFile, AScreenFile to screen.'); Close(AScreenFile); end. 1
ClrEol C l e a r s all t h e c h a r a c t e r s f r o m t h e c u r s o r p o s i t i o n t o t h e e n d o f t h e l i n e w i t h o u t moving the cursor.
procedure ClrEol; For example:
program sample; uses WinCrt; begin Writeln('String here.'); Writeln('Press a k e y . . . ) ; Readln; CursorTo(16,10); ClrEol; end. 1
ClrScr Clears the screen a n d returns the cursor to the upper-left corner o f the screen.
procedure ClrScr; For example:
program sample; uses WinCrt; begin Writeln('Hi. Press a key...'); Readln; ClrScr; end.
517
518
Part I I I — R e f e r e n c e s
CursorTo M o v e s t h e c u r s o r t o t h e s p e c i f i e d c o o r d i n a t e s i n a virtual s c r e e n .
procedure CursorTo(X, Y: Integer); T h e u p p e r - l e f t c o r n e r o f t h e C R T w i n d o w is r e p r e s e n t e d b y t h e c o o r d i n a t e s 0,0. CursorTo sets t h e Cursor v a r i a b l e t o (X,Y). F o r e x a m p l e :
program sample; uses WinCrt; begin CursorTo(18,15); Writeln( 18/15 coordinates. ); end. 1
1
DoneWinCrt Destroys any existing C R T .
procedure DoneWinCrt; C a l l i n g DoneWinCrt b e f o r e a n a p p l i c a t i o n t e r m i n a t e s p r e v e n t s t h e C R T w i n d o w f r o m e n t e r i n g a n i n a c t i v e state. F o r e x a m p l e :
program sample; uses WinCrt; begin Writeln('This is a CRT window.'); Writeln('Return. ); Readln; DoneWinCRT; Writeln('This is another CRT window.'); end. 1
E — T h e WinCrt Unit
GotoXY M o v e s t h e c u r s o r t o t h e s p e c i f i e d c o o r d i n a t e s w i t h a virtual s c r e e n .
procedure GotoXY(X, Y: Integer); T h e upper-left corner o f the virtual screen corresponds to the c o o r d i n a t e s 1,1. U s e CursorTo r a t h e r t h a n GotoXY w h e n y o u d e v e l o p n e w W i n d o w s a p p l i c a t i o n s . GotoXY is available strictly f o r c o m p a t i b i l i t y w i t h t h e C r t u n i t o f D O S - b a s e d T u r b o Pascal. F o r e x a m p l e :
program sample; uses WinCrt; begin GotoXY(20,20); Writeln('Hi'); end.
InitWinCrt Creates the C R T window.
procedure InitWinCrt; Ifyou u s e Read, Readln, Write, o r Writ eln i n a file that h a s b e e n a s s i g n e d t o t h e C R T , InitWinCrt is c a l l e d automatically f o r you. F o r e x a m p l e :
program sample; uses Strings, WinCrt, WinDOS; begin StrCopy(WindowTitle,'CRT Window created by InitWinCRT.'); InitWinCRT; end.
519
520
Part I I I — R e f e r e n c e s
KeyPressed D e c i d e s w h e t h e r t h e u s e r has p r e s s e d a k e y . function KeyPressed: Boolean; U s e Re ad Key t o read t h e k e y . Return
Value
True
I f a k e y has b e e n p r e s s e d
False
I f a k e y has n o t b e e n p r e s s e d
For example: program sample; uses WinCrt; begin repeat Write('A continuous string'); until KeyPressed; end.
ReadBuf I n p u t s a l i n e from t h e C R T w i n d o w . function ReadBuf(Buffer: PChar; Count: Word): Word; Buffer p o i n t s t o a l i n e b u f f e r that has s p a c e for Count n u m b e r o f c h a r a c t e r s . Count holds t h e n u m b e r o f c h a r a c t e r s t o read in t h e b u f f e r . U p t o Count - 2 c h a r a c t e r s c a n b e inserted. A n e n d - o f - l i n e m a r k e r (a # 1 3 f o l l o w e d b y a # 10) is a u t o m a t i c a l l y a p p e n d e d t o t h e l i n e w h e n t h e u s e r p r e s s e s E n t e r ( R e t u r n ) . T h e c o m m a n d returns t h e n u m b e r o f c h a r a c t e r s read, including t h e e n d - o f - l i n e o r end-of-file m a r k e r . F o r e x a m p l e : program sample; uses WinCrt; var
E — T h e WinCrt Unit
Chars: PChar; begin GetMem(Chars, 20); Chars := #20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0; Writeln( Enter a phrase:'); ReadBuf(Chars, 20); Writeln(' You entered: '); Writeln(Chars); end. 1
ReadKey Reads a character from the keyboard.
function ReadKey: Char; T h e c h a r a c t e r is n o t e c h o e d o n t h e s c r e e n . F o r e x a m p l e :
program sample; uses WinCrt; var AChar: Char; begin Writeln('Press a key'); AChar := Readkey; Writeln(' You pressed ', AChar, ' . ' ) ; end.
ScrollTo S c r o l l s t h e C R T w i n d o w t o d i s p l a y t h e virtual s c r e e n l o c a t i o n s p e c i f i e d b y X,Y in the upper-left corner.
procedure ScrollTo(X, Y: Integer); T h e upper-left corner of the virtual screen c o r r e s p o n d s coordinates 0,0. For e x a m p l e :
to
the
521
522
Part I I I — R e f e r e n c e s
program sample; uses WinCrt; begin GotoXY(10,20); Writeln('Hi'); Writeln( Enter a line and Return.'); Readln; ScrollTo(0,8); end. 1
TrackCursor S c r o l l s t h e C R T w i n d o w if n e c e s s a r y t o m a k e t h e c u r s o r v i s i b l e .
procedure TrackCursor; For example:
program sample; uses WinCrt; var I: integer; begin for I := 1 to 20 do Write('CursoR'); TrackCursor; Readln; end.
WhereX Returns the X coordinate of the current cursor position,
function WhereX: Integer;
E — T h e WinCrt Unit
For example: program sample; uses WinCrt; begin Writeln(WhereX,
'WhereX. ); 1
end.
WhereY Returns the Y coordinate o f the current cursor position. function WhereY:
Integer;
For example: program sample; uses WinCrt; begin Writeln(WhereY,
'WhereY. ); 1
end.
ffiiteBuf Writes a specified b l o c k o f characters t o the C R T w i n d o w , procedure WriteBuf(Buffer:
PChar;
Count:
Word);
B u f f e r p o i n t s t o t h e first c h a r a c t e r i n t h e b l o c k . C o u n t h o l d s t h e n u m b e r of characters to write to the buffer. If A u t o T r a c k i n g is o n , t h e C R T w i n d o w scrolls t o m a k e c e r t a i n that t h e c u r s o r is visible after w r i t i n g t h e b l o c k o f c h a r a c t e r s . F o r e x a m p l e :
523
524
Part I I I — R e f e r e n c e s
program sample; uses WinCrt; var ABuffer: PChar; begin GetMem(ABuffer, 100); ABuffer := 'WriteBuf'; WriteBuf(ABuffer, 100); end.
WtiteChar Writes o n e character to the C R T w i n d o w .
procedure WriteChar(Ch: Char); For example:
program sample; uses WinCrt; begin WriteChar( F ); end. 1
1
F REFERENCE
A WINCRT EXAMPLE T h e f o l l o w i n g a p p l i c a t i o n i m p l e m e n t s a m i n i b r o w s e r that traces a h i e r a r c h y o f o b j e c t s i n e i t h e r T u r b o Pascal o r C + + . It w a s o r i g i n a l l y w r i t t e n i n T u r b o Pascal f o r D O S , b u t r e q u i r e d a l m o s t n o c h a n g e s t o b e c o m p i l e d w i t h T u r b o Pascal f o r W i n d o w s a n d r u n as a W i n d o w s a p p l i c a t i o n . T h e m a i n a d d i t i o n t o this v e r s i o n is t h e W i n C r t u n i t , w h i c h i m p l e m e n t s a text w i n d o w i n W i n d o w s f o r t h e a p p l i c a t i o n ' s o u t p u t . T h e a p p l i c a t i o n is far f r o m c o m p l e t e a n d c o u l d u s e m a n y a d d i t i o n s t o b e u s e f u l as a b r o w s e r , b u t it illustrates h o w a t y p i c a l T u r b o Pascal D O S - b a s e d ( a n d o b j e c t - o r i e n t e d ) a p p l i c a t i o n c a n b e r u n (with little m o d i f i c a t i o n ) i n W i n d o w s . It u s e s o b j e c t - o r i e n t e d t e c h n i q u e s , b u t n o t t h e O b j e c t W i n d o w s library. T h e application consists o f a m a i n m o d u l e a n d t w o units (nodes2 a n d cell list), w h i c h are p r i n t e d h e r e . This minibrowser m o d u l e reconstructs an object hierarchy from either Pascal or C + + source c o d e . T h e reconstruction p r o b l e m c a n b e dissected into several s m a l l e r p r o b l e m s : • Getting a "key" object from a user • S e a r c h i n g a s p e c i f i e d p r o j e c t ' s files f o r k e y w o r d s that r e c o n s t r u c t a h i e r a r c h y f o r that " k e y " o b j e c t • D i s p l a y i n g t h e r e s u l t s o r a l l o w i n g a u s e r t o edit t h e files c o n t a i n i n g objects in the hierarchy
526
Part I I I — R e f e r e n c e s
A u s e r s p e c i f i e s a n o b j e c t s h e w a n t s to k n o w a b o u t . T h e m i n i b r o w s e r then reads a p r o j e c t file (to l e a r n the files f o r u s e i n b u i l d i n g a h i e r a r c h y ) . It then reconstructs e i t h e r a C + + o r T u r b o Pascal h i e r a r c h y , d e p e n d i n g o n the l a n g u a g e y o u specify at run-time. T h e m e t h o d s Init_f iles a n d Init_Types h a n d l e file- a n d h i e r a r c h y - t y p e i n i t i a l i z a t i o n . T h e m i n i b r o w s e r ( t h r o u g h t h e Hierarchy o b j e c t ) t h e n s e a r c h e s t h e files s p e c i f i e d i n t h e p r o j e c t file, first f o r b a s e t y p e s — " o b j e c t s " o r " c l a s s e s " — (through the base m e t h o d ) , a n d then for derived types (through the derived m e t h o d ) . I f it f i n d s a d e r i v e d t y p e , it d e t e r m i n e s its a n c e s t o r ( t h r o u g h t h e a n c e s t o r m e t h o d ) a n d t h e n recursively b a c k t r a c k s t o its a n c e s t o r , a d d i n g t h e o b j e c t n a m e t o a list as it g o e s . It t h e n s e a r c h e s f o r w a r d a g a i n f o r b a s e a n d d e r i v e d t y p e s . If it finds a b a s e t y p e , t h e s e a r c h is over, a n d it s e n d s a m e s s a g e t o B a c k T r a c k t o display the constructed hierarchy. D e p e n d i n g o n w h e t h e r y o u w a n t t o d i s p l a y o r e d i t , it t h e n s e n d s a m e s s a g e t o t h e a p p r o p r i a t e o b j e c t — DisplayStr o r Editor. E a c h part o f t h e m i n i b r o w s e r is i m p l e m e n t e d as a n " o b j e c t , " s o y o u c a n easily m o d i f y a n d e x t e n d t h e b i g o b j e c t ( t h e m i n i b r o w s e r m o d u l e ) w i t h o u t c h a n g i n g its o v e r a l l d e s i g n b y reimplementing selective objects. F o r e x a m p l e , t h e Editor o b j e c t i n t h e m a i n m o d u l e o b t a i n s file, l i n e , a n d p o s i t i o n i n f o r m a t i o n . T o e x t e n d this m o d u l e , a d d a m e t h o d that p a s s e s this i n f o r m a t i o n t o y o u r e d i t o r o f c h o i c e . O n e l i n e o f c o d e ( a n d a n e d i t o r library) d o e s t h e trick. unit nodes2; { Contains abstract cell and cell-list types } interface uses CRT, DOS, cellist; type AnyTypePtr = "AnyType; AnyType = object(Node) constructor init; destructor done; virtual; procedure DSAction; virtual; procedure BTAction; virtual; procedure EditAction; virtual; end; AnyTypeListPtr = "AnyTypeList; AnyTypeList = object(List) constructor init; destructor Done; virtual;
{ Type Action { Type Action { Type Action
} } }
F — A WinCrt Example
procedure GetNodes; virtual; end; implementation { constructors } constructor AnyType.init; constructor AnyTypeList.Init;
{ Process AnyTypeList }
begin end; begin end;
{ abstract } { abstract }
begin end; begin end;
{ abstract } { abstract }
{ destructors } destructor AnyType.done; destructor AnyTypeList.Done; { methods } procedure procedure procedure procedure
AnyType.DSAction; AnyType.BTAction; AnyType.EditAction; AnyTypeList.GetNodes;
begin begin begin begin
end; end; end; end;
{ { { {
abstract abstract abstract abstract
end. { unit nodes2 } unit cellist; { Contains base, node, and list types } {$S-} interface type { Abstract base object type } BasePtr = "Base; Base = object destructor Done; virtual; end; { Abstract linked list node type } NodePtr = "Node; Node = object(Base) Next: NodePtr; end; { Simplified Linked list type } ListPtr = "List; List = object(base)
} } } }
527
528
Part III—References
Last: NodePtr; procedure Append(N: NodePtr); procedure Clear; function First: NodePtr; function Next(N: NodePtr): NodePtr; end; implementation { destructor } destructor Base.Done; begin end; { List methods } procedure List.Append(N: NodePtr); begin if Last = nil then Last := N else N".Next := Last".Next; Last".Next := N; Last := N; end; procedure List.Clear; begin Last := nil; end; function List.First: NodePtr; begin if Last = nil then First := nil else First := Last".Next; end; function List.Next(N: NodePtr): NodePtr; begin if N = Last then Next := nil else Next := N".Next; end; end. { Unit cell list } { Main module } program browser; uses WINCRT, nodes2, cellist;
{ Contains specific browser } { Key unit needed for Windows }
F — A WinCrt Example
type StringPtr = "String; BrowserListPtr = "BrowserList; BrowserList = object(AnyTypeList) constructor init; destructor done; virtual; procedure GetNodes; virtual; end; DisplayStrPtr = "DisplayStr; DisplayStr = object(AnyType) Value: StringPtr; constructor Init(V: String); destructor Done; virtual; procedure DSAction; virtual; end; BackTrackPtr = "BackTrack; BackTrack = object(AnyType) Value: StringPtr; constructor Init(V: String); destructor Done; virtual; procedure BTAction; virtual; end;
{ Process a StrCell }
{ Process a BTCell }
EditPtr = "Editor; Editor = object(AnyType) FileName : String; Line : String; LineNo : word; Position : word; constructor Init(F: string; L: string; Ln: word; P: word); destructor Done; virtual; procedure EditAction; virtual; { Edit } end; TextFile = object(base) F : Text; FileName : String; Line : String; Buf : array[0..8191] of char; { Buffer for faster I/O }
529
530
Part III—References
LineNo : word; Position : word; function open_file: boolean; end; HierarchyPtr = "hierarchy; Hierarchy = object(TextFile) Recurse : boolean; Method : String; Language_type : char; End_type, Base_type, Derived_type : string[30]; Object_type, Search_type, Ancestor_type : String[30]; function base : boolean; { Looks for base types } function derived : boolean; { Looks for derived types } function ancestor : boolean; { Looks for ancestors } constructor init; destructor done; virtual; procedure init_types; { Sets types for C++ or Pascal } procedure init_files; { Sets files for C++ or Pascal } procedure construct; { Flow controller } procedure Reconstruct; { Calls construct and simplifies recursion} procedure update_backtrack_list; { Keeps track of types } procedure find_methods; { Finds methods } end; var Display, H : L : P :
{ Globals } Edit : boolean; HierarchyPtr; BrowserListPtr; AnyTypePtr;
{ Constructors } constructor DisplayStr.Init(V: String); begin GetMem(Value, Length(V) + 1 ) ; Value" := V; end; constructor BackTrack.Init(V: String); begin GetMem(Value, Length(V) + 1 ) ; Value" := V; end;
F — A WinCrt Example
constructor begin FileName Line LineNo Position end;
Editor.Init(F: string; L: string; Ln: word; P: word); := := := :=
F; L; Ln; P;
constructor Hierarchy.init; begin end; constructor BrowserList.init; begin end; {destructors } destructor Editor.Done; begin end; destructor DisplayStr.Done; begin
FreeMem(Value, Length(Value") + 1 ) ; end;
destructor BackTrack.Done; begin FreeMem(Value, Length(Value") + 1 ) ; end; destructor Hierarchy.done; begin end; destructor BrowserList.done; begin end; { Methods }
procedure DisplayStr.DSAction; var Ch : char; begin writeln(Value"); Ch := readkey; end; procedure BackTrack.BTAction; begin writeln(Value"); end; procedure Editor.EditAction; var Ch : char; begin writeln(#13, #10,'File
{ Show the object hierarchy }
= ',FileName);
531
532
Part I I I — R e f e r e n c e s
writeln( Line = ',Line); writeln('LineNumber= ',LineNo); writeln('Position = ,Position); { Call editor here and pass it appropriate information. } end; 1
1
procedure hierarchy.init_types; begin case Language_type of •p*: begin { Pascal } Base_type := ' = object'; Derived_type := ' = object('; End_type := 'end'; end; 'c': begin { C++ } Base_type := 'class '; Derived_type := ' :'; End_type := '}'; end; end; { case } end; procedure hierarchy.init_files; begin case Language_type of 'p': FileName := 'cltest2.pas'; { Pascal } 'c': FileName := 'cltest.cpp'; { C++ } end; { case } { Add functions here to read a project's files } end; procedure hierarchy.find_methods; var NextLine : string; TempPosition : word; begin Method := ''; NextLine := Line; TempPosition := 0; While (TempPosition = 0) do begin TempPosition := Pos(End_type,NextLine); Method := Method + NextLine + #13 + #10; readln(F,NextLine);
F — A WinCrt Example
end; L".Append(New(DisplayStrPtr,Init(Method))); L".Append(New(EditPtr,Init(FileName,Line,LineNo,Position))); end; function hierarchy.base: boolean; begin LineNo := 1; case Language_type of 'p': Search_type := Object_type + Base_type; 'c': Search_type := Base_type + Object_type; end; { case } while not eof(F) do begin readln(F,Line); Position := Pos(Search_type,Line); If (Position > 0) then begin Position := Pos(Derived_type,Line); If (Position = 0) then begin findjnethods; base := true; exit; end; end; inc(LineNo); end; base := false; end; function hierarchy.derived: boolean; begin case Language_type of 'p': Search_type := Object_type + Derived_type; 'c': Search_type := Base_type + Object_type + Derived_type; end; { case } LineNo := 1; while not eof(F) do begin readln(F,Line); Position := Pos(Search_type,Line); If (Position > 0) then
533
534
Part III—References
begin If ancestor then begin find_methods; derived := true; exit; end; end; inc(LineNo); end; derived := false; end; function hierarchy.ancestor: boolean; var T_Ancestor_type : string[30]; I,J,L : integer; begin Ancestor_type := ''; T_Ancestor_type := '; I := Length(Line); { Start while (Line[I] = #32) do { Space dec(I); while (Line[I] = ) ) do { Empty dec(I); case Language_type of 'c' : while (Line[I] #32) do { Space begin T_Ancestor_type := T_Ancestor_type dec(I); end; 'P': while (Line[IJ ' ( ) do begin T_Ancestor_type := T_Ancestor_type dec(l); end; end; { case } 1
1
1
at the end of the line } } in C++ }
} + Line[I];
1
+ Line[I];
L := Length(T_Ancestor_type); for I := L downto 1 do { Reverse the list } Ancestor_type := Ancestor__type + T_Ancestor_type[I]; end;
F — A WinCrt Example
535
procedure hierarchy.update_backtrack_list; begin L".Append(New(BackTrackPtr, Init(Object_type))); end; function TextFile.open_file: boolean; begin {$1-} { Test for I/O error } assign(F,FileName); Reset(f); {$1+}
Open_file := (IOResult = 0); end; procedure hierarchy.Reconstruct; var Count : integer; begin Count := 1; Recurse := true; While Count < 10 do While Recurse do begin construct; inc(Count); end; end;
{ Still more ancestors } { Recursively backtrack for ancestors }
procedure hierarchy.construct; begin If Open_file then { If open successful } begin SetTextBuf(F,buf); update_backtrack_list; Close(F); If Open_file then If Derived then { If derived class, find its ancestor } begin Object_type := ancestor_type; { Set up for backtrack } Close(F); Recurse := true; { Still more ancestors } end ELSE
536
Part III—References
Close(F); IF Open_file then If Base then begin Close(F); Recurse := false; end; end; end;
{ If base type, you are done. }
{ No more ancestors }
procedure display_mode; var Ch : char; begin write('e-Edit or d-display '); Ch := Readkey; writeln; If Ch = 'e' then Edit := true Else Display := true; end; procedure BrowserList.GetNodes; begin P := AnyTypePtr(First); while P nil do begin P .BTAction; P := AnyTypePtr(Next(P)); end;
{ Display/edit option }
{ Process the browser list } { Set pointer to first node }
A
If Display = true then begin P := AnyTypePtr(First); while P nil do begin P .DSAction; P := AnyTypePtr(Next(P)); end; end;
{ Is it displaying ? }
If Edit = true then begin P := AnyTypePtr(First); while P nil do begin
{ Editing ? }
A
F — A WinCrt Example
P .EditAction; P := AnyTypePtr(Next(P)); end; end; end; A
{ main } begin Clrscr; Edit := false; { Initializations } Display := false; New(L,init); { Initialize a new browser list } L".clear; New(H,init); { Initialize a new hierarchy list } write('Enter Language — p or c : '); readln(H .Language_type); write('Enter Object: '); readln(H".Object_type); writeln; ! - r .Init_files; H .Init_types; H".Reconstruct; display_mode; { Set display or edit } L".GetNodes; { Process the browser list } Dispose(L,Done); { Clean up } Dispose(H,Done); A
A
end. { main }
537
G
REFERENCE
THE
STRINGS UNIT
T h e S t r i n g s u n i t s u p p o r t s a class o f c h a r a c t e r strings t e r m i n a t e d b y a n u l l b y t e , c a l l e d null-terminated strings. T h e W i n d o w s A p p l i c a t i o n P r o g r a m m i n g Interface (API) r e q u i r e s this f o r m a t . N u l l - t e r m i n a t e d strings differ f r o m typical T u r b o P a s c a l s t r i n g s , w h o s e l e n g t h is d e t e r m i n e d b y a l e n g t h b y t e . A T u r b o Pascal string is l i m i t e d t o 2 5 5 c h a r a c t e r s . T h e size o f a n u l l t e r m i n a t e d string is l i m i t e d b y t h e d a t a s e g m e n t ( 6 4 K ) . T h e Strings unit has m a n y functions a n d p r o c e d u r e s for manipulating n u l l - t e r m i n a t e d strings a n d f o r c o n v e r t i n g n u l l - t e r m i n a t e d strings t o T u r b o Pascal s t r i n g s . T a b l e G . l lists t h e f u n c t i o n s a n d p r o c e d u r e s i n t h e strings u n i t . Table
G. 1. Strings
Function
Name
unit
functions. Description
StrCat
A p p e n d s a c o p y o f o n e string t o t h e e n d o f a n o t h e r a n d r e t u r n s t h e c o n c a t e n a t e d string
StrComp
C o m p a r e s t w o strings
StrCopy
C o p i e s o n e string t o a n o t h e r
StrDispose
D i s p o s e s o f a p r e v i o u s l y a l l o c a t e d string
StrECopy
C o p i e s o n e string t o a n o t h e r a n d r e t u r n s a p o i n t e r t o t h e e n d o f t h e r e s u l t i n g string continues
540
Part III — R e f e r e n c e s
Table
G.l.
Function
continued Name
Description
StrEnd
Returns a p o i n t e r to the e n d o f a string
StrlComp
C o m p a r e s t w o strings w i t h o u t c a s e sensitivity
StrLCat
A p p e n d s characters f r o m a string to the e n d o f a n o t h e r a n d returns
the c o n c a t e n a t e d string
StrLComp
C o p i e s characters f r o m o n e string to a n o t h e r
StrLCopy
C o m p a r e s t w o strings, u p to a m a x i m u m length
StrLen
Returns the n u m b e r o f characters in S t r
StrLIComp
C o m p a r e s t w o strings, u p to a m a x i m u m length, w i t h o u t c a s e sensitivity
StrLower
C o n v e r t s a string t o l o w e r c a s e
StrMove
C o p i e s characters f r o m o n e string to a n o t h e r
StrNew
Allocates a string o n the h e a p
StrPas
C o n v e r t s a n u l l - t e r m i n a t e d string t o a Pascal style string
StrPCopy
C o p i e s a Pascal style s t r i n g t o a n u l l - t e r m i n a t e d string
StrPos
R e t u r n s a p o i n t e r t o t h e first o c c u r r e n c e o f a s t r i n g i n a n o t h e r string
StrRScan
R e t u r n s a p o i n t e r t o t h e first o c c u r r e n c e o f a string in a n o t h e r string
StrScan
R e t u r n s a p o i n t e r t o t h e first o c c u r r e n c e o f a c h a r a c t e r i n a string
StrUpper
C o n v e r t s a string to u p p e r c a s e
StrCat A p p e n d s a c o p y o f o n e string t o t h e e n d o f a n o t h e r string a n d r e t u r n s t h e c o n c a t e n a t e d string.
function StrCat(Test, Source: PChar): PChar;
G — T h e Strings U n i t
St rCat d o e s n o t c h e c k t h e string l e n g t h . T h e d e s t i n a t i o n b u f f e r m u s t h a v e s p a c e f o r at least StrLen(Test) + Strl_en(Source) + 1 c h a r a c t e r s . F o r example:
program Sample; uses Strings, WinCrt; const Windows: PChar = 'Windows'; Bible : PChar = 'Bible'; var S: array[0..15] of Char; begin StrCopy(S, Windows); StrCat(S, ' '); StrCat(S, Bible); Writeln(S); end.
StrComp C o m p a r e s t w o strings.
function StrComp(Str1, Str2 : PChar): Integer; Return
Values:
0 if Str1 > Str2 For example:
program Sample; uses Strings, WinCrt; var C: Integer; Result: PChar; S1, S2: array[0..79] of Char; begin
541
542
Part III — R e f e r e n c e s
Readln(S1); Readln(S2); C := StrComp(S1, S2); if C < 0 then Result := ' is less than ' else if C > 0 then Result := ' is greater than else Result := ' is equal to '; Writeln(S1, Result, S2); end. 1
StrCopy C o p i e s o n e string t o a n o t h e r .
function StrCopy(Test, Source: PChar): PChar; StrCopy d o e s n o t c h e c k t h e s t r i n g l e n g t h . T h e d e s t i n a t i o n b u f f e r m u s t h a v e r o o m f o r at least St rLen (Source) + 1 c h a r a c t e r s . F o r e x a m p l e :
program Sample; uses Strings, WinCrt; var S: array[0..15] of Char; begin StrCopy(S, 'Windows Bible'); Writeln(S); end.
StrDispose D i s p o s e s o f a string o n a h e a p .
function StrDispose(Str: PChar); StrDispose d i s p o s e s o f a s t r i n g that w a s p r e v i o u s l y a l l o c a t e d w i t h StrNew. I f Str is n i l , StrDispose d o e s n o t d o a n y t h i n g . F o r e x a m p l e :
program Sample; uses Strings, WinCrt;
G — T h e Strings U n i t
var P: PChar; S: array[0..79] of Char; begin Readln(S); P := StrNew(S); Writeln(P); StrDispose(P); end.
StrECopy C o p i e s o n e s t r i n g t o a n o t h e r s t r i n g a n d returns a p o i n t e r t o t h e e n d o f t h e n e w string.
function StrECopy(Test, Source: Pchar): PChar; StrECopy d o e s n o t c h e c k t h e s t r i n g l e n g t h . T h e d e s t i n a t i o n b u f f e r m u s t have s p a c e for at least St rLen (Source) + 1 characters. F o r e x a m p l e :
program Sample; uses Strings, WinCrt; const Windows: PChar = 'Windows'; Bible : PChar = 'Bible'; var S: array[0..15] of Char; begin StrECopy(StrECopy(StrECopy(S, Windows), ' '), Bible); Writeln(S); end.
StrEnd Returns a p o i n t e r t o t h e e n d o f a string,
function StrEnd(Str: PChar): Pchar;
543
544
Part III — R e f e r e n c e s
For example:
program Sample; uses Strings, WinCrt; var S: array[0..79] of Char; begin Readln(S); Writeln('String length is ', StrEnd(S) - S); end.
StrlComp C o m p a r e s t w o strings w i t h o u t c a s e sensitivity.
function StrIComp(Str1, Str2:PChar): Integer; For example:
program Sample; uses Strings, WinCrt; var Result: PChar; S1, S2: array[0..79] of Char; begin Readln(S1); Readln(S2); if Strl_Comp(S1, S2, 8) = 0 then Result := 'equal' else Result := 'not equal'; Writeln('The first eight characters are ', Result); end.
StrLCat A p p e n d s c h a r a c t e r s f r o m o n e string t o t h e e n d o f a n o t h e r s t r i n g a n d r e t u r n s t h e c o n c a t e n a t e d string.
G — T h e Strings U n i t
function StrLCat(Test, Source: PChar; MaxLen: Word): PChar; For example:
program Sample; uses Strings, WinCrt; var S: array[0..9] of Char; begin StrLCopy(S, 'This', SizeOf(S) - 1) StrLCat(S, ', SizeOf(S) - 1); StrLCat(S, 'String , SizeOf(S) - 1); Writeln(S); end. 1
1
StrLComp C o m p a r e s t w o strings, u p to a m a x i m u m length.
function StrLComp(Str1, Str2: PChar; MaxLen: Word): Integer; For example:
program Sample; uses Strings, WinCrt; var Result: PChar; S1, S2: array[0..79] of Char; begin Readln(S1); Readln(S2); if StrLComp(S1, S2, 8) = 0 then Result := 'equal' else Result := 'not equal'; Writeln('The first eight characters are ', Result); end.
545
546
Part III — R e f e r e n c e s
StrLCopy C o p i e s c h a r a c t e r s f r o m o n e string t o a n o t h e r string.
function StrLCopy(Test, Source: PChar; MaxLen: Word): PChar; For example:
program Sample; uses Strings, WinCrt; var S: array[0..9] of Char; begin StrLCopy(S, 'A string', SizeOf(S) - 1); Writeln(S); end.
StrLen R e t u r n s t h e n u m b e r of c h a r a c t e r s i n Str.
function StrLen(Str: PChar): Word; For example:
program Sample; uses Strings, WinCrt; var S: array[0..79] of Char; begin Readln(S); Writeln('String length is ', StrLen(S)); end.
G — T h e Strings U n i t
StrUComp C o m p a r e s t w o s t r i n g s , u p t o a m a x i m u m l e n g t h , w i t h o u t c a s e sensitivity.
function StrLIComp(Str1, Str2: PChar; MaxLen: Word): Integer; For example:
program Sample; uses Strings, WinCrt; var C: Integer; Result: PChar; S1, S2: array[0..79] of Char; begin Readln(S1); Readln(S2); C := StrComp(S1, S2); if C < 0 then Result := ' is less than else if C > 0 then Result := ' is greater than ' else Result := ' is equal to ; Writeln(S1, Result, S2); end. 1
1
StrLower C o n v e r t s a string t o l o w e r c a s e .
function StrLower(Str: PChar): PChar; For example:
program Sample; uses Strings, WinCrt; var S: array[0..79] of Char; begin Readln(S); Writeln(StrUpper(S)); Writeln(StrLower(S)); end.
547
548
Part III — R e f e r e n c e s
StrMove C o p i e s c h a r a c t e r s f r o m o n e string t o a n o t h e r string.
function StrMove(Test,
Source:
PChar; Count: Word):
PChar;
For example:
program Sample; uses Strings, WinCrt; { Allocate a string on the heap } function StrNew(S: PChar): PChar; var L: Word; P: PChar; begin if (S = nil) or (S = #0) then StrNew := nil else begin L := StrLen(S) + 1; GetMem(P, L); StrNew := StrMove(P, S, L); end; end; { Dispose the string allocated on the heap } procedure StrDispose(S: PChar); begin if S nil then FreeMem(S, StrLen(S) + 1 ) ; end; A
StrNew A l l o c a t e s a string o n t h e h e a p .
function StrNew(Str: PChar):
PChar;;
StrNew a l l o c a t e s a c o p y o f S t r o n t h e h e a p . If S t r is n i l or p o i n t s t o a n e m p t y string, St rNew r e t u r n s n i l a n d d o e s n o t a l l o c a t e s p a c e o n t h e h e a p f o r t h e string. O t h e r w i s e , StrNew m a k e s a d u p l i c a t e o f S t r , d e t e r m i n i n g t h e s p a c e n e e d e d b y a call t o t h e GetMem s t a n d a r d p r o c e d u r e . It r e t u r n s a p o i n t e r t o t h e d u p l i c a t e d string. T h e a l l o c a t e d s p a c e is S t r L e n ( S t r ) + 1 bytes long.
G — T h e Strings U n i t
For example:
program Sample; uses Strings, WinCrt; function StrNew(S: PChar): PChar; var L: Word; P: PChar; begin if (S = nil) or (S" = #0) then StrNew := nil else begin L := StrLen(S) + 1; GetMem(P, L); StrNew := StrMove(P, S, L); end; end;
StrPas C o n v e r t s a n u l l - t e r m i n a t e d string t o a T u r b o P a s c a l string. F o r e x a m p l e :
program Sample; uses Strings, WinCrt; function StrPas(Str: PChar): PChar; uses Strings, WinCrt; var A: array[0..79] of Char; S: string[79]; begin Readln(A); S := StrPas(A); Writeln(S); end.
549
550
Part III — R e f e r e n c e s
StrPCopy C o p i e s a T u r b o Pascal string t o a n u l l - t e r m i n a t e d string.
function StrPCopy(Test: PChar; Source: String); StrPCopy d o e s n o t c h e c k t h e string l e n g t h . T h e d e s t i n a t i o n b u f f e r m u s t h a v e s p a c e f o r at least Length(Source)
+ 1 c h a r a c t e r s . For e x a m p l e :
program Sample; uses Strings, WinCrt; var A: array[0..79] of Char; S: string[79]; begin Readln(S); StrPCopy(A, S); Writeln(A); end.
StrPos R e t u r n s a p o i n t e r t o t h e first o c c u r r e n c e o f a string i n a n o t h e r string,
function StrPos(Str1, Str2: PChar): PChar; Return
Value:
0 if Str2 d o e s n o t o c c u r i n Str1. F o r e x a m p l e :
program Sample; uses Strings, WinCrt; var P: PChar; S, SubStr: array[0..79] of Char; begin Readln(S); Readln(SubStr);
G — T h e Strings U n i t
P := StrPos(S, SubStr); if P = nil then Writeln('String not found'); else Writeln('String found at index ', P - S); end.
StrRScan R e t u r n s a p o i n t e r t o t h e first o c c u r r e n c e o f a s t r i n g i n a n o t h e r string,
function StrRScan(Str: PChar; Chr: Char): PChar; Return Value: 0 if Chr d o e s n o t o c c u r i n Str. F o r e x a m p l e :
program Sample; uses Strings, WinCrt; {Return a pointer to the name part of a full path name } function NamePart(FileName: PChar): PChar; var P: PChar; begin P := StrRScan(FileName, ' \ ' ) ; if P = nil then begin P := StrRScan(FileName, ' : ' ) ; if P = nil then P := FileName; end; NamePart := P; end;
StrScan R e t u r n s a p o i n t e r t o t h e first o c c u r r e n c e o f a c h a r a c t e r i n a string,
function StrScan(Str: PChar; Chr: Char): PChar;
551
552
Part III — R e f e r e n c e s
Return
Value:
0 if Chr d o e s n o t o c c u r i n Str. F o r e x a m p l e :
program Sample; uses Strings, WinCrt; { Return true if file name has wild cards in it } function HasWildcards(FileName: PChar): Boolean; begin HasWildcards := (StrScan(FileName, '*') nil) or (StrScan(FileName, '?') nil); end;
StrUpper C o n v e r t s a string t o u p p e r c a s e .
function Strllpper(Str: PChar): PChar; For example:
Program sample; uses Strings, WinCrt; var S: array[0..79] of Char; begin Readln(S); Writeln(StrUpper(S)); Writeln(Strl_ower(S)); end.
H REFERENCE
THE TURBO PASCAL FOR WINDOWS SYSTEM UNIT T h e S y s t e m u n i t ( S Y S T E M . T P U ) is t h e T u r b o Pascal r u n - t i m e library. It i m p l e m e n t s l o w - l e v e l , r u n - t i m e s u p p o r t r o u t i n e s f o r all b u i l t - i n f e a t u r e s , s u c h as file I/O, s t r i n g - h a n d l i n g , f l o a t i n g p o i n t , a n d d y n a m i c m e m o r y a l l o c a t i o n . B e c a u s e all u n i t s a n d p r o g r a m s a u t o m a t i c a l l y u s e t h e S y s t e m u n i t , y o u n e v e r n e e d t o refer t o it i n a Uses c l a u s e . T a b l e H . l lists t h e S y s t e m u n i t ' s v a r i a b l e s a n d c o n s t a n t s . T a b l e H . 2 is a n a l p h a b e t i c a l i n d e x o f all t h e p r o c e d u r e s a n d functions in the System unit. Table
H. 1. System
unit variables Variables
and typed
constants.
(Uninitialized)
Variable
Type
Description
Input
Text
I n p u t s t a n d a r d file
Output
Text
O u t p u t s t a n d a r d file continues
554
Part I I I — R e f e r e n c e s
Table
H.l.
continued Constants
(Initialized
Variables)
Variable
Type
Value
Description
CmdLine
PChar
nil
C o m m a n d line pointer
CmdShow
Integer
0
CmdShow p a r a m e t e r s for CreateWindow
ErrorAddr
Pointer
nil
R u n - t i m e error a d d r e s s
ExitCode
Integer
0
Exit c o d e
ExitProc
Pointer
nil
Exit p r o c e d u r e
FileMode
Byte
2
File o p e n m o d e
HeapBlock
Word
8192
H e a p b l o c k size
HeapError
Word
nil
H e a p error f u n c t i o n
HeapLimit
Word
1024
H e a p s m a l l b l o c k limit
HeapList
Word
0
H e a p s e g m e n t list
HInstance
Word
0
H a n d l e o f this
HPrevInst
Word
0
H a n d l e of previous
instance
instance InOutRes
Integer
0
I/O result
PrefixSeg
Word
0
RandSeed
Lonelnt
0
Program segment prefix (PSP) R a n d o m seed
Table
H.2.
System
procedures
and
buffer
functions.
Procedure/Function
Type
Use
Abs
Func
Returns the absolute value of the argument
Addr
Func
Returns the address of a specified object
Append
Proc
O p e n s a n e x i s t i n g file for appending
ArcTan
Func
Returns the arctangent of the argument
H — T h e T u r b o Pascal for W i n d o w s S y s t e m U n i t
Procedure/Function
Type
Use
Assign
Proc
Assigns the n a m e of an e x t e r n a l file t o a file variable
BlockRead
Proc
Reads o n e or more into a variable
records
BlockWrite
Proc
Writes o n e o r m o r e f r o m a variable
records
Chr
Func
R e t u r n s a character w i t h a specified ordinal n u m b e r
Close
Proc
C l o s e s a n o p e n file
Concat
Func
Concatenates a sequence of strings
Copy
Func
Returns a substring of a string
Cos
Func
Returns the cosine of the a r g u m e n t (x is a n a n g l e , in radians)
CSeg
Func
Returns t h e current value o f the C S
register
Dec
Proc
C l o s e s a n o p e n file
Delete
Proc
Deletes a substring from a string
Dispose
Proc
D i s p o s e s a d y n a m i c variable
DSeg
Func
Returns the current value o f the D S
register
Eof
Func
R e t u r n s t h e e n d - o f - f i l e status
Eoln
Func
Returns the end-of-line status o f a text file
Erase
Proc
Erases a n e x t e r n a l file
Exit
Proc
Exp
Func
Exits immediately from the current b l o c k Returns the exponential of the argument
continues
555
556
Part I I I — R e f e r e n c e s
Table
H.2.
continued
Procedure/Function
Type
FilePos
Func
FileSize
Func
Use R e t u r n s t h e c u r r e n t file p o s i t i o n o f a file R e t u r n s t h e c u r r e n t size o f a file
FillChar
Proc
Fills a s p e c i f i e d n u m b e r (count) o f c o n t i g u o u s bytes with a specified value (can b e type B y t e or C h a r )
Flush
Proc
F l u s h e s t h e b u f f e r o f a text file o p e n f o r o u t p u t
Frac
Func
R e t u r n s t h e fractional part o f the argument
FreeMem
Proc
D i s p o s e s a d y n a m i c variable o f a s p e c i f i e d size
GetDir
Proc
R e t u r n s t h e c u r r e n t directory o f s p e c i f i e d drive
GetMem
Proc
C r e a t e s a d y n a m i c variable of t h e s p e c i f i e d size a n d p u t s t h e a d d r e s s o f t h e b l o c k in a p o i n t e r variable
Halt
Proc
Stops program execution a n d returns system
Hi
Func
to the operating
R e t u r n s t h e high-order
byte
of the argument Inc
Proc
I n c r e m e n t s a variable
Insert
Proc
Inserts a s u b s t r i n g into a string
Int
Func
R e t u r n s t h e integer
part o f
the argument IOResult
Func
R e t u r n s t h e status o f t h e last I/O o p e r a t i o n p e r f o r m e d
Length
Func
Returns the dynamic length o f a string
Ln
Func
Returns the natural logarithm o f t h e a r g u m e n t
H — T h e T u r b o Pascal f o r W i n d o w s S y s t e m U n i t
Procedure/Function
Type
Use
Lo
Func
Returns t h e low-order byte of the argument
MaxAvail
Func
R e t u r n s t h e size o f t h e largest c o n t i g u o u s free b l o c k in t h e heap
MemAvail
Func
R e t u r n s t h e a m o u n t o f all free m e m o r y in t h e
heap
MkDir
Proc
Creates a subdirectory
Move
Proc
C o p i e s bytes f r o m source to destination
New
Proc
Creates a n e w dynamic v a r i a b l e a n d sets a p o i n t e r v a r i a b l e t o p o i n t t o it
Odd
Func
Tests w h e t h e r t h e argument is a n o d d n u m b e r
Ofs
Func
Tests w h e t h e r t h e argument is a n o d d n u m b e r
Ord
Func
Returns the ordinal n u m b e r of an ordinal-type value
ParamCount
Func
Returns the n u m b e r of parameters passed to the program on the command line
ParamStr
Func
Returns a specified command-line parameter
Pi
Func
Returns the value of pi
Pos
Func
S e a r c h e s f o r a s u b s t r i n g in a string
Pred
Func
Returns the predecessor of the argument
Ptr
Func
Converts a segment base and a n offset a d d r e s s t o a pointer-type value
Random
Func
R e t u r n s a random
number continues
557
558
Part I I I — R e f e r e n c e s
Table
H.2.
continued
Procedure/Function
Type
Randomize
Proc
Read
Proc
Use Initializes t h e b u i l t - i n random n u m b e r g e n e r a t o r w i t h a random v a l u e (obtained from the system clock) F o r t y p e d files, reads a file c o m p o n e n t into a variable. F o r text files, reads o n e o r m o r e values into o n e or m o r e variables
Readln
Proc
Executes the Read proced u r e , t h e n skips to the next l i n e o f t h e file
Rename
Proc
R e n a m e s a n e x t e r n a l file
Reset
Proc
O p e n s a n e x i s t i n g file
Rewrite
Proc
C r e a t e s a n d o p e n s a n e w file
Round
Func
R o u n d s a real-type
value to
a n integer-type value RunError
Proc
Halts program execution
ScrollTo
Proc
Scrolls the C R T w i n d o w to s h o w virtual s c r e e n l o c a t i o n
Seek
Proc
Moves the current position o f a file t o a s p e c i f i e d component
SeekEof
Func
R e t u r n s t h e end-of-file status o f a file
SeekEoln
Func
Returns the end-of-line status o f a file
Seg
Func
Returns the segment of a specified object
SetTextBuf
Proc
A s s i g n s a n I/O b u f f e r t o a text file
Sin
Func
Returns the sine of the argument
H — T h e T u r b o Pascal for W i n d o w s S y s t e m U n i t
Procedure/Function
Type
SizeOf
Func
SPtr
Func
Use Returns t h e n u m b e r o f bytes occupied by t h e argument Retruns the current value of the SP
Sqr
Func
register
Returns t h e square of t h e argument
Sqrt
Func
R e t u r n s t h e s q u a r e root
of
the argument SSeg
Func
Returns the current value of t h e S S register
Str
Proc
Converts a numeric value to a string
Succ
Func
Returns the successor of the argument
Swap
Func
S w a p s t h e high- a n d l o w o r d e r bytes o f t h e a r g u m e n t
Trunc
Func
T r u n c a t e s a real-type
value
to an integer-type value Truncate
Proc
T r u n c a t e s t h e file at t h e c u r r e n t file p o s i t i o n
UpCase
Func
Converts a character to uppercase
Val
Proc
C o n v e r t s a s t r i n g v a l u e t o its numeric representation
Write
Proc
F o r t y p e d files, w r i t e s a v a r i a b l e i n t o a file c o m p o n e n t ; f o r text files, w r i t e s o n e or more values to t h e file
Writeln
Proc
Executes the W r i t e procedure, then outputs an endo f - l i n e m a r k e r t o t h e file
559
I REFERENCE
THE
T U R B O PASCAL F O R
WINDOWS WINDOS UNIT
Constants WinDos Constants include the following: • Flag constants • File-mode constants • File-attribute c o n s t a n t s • F i l e - n a m e c o m p o n e n t string l e n g t h s •
F i l e S p l i t r e t u r n flags
Flag Constants T h e F l a g c o n s t a n t s test i n d i v i d u a l flag bits i n t h e F l a g s register after a call t o I n t r o r Ms D o s . T h e y i n c l u d e t h e f o l l o w i n g :
562
Part I I I — R e f e r e n c e s
Constant
Value
fCarry fParity fAuxiliary
$0001 $0004 $0010
fZero fSign fOverflow
$0040 $0080 $0800
File-mode Constants F i l e - h a n d l i n g p r o c e d u r e s u s e f mXXXX c o n s t a n t s w h e n d i s k files a r e o p e n e d and closed. T h e m o d e fields o f T u r b o P a s c a l f o r W i n d o w s ' v a r i a b l e s c o n t a i n o n e o f the following values: Constant
Value
fmClosed
$D7B0
fmlnput
$D7B1
fmOutput
$D7B2
fmlnOut
$D7B3
File-attribute Constants T h e f aXXXX c o n s t a n t s test, set, a n d c l e a r
file-attribute
bits i n c o n j u n c t i o n w i t h
the GetFAttr, SetFAttr, FindFirst, a n d FindNext p r o c e d u r e s . T h e f aXXXX c o n s t a n t s a r e a d d i t i v e . T h e f aAnyFile c o n s t a n t is t h e s u m o f all a t t r i b u t e s . T h e f aXXXX c o n s t a n t s c a n b e a n y o f t h e f o l l o w i n g : Constant
Value
faReadOnly faHidden
$01 $02
faSysFile faVolumelD faDirectory faArchive faAnyFile
$04 $08 $10 $20 $3F
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
File-name Component String Length Constants T h e f sXXXX c o n s t a n t s a r e t h e m a x i m u m f i l e - n a m e c o m p o n e n t s t r i n g l e n g t h s u s e d b y t h e FileSearch a n d FileExpand f u n c t i o n s . T h e y c a n b e a n y o f t h e following: Constant fsPathName fsDirectory fsFileName fsExtension
Value 79 67 8 4
FileSplit Return Flag Constants T h e FileSplit f u n c t i o n u s e s t h e f cXXXX c o n s t a n t s . T h e r e t u r n e d v a l u e is a c o m b i n a t i o n o f t h e fcDirectory, fcFileName, a n d t h e fcExtension bit masks. T h e value indicates w h i c h c o m p o n e n t s w e r e in the path. If t h e n a m e o r e x t e n s i o n c o n t a i n s a n y w i l d - c a r d c h a r a c t e r s (* o r ? ) , t h e fcWildcards flag is set. P o s s i b l e c o n s t a n t v a l u e s a r e Constant
Value
fcExtension
$0001
fcFileName fcDirectory fcWildcards
$0002 $0004 $0008
Types T y p e s i n t h e WinDos u n i t : • File r e c o r d •
TRegisters
•
TDateTime
•
TSearchRec
File Record Type T h e record definitions u s e d internally b y T u r b o Pascal for W i n d o w s are also d e c l a r e d i n t h e WinDos u n i t .
563
564
Part I I I — R e f e r e n c e s
TFileRecis u s e d f o r b o t h t y p e d a n d u n t y p e d files. TTextRecis u s e d internally file t y p e , text. T h e records
b y a n y variable o f t h e p r e d e f i n e d T u r b o Pascal
l o o k like t h e f o l l o w i n g :
type { Typed and untyped files } TFileRec = record Handle: Word; Mode: Word; RecSize: Word; Private: array[1..26] of Byte; UserData: array[1..16] of Byte; Name: array[0..79] of Char; end;
{ Textfile record } PTextBuf = "TTextBuf; TTextBuf = array[0..127] of Char; TTextRec = record Handle: Word; Mode: Word; BufSize: Word; Private: Word; BufPos: Word; BufEnd: Word; BufPtr: "TTextBuf; OpenFunc: Pointer; InOutFunc: Pointer; FlushFunc: Pointer; CloseFunc: Pointer; UserData: array[1..16] of Byte; Name: array[0..79] of Char; Buffer: TTextBuf; end;
I — T h e T u r b o Pascal f o r W i n d o w s W i n D o s U n i t
TRegisters Type T h e I n t r a n d M s D o s p r o c e d u r e s use variables o f type T R e g i s t e r s to specify the input register contents and e x a m i n e the o u t p u t register contents o f a software interrupt. T R e g i s t e r s looks like this: type T R e g i s t e r s = record c a s e I n t e g e r of 0: ( A X , B X , C X , D X , B P , S I , D I , D S , E S , F l a g s : 1: ( A L , A H , B L , B H , C L , C H , D L , D H : B y t e ) ; end;
Word);
N o t e : A variant record is u s e d to m a p the 8-bit registers o n t o p o f their 16-bit equivalents.
TDateTime Type Variables o f TDateTime type are u s e d with the UnpackTime and PackTime procedures to examine and construct 4-byte, p a c k e d date-and-time values for the G e t F T i m e , S e t F T i m e , F i n d F i r s t , a n d F i n d N e x t procedures. TDateTime looks like the following: type TDateTime = r e c o r d Year,Month,Day,Hour,Min,Sec: end; T h e valid ranges o f its fields are Year Month Day Hour Min Sec
1980..2099 1..12 1..31 0..23 0..59 0..59
Word;
565
566
Part I I I — R e f e r e n c e s
TSearchRec Type T h e FindFirst and FindNext procedures use variables of type TSearchRec to scan directories. TSearchRec looks like the following: type TSearchRec = record Fill: array[1..21] of Byte; Attr: Byte; Time: Longint; Size: Longint; Name: array[0..12] of Char; end; T h e information for each file found by one of these procedures is reported in a TSearchRec. Attr contains the file's attributes (constructed from file-attribute constants). Time contains its packed date and time. Size contains its size in bytes. Name contains its name. Fill is reserved by D O S and should not be modified.
An Index of WinDos Procedures and Functions by Function (or Category) Date and Time Procedures
GetDate GetFTime GetTime PackTime SetDate SetFTime SetTime UnpackTime
procedure procedure procedure procedure procedure procedure procedure procedure
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
Directory-handling Procedures and Functions CreateDir GetCurDir RemoveDir SetCurDir D i s k status DiskFree DiskSize
procedure function procedure procedure function function function
Environment-handling Functions GetArgCount GetArgStr GetEnvVar
function function function
File-handling P r o c e d u r e s a n d Functions FileExpand function FileSearch function FileSplit
function
FindFirst FindNext GetFAttr SetFAttr
procedure procedure procedure procedure
Interrupt Support Procedures GetlntVec procedure Intr procedure MsDos procedure SetlntVec procedure Miscellaneous Procedures and Functions DosVersion function GetCBreak GetVerify SetCBreak SetVerify
procedure procedure procedure procedure
DosError Variable Dos E r r o r is u s e d b y m a n y o f t h e p r o c e d u r e s a n d f u n c t i o n s i n t h e W i n D o s u n i t t o r e p o r t e r r o r s . It l o o k s like this: var DosError:
Integer;
T h e v a l u e s s t o r e d i n D o s E r r o r are D O S e r r o r c o d e s .
567
568
Part I I I — R e f e r e n c e s
A value o f 0 indicates n o error; o t h e r possible error c o d e s are as follows: Error
Code
Meaning
2
File n o t f o u n d
3 5 6 8 10 11 18
Path n o t f o u n d Access denied Invalid h a n d l e Not enough memory Invalid environment Invalid format N o m o r e files
Date and Time Procedures T u r b o P a s c a l for W i n d o w s s u p p l i e s a c o m p l e t e set o f d a t e a n d t i m e p r o c e d u r e s . These include: GetDate GetFTime GetTime PackTime SetDate SetFTime SetTime UnpackTime
GetDate Returns the current date in the operating system. procedure GetDate(var Year, Month, Day, DayOfWeek: Word);
GetFTime R e t u r n s t h e d a t e a n d t i m e a file w a s last w r i t t e n . procedure GetFTime(var F; var Time: Longint); F m u s t b e a file v a r i a b l e ( t y p e d , u n t y p e d , o r text file) that h a s b e e n a s s i g n e d a n d o p e n e d . T h e t i m e r e t u r n e d i n Time c a n b e u n p a c k e d t h r o u g h a call t o UnpackTime.
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
GetTime Returns the current time in the operating system,
procedure GetTime(var Hour, Minute, Second, Sec100: Word); For example:
uses WinDos, WinCrt; var H, M, S, Hund : Word; function LeadingZero(W : Word) : String; var S : String; begin Str(W:0,S); if Length(S) = 1 then S := '0' + S; LeadingZero := S; end; begin GetTime(H,M,S,Hund); Writeln('It's ',LeadingZero(H),': , LeadingZero(M), : ,LeadingZero(S), '.',LeadingZero(Hund)); end. 1
1
1
Packlime C o n v e r t s a TDateTime r e c o r d .
procedure PackTime(var T: DateTime; var Time: Longint); C o n v e r t s t h e r e c o r d i n t o a 4-byte, p a c k e d d a t e - a n d - t i m e Longint u s e d b y
SetFTime. F o r e x a m p l e : uses WinDos, WinCrt; var F: text; H, M, S, Hund : Word; { For GetTime} Ftime : Longint; { For Get/SetFTime}
569
570
Part I I I — R e f e r e n c e s
Dt : TDateTime; { For Pack/UnpackTime} function LeadingZero(W : Word) : String; var S : String; begin Str(W:0,S); if Length(S) = 1 then S := '0' + S; LeadingZero := S; end; begin Assign(F, 'File.txt ); GetTime(H,M,S,Hund); Rewrite(F); { Create a new file } GetFTime(F,Ftime); { Get the creation time } Writeln( File created @ ,LeadingZero(H), ': ,LeadingZero(M),':', LeadingZero(S)); UnpackTime(Ftime,Dt); with Dt do begin Writeln( File timestamp = ', LeadingZero(Hour), ' : ' , LeadingZero(Min), : ', LeadingZero(Sec)); Hour := 0; Min := 10; Sec := 0; PackTime(Dt,Ftime); Writeln('Setting file timestamp 'to 12:10 AM'); Reset(F); { Reopen file for reading } { Else close will update time } SetFTime(F,Ftime); end; Close(F); { Close file } end. 1
1
1
1
1
1
SetDate Sets the current date in the operating system,
procedure SetDate(Year, Month, Day: Word); For example:
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
uses WinDos; begin { Set the system date to 5/8/58 } SetDate(1958,5,8); end.
SetFIime S e t s t h e d a t e a n d t i m e a file w a s last w r i t t e n .
procedure SetFTime(var F; Time: Longint); A n y e r r o r s a r e r e p o r t e d i n DosError. T h e o n l y e r r o r c o d e is 6, a n I n v a l i d File H a n d l e . Note: F m u s t b e o p e n .
SetTime Sets t h e current time in the operating system,
procedure SetTime(Hour, Minute, Second, Sec100: Word); For example:
uses WinDos; begin { Set system clock to 12:01 AM } SetTime(0,1,0,0); end.
Unpackfime C o n v e r t s a Longint t o a r e c o r d .
procedure UnpackTime(Time: Longint; var DT: TDateTime); C o n v e r t s a 4-byte, p a c k e d d a t e - a n d - t i m e Longint r e t u r n e d b y GetFTime,
FindFirst, or FindNext i n t o a n u n p a c k e d DateTime r e c o r d .
Directory-handling Procedures and Functions T u r b o Pascal for W i n d o w s s u p p l i e s a c o m p l e t e set of d i r e c t o r y - h a n d l i n g procedures and functions:
571
572
Part I I I — R e f e r e n c e s
CreateDir GetCurDir RemoveDir SetCurDir DiskFree DiskSize
CreateDir Creates a n e w subdirectory.
procedure CreateDir(Dir: PChar) E x e c u t e s t h e s a m e f u n c t i o n s as MkDir, b u t u s e s a T u r b o Pascal style s t r i n g r a t h e r t h a n a n u l l - t e r m i n a t e d string. F o r e x a m p l e :
uses WinCrt, WinDOS; const Create: PChar = 'C:\MyDir'; CDrive: Byte = 3; begin CreateDir(ADir); Writeln('Creating new directory @ ', ADir,'.'); end.
GetCurDir Returns the current directory o f a specified drive.
function GetCurDir(Dir: PChar; Drive: Byte): PChar; T h e following values represent their respective drives. This p r o c e d u r e c o n t i n u e s u n t i l all drives h a v e a n a m e : 0 = D e f a u l t drive 1 = Drive A 2 = Drive B 3 = Drive C For example:
I — T h e T u r b o Pascal f o r W i n d o w s W i n D o s U n i t
uses WinCrt, WinDOS; const CDrive:Byte = 3; var CurDir: PChar; begin GetMem(CurDir, 80); GetCurDir(CurDir, CDrive); Writeln('Current directory = ', CurDir,'.'); end.
RemoveDir Removes an empty subdirectory,
procedure Remove(Dir: PChar); For example:
uses WinCrt, WinDos; const Remove: PChar = 'C:\01dDir'; CDrive: Byte = 3; begin RemoveDir(ADir); Writeln('Directory removed @ ', ADir,'.'); end.
SetCurDif C h a n g e s the current directory to the specified path,
procedure SetCurDir(Dir: PChar) If Dir s p e c i f i e s a drive letter, t h e d r i v e is a l s o c h a n g e d . F o r e x a m p l e :
uses WinCrt,
573
574
Part III—References
WinDOS; const ChangeTo: PChar = 'C:\'; CDrive: Byte = 3; var CurDir:
PChar;
begin GetMem(CurDir, 80); SetCurDir(ChangeTo); GetCurDir(CurDir, CDrive); Writeln('Current directory = ', CurDir,'.'); end.
DiskFree R e t u r n s t h e n u m b e r of free b y t e s o n a d i s k d r i v e . If t h e d r i v e n u m b e r is i n v a l i d , it r e t u r n s -1; o t h e r w i s e it r e t u r n s t h e n u m b e r of k i l o b y t e s (K) f r e e .
function where 0 1 2 3
= = = =
DiskFree(Drive:
Byte):
Longint;
D e f a u l t drive Drive A Drive B Drive C
and so on. For example:
uses WinDos, WinCrt; begin Writeln(DiskFree(0) end.
div 1024,
' K f r e e ');
DiskSize R e t u r n s t h e total s i z e , i n b y t e s , of s p e c i f i e d d i s k d r i v e ,
function DiskSize(Drive: where
Byte):
Longint;
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
0 1 2 3
= = = =
575
D e f a u l t drive Drive A Drive B Drive C
a n d s o o n . D i s k S i z e r e t u r n s t h e v a l u e - 1 if t h e d r i v e n u m b e r is i n v a l i d . For example:
uses WinDos, WinCrt; begin Writeln(DiskSize(0) div 1024, K ) ; end. 1
1
Environment-handling Functions T u r b o Pascal f o r W i n d o w s s u p p l i e s a c o m p l e t e set o f e n v i r o n m e n t - h a n d l i n g functions:
GetArgCount GetArgStr GetEnvVar
GetArgCount Returns the n u m b e r of parameters passed to the application by the c o m m a n d line.
function GetArgCount: Integer For e x a m p l e :
uses WinCrt, WinDOS; var ArgCount:
Integer;
begin ArgCount := GetArgCount; Writeln('There were ', ArgCount,' arguments on the command line'); end.
576
Part III—References
GetArgStr Returns the c o m m a n d - l i n e parameter specified by I n d e x . function
GetArgStr(Test:
PChar;
Index:
Integer;
MaxLen: W o r d ) :
T h e return value d e p e n d s o n the parameter: Parameter
Return
Value
I n d e x < 0 or > G e t A r G C o u n t
E m p t y string
Index = 0
File n a m e o f current m o d u l e ; T e s t = returned value
For example: uses WinCrt, WinDos; var ArgN:
PChar;
begin GetMem(ArgN, 2 0 ) ; G e t A r g S t r ( A r g N , 1, 1 9 ) ; W r i t e l n ( ' T h e 1 s t argument was end.
''',
ArgN,
'''.');
GetEnvVar Returns a pointer to the value o f a specified environment variable. function
GetEnvVar(VarName:
PChar):
PChar;
Returns value 0 if the specified environment variable d o e s not exist. For example: uses WinCrt, WinDos; var EnvironVar:
PChar;
begin GetMem(EnvironVar,
255);
PChar
I — T h e T u r b o Pascal f o r W i n d o w s W i n D o s U n i t
EnvironmentVar := GetEnvVar( Path ) ; Writeln('The current path is: '); Writeln(EnvironVar); end. 1
1
File-handling Procedures and Functions T u r b o Pascal f o r W i n d o w s s u p p l i e s a c o m p l e t e set o f f i l e - h a n d l i n g p r o c e d u r e s and functions:
FileExpand FileSearch FileSplit FindFirst FindNext GetFAttr SetFAttr
FileExpand E x p a n d s a file n a m e i n t o a fully q u a l i f i e d file n a m e ,
function FileExpand(Test, Name: PChar): PChar; For example:
uses WinCrt, WinDOS; const MyFile: PChar = 'File.txt'; var Location: PChar; begin GetMem(Location, 80); FileExpand(Location, MyFile); Writeln(MyFile, ' is @ , Location, ' . ' ) ; end. 1
577
578
Part I I I — R e f e r e n c e s
FileSearch S e a r c h e s f o r a file.
function FileSearch(Test, Name, List: PChar): PChar; S e a r c h e s i n a list o f d i r e c t o r i e s (DirList). T h e d i r e c t o r i e s i n DirList must be separated by semicolons. For example:
uses WinCrt, WinDos; var S: array[0..fsPathName] of Char; begin FileSearch(S, 'Turbo.Exe', GetEnvVar('Path ) ) ; if S[0] = #0 then Writeln('Turbo.Exe wasn't found') else Writeln('Found as ', FileExpand(S, S)); end. 1
FileSplit Splits a file n a m e i n t o its t h r e e c o m p o n e n t s ,
function FileSplit(Path, Dir, Name, Ext: PChar): Word; For example:
uses Strings, WinCrt, WinDos; var Path: array[0..fsPathName] of Char; Dir: array[0..fsDirectory] of Char; Name: array[0..fsFileName] of Char; Ext: array[0..fsExtension] of Char; begin Write('Filename (Work.pas): '); Readln(Path); FileSplit(Path, Dir, Name, Ext); if Name[0] = #0 then StrCopy(Name, 'Work');
I — T h e Turbo PascalforWindows WinDos Unit
if Ext[0] = #0 then StrCopy(Ext, '.PAS'); StrECopy(StrECopy(StrECopy(Path, Dir), Name), Ext); Writeln('New name = ', Path); end.
FindFirst Searches the specified directory for the matching file, procedure FindFirst(Path: PChar; Attr: Word; var F: TSearchRec); For example: uses WinDos, WinCrt; var Dirlnfo: TSearchRec; begin FindFirst('*.PAS', Archive, Dirlnfo); while DosError = 0 do begin Writeln(Dirlnfo.Name); FindNext(Dirlnfo); end; end.
FindNext Finds the next entry that matches the n a m e and attributes specified in an earlier call to FindFirst. procedure FindNext(var F: TSearchRec); Errors are reported in DosError. The only possible error code is 18: no more files. For example: uses WinDos, WinCrt; var Dirlnfo: TSearchRec; begin
579
580
Part I I I — R e f e r e n c e s
Fine-First( *.PAS' , Archive, Dirlnfo); while DosError = 0 do begin Writeln(DirInfo.Name); FindNext(Dirlnfo); end; end. 1
GetFAttr R e t u r n s t h e attributes o f a file.
procedure GetFAttr(var F; var Attr: Word); F m u s t b e a file v a r i a b l e ( t y p e d , u n t y p e d , o r text file) that h a s b e e n assigned but has not b e e n o p e n e d . For example:
uses WinDos, WinCrt; var F: file; Attr: Word; begin { Get file name from command line } Assign(F, ParamStr(1)); GetFAttr(F, Attr); Writeln(ParamStr(1)); if DosError 0 then Writeln('DOS error code = ', DosError) else begin Write('Attribute = ', Attr); { Determine file attribute type using the flags in the WinDos unit } if Attr and faReadOnly 0 then Writeln( Read only file'); if Attr and faHidden 0 then Writeln('Hidden file'); if Attr and faSysFile 0 then Writeln('System file'); if Attr and faVolumelD 0 then Writeln('Volume ID'); if Attr and faDirectory 0 then Writeln( Directory name'); if Attr and faArchive 0 then Writeln('Archive (normal f i l e ) ) ; end; { else } end. 1
1
1
I — T h e T u r b o Pascal f o r W i n d o w s W i n D o s U n i t
SetFAttr S e t s t h e a t t r i b u t e s o f a file.
procedure SetFAttr(var F; Attr: Word); E r r o r s are r e p o r t e d i n DosError. T h e p o s s i b l e e r r o r c o d e s a r e : 3
(Invalid path)
5
(File a c c e s s d e n i e d )
Note:
T h e file c a n n o t b e o p e n . F o r e x a m p l e :
uses WinDos; var F: file; begin Assign(F, 'C:\Myfile.txt'); SetFAttr(F, faHidden); Readln; SetFAttr(F, faArchive); end.
Interrupt Support Procedures T u r b o P a s c a l f o r W i n d o w s s u p p l i e s a c o m p l e t e set o f i n t e r r u p t procedures:
GetlntVec Intr MsDos SetlntVec
GetlntVec Returns the address stored in a specified interrupt vector,
procedure GetIntVec(IntNo: Byte; var Vector: Pointer);
support
581
582
Part III—References
For example: uses WinDos, WinCrt; var Int1 : Pointer; {$F+} procedure TimerHandler; interrupt; begin { Timer ISR } end; {$F-} begin GetIntVec($1C,Int1); SetIntVec($1C,Addr(TimerHandler)); Writeln( Press a key to e x i t ) ; repeat until Keypressed; SetIntVec($01C,Int1); end. 1
1
Intr Executes a specified software interrupt. procedure Intr(IntNo: Byte; var Regs: TRegisters); where IntNo is the software interrupt n u m b e r (0...255). TRegisters is a record defined in D O S .
N o t e : D o not use software interrupts that 1. D e p e n d o n specific values in SP or SS for entry 2. Modify SP or SS o n exit.
For example: uses WinCrt, WinDos; var
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
Date, Year, Month, Day : String; Regs : TRegisters; begin Regs.ah := $2a; with Regs do intr($21,Regs); with Regs do begin Str(cx,Year); Str(dh,Month); Str(dl,Day); end; Date := Month+'/'+Day+'/'+Year; writeln('Date = ', Date); end.
MsDos Executes a D O S function call.
procedure MsDos(var Regs: TRegisters); R e m e m b e r n o t t o u s e s o f t w a r e i n t e r r u p t s that e i t h e r d e p e n d o n s p e c i f i c v a l u e s i n SP or SS for e n t r y or that m o d i f y SP or SS o n exit. For e x a m p l e :
uses WinCrt, WinDos; var Date, Year, Month, Day : String; Regs : TRegisters; begin Regs.ah := $2a; with Regs do msdos(Regs); with Regs do
583
584
Part I I I — R e f e r e n c e s
begin Str(cx,Year); Str(dh,Month); Str(dl,Day); end; Date := Month+'/'+Day+'/'+Year; Writeln('Date = , Date); end. 1
SetlntVec Sets a specified interrupt vector to a specified address,
procedure SetIntVec(IntNo: Byte; Vector: Pointer);
Miscellaneous Procedures and Functions T u r b o P a s c a l f o r W i n d o w s s u p p l i e s several m i s c e l l a n e o u s p r o c e d u r e s a n d functions:
DosVersion GetCBreak GetVerify SetCBreak SetVerify
DosVersion Returns the D O S version number.
function DosVersion: Word; T h e r e s u l t ' s l o w b y t e is t h e m a j o r v e r s i o n n u m b e r , a n d t h e h i g h b y t e is the minor version number. For example:
uses WinDos; var Ver: Word; begin Ver := DosVersion; Writeln('DOS version = ', Lo(Ver), '.', Hi(Ver)); end.
I — T h e T u r b o Pascal for W i n d o w s W i n D o s U n i t
GetCBreak R e t u r n s t h e state of Ctrl-Break c h e c k i n g i n D O S .
procedure GetCBreak(var Break: Boolean); For e x a m p l e :
uses WinDos, WinCrt; const OffOn ('off
: array [Boolean] of String[3] = Von');
var cb : Boolean; begin GetCBreak(cb); Writeln('Control-Break checking is ', OffOn[cb]); cb := not(cb); Writeln('Turning Control-Break checking ', 0ff0n[cb]); SetCBreak(cb); end.
GetVerify R e t u r n s t h e state of t h e verify flag i n D O S .
procedure GetVerify(var Verify: Boolean); For e x a m p l e :
uses WinDos, WinCrt; const OffOn : array [Boolean] of String[3] = var Boo : Boolean;
( off','on ) ; 1
1
585
586
Part I I I — R e f e r e n c e s
begin GetVerify(Boo); Writeln('Write verify = OffOn[Boo]); Boo := not(Boo); Writeln('Turning write verify ', OffOn[Boo]); SetVerify(Boo); end.
SetCBreak S e t s t h e state o f C t r l - B r e a k c h e c k i n g i n D O S .
procedure SetCBreak(Break: Boolean);
SetVerify S e t s t h e state o f t h e verify flag i n D O S .
procedure SetVerify(Verify: Boolean);
J
REFERENCE
DEBUGGING TURBO PASCAL FOR WINDOWS
APPUGfflONS
T h e T u r b o P a s c a l f o r W i n d o w s D e b u g g e r is a p o w e r f u l t o o l f o r d e b u g g i n g W i n d o w s a p p l i c a t i o n s . It g o e s a m a j o r s t e p o r t w o f u r t h e r t h a n t h e b u i l t - i n d e b u g g i n g c a p a b i l i t i e s o f t h e T u r b o Pascal f o r W i n d o w s c o m p i l e r . T h e T u r b o Pascal f o r W i n d o w s c o m p i l e r ' s b u g - d e t e c t i n g p o w e r f o c u s e s o n m a k i n g s u r e that y o u r a p p l i c a t i o n c o d e m a k e s syntactic s e n s e . If y o u h a v e a n u n k n o w n i d e n t i f i e r o r h a v e o m i t t e d a n e c e s s a r y s e m i c o l o n , it'll f i n d it. B u t it c a n n o t g u a r a n t e e m o r e t h a n c o r r e c t syntax. Y o u r c o d e c a n survive c o m p i l e r b u g d e t e c t i o n a n d still c r a s h m i s e r a b l y (at r u n - t i m e ) . R u n - t i m e e r r o r s are t h e d o m a i n o f a n o t h e r class o f b u g d e t e c t o r s , " d e b u g g e r s . " D e b u g g e r s h e l p y o u i s o l a t e a n d c o r r e c t m i s t a k e s that u s u a l l y are n o t d u e t o e r r o r s i n s y n t a x . T h i s is a b r o a d a n d c o m p l e x g r o u p o f e r r o r s that y o u c a n m a k e i n t h e l o g i c o f y o u r c o d e , b y n o t a c c o u n t i n g f o r t h e full r a n g e o f p o s s i b l e a c t i o n s o f y o u r c o d e , a n d s o o n . D e b u g g i n g , i n this r e a l m , is a n i m p e r f e c t "art" at b e s t , a n d d e b u g g i n g W i n d o w s a p p l i c a t i o n s is m o r e i m p e r f e c t yet. T h e k e y , I t h i n k , t o d e b u g g i n g W i n d o w s a p p l i c a t i o n s lies i n i s o l a t i n g t h e m o r e likely e r r o r - p r o n e areas o f y o u r c o d e .
588
Part I I I — R e f e r e n c e s
A f e w s i m p l e d e v e l o p m e n t tactics w i l l h e l p : 1. C o d e i n s m a l l f r a g m e n t s . U s e o b j e c t - o r i e n t e d t e c h n i q u e s t o k e e p d a t a a n d the behavior for manipulating data in objects. 2. D e v e l o p o b j e c t s , u n i t s , o r o t h e r s t r u c t u r a l b l o c k s o n e at a t i m e . M a k e s u r e that a n o b j e c t o r a b l o c k w o r k s b e f o r e m o v i n g o n t o o t h e r o b j e c t s o r b l o c k s , p a r t i c u l a r l y if t h e s e o b j e c t s a n d b l o c k s are i n t e r r e l a t e d . 3. R e d u c e t h e n u m b e r o f p r o c e d u r e s , f u n c t i o n s , a n d s o o n that c a n m a n i p u l a t e d a t a . If y o u d o n ' t u s e o b j e c t s , u s e l o c a l v a r i a b l e s . T h e s e tactics w i l l h e l p , b u t t h e y p r o b a b l y w o n ' t e l i m i n a t e all y o u r b u g s . W h e n y o u d i s c o v e r a b u g i n y o u r W i n d o w s a p p l i c a t i o n , call o n T u r b o D e b u g g e r f o r W i n d o w s . I n effect, it s l o w s d o w n t h e e x e c u t i o n o f a n a p p l i c a t i o n a n d lets y o u e x a m i n e its s p e c i f i c a s p e c t s . Y o u c a n e x a m i n e t h e stack, v a r i a b l e v a l u e s , C P U registers, W i n d o w s messages, a n d so o n . T u r b o D e b u g g e r gives y o u seven m a i n ways to explore: 1. T r a c i n g ( e x e c u t i n g a n a p p l i c a t i o n o n e l i n e at a t i m e ) . 2. B a c k t r a c i n g ( s t e p p i n g b a c k w a r d t h r o u g h t h e a p p l i c a t i o n c o d e a l i n e at a time, a n d reversing the e x e c u t i o n ) . 3. S t e p p i n g ( e x e c u t i n g t h e a p p l i c a t i o n c o d e o n e l i n e at a t i m e b u t " s t e p p i n g o v e r " a n y calls t o p r o c e d u r e s o r f u n c t i o n s ) . T h i s w a y , t h e p r o c e d u r e o r f u n c t i o n is e x e c u t e d as a b l o c k a n d a n y v a l u e s are returned, but y o u don't "trace" through the procedure or function a l i n e at a t i m e . 4. V i e w i n g ( o p e n i n g a w i n d o w f o r v i e w i n g t h e states o f v a r i o u s c o m p o n e n t s o f t h e a p p l i c a t i o n ) . T h e s e c o m p o n e n t s are t h e a p p l i c a t i o n ' s v a r i a b l e s , b r e a k p o i n t s y o u set, t h e stack, a T u r b o D e b u g g e r l o g , a d a t a file, a s o u r c e file, C P U c o d e , m e m o r y , registers, n u m e r i c p r o c e s s o r i n f o r m a t i o n , o b j e c t h i e r a r c h i e s , t h e a p p l i c a t i o n ' s e x e c u t i o n history, and the application's output. 5. I n s p e c t i n g d a t a s t r u c t u r e s ( s u c h as arrays). 6. C h a n g i n g ( m a n i p u l a t i n g t h e a p p l i c a t i o n b y r e p l a c i n g t h e c u r r e n t v a l u e o f a v a r i a b l e w i t h a n e w v a l u e that y o u s p e c i f y ) . 7. W a t c h i n g a p p l i c a t i o n v a r i a b l e s ( t r a c k i n g t h e c h a n g i n g v a l u e s o f variables y o u specify). A l l t h e T u r b o D e b u g g e r f o r W i n d o w s f e a t u r e s are available i n p u l l - d o w n menus. T h e s i m p l e s t w a y t o u s e T u r b o D e b u g g e r f o r W i n d o w s is l o a d t h e application y o u w a n t to d e b u g into a T u r b o Pascal for W i n d o w s edit w i n d o w , a n d t h e n select D e b u g g e r f r o m t h e T u r b o Pascal f o r W i n d o w s R u n / D e b u g g e r
J — D e b u g g i n g T u r b o Pascal f o r W i n d o w s A p p l i c a t i o n s
m e n u . M a k e s u r e , t h o u g h , that y o u select O p t i o n s / L i n k e r / D e b u g i n f o i n E X E before you run Turbo Debugger. T h e specifics o f h o w y o u d e b u g y o u r application d e p e n d o n the k i n d o f application a n d possible error. In general, y o u d o n ' t want to trace t h r o u g h a n e n t i r e W i n d o w s a p p l i c a t i o n . I n s t e a d , try t o i s o l a t e t h e e r r o r as b e s t y o u c a n a n d set b r e a k p o i n t s i n likely t r o u b l e d a r e a s . (I k n o w , I k n o w ; if y o u k n o w w h e r e t h e e r r o r is, y o u p r o b a b l y d o n ' t n e e d t h e d e b u g g e r — y e s a n d n o . ) If y o u ' r e d e v e l o p i n g t h e a p p l i c a t i o n o b j e c t b y o b j e c t o r b l o c k b y b l o c k , y o u c a n at least r e d u c e t h e b u g t o that a r e a . Set a b r e a k p o i n t a n d t h e n trace t h r o u g h t h e application from the breakpoint. I n m a n y s i t u a t i o n s , m a k i n g s u r e that a p r o c e d u r e , f u n c t i o n , o r m e t h o d g e t s c a l l e d , o r m o n i t o r i n g a v a r i a b l e ' s v a l u e s , c a n l o c a t e t h e b u g . I u s u a l l y start any d e b u g session by setting breakpoints a n d a d d i n g the variables within those b r e a k p o i n t s u s i n g A d d W a t c h . T h e n I s t e p o r trace t h r o u g h t h e c o d e . If y o u g e t a r u n - t i m e e r r o r that typically l o o k s like t h i s :
Runtime error 204 at 0002:018 n o t e t h e a d d r e s s ( y o u p r o b a b l y w i l l w a n t t o w r i t e it d o w n ) , a n d u s e t h e F i n d Error c o m m a n d o n the T u r b o Pascal for W i n d o w s Search m e n u to locate the error in your source c o d e . T h e Find Error dialog b o x appears. Enter the address o f the error in the Error Address b o x . T u r b o Pascal for W i n d o w s t h e n r e c o m p i l e s y o u r c o d e a n d s t o p s w h e n it r e a c h e s t h e a d d r e s s y o u specify, h i g h l i g h t i n g t h e s t a t e m e n t that caused the error. T h e n , fix t h e e r r o r (in t h e edit w i n d o w ) a n d r e c o m p i l e . R e p e a t t h e p r o c e s s if y o u h a v e t o .
589
K REFERENCE
TURBO PASCAL FOR WINDOWS ERROR MESSAGES T u r b o Pascal f o r W i n d o w s g e n e r a t e s t w o k i n d s o f e r r o r m e s s a g e s : c o m p i l e r error messages and run-time error messages. If y o u ' r e u s i n g t h e I D E t o c o m p i l e y o u r s o u r c e c o d e a n d a c o m p i l e r e r r o r o c c u r s , T u r b o Pascal f o r W i n d o w s m a k e s t h e E d i t w i n d o w active a n d m o v e s t h e c u r s o r t o t h e l o c a t i o n w h e r e it d e t e c t e d t h e e r r o r i n y o u r s o u r c e c o d e . If t h e e r r o r o c c u r s w h e n y o u ' r e u s i n g t h e c o m m a n d - l i n e c o m p i l e r , T u r b o Pascal for W i n d o w s displays the error message a n d n u m b e r a n d the o f f e n d i n g s o u r c e l i n e . A caret ( ^ ) i n t h e d i s p l a y e d s o u r c e l i n e i n d i c a t e s t h e error's location. If y o u r a p p l i c a t i o n g e n e r a t e s a n e r r o r at r u n - t i m e , it w i l l t e r m i n a t e , a n d t h e f o l l o w i n g m e s s a g e is d i s p l a y e d :
Runtime error at < x x x x : y y y y > where: • nurn is t h e r u n - t i m e e r r o r n u m b e r •
x x x x : y y y y i s the run-time error address
592
Part I I I — R e f e r e n c e s
Compiler Error Messages C o m p i l e r e r r o r m e s s a g e s are n u m b e r e d f r o m 1 t o 168. T h e f o l l o w i n g e r r o r m e s s a g e s are c u r r e n t l y i m p l e m e n t e d i n T u r b o Pascal f o r W i n d o w s 1.0.
N o t e : N o t all n u m b e r s h a v e a c o r r e s p o n d i n g e r r o r m e s s a g e .
Error
Number
Error
Message
1
Out of memory
2
Identifier e x p e c t e d
3
U n k n o w n identifier
4
D u p l i c a t e identifier
5
Syntax error
6
E r r o r i n real c o n s t a n t
7
Error in integer constant
8
String constant exceeds line
9
T o o m a n y n e s t e d files
10
U n e x p e c t e d e n d o f file
11
Line t o o l o n g
12
T y p e identifier e x p e c t e d
13
T o o m a n y o p e n files
14
I n v a l i d file n a m e
15
File n o t f o u n d
16
D i s k full
17
Invalid c o m p i l e r directive
18
T o o m a n y files
19
U n d e f i n e d type in pointer definition
20
Variable identifier e x p e c t e d
21
Error in type
22
Structure t o o large
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Error
Number
Error
Message
23
Set base type out of range
24
F i l e c o m p o n e n t s m a y n o t b e files o r o b j e c t s
25
I n v a l i d string l e n g t h
26
Type mismatch
27
Invalid subrange base type
28
Lower b o u n d > than upper b o u n d
29
Ordinal type expected
30
Integer constant expected
31
Constant expected
32
I n t e g e r o r real c o n s t a n t e x p e c t e d
33
Pointer type identifier e x p e c t e d
34
I n v a l i d f u n c t i o n result t y p e
35
Label identifier e x p e c t e d
36
B E G I N expected
37
E N D expected
38
Integer expression expected
39
Ordinal expression expected
40
Boolean expression expected
41
O p e r a n d types d o not match operator
42
Error in expression
43
Illegal assignment
44
Field identifier e x p e c t e d
45
O b j e c t file t o o l a r g e
46
Undefined external
47
I n v a l i d o b j e c t file r e c o r d
48
C o d e segment t o o large
49
D a t a s e g m e n t t o o large
50
D O expected continues
593
594
Part I I I — R e f e r e n c e s
Error
Number
Error
Message
51
Invalid P U B L I C definition
52
Invalid E X T R N definition
53
T o o many E X T R N definitions
54
O F expected
55
INTERFACE expected
56
Invalid relocatable reference
57
T H E N expected
58
T O or D O W N T O expected
59
Undefined forward
61
Invalid typecast
62
Division by zero
63
I n v a l i d file t y p e
64
C a n n o t r e a d o r w r i t e v a r i a b l e s o f this t y p e
65
Pointer variable e x p e c t e d
66
String variable e x p e c t e d
67
String expression e x p e c t e d
68
Circular unit reference
69
Unit n a m e mismatch
70
Unit version mismatch
72
U n i t file f o r m a t e r r o r
73
IMPLEMENTATION expected
74
C o n s t a n t a n d case types don't m a t c h
75
R e c o r d variable e x p e c t e d
76
Constant out of range
77
File v a r i a b l e e x p e c t e d
78
Pointer expression expected
79
I n t e g e r o r real e x p r e s s i o n e x p e c t e d
80
Label not within current block
81
Label already defined
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Error
Number
Error
Message
82
U n d e f i n e d l a b e l i n p r e c e d i n g s t a t e m e n t part
83
Invalid @ argument
84
UNIT expected
85
";" e x p e c t e d
86
":" e x p e c t e d
87
"," expected
88
"(" expected
89
" ) " expected
90
" = " expected
91
" : = " expected
92
"[" or "(." expected
93
" ] " or " . ) " expected
94
"." expected
95
expected
96
T o o m a n y variables
97
Invalid F O R control variable
98
Integer variable e x p e c t e d
99
File a n d p r o c e d u r e t y p e s are n o t a l l o w e d h e r e
100
String length mismatch
101
I n v a l i d o r d e r i n g o f fields
102
String constant expected
103
I n t e g e r o r real v a r i a b l e e x p e c t e d
104
O r d i n a l variable e x p e c t e d
105
I N L I N E error
106
Character expression expected
112
C A S E constant out of
113
Error in statement
114
C a n n o t call a n i n t e r r u p t p r o c e d u r e
range
continues
595
596
Part I I I — R e f e r e n c e s
Error
Number
Error
Message
116
Must be in 8087 m o d e to compile
117
Target address not f o u n d
118
I n c l u d e files are n o t a l l o w e d h e r e
120
NIL expected
121
Invalid qualifier
122
Invalid variable reference
123
T o o many symbols
124
S t a t e m e n t part t o o l a r g e
126
Files m u s t b e v a r p a r a m e t e r s
127
T o o many conditional symbols
128
M i s p l a c e d conditional directive
129
E N D I F directive missing
130
E r r o r i n initial c o n d i t i o n a l d e f i n e s
131
H e a d e r does not match previous definition
132
Critical disk error
133
C a n n o t e v a l u a t e this e x p r e s s i o n
136
Invalid indirect reference
137
S t r u c t u r e d v a r i a b l e s are n o t a l l o w e d h e r e
140
Invalid
142
Procedure or function variable e x p e c t e d
143
Invalid p r o c e d u r e or function reference
146
File a c c e s s d e n i e d
147
Object type e x p e c t e d
148
L o c a l o b j e c t t y p e s are n o t a l l o w e d
149
VIRTUAL expected
150
M e t h o d identifier e x p e c t e d
151
V i r t u a l c o n s t r u c t o r s are n o t a l l o w e d
152
C o n s t r u c t o r identifier e x p e c t e d
floating-point
operation
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
Error
Number
Error
Message
153
Destructor identifier e x p e c t e d
154
Fail o n l y a l l o w e d w i t h i n c o n s t r u c t o r s
155
Invalid c o m b i n a t i o n o f o p c o d e a n d operands
156
M e m o r y reference expected
157
C a n n o t a d d o r subtract relocatable symbols
158
Invalid register c o m b i n a t i o n
159
286/287 i n s t r u c t i o n s are n o t e n a b l e d
160
Invalid symbol reference
161
C o d e generation error
162
ASM expected
163
Duplicate dynamic method index
164
D u p l i c a t e resource identifier
165
Duplicate or invalid export i n d e x
166
Procedure or function identifier e x p e c t e d
167
C a n n o t e x p o r t this s y m b o l
168
Duplicate export name
T h e following section provides m o r e detailed explanations of the compiler e r r o r m e s s a g e s . W h e n p o s s i b l e , s u g g e s t i o n s f o r c o r r e c t i n g t h e e r r o r s are supplied.
Compiler error 1: Out of memory This error occurs w h e n the compiler runs out o f m e m o r y . T o s o l v e this p r o b l e m , y o u m i g h t : • T r y t o i n c r e a s e t h e a m o u n t o f available m e m o r y i n W i n d o w s . • Set O p t i o n s / L i n k e r / L i n k b u f f e r t o d i s k . • If y o u ' r e n o t u s i n g t h e I D E a n d are u s i n g t h e c o m m a n d - l i n e c o m p i l e r , u s e t h e /L o p t i o n t o p l a c e t h e l i n k b u f f e r o n d i s k . If n o n e o f t h e s e s o l u t i o n s h e l p s , y o u r a p p l i c a t i o n (or u n i t ) m i g h t b e t o o l a r g e t o c o m p i l e i n t h e a m o u n t o f m e m o r y available o n y o u r s y s t e m . T r y d i v i d i n g t h e a p p l i c a t i o n o r u n i t that w o n ' t c o m p i l e i n t o t w o o r m o r e s m a l l e r units.
597
598
Part I I I — R e f e r e n c e s
Compiler error 2: Identifier expected T h e c o m p i l e r e x p e c t e d a n i d e n t i f i e r at this p o i n t . O n e p o s s i b i l i t y is that y o u ' r e trying t o r e d e c l a r e a r e s e r v e d w o r d . A n o t h e r p o s s i b i l i t y is t h e e x i s t e n c e o f misplaced syntax p r e c e d i n g the location o f the error.
Compiler error 3: Unknown identifier M o s t likely, this i d e n t i f i e r h a s n ' t b e e n d e c l a r e d o r isn't visible w i t h i n t h e c u r r e n t scope.
Compiler error 4: Duplicate identifier T h e i d e n t i f i e r is a l r e a d y b e i n g u s e d w i t h i n t h e c u r r e n t b l o c k . Y o u ' r e e i t h e r actually duplicating the identifier or possibly misspelling o n e o f the duplicated identifiers.
Compiler error 5: Syntax error T h e c o m p i l e r d e t e c t e d a n illegal c h a r a c t e r .
Compiler error 6: Error in real constant Y o u s h o u l d specify a real c o n s t a n t i n t h e f o l l o w i n g f o r m : const RealConst
= 3.5688855;
Compiler error 7: Error in integer constant Y o u s h o u l d specify a n i n t e g e r c o n s t a n t i n t h e f o l l o w i n g f o r m : const IntConst
= 380;
N o t e : Whole
real n u m b e r s greater t h a n t h e m a x i m u m
integer
allowed must be followed by a decimal point and a zero. For example: 84,245,567,797.0
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
Compiler error 8: String constant exceeds line Y o u p o s s i b l y o m i t t e d t h e c l o s i n g q u o t e i n a string c o n s t a n t o r m i s t y p e d it.
Compiler error 9: Too many nested files T h e c o m p i l e r p e r m i t s a m a x i m u m o f 15 n e s t e d s o u r c e - c o d e files. O n e p o s s i b i l e s o u r c e o f e r r o r is a n e x c e s s i v e n u m b e r o f n e s t e d I n c l u d e files.
Compiler error 10: Unexpected end of file T h i s e r r o r is g e n e r a t e d w h e n : • Y o u r s o u r c e c o d e file e n d s b e f o r e t h e final End o f t h e m a i n s t a t e m e n t part. I n this c a s e , t h e begins a n d ends a r e p r o b a b l y u n b a l a n c e d . • A n I n c l u d e file e n d s i n t h e m i d d l e o f a s t a t e m e n t part. E v e r y s t a t e m e n t part m u s t b e c o n t a i n e d i n o n e file. • Y o u didn't close a c o m m e n t .
Compiler error 11: line too long T h e m a x i m u m l e n g t h o f a l i n e is 126 c h a r a c t e r s .
Compiler error 12: Type identifier expected T h e identifier doesn't d e n o t e a type correctly.
Compiler error 13: Too many open files T h i s e r r o r u s u a l l y m e a n s that: 1. Y o u h a v e n ' t s p e c i f i e d a FILES n u m b e r i n y o u r C O N F I G . S Y S
file.
2. Y o u h a v e s p e c i f i e d t o o f e w files i n y o u r C O N F I G . S Y S . I n c r e a s e t h e n u m b e r o f files i n y o u r C O N F I G . S Y S t o 20 o r m o r e u s i n g t h e FILES s t a t e m e n t :
FILES = 30;
599
600
Part I I I — R e f e r e n c e s
Compiler error 14: Invalidfilename T h e file n a m e is i n v a l i d o r s p e c i f i e s a n o n e x i s t e n t p a t h .
Compiler error 15: File not found T h e file c o u l d n ' t b e l o c a t e d i n t h e c u r r e n t d i r e c t o r y o r i n a n y o f t h e s e a r c h directories you've specified in the Directories path.
Compiler error 16: Disk fidl D e l e t e files, u s e a n e w d i s k , a n d s o o n , t o free u p s o m e a d d i t i o n a l d i s k s p a c e .
Compiler error 17: Invalid compiler directive U s u a l l y , o n e o f t h e f o l l o w i n g p r o b l e m s exists: • T h e c o m p i l e r d i r e c t i v e letter is u n k n o w n . • O n e o f t h e c o m p i l e r - d i r e c t i v e p a r a m e t e r s is i n v a l i d . • Y o u ' r e u s i n g a global c o m p i l e r directive w h e n c o m p i l a t i o n o f the application's main b o d y has b e g u n .
Compiler error 18: Too many files Y o u ' r e u s i n g t o o m a n y files w h e n y o u c o m p i l e t h e p r o g r a m o r u n i t . O n e s o l u t i o n is t o c o m b i n e I n c l u d e files o r u n i t s .
Compiler error 19: Undefined type in pointer definition W h e n y o u d e c l a r e d t h e p o i n t e r t y p e , y o u r e f e r e n c e d a t y p e that h a s n ' t b e e n declared.
Compiler error 20: Variable identifier expected T h e identifier doesn't d e n o t e a variable correctly.
Compiler error 21: Error in type T h e s y m b o l y o u ' r e u s i n g c a n n o t b e g i n a type d e f i n i t i o n .
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 22: Structure too large I n T u r b o P a s c a l for W i n d o w s , s t r u c t u r e d t y p e s m u s t b e n o l a r g e r t h a n 6 5 5 2 0 bytes (64K).
Compiler error 23: Set base type out of range T h e b a s e t y p e o f a set m u s t b e a s u b r a n g e b e t w e e n 0 a n d 2 5 5 o r a n e n u m e r a t e d type with fewer than 257 possible values.
Compiler error 24: File components may not be files or objects T h e c o m p o n e n t t y p e o f a file t y p e c a n n o t b e a n o b j e c t t y p e o r a file t y p e , n o r c a n it b e a n y s t r u c t u r e d t y p e w i t h i n a n o b j e c t t y p e o r file t y p e .
Compiler error 25: Invalid string length T h e m a x i m u m l e n g t h o f a string m u s t b e i n t h e r a n g e 1 . . 2 5 5 .
Compiler error 26: Type mismatch U s u a l l y , this e r r o r r e s u l t s f r o m o n e o f t h e
following:
• I n c o m p a t i b l e types o f the variable a n d the expression in a n assignment statement. • I n c o m p a t i b l e t y p e s o f t h e a c t u a l a n d f o r m a l p a r a m e t e r i n a call t o a procedure or function. • A n e x p r e s s i o n t y p e that's i n c o m p a t i b l e w i t h t h e i n d e x t y p e i n array indexing. • Incompatible types o f o p e r a n d s in an expression.
Compiler error 27: Invalid subrange base type O r d i n a l t y p e s are t h e o n l y v a l i d b a s e t y p e s .
601
602
Part I I I — R e f e r e n c e s
Compiler error 28: Lower bound > than upper bound W h e n y o u declared the subrange type, y o u specified a lower b o u n d greater than the u p p e r b o u n d .
Compiler error 29: Ordinal type expected P o i n t e r , r e a l , string, a n d s t r u c t u r e d t y p e s a r e n ' t a l l o w e d i n this s i t u a t i o n .
Compiler error 30: Integer constant expected O n l y a n i n t e g e r c o n s t a n t is p e r m i t t e d i n this s i t u a t i o n .
Compiler error 31: Constant expected O n l y a c o n s t a n t is p e r m i t t e d i n this s i t u a t i o n .
Compiler error 32: Integer or real constant expected O n l y a n u m e r i c c o n s t a n t is p e r m i t t e d i n this s i t u a t i o n .
Compiler error 33: Pointer type identifier expected T h e identifier doesn't d e n o t e a type properly.
Compiler error 34: Invalid Junction result type V a l i d f u n c t i o n result t y p e s c a n b e o n l y s i m p l e t y p e s , string t y p e s , a n d p o i n t e r types.
Compiler error 35: Label identifier expected T h e identifier doesn't d e n o t e a label properly.
Compiler error 36: BEGIN expected A b e g i n w a s e x p e c t e d at this p o i n t , o r t h e r e ' s a n e r r o r i n t h e b l o c k s t r u c t u r e o f the unit or program.
K — T u r b o PascalforWindows Error Messages
Begin
End T h e begin. . .end b l o c k c o n s t i t u t e s a c o n s t r u c t , w h i c h is a c o m p o u n d s t a t e m e n t . T h e begin a n d end reserved w o r d s act as s t a t e m e n t b r a c k e t s . For example:
{ Compound statement used within an "if" statement } if First < Last then begin Temp := First; First := Last; Last := Temp; end;
Compiler error 37: END expected A n end was expected here, or there's an error in the block structure of the unit or program. Use end with: • begin to form c o m p o u n d statements • case to form case statements • record to declare record types • obj ect to declare object types • asm to call the inline assembler For example: { with "begin" to form compound statement } if First < Last then begin Temp := First; First := Last; Last := Temp; end; { with "case" statement }
603
604
Part III—References
case Ch of 'A'.-'Z , 'a'.-'z': WriteLn('Letter'); '0'..'9': WriteLn('Digit'); ' + ', '-', '*', '/': WriteLn('Operator'); else WriteLn('Special character'); end; 1
{ with record type definitions } type Class = (Num, Dat, Str); Date = record D, M, Y: Integer; end; Facts = record Name: string[10]; case Kind: Class of Num: (N: real); Dat: (D: Date); Str: (S: string); end; { with object type definitions } type LocationPtr = "Location; Location = object X, Y: Integer; procedure Init(PX, PY: Integer); function GetX: Integer; function GetY: Integer; end; { with asm } asm mov ax,1 mov cx, 100 end;
Compiler error 38: Integer expression expected A n Integer type was expected.
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
Compiler error 39: Ordinal expression expected The expression must b e o f an ordinal type.
Compiler error 40: Boolean expression expected T h e e x p r e s s i o n m u s t b e o f t y p e Boolean.
Compiler error 41: Operand types do not match operator T h e o p e r a t o r c a n n o t b e u s e d o n o p e r a n d s o f this type; f o r e x a m p l e , 'C
d i v '6'.
Compiler error 42: Error in expression T h i s s y m b o l c a n n o t p a r t i c i p a t e i n this e x p r e s s i o n . Possibly, y o u ' v e o m i t t e d a n operator between two operands.
Compiler error 43: Illegal assignment Y o u c a n n o t a s s i g n v a l u e s t o files a n d u n t y p e d v a r i a b l e s . Y o u c a n a s s i g n v a l u e s t o a f u n c t i o n i d e n t i f i e r o n l y w i t h i n t h e s t a t e m e n t part o f t h e f u n c t i o n .
Compiler error 44: Field identifier expected T h e i d e n t i f i e r d o e s n ' t d e n o t e a field i n t h e r e c o r d v a r i a b l e .
Compiler error 45: Objectfiletoo large T u r b o Pascal f o r W i n d o w s c a n n o t l i n k i n O B J files l a r g e r t h a n 6 4 K .
Compiler error 46: Undefined external T h e e x t e r n a l p r o c e d u r e o r f u n c t i o n d o e s n ' t h a v e a m a t c h i n g PUBLIC d e f i n i t i o n i n a n o b j e c t file. C h e c k t o m a k e s u r e that y o u ' v e s p e c i f i e d all o b j e c t files i n $L f i l e - n a m e d i r e c t i v e s , a n d verify that y o u ' v e c o r r e c t l y s p e l l e d t h e p r o c e d u r e o r f u n c t i o n i d e n t i f i e r i n t h e . A S M file. T h e $L ( L i n k O b j e c t File) d i r e c t i v e i n s t r u c t s t h e c o m p i l e r t o l i n k t h e n a m e d file w i t h t h e p r o g r a m o r u n i t b e i n g c o m p i l e d . U s e t h e $L d i r e c t i v e t o l i n k in c o d e written in assembly language for subprograms declared to b e external.
605
606
Part I I I — R e f e r e n c e s
Compiler error 47: Invalid objectfilerecord T h e O B J file c o n t a i n s a n i n v a l i d o b j e c t r e c o r d .
Compiler error 48: Code segment too large T h e m a x i m u m size o f a p r o g r a m ' s o r u n i t ' s c o d e is 6 5 5 2 0 b y t e s ( 6 4 K ) . T o b r e a k a c o d e s e g m e n t correctly, d o the following: • If y o u ' r e c o m p i l i n g a p r o g r a m , r e c o n s t r u c t t h e p r o g r a m b y m o v i n g s o m e o f its p r o c e d u r e s o r f u n c t i o n s i n t o a u n i t . • If y o u ' r e c o m p i l i n g a u n i t , d i v i d e it i n t o t w o o r m o r e u n i t s .
Compiler error 49: Data segment too large T h e m a x i m u m size o f a p r o g r a m ' s d a t a s e g m e n t is 6 5 5 2 0 b y t e s ( 6 4 K ) , i n c l u d i n g t h e d a t a d e c l a r e d b y t h e u s e d u n i t s . If y o u n e e d m o r e g l o b a l d a t a t h a n t h i s , d e c l a r e t h e l a r g e r s t r u c t u r e s as p o i n t e r s , a n d a l l o c a t e t h e m d y n a m i c a l l y u s i n g t h e New p r o c e d u r e . T h e New p r o c e d u r e c r e a t e s a n e w d y n a m i c v a r i a b l e a n d s p e c i f i e s a p o i n t e r v a r i a b l e t o p o i n t t o it. F o r e x a m p l e :
New(P, Init(326, 243));
Compiler error 50: DO expected T h e r e s e r v e d w o r d do h a s n ' t b e e n u s e d c o r r e c t l y . do (a r e s e r v e d w o r d ) is u s e d i n while, for, a n d with s t a t e m e n t s . F o r e x a m p l e :
while Ch = ' do Ch := GetChar; for Ch := 1 to 100 do Ch := GetChar; with Date[C] do month := 1; 1
Compiler error 51: Invalid PUBIJC definition T h i s e r r o r c a n o c c u r if: • T w o or m o r e PUBLIC directives in assembly l a n g u a g e c o d e define the s a m e identifier. • T h e O B J file d e f i n e s P U B L I C s y m b o l s that a r e n ' t i n t h e CODE s e g m e n t .
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 52: Invalid EXTRN definition T h i s e r r o r c a n o c c u r if: • T h e i d e n t i f i e r w a s r e f e r r e d t o t h r o u g h a n EXTRN d i r e c t i v e i n a s s e m b l y l a n g u a g e , b u t wasn't declared in the T u r b o Pascal for W i n d o w s p r o g r a m o r u n i t , n o r i n t h e i n t e r f a c e part o f a n y o f t h e u s e d u n i t s . • T h e identifier d e n o t e s a n absolute variable. • T h e identifier d e n o t e s a n inline p r o c e d u r e o r function.
Compiler error 53: Too many EXTRN definitions T u r b o Pascal f o r W i n d o w s d o e s n ' t allow .OBJ files w i t h m o r e t h a n 256 EXTRN definitions.
Compiler error 54: OF expected Y o u h a v e n ' t u s e d t h e r e s e r v e d w o r d of c o r r e c t l y . of is u s e d i n array, set, a n d file t y p e d e c l a r a t i o n s , a n d i n case s t a t e m e n t s . F o r example: { array declaration } type InList = array[1..650] of Integer; CharData = array[ A'.. Z'] of Byte; Matrix = array[0..5, 0..5] of real; 1
1
{ Set types } type Day = (Sun, Mon, Tue, Wed, Thu, Fri, Sat); CharSet = set of Char; Digits = set of 0..9; Days = set of Day; { File type declarations } type Person = record FirstName: string[15]; LastName : string[25]; Address : string[35]; end;
607
608
Part I I I — R e f e r e n c e s
PersonFile = file of Person; NumberFile = file of Integer; SwapFile = file; {case statement } case Ch of 'A'-.'Z', ' a ' - . ' z ' : WriteLn('Letter'); '0'..'9': WriteLn('Digit'); ' + ', '-', '*', '/': WriteLn('Operator'); else WriteLn('Special character'); end;
Compiler error 55: INTERFACE expected Y o u h a v e n ' t u s e d t h e r e s e r v e d w o r d interface c o r r e c t l y . T h e i n t e r f a c e s e c t i o n o f a u n i t is t h e p u b l i c part. It d e t e r m i n e s w h i c h c o m p o n e n t s are v i s i b l e a n d a c c e s s i b l e t o a n y p r o g r a m (or o t h e r u n i t ) u s i n g that unit. T h e i n t e r f a c e s e c t i o n b e g i n s w i t h t h e r e s e r v e d w o r d interface, w h i c h a p p e a r s after t h e unit h e a d e r , a n d e n d s with t h e reserved w o r d implementation. In the unit interface, y o u declare constants, data types, variables, procedures, and functions. T h e "bodies" o f t h e public p r o c e d u r e s a n d functions are in the i m p l e m entation section. A uses c l a u s e c a n a p p e a r i n t h e i n t e r f a c e s e c t i o n . (If a uses c l a u s e is p r e s e n t , uses m u s t i m m e d i a t e l y f o l l o w t h e r e s e r v e d w o r d interface).
Compiler error 56: Invalid relocatable reference T h i s e r r o r c a n o c c u r if: • T h e O B J file c o n t a i n s d a t a a n d r e l o c a t a b l e r e f e r e n c e s i n s e g m e n t s o t h e r t h a n C O D E . F o r e x a m p l e , y o u m i g h t b e trying t o d e c l a r e initialized v a r i a b l e s i n t h e D A T A s e g m e n t . • T h e O B J file c o n t a i n s b y t e - s i z e d r e f e r e n c e s t o r e l o c a t a b l e s y m b o l s . T h i s e r r o r c a n o c c u r if y o u u s e t h e HIGH a n d LOW o p e r a t o r s w i t h r e l o c a t a b l e s y m b o l s , o r if y o u refer t o r e l o c a t a b l e s y m b o l s i n DB d i r e c t i v e s . • A n o p e r a n d refers t o a r e l o c a t a b l e s y m b o l that y o u d i d n ' t d e f i n e i n t h e CODE o r DATA s e g m e n t s . • A n o p e r a n d refers t o a n EXTRN p r o c e d u r e o r f u n c t i o n w i t h a n offset.
K — T u r b o Pascal for Windows
Error Messages
Compiler error 57: THEN expected Y o u haven't u s e d the reserved w o r d t h e n correctly. F o r example: { if
'if-then'
statements
}
( I < Min) o r ( I > Max) t h e n I
: = 0;
i f ParamCount 2 t h e n begin W r i t e L n ( Bad command l i n e ' ) ; Halt(1); end else begin ReadFile(ParamStr(1)); WriteFile(ParamStr(2)); 1
end;
Compiler error 58: TO or DOWNTO expected Y o u haven't u s e d the reserved w o r d t o or downto correctly. F o r example: { for
...
to, for
...
downto }
f o r I : = 1 t o ParamCount do WriteLn(ParamStr(I); f o r I : = 1 t o 21 do f o r J : = 1 t o 21 do begin X : = 0; f o r K : = 1 t o 21 do X : = X + M a t 1 [ I , K] * Mat2[K, J ] ; M a t [ I , J ] := X; end;
Compiler error 59: Undefined forward This error might o c c u r if: • Y o u declared the procedure or function in the interface part o f a unit, but didn't define it in the implementation part. • Y o u declared the procedure or function forward but didn't define it.
609
610
Part I I I — R e f e r e n c e s
Compiler error 61: Invalid typecast T h i s e r r o r m i g h t o c c u r if: • I n a v a r i a b l e t y p e c a s t , t h e sizes o f t h e v a r i a b l e r e f e r e n c e a n d t h e d e s t i n a t i o n t y p e differ. • Y o u ' r e attempting to typecast a n expression w h e r e only a variable r e f e r e n c e is a l l o w e d .
Compiler error 62: Division by zero T h e preceding o p e r a n d attempts to divide by zero.
Compiler error 63: Invalidfiletype T h e f i l e - h a n d l i n g p r o c e d u r e d o e s n ' t s u p p o r t t h e g i v e n file's t y p e . F o r e x a m p l e , y o u m i g h t h a v e m a d e a call t o Readln w i t h a t y p e d file o r t o Seek w i t h a text file.
Compiler error 64: Cannot read or write variables of this type Read a n d Readln c a n i n p u t t h e f o l l o w i n g v a r i a b l e t y p e s :
Char Integer real string Write a n d Writeln c a n o u t p u t t h e f o l l o w i n g v a r i a b l e t y p e s :
Char Integer real string Boolean
Compiler error 65: Pointer variable expected This variable must b e o f a pointer type. A p o i n t e r type variable contains the m e m o r y address o f a d y n a m i c variable of a specified base type.
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 66: String variable expected T h i s v a r i a b l e m u s t b e o f a string t y p e .
Compiler error 67: String expression expected T h i s e x p r e s s i o n m u s t b e o f a string t y p e .
Compiler error 68: Circular unit reference T w o u n i t s c a n n o t use e a c h o t h e r i n t h e i r i n t e r f a c e p a r t s .
Compiler error 69: Unit name mismatch T h e n a m e o f t h e u n i t f o u n d i n t h e T P U file d o e s n ' t m a t c h t h e n a m e s p e c i f i e d i n t h e uses c l a u s e . O r , t h e n a m e o f t h e u n i t file n a m e d o e s n ' t m a t c h t h e n a m e o f t h e u n i t i n t h e u n i t h e a d e r w i t h i n t h e file.
Compiler error 70: Unit version mismatch O n e o r m o r e o f t h e u n i t s u s e d b y this u n i t h a v e b e e n c h a n g e d s i n c e this u n i t w a s compiled. Use Compile/Make or Compile/Build to automatically recompile the u n i t s that h a v e c h a n g e d . T h e C o m p i l e / M a k e c o m m a n d c r e a t e s a n E X E file a c c o r d i n g t o t h e f o l l o w ing rules: • If a p r i m a r y file h a s b e e n n a m e d i n t h e P r i m a r y F i l e d i a l o g b o x , that file is c o m p i l e d . O t h e r w i s e , t h e file i n t h e active edit w i n d o w is c o m p i l e d . T u r b o Pascal c h e c k s all files that t h e file b e i n g c o m p i l e d d e p e n d s o n t o s e e w h e t h e r t h e y exist a n d that t h e y are c u r r e n t . • If t h e s o u r c e file f o r a g i v e n u n i t h a s b e e n m o d i f i e d s i n c e t h e T ^ U ( o b j e c t c o d e ) file w a s c r e a t e d , that u n i t is r e c o m p i l e d . • If t h e i n t e r f a c e f o r a g i v e n u n i t h a s b e e n c h a n g e d , all o t h e r u n i t s that d e p e n d o n it are r e c o m p i l e d . • If a u n i t l i n k s i n a n O B J file ( e x t e r n a l r o u t i n e s ) , a n d t h e O B J file is n e w e r t h a n t h e u n i t ' s T P U file, t h e u n i t is r e c o m p i l e d . • If a u n i t c o n t a i n s a n I n c l u d e file a n d t h e I n c l u d e file is n e w e r t h a n that u n i t ' s T P U file, t h e u n i t is r e c o m p i l e d . • If t h e s o u r c e t o a u n i t ( T P U file) c a n n o t b e l o c a t e d , that u n i t is n o t c o m p i l e d , b u t u s e d as is.
611
612
Part I I I — R e f e r e n c e s
T h i s o p t i o n is i d e n t i c a l t o C o m p i l e / B u i l d e x c e p t that it's c o n d i t i o n a l . ( B u i l d r e b u i l d s all files r e g a r d l e s s o f w h e t h e r t h e y ' r e o u t o f d a t e . ) T h e C o m p i l e / B u i l d c o m m a n d r e b u i l d s all t h e c o m p o n e n t s o f y o u r p r o g r a m regardless o f w h e t h e r they're current. T h i s o p t i o n is i d e n t i c a l t o C o m p i l e / M a k e e x c e p t that it is u n c o n d i t i o n a l . ( M a k e r e b u i l d s o n l y t h o s e files that a r e n ' t c u r r e n t . ) T h e C o m p i l e / B u i l d c o m m a n d r e c o m p i l e s all t h e files i n c l u d e d i n t h e p r i m a r y file. If y o u a b o r t a B u i l d c o m m a n d b y p r e s s i n g C t r l - B r e a k o r g e t e r r o r s that s t o p t h e b u i l d , y o u c a n p i c k u p w h e r e it left o f f b y c h o o s i n g C o m p i l e / M a k e .
Compiler error 72: Unitfileformat error T h e T P U file is i n v a l i d . C h e c k t o e n s u r e that it's a T P U file.
Compiler error 73: IMPLEMENTATION expected E i t h e r t h e r e s e r v e d w o r d implementation d o e s n ' t a p p e a r c o r r e c t l y o r y o u ' v e u s e d it i m p r o p e r l y . T h e implementation part o f t h e u n i t is w h e r e y o u find t h e b o d i e s o f t h e p r o c e d u r e s a n d f u n c t i o n s d e c l a r e d i n t h e i n t e r f a c e part o f t h e u n i t .
Compiler error 74: Constant and case types don't match T h e t y p e o f t h e case c o n s t a n t is i n c o m p a t i b l e w i t h t h e case s t a t e m e n t ' s selector expression.
Compiler error 75: Record variable expected This variable must b e o f a record type. A r e c o r d c o n t a i n s a n u m b e r o f c o m p o n e n t s , o r fields, that c a n b e o f different types. F o r e x a m p l e :
{ Record Type Definitions } type Class = (Num, Dat, Str); Date = record D, M, Y: Integer; end; Facts = record Name: string[10];
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
case Kind: Num: (N: Dat: (D: Str: (S:
Class of real); Date); string);
end;
Compiler error 76: Constant out of range Y o u ' r e p r o b a b l y trying t o d o o n e o f t h e f o l l o w i n g : • I n d e x a n array w i t h a n o u t - o f - r a n g e c o n s t a n t . • Assign a n out-of-range constant to a variable. • Pass a n o u t - o f - r a n g e c o n s t a n t as a p a r a m e t e r t o a p r o c e d u r e or function.
Compiler error 77: File variable expected T h i s v a r i a b l e m u s t b e o f a file t y p e . A file t y p e c o n s i s t s o f a l i n e a r s e q u e n c e o f c o m p o n e n t s o f t h e c o m p o n e n t t y p e , w h i c h c a n b e a n y t y p e e x c e p t a file t y p e . If t h e w o r d o f a n d t h e c o m p o n e n t t y p e a r e o m i t t e d , t h e t y p e d e n o t e s a n u n t y p e d file. T h e p r e d e f i n e d file t y p e T e x t signifies a file c o n t a i n i n g c h a r a c t e r s o r g a n i z e d i n t o l i n e s . F o r e x a m p l e : { File
type declarations
}
type Person = record FirstName: string[15]; LastName : string[25]; Address : string[35]; end; PersonFile = file of Person; NumberFile = file of Integer; SwapFile = file;
613
614
Part I I I — R e f e r e n c e s
Compiler error 78: Pointer expression expected This expression must b e o f a pointer type. A pointer type variable contains t h e m e m o r y address o f a d y n a m i c variable o f a specified base type.
Compiler error 79: Integer or real expression expected T h i s e x p r e s s i o n m u s t b e o f e i t h e r a n Integer o r Real t y p e .
Compiler error 80: Label not within current block A goto s t a t e m e n t c a n n o t r e f e r e n c e a l a b e l o u t s i d e t h e c u r r e n t b l o c k .
Compiler error 81: Label already defined T h e label already marks a statement.
Compiler error 82: Undefined label in preceding statement part Y o u d e c l a r e d a n d r e f e r e n c e d t h e l a b e l i n a s t a t e m e n t part, b u t y o u n e v e r d e f i n e d it.
Compiler error 83: Invalid @ argument Valid a r g u m e n t s are variable references a n d p r o c e d u r e o r function identifiers.
Compiler error 84: UNIT expected T h e r e s e r v e d w o r d unit d o e s n ' t a p p e a r w h e r e it s h o u l d . U n i t s a r e t h e basis o f m o d u l a r p r o g r a m m i n g in T u r b o Pascal for W i n d o w s . Y o u u s e units t o create libraries a n d t o d i v i d e l a r g e p r o g r a m s i n t o l o g i c a l l y r e l a t e d m o d u l e s .
Compiler error 85:";" expected A semicolon was expected.
K — T u r b o Pascal f o r Windows
Compiler error 86:":" expected A colon was expected.
Compiler error 87:"," expected A c o m m a was expected.
Compiler error 88:"(" expected A n o p e n i n g parenthesis was expected.
Compiler error 89:")" expected A closing parenthesis was expected.
Compiler error 90: "=" expected A n equal sign was expected.
Compiler error 91: ":=" expected A n assignment operator was expected.
Compiler error 92:"[" or"(." expected A left b r a c k e t w a s e x p e c t e d .
Compiler error 93:"]" or".)" expected A right b r a c k e t w a s e x p e c t e d .
Compiler error 94:"." expected A period was expected.
Error M e s s a g e s
615
616
Part I I I — R e f e r e n c e s
Compiler error 95:expected A subrange was expected. A s u b r a n g e t y p e is a r a n g e o f v a l u e s f r o m a n o r d i n a l t y p e c a l l e d t h e h o s t t y p e . T h e d e f i n i t i o n o f a s u b r a n g e t y p e s p e c i f i e s t h e least a n d t h e largest v a l u e i n t h e s u b r a n g e . B o t h c o n s t a n t s m u s t b e o f t h e s a m e o r d i n a l t y p e , a n d t h e first c o n s t a n t m u s t b e less t h a n o r e q u a l t o t h e s e c o n d c o n s t a n t . F o r e x a m p l e : 0..99 -128..127
Compiler error 96: Too many variables Global T h e total size o f t h e g l o b a l v a r i a b l e s d e c l a r e d w i t h i n a p r o g r a m o r u n i t c a n n o t exceed 64K. Local T h e t o t a l size o f t h e l o c a l v a r i a b l e s d e c l a r e d w i t h i n a p r o c e d u r e o r f u n c t i o n cannot exceed 64K.
Compiler error 97: Invalid FOR control variable T h e for s t a t e m e n t c o n t r o l v a r i a b l e m u s t b e a s i m p l e v a r i a b l e d e f i n e d i n t h e d e c l a r a t i o n part of t h e c u r r e n t s u b p r o g r a m . F o r e x a m p l e :
{for ... to, for ... downto } for I := 1 to ParamCount do Writel_n(ParamStr(I); for I := 1 to 10 do for J := 1 to 10 do begin X := 0; for K := 1 to 10 do X := X + Mat1[I, K] * Mat2[K, J ] ; Mat[I, J] := X; end;
Compiler error 98: Integer variable expected T h i s v a r i a b l e m u s t b e of a n Integer t y p e .
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 99: File and procedure types are not allowed here A typed constant cannot b e o f a fde type.
Compiler error 100: String length mismatch T h e length o f the string constant d o e s n ' t m a t c h the n u m b e r o f c o m p o n e n t s in t h e c h a r a c t e r array.
Compiler error 101: Invalid ordering of fields T h e fields o f a record-type constant m u s t b e written in the o r d e r o f declaration.
Compiler error 102: String constant expected A string c o n s t a n t d o e s n ' t a p p e a r w h e r e it s h o u l d . I n i n l i n e a s s e m b l e r s t a t e m e n t s , string c o n s t a n t s m u s t b e e n c l o s e d i n single or d o u b l e quotes. T w o c o n s e c u t i v e q u o t e s o f t h e s a m e t y p e as t h e e n c l o s i n g q u o t e s c o u n t as o n l y o n e c h a r a c t e r . S t r i n g c o n s t a n t s o f a n y l e n g t h are a l l o w e d i n DB d i r e c t i v e s , a n d c a u s e allocation o f a s e q u e n c e of bytes containing the A S C I I values o f the characters i n t h e string. W h e n n o t i n a DB d i r e c t i v e , a string c o n s t a n t c a n b e n o l o n g e r t h a n f o u r c h a r a c t e r s , a n d d e n o t e s a n u m e r i c v a l u e that c a n p a r t i c i p a t e i n a n e x p r e s s i o n . T h e n u m e r i c v a l u e o f a string c o n s t a n t is c a l c u l a t e d as:
+ 0rd(Ch1) + 0rd(Ch2) shl 8 + 0rd(Ch3) shl 16 + 0rd(Ch4) shl 24 where • Ch1 is t h e r i g h t m o s t (last) c h a r a c t e r • Ch4 is t h e l e f t m o s t (first) c h a r a c t e r If t h e string is s h o r t e r t h a n f o u r c h a r a c t e r s , t h e l e f t m o s t (first) c h a r a c t e r o r c h a r a c t e r s are a s s u m e d t o b e 0 ( z e r o ) . H e r e are s o m e e x a m p l e s o f string c o n s t a n t s a n d t h e i r c o r r e s p o n d i n g numeric values:
617
618
Part I I I — R e f e r e n c e s
String
Constant
Numeric
a'
00000061H
ba'
00006261H
cba
636261H
1
'dcba'
64636261H
'a'
00006120H
a'
20202061H
'a'*2 1
000000E2H
a - A' 1
Not
Value
1
00000020H
'a'
FFFFFF9EH
Compiler error 103: Integer or real variable expected T h i s v a r i a b l e m u s t b e o f a n Integer o r Real t y p e .
Compiler error 104: Ordinal variable expected This variable must b e o f a n ordinal type. T u r b o P a s c a l h a s n i n e p r e d e f i n e d o r d i n a l t y p e s . Five o f t h e s e i n t e g e r t y p e s d e n o t e a s p e c i f i c s u b s e t o f t h e w h o l e n u m b e r s , as s h o w n i n t h e f o l l o w i n g : Type
Range
Size
Shortint
1 2 8 . . 127
8-bit
Integer
-32768.-32767
16-bit
Longint
-2147483648. .2147483647
32-bit
Byte
0.255
8-bit
Word
0.65535
16-bit
T h e o t h e r f o u r p r e d e f i n e d o r d i n a l t y p e s a r e t h e b o o l e a n s (Boolean,
WordBool, LongBool), a n d Char. T w o o t h e r classes o f u s e r - d e f i n e d o r d i n a l t y p e s a r e e n u m e r a t e d t y p e s a n d subrange types.
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 105: INLINE error T h e < o p e r a t o r isn't p e r m i t t e d i n c o n j u n c t i o n w i t h r e l o c a t a b l e r e f e r e n c e s t o variables. T h e s e r e f e r e n c e s a r e always w o r d - s i z e d .
Compiler error 106: Character expression expected T h i s e x p r e s s i o n m u s t b e o f a Char t y p e .
Compiler error 112: CASE constant out of range F o r Integer t y p e case s t a t e m e n t s , t h e c o n s t a n t s m u s t b e w i t h i n t h e r a n g e -32768..32767.
Compiler error 113: Error in statement T h i s s y m b o l c a n n o t start a s t a t e m e n t .
Compiler error 114: Cannot call an interrupt procedure Y o u c a n n o t d i r e c t l y call a n i n t e r r u p t p r o c e d u r e . T h e i n t e r r u p t d i r e c t i v e a l l o w s y o u t o d e c l a r e interrupt p r o c e d u r e s . A n interrupt p r o c e d u r e l o o k s like this: procedure IntProc(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt; T h e registers a r e p a s s e d as p s e u d o - p a r a m e t e r s s o that y o u c a n u s e a n d m o d i f y t h e m in the c o d e o f the interrupt p r o c e d u r e .
Compiler error 116: Must be in 80x87 mode to compile T h i s c o n s t r u c t c a n b e c o m p i l e d o n l y i n t h e { $ N + } state. O p e r a t i o n s o n t h e 8 0 x 8 7 Real t y p e s (Single, Double, Extended, a n d Comp) a r e n o t a l l o w e d i n t h e { $ N - } state.
619
620
Part I I I — R e f e r e n c e s
Compiler error 117: Target address not found T h e S e a r c h / F i n d E r r o r c o m m a n d c o u l d n ' t l o c a t e a s t a t e m e n t that c o r r e s p o n d s to the specified address.
Compiler error 118: Includefilesare not allowed here E v e r y s t a t e m e n t part m u s t b e c o n t a i n e d e n t i r e l y i n o n e file.
Compiler error 120: NIL expected T y p e d c o n s t a n t s o f p o i n t e r t y p e s c a n b e initialized o n l y t o t h e v a l u e n i l .
Compiler error 121: Invalid qualifier Y o u ' r e p r o b a b y trying t o d o o n e o f t h e f o l l o w i n g : • I n d e x a v a r i a b l e that is n o t a n array. • S p e c i f y fields i n a v a r i a b l e that is n o t a r e c o r d . • D e r e f e r e n c e a v a r i a b l e that is n o t a p o i n t e r .
Compiler error 122: Invalid variable reference T h i s c o n s t r u c t f o l l o w s t h e s y n t a x o f a v a r i a b l e r e f e r e n c e , b u t it d o e s n ' t d e n o t e a memory location. Y o u ' r e probably calling a pointer function, but forgetting to dereference t h e result.
Compiler error 123: Too many symbols T h e program or unit declares m o r e than 64K of symbols. I f y o u ' r e c o m p i l i n g w i t h { $ D + } , try t u r n i n g it off. {Note: T h i s s t e p p r e v e n t s y o u f r o m finding r u n - t i m e e r r o r s i n that m o d u l e . ) Y o u c a n a l s o try m o v i n g s o m e d e c l a r a t i o n s i n t o a s e p a r a t e u n i t .
Compiler error 124: Statement part too large T u r b o Pascal limits t h e size o f a s t a t e m e n t part t o a b o u t 2 4 K . If y o u e n c o u n t e r this e r r o r , m o v e s e c t i o n s o f t h e s t a t e m e n t part i n t o o n e or more procedures.
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 126: Files must be var parameters Y o u ' r e p r o b a b l y trying t o d e c l a r e a file-type v a l u e p a r a m e t e r . File-type p a r a m e t e r s m u s t b e v a r p a r a m e t e r s .
Compiler error 127: Too many conditional symbols T h e r e isn't e n o u g h r o o m t o d e f i n e f u r t h e r c o n d i t i o n a l s y m b o l s . Try to eliminate s o m e symbols, o r shorten s o m e o f the symbolic n a m e s .
Compiler error 128: Misplaced conditional directive T h e c o m p i l e r e n c o u n t e r e d a n {$ELSE} o r {$ENDIF} d i r e c t i v e w i t h o u t a m a t c h i n g {$IFDEF}, {$IFNDEF}, o r {$IF0PT} d i r e c t i v e .
Compiler error 129: ENDEF directive missing T h e s o u r c e file e n d e d w i t h i n a c o n d i t i o n a l c o m p i l a t i o n c o n s t r u c t . T u r b o Pascal requires a n e q u a l n u m b e r o f { $ I F x x x } s a n d {$ENDIF}sin a s o u r c e file.
Compiler error 130: Error in initial conditional defines T h e initial c o n d i t i o n a l s y m b o l s s p e c i f i e d i n O p t i o n s / C o m p i l e r / C o n d i t i o n a l D e f i n e s ( o r i n a /D directive) a r e i n v a l i d . T u r b o P a s c a l f o r W i n d o w s e x p e c t s z e r o o r m o r e identifiers s e p a r a t e d b y blanks, commas, or semicolons.
Compiler error 131: Header does not match previous definition T h e p r o c e d u r e o r f u n c t i o n h e a d e r s p e c i f i e d i n a n i n t e r f a c e part o r FORWARD d e c l a r a t i o n d o e s n ' t m a t c h this h e a d e r .
Compiler error 132: Critical disk error A critical e r r o r o c c u r r e d d u r i n g c o m p i l a t i o n (for e x a m p l e , a D r i v e N o t R e a d y error).
621
622
Part I I I — R e f e r e n c e s
Compiler error 133: Cannot evaluate this expression Y o u m i g h t b e trying t o u s e a n o n s u p p o r t e d f e a t u r e i n a c o n s t a n t e x p r e s s i o n o r in a d e b u g expression. F o r e x a m p l e , y o u m i g h t b e a t t e m p t i n g t o u s e t h e Sin f u n c t i o n i n a const d e c l a r a t i o n , o r a t t e m p t i n g t o call a u s e r - d e f i n e d f u n c t i o n i n a d e b u g e x p r e s s i o n .
Compiler error 136: Invalid indirect reference T h e statement attempts to m a k e an invalid indirect reference. For e x a m p l e , y o u might b e using an absolute variable w h o s e base variable is n o t k n o w n i n t h e c u r r e n t m o d u l e , o r u s i n g a n i n l i n e r o u t i n e that r e f e r e n c e s a variable not k n o w n in the current m o d u l e .
Compiler error 137: Structured variables are not allowed here Y o u m i g h t b e trying t o p e r f o r m a n o n s u p p o r t e d o p e r a t i o n o n a s t r u c t u r e d variable. F o r e x a m p l e , y o u m i g h t b e trying t o m u l t i p l y t w o r e c o r d s .
Compiler error 140: Invalidfloating-pointoperation A n o p e r a t i o n o n t w o real t y p e v a l u e s p r o d u c e d a n o v e r f l o w o r a d i v i s i o n by zero.
Compiler error 142: Procedure or function variable expected I n this c o n t e x t , t h e a d d r e s s o p e r a t o r ( @ ) c a n b e u s e d o n l y w i t h a p r o c e d u r e o r function variable.
Compiler error 143: Invalid procedure or function reference Y o u ' r e p r o b a b l y trying t o call a p r o c e d u r e i n a n e x p r e s s i o n . A p r o c e d u r e o r a f u n c t i o n m u s t b e c o m p i l e d i n t h e { $ F + } state, a n d c a n n o t b e d e c l a r e d w i t h i n l i n e o r i n t e r r u p t if it is t o b e a s s i g n e d t o a p r o c e d u r e variable.
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s
Compiler error 146: File access denied T h e file c o u l d n ' t b e o p e n e d o r c r e a t e d . T h e p r o g r a m m i g h t b e trying t o w r i t e t o a r e a d - o n l y file.
Compiler error 147: Object type expected T h e identifier doesn't d e n o t e a n object type.
Compiler error 148: Local object types are not allowed O b j e c t t y p e s can b e d e f i n e d only in t h e o u t e r m o s t s c o p e o f a p r o g r a m o r u n i t . O b j e c t type definitions within p r o c e d u r e s a n d functions are n o t allowed.
Compiler error 149: \TKTUAL expected T h e k e y w o r d virtual is m i s s i n g . virtual is a p r o c e d u r e d i r e c t i v e . A virtual m e t h o d is a m e t h o d w h o s e call is l i n k e d t o its c o d e at r u n - t i m e , by a p r o c e s s c a l l e d late b i n d i n g . F o r example:
procedure Method(<parameter list>); virtual; D e c l a r i n g a m e t h o d as virtual m a k e s it p o s s i b l e for m e t h o d s w i t h t h e s a m e n a m e t o b e i m p l e m e n t e d in d i f f e r e n t w a y s u p a n d d o w n a h i e r a r c h y of object types.
Compiler error 150: Method identifier expected T h e identifier doesn't d e n o t e a m e t h o d .
Compiler error 151: Virtual constructors are not allowed A c o n s t r u c t o r m e t h o d m u s t b e static.
Compiler error 152: Constructor identifier expected T h e identifier doesn't d e n o t e a constructor.
Compiler error 153: Destructor identifier expected T h e identifier doesn't d e n o t e a destructor.
623
624
Part I I I — R e f e r e n c e s
Compiler error 154: Fail only allowed within constructors T h e F a i l standard procedure can be used only within constructors.
Compiler error 155: Invalid combination of opcode and operands T h e a s s e m b l e r o p c o d e d o e s n ' t a c c e p t this c o m b i n a t i o n o f o p e r a n d s . P o s s i b l e c a u s e s are • T o o m a n y o r t o o f e w o p e r a n d s for this a s s e m b l e r o p c o d e ; for e x a m p l e , I N C A X , B X o r M O V AX. • T h e n u m b e r o f o p e r a n d s is c o r r e c t , b u t t h e i r t y p e s o r o r d e r d o n ' t m a t c h t h e o p c o d e ; for e x a m p l e , DEC 1, MOV AX,CL o r MOV 1 , AX.
Compiler error 156: Memory reference expected T h e a s s e m b l e r o p e r a n d isn't a m e m o r y r e f e r e n c e , w h i c h is r e q u i r e d h e r e . M o s t likely, y o u ' v e o m i t t e d t h e s q u a r e b r a c k e t s a r o u n d a n i n d e x r e g i s t e r o p e r a n d ; for e x a m p l e , MOV A X , B X + S I r a t h e r t h a n MOV A X , [ B X + S I ] .
Compiler error 157: Cannot add or subtract relocatable symbols T h e o n l y a r i t h m e t i c o p e r a t i o n that c a n b e p e r f o r m e d o n a r e l o c a t a b l e s y m b o l i n a n a s s e m b l e r o p e r a n d is a d d i t i o n o r s u b t r a c t i o n o f a c o n s t a n t . V a r i a b l e s , p r o c e d u r e s , f u n c t i o n s , a n d l a b e l s are r e l o c a t a b l e s y m b o l s . A s s u m i n g that Var is v a r i a b l e a n d Const is a c o n s t a n t , t h e n t h e i n s t r u c t i o n s MOV
A X , Const+Const a n d MOV A X , Var+Const are v a l i d , b u t MOV A X , Var+Var is n o t .
Compiler error 158: Invalid register combination V a l i d index-register c o m b i n a t i o n s are [ BX ] , [ BP ] , [ S I ] , [ DI ] , [ B X + S I ] , [ BX+DI ] , [ B P + S I ] , a n d [ B P + D I ] . O t h e r i n d e x - r e g i s t e r c o m b i n a t i o n s , s u c h as [ A X ] , [ B P + B X ] , a n d [ S I + D X ] , are n o t a l l o w e d . L o c a l v a r i a b l e s are always a l l o c a t e d o n t h e stack a n d a c c e s s e d b y w a y o f t h e B P register. T h e a s s e m b l e r a u t o m a t i c a l l y a d d s [ BP ] i n r e f e r e n c e s t o s u c h v a r i a b l e s ; t h e r e f o r e , a c o n s t r u c t like L o c a l [ B X ] ( w h e r e L o c a l is a l o c a l v a r i a b l e ) a p p e a r s v a l i d , b u t it's n o t , b e c a u s e t h e final o p e r a n d w o u l d b e c o m e Local[BP+BX].
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s 62
Compiler error 159:286/287 instructions are not enabled U s e a { $ G + } c o m p i l e r d i r e c t i v e t o e n a b l e 286/287 o p c o d e s , b u t n o t i c e that t h e resulting c o d e cannot b e r u n o n 8086- a n d 8088-based machines.
Compiler error 160: Invalid symbol reference This symbol cannot b e accessed in a n assembler o p e r a n d . Possible causes are • Y o u ' r e trying t o a c c e s s a s t a n d a r d p r o c e d u r e , a s t a n d a r d f u n c t i o n , o r t h e Mem, MemW, MemL, Port, o r PortW s p e c i a l arrays i n a n a s s e m b l e r operand. • Y o u ' r e trying t o a c c e s s a string, f l o a t i n g - p o i n t , o r set c o n s t a n t i n a n assembler operand. • Y o u ' r e trying t o a c c e s s a n i n l i n e p r o c e d u r e o r f u n c t i o n i n a n a s s e m b l e r operand. • Y o u ' r e trying t o a c c e s s t h e ^Result s p e c i a l s y m b o l o u t s i d e a f u n c t i o n . • Y o u ' r e trying t o g e n e r a t e a s h o r t J M P i n s t r u c t i o n that j u m p s t o s o m e thing other than a label.
Compiler error 161: Code generation error T h e p r e c e d i n g s t a t e m e n t part c o n t a i n s a L O O P N E , L O O P E , L O O P , o r J C X Z i n s t r u c t i o n that c a n n o t r e a c h its target l a b e l .
Compiler error 162: ASM expected T h e c o m p i l e r e x p e c t s a n asm r e s e r v e d w o r d at this l o c a t i o n .
Compiler error 163: Duplicate dynamic method index This dynamic m e t h o d index has b e e n u s e d already by another m e t h o d .
Compiler error 164: Duplicate resource identifier T h i s r e s o u r c e file c o n t a i n s a r e s o u r c e w i t h a n a m e o r I D that h a s b e e n u s e d already by another resource.
5
626
Part I I I — R e f e r e n c e s
Compiler error 165: Duplicate or invalid export index T h e o r d i n a l n u m b e r s p e c i f i e d i n t h e i n d e x c a u s e is n o t w i t h i n t h e r a n g e 1..32767, or has b e e n u s e d already by another e x p o r t e d routine.
Compiler error 166: Procedure or function identifier expected T h e exports clause allows only procedures a n d functions to be exported.
Compiler error 167: Cannot export this symbol A p r o c e d u r e o r f u n c t i o n c a n n o t b e e x p o r t e d u n l e s s it w a s d e c l a r e d w i t h t h e export function.
Compiler error 168: Duplicate export name T h e n a m e specified in the n a m e clause has b e e n u s e d already by another exported routine.
Run-time Error Messages Error
Number
Error
Message
1
Invalid function n u m b e r
2
File n o t f o u n d
3
Path not f o u n d
4
T o o m a n y o p e n files
5
File a c c e s s d e n i e d
6
I n v a l i d file h a n d l e
12
I n v a l i d file a c c e s s c o d e
15
I n v a l i d drive n u m b e r
16
C a n n o t remove current directory
17
C a n n o t r e n a m e a c r o s s drives
100
Disk read error
K — T u r b o Pascal for W i n d o w s Error M e s s a g e s 62
Error
Number
Error
Message
101
Disk write error
102
File n o t a s s i g n e d
103
File n o t o p e n
104
File n o t o p e n for i n p u t
105
File n o t o p e n for o u t p u t
106
Invalid numeric format
200
Division by zero
201
Range check error
202
Stack overflow error
203
H e a p overflow error
204
Invalid pointer operation
205
Floating point overflow
206
Floating point underflow
207
I n v a l i d floating p o i n t o p e r a t i o n
210
O b j e c t n o t initialized
211
C a l l t o abstract m e t h o d
212
Stream registration error
213
Collection index out of range
214
C o l l e c t i o n overflow error
Run-time error 1: Invalid function number Y o u t r i e d t o call a n o n e x i s t e n t D O S f u n c t i o n .
Run-time error 2: File not found T h e r o u t i n e s Reset, Append, Rename, a n d Erase r e p o r t this e r r o r if t h e n a m e a s s i g n e d t o t h e file v a r i a b l e d o e s n ' t s p e c i f y a n e x i s t i n g file.
7
628
Part I I I — R e f e r e n c e s
Run-time error 3: Path not found T h e r o u t i n e s R e s e t , A p p e n d , R e w r i t e , Rename, a n d E r a s e r e p o r t this e r r o r if t h e n a m e a s s i g n e d t o t h e file v a r i a b l e is i n v a l i d o r s p e c i f i e s a n o n - e x i s t e n t subdirectory. T h e r o u t i n e s C h D i r , M k D i r , a n d RmDir r e p o r t this e r r o r if t h e p a t h is i n v a l i d o r if it s p e c i f i e s a n o n - e x i s t e n t s u b d i r e c t o r y .
Run-time error 4: Too many open files T h e r o u t i n e s R e s e t , R e w r i t e , a n d A p p e n d r e p o r t this e r r o r if t h e p r o g r a m h a s t o o m a n y o p e n files. D O S n e v e r a l l o w s m o r e t h a n 15 o p e n files p e r p r o c e s s . If y o u g e t this e r r o r w i t h less t h a n 15 o p e n files, t h e C O N F I G . S Y S file m i g h t n o t i n c l u d e a F I L E S = x x e n t r y (or x x m i g h t s p e c i f y t o o f e w files). Increase the n u m b e r xx to s o m e suitable value, b e t w e e n 20 a n d 30.
Run-time error 5: File access denied Reported
By
When
Problem
Occurs
Reset
F i l e M o d e a l l o w s writing, a n d t h e n a m e a s s i g n e d t o t h e file variable specifies a directory o r a reado n l y file.
Append
F i l e M o d e a l l o w s writing, a n d t h e n a m e a s s i g n e d t o t h e file variable specifies a directory o r a reado n l y file.
Rewrite
T h e directory is full, o r t h e n a m e a s s i g n e d t o t h e file variable specifies a directory o r a n e x i s t i n g read-only file.
Rename
T h e n a m e a s s i g n e d t o t h e file variable specifies a directory, o r t h e n e w n a m e s p e c i f i e s a n e x i s t i n g file.
Erase
T h e n a m e a s s i g n e d t o t h e file variable s p e c i f i e s a directory o r a read-only file.
MkDir
A file w i t h t h e s a m e n a m e exists in t h e p a r e n t directory, o r there is n o room in t h e p a r e n t directory, o r t h e p a t h s p e c i f i e s a d e v i c e .
RmDir
T h e directory isn't e m p t y , o r t h e p a t h d o e s n ' t specify a directory, o r t h e p a t h specifies t h e root directory.
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
Reported
By
When
Problem
Occurs
Read
( O n a t y p e d o r u n t y p e d file): T h e file is n o t o p e n for reading.
BlockRead
( O n a t y p e d o r u n t y p e d f i l e ) : T h e file is n o t o p e n for reading.
Write
( O n a t y p e d o r u n t y p e d f i l e ) : T h e file is n o t o p e n for writing.
BlockWrite
( O n a t y p e d o r u n t y p e d f i l e ) : T h e file is n o t o p e n for writing.
Run-time error 6: Invalidfilehandle T h i s e r r o r is r e p o r t e d if a n i n v a l i d file h a n d l e is p a s s e d t o a D O S s y s t e m c a l l . T h i s e r r o r s h o u l d n e v e r o c c u r ; if it d o e s , y o u k n o w that t h e file v a r i a b l e is s o m e h o w t r a s h e d .
Run-time error 12: Invalidfileaccess code Reset a n d Append r e p o r t this e r r o r ( o n a t y p e d o r u n t y p e d file) if t h e v a l u e o f F i l e M o d e is i n v a l i d .
Run-time error 15: Invalid drive number GetDir a n d ChDir r e p o r t this e r r o r if t h e d r i v e n u m b e r is i n v a l i d .
Run-time error 16: Cannot remove current directory RmDir r e p o r t s this e r r o r if t h e p a t h s p e c i f i e s t h e c u r r e n t d i r e c t o r y .
Run-time error 17: Cannot rename across drives Rename r e p o r t s this e r r o r if b o t h n a m e s a r e n o t o n t h e s a m e d r i v e .
Run-time error 100: Disk read error R e a d r e p o r t s this e r r o r o n a t y p e d file if y o u a t t e m p t t o r e a d p a s t t h e e n d o f t h e file.
629
630
Part I I I — R e f e r e n c e s
Run-time error 101: Disk write error Close, Write, Writeln, a n d Flush r e p o r t this e r r o r if t h e d i s k b e c o m e s f u l l .
Run-time error 102: File not assigned Reset,Rewrite,Append,Rename, a n d Erase r e p o r t this e r r o r if t h e file v a r i a b l e h a s n o t b e e n a s s i g n e d a n a m e t h r o u g h a call t o Assign.
Run-time error 103: File not open T h e f o l l o w i n g p r o c e d u r e s ( o r f u n c t i o n s ) r e p o r t this e r r o r if t h e file isn't o p e n : BlockRead BlockWrite Close Eof FilePos FileSize Flush Read Seek Write
Run-time error 104: File not open for input T h e f o l l o w i n g p r o c e d u r e s (or f u n c t i o n s ) r e p o r t this e r r o r o n a text file if t h e file isn't o p e n f o r i n p u t : Eof Eoln Read ReadLn SeekEof SeekEoln
Run-time error 105: File not open for output T h i s e r r o r o c c u r s if y o u try t o u s e s t a n d a r d i n p u t a n d o u t p u t f u n c t i o n s s u c h as Readln a n d Writeln w i t h o u t t h e Uses WinCRT; s t a t e m e n t . T o c o r r e c t this e r r o r , just a d d Uses WinCRT; t o y o u r p r o g r a m .
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
Run-time error 106: Invalid numeric format Read a n d Read I n r e p o r t this e r r o r if a n u m e r i c v a l u e r e a d f r o m a text file d o e s n ' t c o n f o r m to the proper numeric format.
Run-time error 200: Division by zero T h e p r o g r a m a t t e m p t e d t o d i v i d e a n u m b e r b y 0 d u r i n g a /, mod, o r d i v operation.
Run-time error 201: Range check error T h i s e r r o r is r e p o r t e d b y s t a t e m e n t s c o m p i l e d i n t h e { $ R + } state, w h e n o n e o f t h e f o l l o w i n g s i t u a t i o n s arises: • T h e i n d e x o f a n array w a s o u t o f r a n g e . • T h e p r o g r a m attempted to assign a n out-of-range value to a variable. • T h e p r o g r a m a t t e m p t e d t o p a s s a n o u t - o f - r a n g e v a l u e as a p a r a m e t e r t o a procedure or function.
Run-time error 202: Stack overflow error A n a p p l i c a t i o n r e p o r t s this e r r o r o n e n t r y t o a p r o c e d u r e o r f u n c t i o n c o m p i l e d i n t h e { $ S + } state w h e n t h e r e isn't e n o u g h stack s p a c e t o a l l o c a t e t h e subprogram's local variables. I n c r e a s e t h e size o f t h e stack w i t h t h e $M c o m p i l e r d i r e c t i v e . T h e S t a c k O v e r f l o w e r r o r c a n a l s o b e c a u s e d b y infinite r e c u r s i o n , o r b y a n a s s e m b l y l a n g u a g e p r o c e d u r e that d o e s n ' t m a i n t a i n t h e stack p r o p e r l y .
Run-time error 203: Heap overflow error New a n d GetMem r e p o r t this e r r o r w h e n t h e r e isn't e n o u g h free s p a c e i n t h e h e a p t o a l l o c a t e a b l o c k o f t h e r e q u e s t e d size.
Run-time error 204: Invalid pointer operation Dispose a n d FreeMem r e p o r t this e r r o r if t h e p o i n t e r is n i l o r if it p o i n t s t o a location outside the heap.
631
632
Part I I I — R e f e r e n c e s
Run-time error 205: Floating point overflow A floating-point o p e r a t i o n p r o d u c e d a n u m b e r t o o l a r g e f o r T u r b o Pascal (or t h e n u m e r i c c o p r o c e s s o r , if t h e r e is o n e ) t o h a n d l e .
Run-time error 206: Floating point underflow A
floating-point o p e r a t i o n p r o d u c e d a n u n d e r f l o w . T h i s e r r o r is r e p o r t e d o n l y if y o u a r e u s i n g a n u m e r i c c o p r o c e s s o r w i t h a c o n t r o l w o r d that u n m a s k s u n d e r f l o w e x c e p t i o n s . B y d e f a u l t , a n u n d e r f l o w c a u s e s a result o f z e r o t o b e r e t u r n e d .
Run-time error 207: Invalidfloatingpoint operation O n e o f the following
floating-point
errors o c c u r r e d :
• T h e real v a l u e p a s s e d toTruncorRound c o u l d n o t b e c o n v e r t e d t o a n i n t e g e r w i t h i n t h e Longint r a n g e ( - 2 1 4 7 4 8 3 6 4 8 t o 2 1 4 7 4 8 3 6 4 7 ) . • T h e a r g u m e n t p a s s e d t o t h e Sqrt f u n c t i o n w a s n e g a t i v e . • T h e a r g u m e n t p a s s e d t o t h e Ln f u n c t i o n w a s 0 o r n e g a t i v e . • A n 8 0 x 8 7 stack o v e r f l o w o c c u r r e d .
Run-time error 210: Object not initialized W i t h r a n g e - c h e c k i n g o n , y o u m a d e a call t o a n o b j e c t ' s virtual m e t h o d , b e f o r e t h e o b j e c t h a d b e e n initialized b y w a y o f a c o n s t r u c t o r c a l l .
Run-time error 211: Call to abstract method T h i s e r r o r is g e n e r a t e d b y t h e Abstract p r o c e d u r e i n t h e W O b j ects u n i t . It i n d i c a t e s that y o u r p r o g r a m t r i e d t o e x e c u t e a n abstract virtual method.
Run-time error 212: Stream registration error T h i s e r r o r is g e n e r a t e d b y t h e RegisterType p r o c e d u r e i n t h e WOb j ects u n i t . It i n d i c a t e s that o n e o f t h e f o l l o w i n g errors h a s o c c u r r e d : • T h e stream registration record d o e s n o t reside in the data segment. • T h e Ob j Type field o f t h e s t r e a m r e g i s t r a t i o n r e c o r d is 0 .
K — T u r b o Pascal f o r W i n d o w s Error M e s s a g e s
• T h e type has already b e e n registered. • A n o t h e r t y p e w i t h t h e s a m e Ob j T y p e v a l u e a l r e a d y e x i s t s .
Run-time error 213: Collection index out of range T h e i n d e x p a s s e d t o a T C o l l e c t i o n m e t h o d is o u t o f r a n g e .
Run-time error 214: Collection overflow error T h i s e r r o r is r e p o r t e d b y a T C o l l e c t i o n if a n a t t e m p t is m a d e t o a d d a n e l e m e n t w h e n the collection cannot be expanded.
633
L REFERENCE
WINDOW MANAGER INTERFACE PROCEDURES AND FUNCTIONS A l p h a b e t i c a l listing o f W i n d o w s M a n a g e r I n t e r f a c e p r o c e d u r e s a n d f u n c t i o n s :
Caret Clipboard Cursor Dialog-Box Display and Movement Error Hardware Hook Information
Input Menu Message Painting Property Scrolling System Window-Creation
Caret Procedures and Functions CreateCaret DestroyCaret GetCaretBlinkTime GetCaretPos
HideCaret SetCaretBlinkTime SetCaretPos ShowCaret
636
Part I I I — R e f e r e n c e s
CreateCaret procedure CreateCaret(Wnd: HWnd; ABitmap: HBitmap; Width, Height: Integer); C r e a t e s a n e w s h a p e f o r t h e s y s t e m caret. Parameters
Description
Wnd
O w n i n g w i n d o w o f t h e n e w caret
ABitmap
B i t m a p that d e f i n e s t h e caret; if 0 caret is b l a c k ; if 1 caret is g r a y
Width
Caret w i d t h (in logical units)
Height
Caret height (in logical units)
DestroyCaret procedure DestroyCaret; D e s t r o y s t h e c u r r e n t caret, frees it f r o m t h e o w n i n g w i n d o w , a n d r e m o v e s it f r o m t h e s c r e e n (if it is c u r r e n t l y v i s i b l e ) .
GetCaretBlinkrime function GetCaretBlinkTime: Word; G e t s caret b l i n k ( t i m e b e t w e e n flashes o f t h e c a r e t ) . Return Value: B l i n k rate (in m i l l i s e c o n d s ) .
GetCaretPos procedure GetCaretPos(var Point: TPoint); G e t s t h e c u r r e n t caret p o s i t i o n (in c l i e n t c o o r d i n a t e s ) . Parameter Point
Description R e c e i v i n g TPoint s t r u c t u r e
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
HideCaret procedure HideCaret(Wnd: HWnd); N o n d e s t r u c t i v e l y r e m o v e s t h e caret f r o m t h e d i s p l a y s c r e e n . Parameter Wnd
Description O w n i n g w i n d o w o f caret o r 0 if o w n i n g w i n d o w is i n c u r r e n t task
SetCaretBlinkTime procedure SetCaretBlinkTime(MSeconds: Word); S e t s t h e e l a p s e d t i m e b e t w e e n caret Parameter MSeconds
flashes.
Description B l i n k rate ( i n m i l l i s e c o n d s )
SetCaretPos procedure SetCaretPos(X, Y :
Integer);
M o v e s t h e caret t o t h e s p e c i f i e d (X, Y) p o s i t i o n . Parameter X, Y
Description N e w position (in logical coordinates)
ShowCaret procedure ShowCaret(Wnd: HWnd); S h o w s a caret that is o w n e d b y Wnd o n t h e d i s p l a y . Parameter Wnd
Description W i n d o w i d e n t i f i e r o r 0 f o r a w i n d o w i n t h e c u r r e n t task.
637
638
Part I I I — R e f e r e n c e s
Clipboard Procedures and Functions ChangeClipboardChain CloseClipboard EmptyClipboard EnumClipboardFormats GetClipboardData GetClipboardFormatName GetClipboardOwner GetClipboardViewer GetPriorityClipboardFormat IsClipboardFormatAvailable OpenClipboard RegisterClipboardFormat SetClipboardData SetClipboardViewer
ChangeClipboardChain function ChangeClipboardChain(Wnd, WndNext: HWnd): Bool; R e m o v e s Wnd f r o m t h e c h a i n o f c l i p b o a r d v i e w e r s a n d r e p l a c e s it w i t h WndNext. Parameters
Description
Wnd
W i n d o w to be removed from chain
WndNext
W i n d o w that f o l l o w s Wnd i n t h e c l i p b o a r d - v i e w e r c h a i n .
Return Value: N o n z e r o if t h e w i n d o w is f o u n d a n d r e m o v e d .
CloseClipboard function CloseClipboard: Bool; Closes the clipboard to allow the clipboard to be accessed by other applications. Return
Value:
N o n z e r o if c l i p b o a r d is c l o s e d ; e l s e 0.
EmptyClipboard function EmptyClipboard: Bool;
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
E m p t i e s t h e c l i p b o a r d a n d frees handles t o d a t a i n t h e c l i p b o a r d . O w n e r s h i p is a s s i g n e d t o t h e w i n d o w that has t h e c l i p b o a r d o p e n . Return Value: N o n z e r o if t h e c l i p b o a r d is e m p t i e d ; 0 if error.
EnumClipboardFofmats function EnumClipboardFormats(Format: Word): Word; E n u m e r a t e s list of available c l i p b o a r d formats. Parameter Format
Description K n o w n format or 0 for first format in list; t h e formats are s p e c i f i e d b y t h e cf _Clipboard formats.
Return Value: N e x t k n o w n c l i p b o a r d f o r m a t ; 0 if e n d o f f o r m a t list o r if c l i p b o a r d c l o s e d .
GetClipboardData function GetClipboardData(Format: Word): "["Handle; Gets clipboard data in a specified format. T h e clipboard controls the memory block. Parameter Format
returned
Description C l i p b o a r d d a t a format; one of t h e cf _ Clipboard formats' c o n s t a n t s
Return Value: M e m o r y b l o c k c o n t a i n i n g c l i p b o a r d d a t a ; 0 if error.
GetClipboardFormatName function GetClipboardFormatName(Format: Word; FormatName: PChar; MaxCount: Integer): Integer; G e t s a registered Parameters
f o r m a t n a m e from t h e c l i p b o a r d . Description
Format
C l i p b o a r d format; one of t h e cf _ Clipboard formats' constants
FormatName
Receiving buffer
MaxCount
Size o f buffer
639
640
Part I I I — R e f e r e n c e s
Return Value: A c t u a l l e n g t h o f c o p i e d string; 0 if i n v a l i d f o r m a t r e q u e s t e d .
GetClipboardOwner function GetClipboardOwner: HWnd; G e t s t h e w i n d o w that c u r r e n t l y o w n s t h e c l i p b o a r d . Return Value: O w n i n g w i n d o w ; 0 if n o o w n e r .
GetClipboardViewer function GetClipboardViewer: HWnd; G e t s t h e first w i n d o w i n t h e c l i p b o a r d - v i e w e r c h a i n . Return Value: W i n d o w c u r r e n t l y r e s p o n s i b l e f o r d i s p l a y i n g t h e c l i p b o a r d ; 0 if n o v i e w e r .
GetPriorityClipboardFormat function GetPriorityClipboardFormat(var Count: Integer): Integer;
PriorityList;
G e t s t h e first c l i p b o a r d f o r m a t i n PriorityList f o r which d a t a e x i s t s . Parameters
Description
PriorityList
I n t e g e r array c o n t a i n i n g c l i p b o a r d f o r m a t s i n p r i o r i t y o r d e r ; t h e f o r m a t s a r e c f _ Clipboard f o r m a t s
Count
S i z e o f PriorityList
Return Value: H i g h e s t p r i o r i t y f o r m a t i n list: - 1 if n o m a t c h ; 0 if t h e r e ' s n o d a t a i n t h e clipboard.
IsClipboardFormatAvailable function IsClipboardFormatAvailable(Format: Word): Bool; D e t e r m i n e s w h e t h e r d a t a i n t h e s p e c i f i e d f o r m a t is i n t h e c l i p b o a r d . Parameter Format
Description Registered clipboard format; o n e o f the c f formats' constants
Clipboard
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Return Value: N o n z e r o if d a t a available i n F o r m a t ; e l s e 0.
OpenClipboard function OpenClipboard(Wnd: HWnd): Bool; Opens the clipboard for exclusive use by an application. Parameter Wnd
Description Window identifier
Return Value: Nonzero if successful; 0 if Clipboard already opened by another application.
RegisterClipboardFormat function RegisterClipboardFormat(FormatName: PChar): Word; Registers a c l i p b o a r d f o r m a t , incrementing b e e n previously registered. Parameter FormatName
t h e f o r m a t ' s reference
c o u n t if it had
Description Format n a m e (null-terminated)
Return Value: R e g i s t e r e d f o r m a t identifier
($C000 t o $ F F F F ) if s u c c e s s f u l ; e l s e 0.
SetClipboardData function SetClipboardData(Format: Word; Mem: THandle): THandle; S e t s a d a t a handle to the clipboard in Format. U s u a l l y the d a t a handle before the f u n c t i o n returns. Parameters
Description
Format
O n e of the cf _ Clipboard formats' constants
Mem
H a n d l e to g l o b a l m e m o r y b l o c k c o n t a i n i n g d a t a in format or 0 for wm_RenderFormat m e s s a g e
Return Value: D a t a identifier assigned b y Clipboard.
is freed
641
642
Part I I I — R e f e r e n c e s
SetClipboardViewer function SetClipboardViewer(Wnd: HWnd): HWnd; A d d s a w i n d o w t o t h e c h a i n o f w i n d o w s t o b e n o t i f i e d b y a wm_DrawClipboard message whenever the clipboard changes. Parameter Wnd
Description W i n d o w identifier
Return Value: Next w i n d o w in clipboard-viewer chain.
Cursor Procedures and Functions ClipCursor CreateCursor DestroyCursor GetCursorPos LoadCursor SetCursor SetCursorPos ShowCursor
ClipCursor procedure ClipCursor(Rect: LPRect); K e e p s c u r s o r w i t h i n Rect. I f Rect is n i l t h e c u r s o r is u n b o u n d e d . Parameter Rect
Description B o u n d i n g TRect i n s c r e e n c o o r d i n a t e s
CreateCursor function CreateCursor(Instance: THandle; Xhotspot, Yhotspot, Width, Height: Integer; ANDBitPlane, XORBitPlane: Pointer): HCursor; Creates a cursor.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
643
Description
Instance
M o d u l e instance creating the cursor
Xhotspot, Yhotspot
Position o f cursor hotspot
Width
C u r s o r width (in pixels)
Height
C u r s o r h e i g h t (in p i x e l s )
ANDBitPlane
Array o f b y t e s c o n t a i n i n g AND m a s k
XORBitPlane
Array o f b y t e s c o n t a i n i n g XOR m a s k
Return Value: C u r s o r i d e n t i f i e r if s u c c e s s f u l ; e l s e 0.
DestroyCursor function D e s t r o y C u r s o r ( C u r s o r :
HCursor): Bool;
D e s t r o y s c u r s o r a n d frees a s s o c i a t e d m e m o r y . Parameter Cursor
Description C u r s o r identifier
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
GetCursorPos procedure G e t C u r s o r P o s ( v a r
Point: TPoint);
Gets the screen coordinates o f the cursor's current position. Parameter Point
Description R e c e i v i n g TPoint s t r u c t u r e
LoadCursor function LoadCursor(Instance: THandle; CursorName: PChar): HCursor; Loads the n a m e d cursor resource.
644
Part I I I — R e f e r e n c e s
Parameters
Description
Instance
M o d u l e i n s t a n c e w h o s e e x e c u t a b l e file c o n t a i n s t h e cursor or 0 for predefined cursor
CursorName
String (null-terminated) o r integer I D n a m e o r a pred e f i n e d c u r s o r , s p e c i f i e d w i t h o n e o f t h e idc_ Standard c u r s o r I D s ' c o n s t a n t s .
Return Value: C u r s o r i d e n t i f i e r if s u c c e s s f u l ; 0 if c u r s o r is n o t f o u n d ; u n d e f i n e d if n o t a c u r s o r resource.
SetCursor function SetCursor(Cursor: HCursor): HCursor; Sets the cursor shape t o the specified cursor resource. Parameter Cursor
Description C u r s o r resource identifier (previously returned by LoadCursor)
Return Value: P r e v i o u s c u r s o r s h a p e ; 0 if n o p r e v i o u s c u r s o r .
SetCursorPos procedure SetCursorPos(X, Y: Integer); M o v e s t h e c u r s o r t o t h e s p e c i f i e d s c r e e n c o o r d i n a t e s . T h e p o s i t i o n is a d j u s t e d if it lies o u t s i d e t h e ClipCursor r e c t a n g l e . Parameter X, Y
Description N e w p o s i t i o n (in s c r e e n c o o r d i n a t e s ) o f t h e c u r s o r
ShowCursor function ShowCursor(Show: Bool): Integer; S h o w s t h e c u r s o r if its d i s p l a y c o u n t (initially set t o 0 ) is g r e a t e r t h a n o r e q u a l t o 0 . O t h e r w i s e t h e c u r s o r is h i d d e n .
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameter Show
Description N o n z e r o to increment display c o u n t or 0 to decrement display c o u n t
Return Value: N e w display count.
Dialog-Box Procedures and Functions CheckDlgButton CheckRadioButton CreateDialog CreateDialogIndirect CreateDialoglndirectParam CreateDialogParam DefDlgProc DialogBox DialogBoxIndirect DialogBoxIndirectParam DialogBoxParam DlgDirList DlgDirListComboBox DlgDirSelect DlgDirSelectComboBox EndDialog GetDialogBaseUnits GetDlgCtrllD GetDlgltem GetDlgltemlnt GetDlgltemText GetNextDlgGroupItem GetNextDlgTabltem IsDialogMessage IsDlgButtonChecked MapDialogRect SendDlgltemMessage SetDlgltemlnt SetDlgltemText
645
6 4 6 Part III—References
CheckDlgButton procedure CheckDlgButton(Dig: HWnd; IDButton: Integer; Check: Word); Places or removes a check mark from a button control or changes the state of a 3-button control. Parameters
Description
Dig
Dialog box that contains the button
IDButton
Button control to be modified
Check
R e m o v e d (0), checked (1), grayed (2)
CheckRadioButton procedure CheckRadioButton(Dlg: HWnd; IDFirstButton, IDLastButton, IDCheckButton: Integer); Checks IDCheckButton and removes the check mark from the group of radio buttons specified by IDFirstButton and IDLastButton. Parameters
Description
Dig
Dialog box
IDFirstButton
ID offirstradio button in group
IDLastButton
ID of last radio button in group
IDCheckButton
ID of radio button to check
CreateDialog function (Instance: THandle; TemplateName: PChar; WndParent: HWnd DialogFunc: TFarProc): HWnd; Creates a modeless dialog box defined by TemplateName dialog box resource. Parameters
Description
Instance
Module instance whose executablefilecontains the dialog box resource
TemplateName
Dialog box resource n a m e (null-terminated)
WndParent
Parent w i n d o w of the dialog box
DialogFunc
Dialog function procedure-instance address or nil if class defined
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
647
Return Value: D i a l o g b o x w i n d o w h a n d l e if s u c c e s s f u l ; e l s e 0.
CreateDialoglndirect function CreateDialoglndirect(Instance: THandle; DialogTemplate: PChar; Parent: HWnd; DialogFunc: TFarProc): HWnd; Creates a modeless dialog b o x defined by dialog template. Parameters
Description
Instance
M o d u l e instance
DialogTemplate
Structure containing dialog b o x template
WndParent
O w n i n g w i n d o w o f the dialog b o x
DialogFunc
Dialog callback function procedure-instance address
Return Value: D i a l o g b o x w i n d o w h a n d l e if s u c c e s s f u l ; e l s e 0.
CreateDMoglndirectParam function CreateDialogIndirectParam(Instance: THandle; v a r DialogTemplate; WndParent: HWnd; DialogFunc: TFarProc; InitParam: Longint): HWnd; C r e a t e s t h e m o d e l e s s d i a l o g b o x d e f i n e d b y d i a l o g t e m p l a t e . It differs f r o m CreateDialoglndirect b e c a u s e it a l l o w s y o u t o p a s s a p a r a m e t e r , InitParam, t o t h e callback f u n c t i o n . Parameters
Description
Instance
M o d u l e instance
DialogTemplate
Structure containing dialog b o x template
WndParent
O w n i n g w i n d o w of the dialog b o x
DialogFunc
D i a l o g f u n c t i o n p r o c e d u r e - i n s t a n c e a d d r e s s , o r n i l if class d e f i n e d
InitParam
V a l u e p a s s e d t o d i a l o g f u n c t i o n (lParam o f wm_I nit Dialog m e s s a g e ) w h e n t h e d i a l o g b o x is created
Return Value: D i a l o g b o x w i n d o w h a n d l e if s u c c e s s f u l ; e l s e 0.
648
Part III—References
CreateDialogParam f u n c t i o n C r e a t e D i a l o g P a r a m ( I n s t a n c e : THandle; TemplateName: W n d P a r e n t : HWnd; D i a l o g F u n c : T F a r P r o c ; I n i t P a r a m : L o n g i n t ) : HWnd; Creates a modeless dialog b o x defined by TemplateName.
Parameter
Description
Instance
M o d u l e instance w h o s e executable file contains the dialog b o x template
TemplateName
Dialog b o x template n a m e (null-terminated)
Parent
O w n i n g w i n d o w o f the dialog b o x
DialogFunc
D i a l o g function procedure-instance address, o r nil if class defined
InitParam
Value passed to dialog function (lParam o f w m l n i t D i a l o g message) w h e n the dialog b o x is created
Return Value: Dialog b o x w i n d o w handle if successful; else 0.
DefDlgProc function lParam:
DefDlgProc(Dig: Longint):
HWnd; M s g , wParam: Word;
Longint;
Supplies default processing for dialogs with a private w i n d o w class.
Parameters
Description
Dig
Dialog b o x identifier
Msg
Message n u m b e r
wParam
M e s s a g e - d e p e n d e n t information
lParam
Message-dependent information
Return Value: Result o f the message processing.
PChar
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
DialogBox function DialogBox(Instance: THandle; TemplateName: PChar; WndParent: HWnd; DialogFunc: TFarProc): Integer; C r e a t e s a m o d a l d i a l o g b o x d e f i n e d b y TemplateName a n d s e n d s wm_I nit Dialog before displaying the dialog. Parameters
Description
Instance
M o d u l e i n s t a n c e w h o s e e x e c u t a b l e file c o n t a i n s t h e dialog b o x template
TemplateName
Dialog b o x template n a m e (null-terminated)
WndParent
Owning window
DialogFunc
Dialog callback function procedure-instance address
Return Value: EndDialog nResult p a r a m e t e r ; - 1 if d i a l o g c o u l d n o t b e c r e a t e d .
DialogBoxIndirect function DialogBoxIndirect(Instance,
DialogTemplate:THandle;
WndParent: HWnd; DialogFunc: TFarProc): Integer; Creates the modal dialog b o x defined by dialog template, and sends wmlnitDialog before displaying the dialog. Parameters
Description
Instance
M o d u l e i n s t a n c e w h o s e e x e c u t a b l e file c o n t a i n s t h e dialog b o x template
DialogTemplate
Global memory block containing dialog template structure
WndParent
Owning window
DialogFunc
Dialog callback function procedure-instance address
Return Value: EndDialog nResult p a r a m e t e r ; - 1 if d i a l o g c o u l d n o t b e c r e a t e d .
continues
649
650
Part III—References
DialogBoxIndirectParam function
DialogBoxIndirectParam(Instance,
WndParent:
HWnd; D i a l o g F u n c :
TFarProc;
DialogTemplate: InitParam:
THandle;
Longint):
Integer
Creates the modal dialog b o x defined by dialog template and sends w m _ I n i t D i a l o g before displaying the dialog. Also, D i a l o g B o x I n d i r e c t P A r a m a l l o w s y o u t o s e n d a n initial p a r a m e t e r t o t h e c a l l b a c k f u n c t i o n . Parameters
Description
Instance
M o d u l e instance
w h o s e e x e c u t a b l e file c o n t a i n s t h e
dialog b o x template DialogTemplate
Global memory block containing dialog template structure
WndParent
Owning window
DialogFunc
Dialog function procedure-instance address
InitParam
P a s s e d in l P a r a m o f w m _ I n i t D i a l o g m e s s a g e
Return Value: E n d D i a l o g n R e s u l t parameter; - 1 if d i a l o g c o u l d n o t b e c r e a t e d .
DialogBoxParam function
DialogBoxParam(Instance:
Parent:
HWnd; D i a l o g F u n c :
THandle;
TFarProc;
TemplateName:
InitParam:
PChar;
Longint):
Integer;
Creates the m o d a l dialog b o x defined by T e m p l a t e N a m e and sends wm_I n i t D i a l o g b e f o r e d i s p l a y i n g t h e d i a l o g . A l s o a l l o w s y o u t o s e n d a n initial parameter to the callback function. Parameters
Description
Instance
M o d u l e instance w h o s e e x e c u t a b l e file c o n t a i n s t h e dialog b o x template
TemplateName
Dialog b o x template n a m e (null-terminated)
Parent
Owning window
DialogFunc
Dialog function procedure-instance address
InitParam
P a s s e d in l P a r a m o f w m _ I n i t D i a l o g m e s s a g e
Return Value: E n d D i a l o g n R e s u l t parameter; - 1 if d i a l o g c o u l d n o t b e c r e a t e d .
L—Window Manager Interface Procedures and Functions
DlgDMist function DlgDirList(Dig: HWnd; PathSpec: PChar; IDListBox, IDStaticPath: Integer; Filetype: Word): Integer; Fills IDListBox with a file or directory listing that matches the path name specified by PathSpec. Parameter
Description
Dig
Dialog box containing IDListBox
PathSpec
Path name string (null-terminated)
IDListBox
List-box control ID
IDStaticPath
Static-text control ID to display current drive and directory
Filetype
$0000 (read/write), $0001 (read-only), $0002 (hidden), $0004 (system), $0010 (subdirectories), $0020 (archives), $2000 (lb_Dir), $4000(drives), $8000 (exclusive)
Return
Value:
Nonzero if listing made; 0 if invalid search path.
DlgDirListComboBox function DlgDirListComboBox(Dig: HWnd; PathSpec: PChar; IDComboBox, IDStaticPath: Integer; Filetype: Word): Integer; Fills IDComboBox with afileor directory listing that matches the path name specified by PathSpec. Parameters
Description
Dig
Dialog box containing IDComboBox
PathSpec
Path name string (null-terminated)
IDComboBox
Combo box control ID
IDStaticPath
Static-text control ID to display current drive and directory
Filetype
$0000 (read/write), $0001 (read-only), $0002 (hidden), $0004 (system), $0010 (subdirectories), $0020 (archives), $2000 (lb_Dir), $4000(drives), $8000 (exclusive)
Return
Value:
Nonzero if listing made; 0 if invalid search path.
651
652
Part I I I — R e f e r e n c e s
DlgDirSelect function DlgDirSelect(Dig: HWnd; Str: PChar; IDListBox: Integer): Bool; G e t s c u r r e n t list-box s e l e c t i o n a n d fills Str. Parameter
Description
Dig
D i a l o g b o x c o n t a i n i n g IDListBox
Str
Path n a m e buffer
IDListBox
List-box control I D
Return Value: N o n z e r o if c u r r e n t s e l e c t i o n is a d i r e c t o r y ; e l s e 0.
DlgDirSelectComboBox function DlgDirSelectComboBox(Dig: IDComboBox: Integer): Bool;
HWnd; Str: PChar;
G e t s c u r r e n t c o m b o b o x s e l e c t i o n , f r o m a s i m p l e c o m b o b o x (cbs_Simple) o n l y , a n d fills Str. Parameters
Description
Dig
D i a l o g b o x c o n t a i n i n g IDComboBox
Str
Path n a m e buffer
IDComboBox
C o m b o b o x control I D
Return Value: N o n z e r o if c u r r e n t s e l e c t i o n is a d i r e c t o r y ; e l s e 0.
DlgDirSelect function DlgDirSelect(Dig: HWnd; Str: PChar; IDListBox: Integer): Bool; G e t s c u r r e n t list-box s e l e c t i o n a n d fills Str. Parameters
Description
Dig
D i a l o g b o x c o n t a i n i n g IDListBox
Str
Path n a m e buffer
IDListBox
List-box control I D
Return
Value:
N o n z e r o if c u r r e n t s e l e c t i o n is a d i r e c t o r y ; e l s e 0.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
DlgDirSelectComboBox function DlgDirSelectComboBox(Dig: IDComboBox: Integer): Bool;
HWnd; Str: PChar;
G e t s c u r r e n t c o m b o b o x s e l e c t i o n , f r o m a s i m p l e c o m b o b o x (cbs_Simple) o n l y , a n d fills Str. Parameters
Description
Dig
D i a l o g b o x c o n t a i n i n g IDComboBox
Str
Path n a m e buffer
IDComboBox
C o m b o b o x control I D
Return Value: N o n z e r o if c u r r e n t s e l e c t i o n is a d i r e c t o r y ; e l s e 0.
EndDialog procedure EndDialog(Dig: HWnd; Result: Integer); T e r m i n a t e s a m o d a l d i a l o g b o x . T h e v a l u e s p e c i f i e d b y R e s u 11 is r e t u r n e d t o t h e c r e a t i n g DialogBox f u n c t i o n . Parameters
Description
Dig
Dialog to b e destroyed
Result
Return value
GetDialogBaseUnits function GetDialogBaseUnits: Longint; Gets dialog base units. T h e base width represents the average system font w i d t h . T h e d i a l o g u n i t is U a n d V s t h e r e t u r n e d b a s e w i d t h a n d h e i g h t u n i t , respectively. 1
Return Value: H e i g h t (in p i x e l s ) , b a s e u n i t i n h i g h w o r d ; w i d t h ( i n p i x e l s ) , b a s e u n i t i n l o w word.
653
654
Part III—References
GetDlgCtrllD function
GetDlgCtrlID(Wnd:
HWnd):
Integer;
G e t s a control w i n d o w ' s I D value. Parameter
Description
Wnd
Control
Return Value: C o n t r o l ' s numeric identifier;
identifier
0 if error.
GetDlgltem function
GetDlgItem(Dlg:
G e t s a control handle Parameters
HWnd; I D D l g l t e m :
Integer):
HWnd;
contained in t h e specified dialog b o x . Description
Dig
D i a l o g b o x containing t h e control
IDDlgltem
Control ID
Return Value: C o n t r o l identifier;
0 if the specified control doesn't exist.
GetDlgltemlnt function
GetDlgltemlnt(Dig:
Translate:
LPBool;
Signed:
HWnd; I D D l g l t e m : Bool):
Integer;
Word;
Translates a control's text, in a dialog b o x , into an integer
value. Preceding
spaces are stripped. Parameter
Description
Dig
Dialog box
IDDlgltem
Item I D
Translate
Returned B o o l e a n value; 0 if translation error
Return Value: Translated value.
identifier
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
655
GetDlgltemText f u n c t i o n G e t D l g l t e m T e x t ( D i g : HWnd; I D D l g l t e m : S t r : PChar; MaxCount: I n t e g e r ) : I n t e g e r ;
Integer;
G e t s a control's text. Parameters
Description
Dig
D i a l o g b o x identifier
IDDlgltem
Item I D
Str
Buffer to receive
MaxCount
Size o f buffer
text
Return Value: N u m b e r o f characters c o p i e d .
GetNextDlgGroupItem function GetNextDlgGroupItem(Dlg: P r e v i o u s : B o o l ) : HWnd;
HWnd; C t r l :
HWnd;
G e t s the next o r previous w s G r o u p style control from C t r l . T h e search is cyclical. Parameters
Description
Dig
D i a l o g b o x identifier
Ctrl
Search start control identifier
Previous
Z e r o to search for previous control o r n o n z e r o to search for next
Return
Value:
C o n t r o l identifier.
GetNextDlgTabltem function
GetNextDlgTabItem(Dlg:
HWnd; C t r l :
HWnd; P r e v i o u s :
Bool):
G e t s the next o r previous w s _ T a b S t o p style control f r o m C t r l . T h e search is cyclical.
HWnd;
656
Part I I I — R e f e r e n c e s
Parameters
Description
Dig
D i a l o g b o x identifier
Ctrl
S e a r c h start c o n t r o l i d e n t i f i e r
Previous
Z e r o to search for previous control o r n o n z e r o to search for n e x t
Return Value: C o n t r o l identifier.
IsDialogMessage function IsDialogMessage(Dig: HWnd; var Msg: TMsg): Bool; D e t e r m i n e s a n d p r o c e s s e s m e s s a g e s for m o d e l e s s d i a l o g b o x e s , c o n v e r t i n g keyboard messages into c o m m a n d messages. Parameters
Description
Digs
D i a l o g b o x identifier
Msg
TMsg s t r u c t u r e
Return Value: N o n z e r o if Msg p r o c e s s e d (TranslateMessage s h o u l d n ' t b e s e n t m e s s a g e s ) ; e l s e 0.
a n d DispatchMessage
IsDlgButtonChecked function IsDlgButtonChecked(Dlg: HWnd; IDButton: Integer): Word; D e t e r m i n e s w h e t h e r b u t t o n c o n t r o l is c h e c k e d . Parameters
Description
Dig
D i a l o g b o x identifier
IDButton
Button control I D
Return
Value:
N o n z e r o if c h e c k e d ; e l s e 0. F o r 3-state b u t t o n : g r a y e d (2), c h e c k e d (1), o r 0.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
MapDialogRect procedure MapDialogRect(Dig: HWnd; var Rect: TRect); C o n v e r t s d i a l o g b o x u n i t s i n Rect t o s c r e e n u n i t s . Parameters
Description
Dig
D i a l o g b o x identifier
Rect
TRect structure
SendDlgltemMessage function SendDlgItemMessage(Dlg: Msg,
HWnd; IDDlgltem:
Integer;
wParam: Word; lParam: Longint): Longint;
S e n d s a m e s s a g e t o a d i a l o g b o x c o n t r o l s p e c i f i e d b y IDDlgltem. T h e f u n c t i o n r e t u r n s after t h e m e s s a g e is p r o c e s s e d . Parameters
Description
Dig
D i a l o g b o x identifier
IDDlgltem
Integer I D o f destination dialog item
Msg
Message type
wParam
Additional message information
lParam
Additional message information
Return Value: V a l u e r e t u r n e d b y c o n t r o l ' s w i n d o w f u n c t i o n ; 0 if i n v a l i d IDDlgltem.
SetDlgltemlnt procedure SetDlgltemlnt(Dig: HWnd; IDDlgltem: Value: Word; Signed: Bool);
Integer;
S e t s t h e text o f a d i a l o g b o x c o n t r o l t o t h e c o n v e r t e d string v a l u e s p e c i f i e d b y Value.
657
658
Part I I I — R e f e r e n c e s
Parameters
Description
Dig
D i a l o g b o x identifier
IDDlgltem
Control's integer I D
Value
Set value
Signed
N o n z e r o if V a l u e is s i g n e d
SetDlgltemText procedure SetDlgltemText(Dig: HWnd; IDDlgltem: Integer; Str: PChar); S e t s t h e c a p t i o n o r text of a d i a l o g b o x c o n t r o l t o t h e v a l u e s p e c i f i e d b y Str. Parameters
Description
Dig
D i a l o g b o x identifier
IDDlgltem
Control's integer I D
Str
String (null-terminated)
Display and Movement Procedures and Functions ArrangeIconicWindows BeginDeferWindowPos BringWindowToTop CloseWindow DeferWindowPos EndDeferWindowPos GetClientRect GetWindowRect GetWindowText GetWindowTextLength Islconic IsWindowVisible IsZoomed MoveWindow Openlcon SetWindowPos SetWindowText ShowOwnedPopups ShowWindow
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
ArrangelconicWindows function ArrangeIconicWindows(Wnd: HWnd): Word; A r r a n g e s icons
in a n MDI c l i e n t w i n d o w o r icons o n t h e d e s k t o p w i n d o w .
Parameters Wnd
Description Parent w i n d o w
Return Value: H e i g h t o f o n e row o f icons;
0 if n o
identifier
icons.
BeginDefer^lndowPos function BeginDeferWindowPos(NumWindows:
Integer): THandle;
Allocates m e m o r y for multiple window-position data structure. Parameters NumWindows
Description Initial n u m b e r o f w i n d o w s w i t h p o s i t i o n information
that
needs to b e stored. Return Value: Window-position
structure
identifier.
BrmgWmdowToTop procedure BringWindowToTop(Wnd:
HWnd);
Activates a n d b r i n g s Wnd t o t o p o f a stack o f o v e r l a p p i n g w i n d o w s . Parameters Wnd
Description P o p - u p or child w i n d o w
CloseWindow procedure CloseWindow(Wnd: HWnd); M i n i m i z e s Wnd. I c o n s f o r o v e r l a p p e d w i n d o w s are m o v e d into t h e icon area o f the screen. Parameters Wnd
Description Window
to be minimized
659
660
Part I I I — R e f e r e n c e s
DeferWindowPos function DeferWindowPos(WinPosInfo: THandle; Wnd, WndlnsertAfter: HWnd; X, Y, cX, cY: Integer; Flags: Word): THandle; U p d a t e s WinPosInf o f o r t h e w i n d o w i d e n t i f i e d b y Wnd. Parameters
Description
WinPosInfo
Multiple w i n d o w - p o s i t i o n data structure identifier
Wnd
U p d a t e i n f o r m a t i o n is s t o r e d r e g a r d i n g this w i n d o w
WndlnsertAfter
Wnd is i n s e r t e d after this w i n d o w
X, Y
W i n d o w s upper-left corner position
cX
Window's n e w width
cY
Window's n e w height
Flags
O n e o f t h e swp_ Set w i n d o w p o s i t i o n
Return
flags
Value:
U p d a t e d multiple window-position data structure.
EndDeferWindowPos procedure EndDeferWindowPos(WinPosInfo:
THandle);
I n a s i n g l e s c r e e n - r e f r e s h c y c l e , EndDef erWindowPos u p d t a e s t h e size a n d position of o n e or more windows. Parameters WinPosInfo
Description Multiple w i n d o w data structure containing u p d a t e information for multiple windows
GetClientRect procedure GetClientRect(Wnd: HWnd; var Rect: TRect); G e t s a w i n d o w ' s client coordinates. Parameters
Description
Wnd
W i n d o w identifier
Rect
TRect t o r e c e i v e c l i e n t c o o r d i n a t e s
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
GetWindowRect procedure GetWindowRect(Wnd: HWnd; var Rect: TRect); G e t s t h e d i m e n s i o n s o f a w i n d o w ' s b o u n d i n g r e c t a n g l e i n t o Rect ( i n s c r e e n coordinates). Parameters
Description
Wnd
W i n d o w identifier
Rect
R e c e i v i n g TRect s t r u c t u r e
GetWindowText function GetWindowText(Wnd: HWnd; Str: PChar; MaxCount: Integer): Integer; C o p i e s w i n d o w ' s c a p t i o n o r a c o n t r o l ' s text i n t o Str. Parameters
Description
Wnd
W i n d o w o r control identifier
Str
R e c e i v i n g string b u f f e r
MaxCount
Size o f Str
Return Value: N u m b e r o f b y t e s c o p i e d ; 0 if n o text.
GetWIndowTextLength function GetWindowTextLength(Wnd: HWnd): Integer; G e t s a w i n d o w ' s c a p t i o n o r a c o n t r o l ' s text l e n g t h . Parameters Wnd
Description W i n d o w o r control identifier
Return Value: Text length.
Islconic function IsIconic(Wnd: HWnd): Bool; D e t e r m i n e s w h e t h e r a w i n d o w is i c o n i c ( m i n i m i z e d ) .
661
662
Part I I I — R e f e r e n c e s
Parameters Wnd
Description W i n d o w identifier
Return Value: N o n z e r o if m i n i m i z e d ; e l s e 0.
IsWindowVisible function IsWindowVisible(Wnd: HWnd): Bool; D e t e r m i n e s w h e t h e r ShowWindow h a s m a d e a w i n d o w v i s i b l e . Parameters Wnd Return
Description W i n d o w identifier
Value:
N o n z e r o if w i n d o w exists o n - s c r e e n ( e v e n if it is c o v e r e d ) ; e l s e 0.
IsZoomed function IsZoomed(Wnd: HWnd): Bool; D e t e r m i n e s w h e t h e r a w i n d o w is m a x i m i z e d . Parameters Wnd
Description W i n d o w identifier
Return Value: N o n z e r o if m a x i m i z e d ; e l s e 0.
MoveWindow procedure MoveWindow(Wnd: HWnd; X, Y, Width, Height: Integer; Repaint: Bool); S e n d s a wm_Size m e s s a g e t o a w i n d o w . Width a n d Height v a l u e s p a s s e d w i t h wm_Size a r e t h o s e o f t h e c l i e n t a r e a . Parameters
Description
Wnd
P o p - u p o r child w i n d o w identifier
X, Y
N e w upper-left corner o f w i n d o w
Width
N e w window width
Height
N e w w i n d o w height
Repaint
N o n z e r o t o r e p a i n t w i n d o w after m o v i n g
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Openlcon function Openlcon(Wnd: HWnd): Bool; R e s t o r e s a m i n i m i z e d w i n d o w t o its o r i g i n a l size a n d p o s i t i o n . Parameters Wnd Return
Description W i n d o w identifier
Value:
N o n z e r o if s u c c e s s f u l ; e l s e 0.
SetWindowPos procedure SetWindowPos(Wnd, WndlnsertAfter: HWnd; X , Y , c x , c y : Integer; Flags: Word); C h a n g e s t h e size, position, a n d ordering o f a w i n d o w . Parameters
Description
Wnd
W i n d o w identifier
WndlnsertAfter
P r e c e d i n g w i n d o w i n w i n d o w m a n a g e r ' s list
X, Y
Upper-left corner
cx
N e w window width
cy
N e w w i n d o w height
Flags
O n e o f t h e swp_ Set w i n d o w - p o s i t i o n
flags
SetWindowText procedure SetWindowText(Wnd: HWnd; Str: PChar); S e t s t h e c a p t i o n title f o r a w i n d o w o r text o f a c o n t r o l w i t h Str. Parameters
Description
Wnd
W i n d o w o r control identifier
Str
String (null-terminated)
ShowOwnedPopups procedure ShowOwnedPopups(Wnd: HWnd; Show: Bool); S h o w s o r h i d e s , as s p e c i f i e d b y Show, all p o p - u p w i n d o w s a s s o c i a t e d w i t h t h e specified w i n d o w .
663
664
Part I I I — R e f e r e n c e s
Parameters
Description
Wnd
W i n d o w identifier
Show
N o n z e r o t o s h o w all h i d d e n p o p u p s o r 0 t o h i d e all visible p o p - u p s
ShowWindow function ShowWindow(Wnd: HWnd; CmdShow: Integer): Bool; S h o w s o r h i d e s a w i n d o w s p e c i f i e d b y CmdShow. Parameters
Description
Wnd
W i n d o w identifier
CmdShow
O n e of t h e sw_ Show w i n d o w c o n s t a n t s
Return Value: N o n z e r o if w i n d o w w a s p r e v i o u s l y v i s i b l e ; 0 if w i n d o w w a s p r e v i o u s l y h i d d e n .
Error Procedures and Functions FlashWindow MessageBeep MessageBox
FlashWindow function FlashWindow(Wnd: HWnd; Invert: Bool): Bool; F l a s h e s a w i n d o w o r i c o n a n d inverts a n o p e n w i n d o w ' s active s t a t u s . Parameters
Description
Wnd
W i n d o w to b e flashed
Invert
N o n z e r o t o flash o r 0 t o r e t u r n t o o r i g i n a l state ( i g n o r e d for icons)
Return
Value:
N o n z e r o if w i n d o w w a s active p r e v i o u s t o call; e l s e 0.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
MessageBeep procedure MessageBeep(BeepType: Word); B e e p s t h e system speaker. Parameters BeepType
Description Set to 0
MessageBox function MessageBox(Parent: HWnd; Txt, Caption: PChar; TextType: Word):
Integer;
Creates a n d displays a dialog b o x containing t h e specified message a n d caption a n d a n y p r e d e f i n e d i c o n s a n d p u s h - b u t t o n as s p e c i f i e d b y TextType. Parameters
Description
Parent
O w n i n g window of message b o x
Txt
Message t o display (null-terminated)
Caption
D i a l o g - b o x c a p t i o n ( n u l l - t e r m i n a t e d ) o r n i l f o r "Error"
TextType
O n e o r a c o m b i n a t i o n o f t h e m b _ M e s s a g e b o x flags' constants
Return Value: O n e o f t h e I D d i a l o g - b o x c o m m a n d I D s if s u c c e s s f u l ; 0 if t h e r e ' s n o t e n o u g h m e m o r y t o create a n d display message b o x .
Hardware Procedures and Functions EnableHardwarelnput GetAsyncKeyState GetlnputState GetKeyboardState GetKeyNameText GetKeyState GetKBCodePage OemKeyScan SetKeyboardState MapVirtualKey VkKeyScan
665
666
Part I I I — R e f e r e n c e s
EnableHardwarelnput function EnableHardwarelnput(Enablelnput:
Bool): Bool;
D i s a b l e s m o u s e a n d k e y b o a r d i n p u t , s a v i n g o r d i s c a r d i n g i n p u t as s p e c i f i e d b y Enablelnput. Parameters Enablelnput
Description N o n z e r o t o save i n p u t ; 0 t o d i s c a r d i n p u t
Return Value: N o n z e r o ( t h e d e f a u l t ) if i n p u t w a s p r e v i o u s l y e n a b l e d ; e l s e 0.
GetAsyncKeyState function GetAsyncKeyState(Key:
Integer): Integer;
D e t e r m i n e s t h e state o f a virtual k e y . Parameters Key
Description Virtual-key c o d e
Return Value: Key is d o w n if h i g h - o r d e r bit is 1.
GetlnputState function GetlnputState: Bool; Determines whether the system q u e u e currently contains m o u s e , keyboard, or timer events. Return Value: N o n z e r o if i n p u t d e t e c t e d ; e l s e 0 .
GetKeyboardState procedure GetKeyboardState(var
KeyState: Byte);
C o p i e s t h e virtual k e y b o a r d key-set status i n t o KeyState. I f h i g h bit o f b y t e is 1, k e y is d o w n . I f l o w bit is 1, k e y w a s p r e s s e d o d d n u m b e r o f t i m e s s i n c e system start-up. Parameters KeyState
Description 256-byte c h a r a c t e r array
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
GetKeyNameText function GetKeyNameText(lParam:
Longint; Buffer: PChar;
Size: Integer): Integer; G e t s k e y n a m e string f o r k e y s l o n g e r t h a n a s i n g l e c h a r a c t e r . Parameters
Description
lParam
Long parameter to wmKeyDown message
Buffer
Receiving buffer
Size
Size o f buffer
Return Value: N u m b e r o f bytes c o p i e d .
GetKeyState function GetKeyState(VirtKey:
Integer): Integer;
D e t e r m i n e s w h e t h e r t h e state of a virtual k e y is u p , d o w n , o r t o g g l e d . Parameters VirtKey
Description Virtual key
Return Value: K e y is d o w n if h i g h - o r d e r bit is 1; K e y is t o g g l e d if l o w - o r d e r bit is 1.
GetKBCodePage function GetKBCodePage:
Integer;
G e t s the currently loaded O E M o r A N S I table. Return Value: C u r r e n t c o d e p a g e : (437) (850) (860) (861) (863) (865)
USA International Portugal Iceland French Canadian Norway/Denmark
667
668
Part I I I — R e f e r e n c e s
OemKeyScan function OemKeyScan(OemChar: Word): Longint; M a p s OemCh a r i n t o O E M ( I B M c h a r a c t e r set) s c a n c o d e s . T h e O E M c h a r a c t e r set is t h e I B M c h a r a c t e r set. Parameters OemChar Return
Description O E M A S C I I c h a r a c t e r c o d e (0 t o $ 0 F F )
Value.
S c a n c o d e a n d shift state (bit 2 C t r l k e y , bit 1 Shift k e y p r e s s e d ) i n l o w - a n d h i g h o r d e r w o r d , r e s p e c t i v e l y , if s u c c e s s f u l ; else - 1 i n l o w - a n d h i g h - o r d e r w o r d .
SetKeyboardState procedure SetKeyboardState(var
KeyState: Byte);
C o p i e s KeyState i n t o W i n d o w s k e y b o a r d - s t a t e t a b l e . Parameters KeyState
Description A r r a y o f 2 5 5 b y t e s c o n t a i n i n g k e y states
MapVirtualKey function MapVirtualKey(Code, MapType: Word): Word; M a p s a virtual-key o r s c a n c o d e f o r a k e y t o its c o r r e s p o n d i n g s c a n c o d e , virtualk e y c o d e , o r A S C I I v a l u e as s p e c i f i e d b y MapType. Parameters
Description
Code
Virtual-key o r scan c o d e for a key d e t e r m i n e d by MapType v a l u e
MapType
(0) virtual-key c o d e , (1) s c a n c o d e , (2) virtual-key c o d e
Return
Value:
MapType v a l u e s : 0 r e t u r n s s c a n c o d e ; 1 r e t u r n s virtual-key c o d e ; 2 r e t u r n s unshifted ASCII value.
VkKeyScan function VkKeyScan(AChar: Word): Word; T r a n s l a t e s AChar i n t o its c o r r e s p o n d i n g virtual-key c o d e a n d shift state.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters AChar Return
669
Description A N S I c h a r a c t e r t o find c o r r e s p o n d i n g virtual-key c o d e
Value:
V i r t u a l - k e y c o d e i n t h e l o w - o r d e r b y t e ; t h e f o l l o w i n g shift states i n t h e h i g h order byte: (0) N o shift (1) S h i f t e d (2) C o n t r o l c h a r (6) C o n t r o l + A l t (7) S h i f t + C o n t r o l - A l t or ( 3 ) , ( 4 ) , or ( 5 ) , w h i c h a r e n ' t u s e d for c h a r a c t e r s If t h e r e ' s a n e r r o r , b o t h b y t e s a r e - 1 .
Hook Procedures and Functions CallMsgFilter DefHookProc SetWindowsHook UnhookWindowsHook
CallMsgFilter function CallMsgFilter(var Msg: TMsg; Code: Integer): Bool; S e n d s Msg t o t h e c u r r e n t m e s s a g e filter f u n c t i o n . Parameters
Description
Msg
TMsg c o n t a i n i n g m e s s a g e t o b e
Code
Filter f u n c t i o n c o d e
filtered
Return Value: 0 if m e s s a g e s h o u l d b e p r o c e s s e d ; e l s e n o n z e r o .
DefHookProc function DefHookProc(Code: Integer; wParam: Word; lParam: Longint; NextHook: TFarProc): Longint; C a l l s n e x t f u n c t i o n i n c h a i n o f h o o k ( m e s s a g e filter) f u n c t i o n s .
670
Part I I I — R e f e r e n c e s
Parameters
Description
Code
D e t e r m i n e s how m e s s a g e is p r o c e s s e d
wParam
Message word parameter
lParams
Message long parameter
NextHook
T F a r P r o c t o n e x t hook
Return
function
Value:
A value depending o n code.
SetWindowsHook function
SetWindowsHook(FilterType:
FilterFunc:
TFarProc):
Integer;
TFarProc;
Installs a filter f u n c t i o n i n t h e c h a i n o f filter f u n c t i o n s s p e c i f i e d b y F i l t e r T y p e . T h e filter f u n c t i o n is p a s s e d a C o d e , wParam, a n d l P a r a m , w h i c h h a v e v a l u e s that are f i l t e r - t y p e - d e p e n d e n t . Parameters
Description
FilterType
O n e of the wh_ Windows h o o k codes
FilterFunc
Filter f u n c t i o n ' s p r o c e d u r e - i n s t a n c e a d d r e s s
Return
Value:
P r o c e d u r e - i n s t a n c e a d d r e s s o f p r e v i o u s l y i n s t a l l e d filter f u n c t i o n ; nil if n o p r e v i o u s filter.
UnhookWindowsHook function
UnhookWindowsHook(Hook:
R e m o v e s a hook Parameters
Integer;
f u n c t i o n f r o m t h e c h a i n o f hook
HookFunc:
f u n c t i o n s s p e c i f i e d b y Hook.
Description
Hook
O n e o f w h _ Windows hook
HookFunc
Hook f u n c t i o n ' s p r o c e d u r e - i n s t a n c e a d d r e s s
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
TFarProc):
codes
Bool
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
671
Information Procedures and Functions AnyPopup ChildWindowFromPoint EnumChildWindows EnumTaskWindows EnumWindows FindWindow GetNextWindow GetParent GetTopWindow GetWindow GetWindowTask IsChild IsWindow SetParent WindowFromPoint
AnyPopup function AnyPopup: Bool; D e c i d e s w h e t h e r a p o p - u p w i n d o w is o n t h e s c r e e n . Return Value: N o n z e r o if p o p - u p w i n d o w e x i s t s ; e l s e 0.
ChildWindowFromPoint function ChildWindowFromPoint(WndParent: HWnd; APoint: TPoint): HWnd; D e t e r m i n e s w h i c h c h i l d w i n d o w o w n e d b y WndParent c o n t a i n s APoint. Parameters
Description
WndParent
Parent w i n d o w
APoint
TPoint s t r u c t u r e of c l i e n t c o o r d i n a t e s t o b e t e s t e d
Return
Value:
C h i l d w i n d o w that c o n t a i n s t h e p o i n t ; 0 if p o i n t lies o u t s i d e t h e p a r e n t w i n d o w ; WndParent if t h e p o i n t is n o t c o n t a i n e d i n a n y c h i l d w i n d o w .
672
Part I I I — R e f e r e n c e s
EnumChildWindows function EnumChildWindows(WndParent: HWnd; EnumFunc: TFarProc; lParam: Longint): Bool; Enumerates child w i n d o w s o f given parent, passing the child handle a n d lParam t o t h e c a l l b a c k . E n u m e r a t i o n e n d s if t h e callback r e t u r n s 0 o r t h e last c h i l d is e n u m e r a t e d . Parameters
Description
WndParent
Parent w i n d o w o f child w i n d o w s t o e n u m e r a t e
EnumFunc
Callback f u n c t i o n ' s p r o c e d u r e - i n s t a n c e a d d r e s s
lParam
V a l u e p a s s e d t o callback f u n c t i o n
Return Value: N o n z e r o if all c h i l d w i n d o w s h a v e b e e n e n u m e r a t e d ; e l s e 0.
EnumTaskWindows function EnumTaskWindows(Task: THandle; EnumFunc: TFarProc; lParam: Longint): Bool; E n u m e r a t e s all w i n d o w s i n a task, p a s s i n g t h e w i n d o w h a n d l e a n d lParam t o t h e callback. E n u m e r a t i o n e n d s if t h e callback r e t u r n s 0 o r all w i n d o w s a r e enumerated. Parameters
Description
Task
Task identifier
EnumFunc
Callback f u n c t i o n ' s p r o c e d u r e - i n s t a n c e a d d r e s s
lParam
V a l u e p a s s e d t o callback
Return Value: N o n z e r o if all w i n d o w s a r e e n u m e r a t e d ; e l s e 0.
EnumWindows function EnumWindows(EnumFunc: TFarProc; lParam: Longint): Bool; E n u m e r a t e s all p a r e n t w i n d o w s o n t h e s c r e e n p a s s i n g t h e w i n d o w h a n d l e a n d lParam t o t h e callback. E n u m e r a t i o n e n d s if t h e callback r e t u r n s 0 o r all w i n d o w s are e n u m e r a t e d .
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
Description
EnumFunc
Callback f u n c t i o n ' s p r o c e d u r e - i n s t a n c e a d d r e s s
lParam
V a l u e p a s s e d t o callback
Return
Value:
N o n z e r o if all w i n d o w s a r e e n u m e r a t e d ; e l s e 0.
FindWindow function FindWindow(ClassName, WindowName: PChar): HWnd; F i n d s a t o p - l e v e l p a r e n t w i n d o w w i t h m a t c h i n g ClassName a n d WindowName d o e s not search child w i n d o w s . Parameters
Description
ClassName
W i n d o w ' s class n a m e ( n u l l - t e r m i n a t e d o r n i l f o r all)
WindowName
W i n d o w ' s text c a p t i o n o r 0 f o r all
Return Value: W i n d o w h a n d l e ; 0 if n o w i n d o w .
GetNextWindow function GetNextWindow(Wnd: HWnd; Flag: Word): HWnd; G e t s n e x t o r p r e v i o u s w i n d o w f r o m Wnd, if t o p - l e v e l w i n d o w s e a r c h e s f o r n e x t t o p - l e v e l w i n d o w o r if c h i l d w i n d o w s e a r c h e s f o r n e x t c h i l d w i n d o w . Parameters
Description
Wnd
W i n d o w identifier
Flag
O n e o f t h e gw_ Get w i n d o w c o n s t a n t s : gw_HWndNext o r gwJHWndPrev
Return Value: W i n d o w identifier.
GetParent function GetParent(Wnd: HWnd): HWnd; Gets a window's parent w i n d o w handle.
673
674
Part I I I — R e f e r e n c e s
Parameters Wnd
Description W i n d o w identifier
Return Value: P a r e n t w i n d o w i d e n t i f i e r ; 0 if n o p a r e n t w i n d o w .
GetTopWindow function GetTopWindow(Wnd: HWnd): HWnd; G e t s a w i n d o w ' s top-level child w i n d o w . Parameters Wnd
Description Parent w i n d o w identifier
Return Value: C h i l d w i n d o w i d e n t i f i e r ; 0 if n o c h i l d w i n d o w .
GetWindow function GetWindow(Wnd: HWnd; Cmd: Word): HWnd; G e t s t h e w i n d o w w i t h t h e r e l a t i o n s h i p s p e c i f i e d i n Cmd t o t h e w i n d o w s p e c i f i e d i n Wnd. Parameters
Description
Wnd
Original w i n d o w
Cmd
O n e of t h e gw_ Get w i n d o w c o n s t a n t s
Return
Value:
W i n d o w i d e n t i f i e r ; 0 if w i n d o w is n o t f o u n d o r if i n v a l i d Cmd.
GetWindowTask function GetWindowTask(Wnd: HWnd): THandle; G e t s a w i n d o w ' s a p p l i c a t i o n task i d e n t i f i e r . Parameters Wnd Return Value: Task identifier.
Description W i n d o w identifier
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
IsChild function
IsChild(Parent,
Wnd: HWnd):
Bool;
D e t e r m i n e s w h e t h e r Wnd is a c h i l d w i n d o w o f P a r e n t . Parameters
Description
Parent
W i n d o w identifier
Wnd
Test w i n d o w
Return Value: N o n z e r o if c h i l d w i n d o w ; e l s e 0.
IsWindow function
IsWindow(Wnd:
HWnd):
Bool;
D e t e r m i n e s w h e t h e r Wnd is a v a l i d w i n d o w . Parameters Wnd Return
Description W i n d o w identifier
Value:
N o n z e r o if v a l i d ; e l s e 0.
SetParent function
SetParent(WndChild,
WndNewParent:
HWnd): HWnd;
C h a n g e s the parent o f a child w i n d o w to WndNewParent. Parameters
Description
WndChild
C h i l d w i n d o w identifier
WndNewParent
Parent w i n d o w identifier
Return Value: Previous parent w i n d o w .
WindowFromPoint function
WindowFromPoint(Point:
TPoint):
HWnd;
Decides which w i n d o w contains the specified point.
675
676
Part I I I — R e f e r e n c e s
Parameters Point
Description TPoint t o b e c h e c k e d (in s c r e e n c o o r d i n a t e s )
Return Value: W i n d o w i d e n t i f i e r ; 0 if t h e r e ' s n o w i n d o w at s p e c i f i e d p o i n t .
Input Procedures and Functions EnableWindow GetActiveWindow GetCapture GetCurrentTime GetDoubleClickTime GetFocus GetTickCount IsWindowEnabled KillTimer ReleaseCapture SetActiveWindow SetCapture SetDoubleClickTime SetFocus SetSysModalWindow SetTimer SwapMouseButton
EnableWindow function EnableWindow(Wnd: HWnd; Enable: Bool): Bool; Enables or disables m o u s e a n d keyboard input to a w i n d o w or control. Parameters
Description
Wnd
W i n d o w to be enabled or disabled
Enable
N o n z e r o to enable; 0 to disable
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
GetActiveWindow function GetActiveWindow: HWnd; G e t s t h e h a n d l e o f t h e w i n d o w that h a s t h e c u r r e n t i n p u t f o c u s . Return Value: Active w i n d o w identifier.
GetCapture function GetCapture: HWnd; G e t s t h e w i n d o w that is c u r r e n t l y r e c e i v i n g all m o u s e i n p u t . Return Value: W i n d o w t h a t h a s t h e m o u s e c a p t u r e ; 0 if n o w i n d o w .
GetCurrentTlme function GetCurrentTime: Longint; G e t s the elapsed time since the system w a s rebooted. Return Value: C u r r e n t t i m e (in m i l l i s e c o n d s ) .
GetDoubleCHckTime function GetDoubleClickTime: Word; G e t s t h e m a x i m u m t i m e b e t w e e n a series o f t w o m o u s e clicks (that is, a double-click). Return Value: C u r r e n t double-click time (in milliseconds)
GetFocus function GetFocus: HWnd; G e t s t h e w i n d o w that c u r r e n t l y h a s t h e i n p u t f o c u s . Return Value: W i n d o w i d e n t i f i e r if s u c c e s s f u l ; e l s e 0.
677
678
Part I I I — R e f e r e n c e s
GetTickCount function GetTickCount: Longint; G e t s t h e elapsed time since t h e system started. Return
Value:
E l a p s e d time (in milliseconds).
IsWindowEnabled function IsWindowEnabled(Wnd: HWnd): Bool; D e t e r m i n e s w h e t h e r a w i n d o w is e n a b l e d for m o u s e a n d k e y b o a r d i n p u t . Parameters
Description
Wnd Return
W i n d o w identifier Value:
N o n z e r o if e n a b l e d ; e l s e 0.
KillTimer function KillTimer(Wnd: HWnd; IDEvent: Integer): Bool; Kills a t i m e r e v e n t ; r e m o v e s a n y a s s o c i a t e d wm_Timer m e s s a g e s f r o m t h e message queue. Parameters
Description
Wnd
W i n d o w identifier
IDEvent
Timer event I D
Return Value: N o n z e r o if s u c c e s s f u l ; 0 if i n v a l i d IDEvent.
ReleaseCapture procedure
ReleaseCapture;
Releases m o u s e capture; restores n o r m a l input processing.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
SetActiveWindow function
SetActiveWindow(Wnd:
HWnd): HWnd;
Activates a t o p - l e v e l w i n d o w . Parameters
Description
Wnd
W i n d o w identifier
Return Value: P r e v i o u s l y active w i n d o w .
SetCapture function
SetCapture(Wnd:
HWnd): HWnd;
C a u s e s all c u r s o r i n p u t t o b e s e n t t o Wn d r e g a r d l e s s o f t h e p o s i t i o n o f t h e m o u s e . Parameters
Description
Wnd Return
W i n d o w identifier Value:
P r e v i o u s w i n d o w that r e c e i v e d all m o u s e i n p u t ; 0 if t h e r e ' s n o c o r r e s p o n d i n g window.
SetDoubleClickTime procedure
SetDoubleClickTime(Count:
Word);
S e t s m a x i m u m e l a p s e d t i m e a l l o w e d b e t w e e n t h e first a n d s e c o n d clicks o f a m o u s e d o u b l e click. Parameters Count
Description Milliseconds b e t w e e n d o u b l e clicks, or 0 to use default (500) v a l u e .
SetFocus function
SetFocus(Wnd:
HWnd): HWnd;
A s s i g n s i n p u t f o c u s t o a w i n d o w a n d d i r e c t s all k e y b o a r d i n p u t t o t h e w i n d o w .
679
680
Part III—References
Parameters Wnd
Description Window
Return Value: P r e v i o u s w i n d o w having
identifier or 0 to ignore keystrokes
i n p u t f o c u s ; 0 if t h e r e ' s n o c o r r e s p o n d i n g w i n d o w .
SetSysModalWindow function SetSysModalWindow(Wnd: HWnd): HWnd; Makes a Wnd a system-modal window. The system-modal state is terminated w h e n the w i n d o w is destroyed. Parameters
Wnd Return
Description
W i n d o w identifier Value:
Previous system-modal window.
SetTimer function SetTimer(Wnd: HWnd; IDEvent: Integer; Elapse: Word; TimerFunc: TFarProc): Word; Creates a system timer, causing a wm_Time r message to be sent to an application at the interval specified by Elapse. Parameters
Description
Wnd
W i n d o w identifier or 0 if there's no associated w i n d o w
IDEvent
Nonzero timer-event identifier or ignored if Wnd is 0
Elapse
N u m b e r of milliseconds between timer events
TimerFunc
Callback function's procedure-instance address or nil to place wm_Timer messages in application queue
Return
Value:
IDEvent if Wnd is not 0, indicating a n e w timer event; 0 if error.
SwapMouseButton function SwapMouseButton(Swap: Bool): Bool; Reverses or restores the meaning of the left and right m o u s e button specified by Swap.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters Swap
Description N o n z e r o to swap b u t t o n m e a n i n g s or 0 to restore original meanings
Return Value: N o n z e r o if m e a n i n g s r e v e r s e d ; e l s e 0.
Menu Procedures and Functions AppendMenu CheckMenuItem CreateMenu CreatePopupMenu DeleteMenu DestroyMenu DrawMenuBar EnableMenuItem GetMenu GetMenuCheckMarkDimensions GetMenuItemCount GetMenuItemID GetMenuState GetMenuString GetSubMenu GetSystemMenu HiliteMenuItem InsertMenu LoadMenuIndirect ModifyMenu RemoveMenu SetMenu SetMenuItemBitmaps TrackPopupMenu
AppendMenu function AppendMenu(Menu: HMenu; Flags, IDNewItem: Word; Newltem: PChar): Bool; A p p e n d s a n e w i t e m (with a state s p e c i f i e d b y Flags) t o t h e e n d o f a m e n u .
681
682
Part I I I — R e f e r e n c e s
Parameters
Description
Menu
M e n u to be changed
Flags
O n e o r a c o m b i n a t i o n o f t h e f o l l o w i n g mf _ constants:
Menu
flags'
mf_Bitmap mf_Checked mf_Disabled mf_Enabled mf_Grayed mf_MenuBarBreak mf_MenuBreak mf_OwnerDraw mf_Popup mf_Separator mf_String mf_Unchecked IDNewItem
C o m m a n d I D o r m e n u h a n d l e if p o p - u p m e n u .
Newltem
N e w m e n u string, o r w h e n u s i n g a bit m a p as a n i t e m , t h e l o w - o r d e r w o r d h o l d s a h a n d l e t o t h e bit m a p .
Return
Value:
N o n z e r o if s u c c e s s f u l ; e l s e 0.
CheckMenuItem function
CheckMenuItem(Menu:
P l a c e s o r removes Parameters
HMenu;
IDCheckltem,
Check:
Word):
a check mark from m e n u items in a p o p - u p m e n u . Description
Menu
Pop-up menu
IDCheckltem
M e n u item to be checked
Check
H o w i t e m s h o u l d b e c h e c k e d a n d h o w its p o s i t i o n is specified; any combination of the following m f _ Menu
flags:
mf_ByCommand mf_ByPosition mf_Checked mf_Unchecked
Bool
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Return Value: P r e v i o u s state o f Item; - 1 if t h e m e n u i t e m d o e s n o t exist.
CreateMenu function CreateMenu: HMenu; Creates an empty m e n u . Return Value: M e n u i d e n t i f i e r if s u c c e s s f u l ; e l s e 0.
CreatePopupMenu function CreatePopupMenu: HMenu; Creates an empty pop-up m e n u . Return Value: M e n u i d e n t i f i e r if s u c c e s s f u l ; e l s e 0.
DeleteMenu function DeleteMenu(Menu: HMenu; Position, Flags: Word): Bool; D e l e t e s a n i t e m f r o m Menu. If t h e i t e m is a p o p - u p , its h a n d l e is d e s t r o y e d , a n d t h e m e m o r y it u s e d is f r e e d . Parameters
Description
Menu
M e n u identifier
Position
Position or c o m m a n d I D
Flags
O n e o f t h e mf _ Menu flags' c o n s t a n t s : mf_ByPosition mf_ByCommand
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
DestroyMenu function DestroyMenu(Menu: HMenu): Bool; D e s t r o y s Menu a n d frees a s s o c i a t e d m e m o r y .
683
684
Part I I I — R e f e r e n c e s
Parameters Menu
Description M e n u identifier
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
DrawMenuBar procedure DrawMenuBar(Wnd: HWnd); R e d r a w s a w i n d o w ' s m e n u b a r . U s e d if t h e m e n u b a r c h a n g e s after t h e w i n d o w is c r e a t e d . Parameters Wnd
Description W i n d o w identifier
EnableMenuItem function EnableMenuItem(Menu: HMenu; IDEnableltem, Enable: Word): Bool; E n a b l e s , d i s a b l e s , o r grays a m e n u i t e m s p e c i f i e d b y Enable. Parameters
Description
Menu
M e n u identifier
IDEnableltem
I D or position of m e n u item or p o p - u p to be checked
Enable
A c o m b i n a t i o n o f t h e mf _ Menu flags' c o n s t a n t s : mf_Command o r mf_ByPosition w i t h mf_Disabled, mf_Enabled, o r mf_Grayed
Return Value: P r e v i o u s state o f m e n u i t e m ; - 1 if m e n u i t e m d o e s n ' t exist.
GetMenu function GetMenu(Wnd: HWnd): HMenu; Gets a window's menu handle. Parameters Wnd
Description Owning window of menu
Return Value: M e n u i d e n t i f i e r ; 0 if t h e r e ' s n o m e n u ; u n d e f i n e d if Wnd is a c h i l d w i n d o w .
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
GetMenuCheckMarld)imensions function GetMenuCheckMarkDimensions:
Longint;
G e t s the dimensions o f the default check mark bitmap displayed next t o checked m e n u items. Return Value: H e i g h t (in p i x e l s ) i n t h e h i g h - o r d e r w o r d ; w i d t h ( i n p i x e l s ) i n t h e l o w - o r d e r word.
GetMenuItemCount function GetMenuItemCount(Menu: HMenu): Word; G e t s the n u m b e r o f top-level m e n u s a n d the m e n u items in a specified m e n u . Parameters Menu
Description T h e m e n u identifier
Return Value: T h e n u m b e r o f m e n u i t e m s , if s u c c e s s f u l ; -1 if u n s u c c e s s f u l .
GetMenuItemlD function GetMenuItemID(Menu: HMenu; Pos: Integer): Word; G e t s t h e m e n u i t e m ' s n u m e r i c I D l o c a t e d at t h e s p e c i f i e d p o s i t i o n i n t h e m e n u . Parameters
Description
Menu
P o p - u p m e n u identifier
Pos
Item p o s i t i o n , starting at 0 , i n m e n u
Return Value: Item I D if s u c c e s s f u l ; 0 if i t e m is a p o p - u p ; - 1 if e r r o r .
GetMenuState function GetMenuState(Menu: HMenu; ID, Flags: Word): Word; G e t s state i n f o r m a t i o n f o r a s p e c i f i e d m e n u i t e m .
685
686
Part I I I — R e f e r e n c e s
Parameters
Description
Menu
M e n u o r p o p - u p m e n u identifier
ID
M e n u item I D
Flags
O n e of t h e mf _ Menu flags' c o n s t a n t s : mf_ByPosition mf_ByCommand
Return Value: F l a g s m a s k of t h e f o l l o w i n g mf _ Menu flags v a l u e s : mf_Checked mf_Disabled mf_Enabled mf_MenuBarBreak mf_MenuBreak mf_Separator mfJJnchecked If p o p - u p , t h e h i g h - o r d e r b y t e c o n t a i n s t h e n u m b e r o f i t e m s ; - 1 if ID is i n v a l i d .
GetMenuString function GetMenuString(Menu: HMenu; IDItem: Word; Str: PChar; MaxCount: Integer; Flag: Word): Integer; C o p i e s a m e n u i t e m ' s l a b e l i n t o Str. T h e c o p i e d l a b e l is n u l l - t e r m i n a t e d . Parameters
Description
Menu
M e n u identifier
IDItem
M e n u item I D
Str
Receiving buffer
MaxCount
Size o f the buffer
Flag
O n e of t h e mf _ Menu flags' c o n s t a n t s : mf_ByPosition mf_ByCommand
Return Value: N u m b e r o f bytes c o p i e d .
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
GetSubMenu function GetSubMenu(Menu: HMenu; Pos: Integer): HMenu; Gets a pop-up menu's handle. Parameters
Description
Menu
M e n u identifier
Pos
P o s i t i o n o f p o p - u p m e n u i n Menu
Return Value: P o p - u p m e n u identifier; 0, if n o p o p - u p m e n u exists at Pos.
GetSystemMenu function GetSystemMenu(Wnd: HWnd; Revert: Bool): HMenu; G e t s a w i n d o w ' s system m e n u for copying a n d changing. Parameters Wnd
Description W i n d o w identifier
Revert 0 t o r e t u r n h a n d l e t o a copy o f t h e s y s t e m m e n u o r n o n z e r o t o r e t u r n handle to original system m e n u . Return Value: S y s t e m m e n u i d e n t i f i e r ; 0 if Revert is n o n z e r o a n d t h e s y s t e m m e n u h a s n o t been changed.
HiliteMenuItem function HiliteMenuItem(Wnd: HWnd; Menu: HMenu; IDHilite, Hilite: Word): Bool; Highlights o r removes highlighting from a top-level m e n u item. Parameters
Description
Wnd
W i n d o w identifier
Menu
Top-level m e n u identifier
IDHilite
Integer I D or position of m e n u item
Hilite
A c o m b i n a t i o n of t h e mf _ Menu flags, mf _ByCommand or mf_ByPosition w i t h mfJHilite or mf JJnhilite
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
687
688
Part III—References
InsertMenu function InsertMenu(Menu:HMenu; Position, Flags, IDNewItem: Word Newltem: PChar): Bool; Inserts n e w m e n u item with a state specified by Flags. Parameters
Description
Menu
M e n u identifier
Position
C o m m a n d ID or position of m e n u item to insert n e w m e n u item after or - 1 to append to end
Flags
O n e of the mf _ Menuflags,mf _ByCommand or mf _ByPosition combined with any of the following: mf_Bitmap mf_String mf_OwnerDraw mf_Separator mf_Popup mf_MenuBarBreak mf_MenuBreak mf_Checked mfJJnchecked
IDNewItem
N e w m e n u item c o m m a n d ID or m e n u handle if pop-up
Newltem
N e w m e n u item contents
Return
Value:
Nonzero if successful; else 0.
LoadMenuIndirect function LoadMenuIndirect(var MenuTemplate): HMenu; Loads the m e n u defined by MenuTemplate. Parameters
Description
MenuTemplate Array of TMenuItemTemplate structures Return
Value:
Menu identifier if successful.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
689
ModifyMenu function ModifyMenu(Menu: HMenu; Position, Flags, IDNewItem: Word; Newltem: PChar): Bool; C h a n g e s a n e x i s t i n g m e n u i t e m that h a s a n e w state that is s p e c i f i e d b y Flags. Parameters
Description
Menu
M e n u identifier
Position
C o m m a n d I D or position of m e n u item
Flags
C o m b i n a t i o n o f mf_ByCommand or mf_ByPosition w i t h o n e o f t h e f o l l o w i n g mf _ Menu flags' c o n s t a n t s :
mf_Disabled mf_Enabled mf_Grayed mf_Bitmap mf_String mfJDwnerDraw mf_Separator mf_Popup mf_MenuBarBreak mf_MenuBreak mf_Checked mfJJnchecked IDNewItem
Newltem
C o m m a n d I D or m e n u h a n d l e , if flags set t o mf Popup, o f modified m e n u item
String (mf_String), HBitmap (mf_Bitmap), or a p p l i c a t i o n s u p p l i e d d a t a (mf_OwnerDraw)
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
RemoveMenu function RemoveMenu(Menu: HMenu; Position, Flags: Word): Bool; Nondestructively removes a m e n u item a n d a n associated p o p - u p from the specified m e n u . Y o u c a n u s e the p o p - u p in ensuing operations.
690
Part I I I — R e f e r e n c e s
Parameters
Description
Menu
M e n u identifier
Position
C o m m a n d I D or position of m e n u item
Flags
O n e o f t h e mf _
Menu flags, mf _ByCommand o r
m f _ B y P o s i t i o n specifying the nature of the P o s i t i o n argument. Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
SetMenu function
SetMenu(Wnd:
HWnd; M e n u :
HMenu):
Bool;
S e t s a n d r e d r a w s a w i n d o w ' s m e n u t o t h e m e n u s p e c i f i e d b y Menu. T h e p r e v i o u s m e n u is n o t d e s t r o y e d . Parameters
Description
Wnd
W i n d o w identifier
Menu
N e w m e n u or 0 to remove current m e n u
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
SetMenuItemBitmaps f u n c t i o n SetMenuItemBitmaps(Menu: BitmapUnchecked, BitmapChecked:
HMenu; P o s i t i o n , HBitmap): Bool;
Flags:
Word;
A s s o c i a t e s t w o b i t m a p s w i t h a m e n u i t e m . O n e is d i s p l a y e d w h e n t h e i t e m is c h e c k e d a n d t h e o t h e r w h e n t h e i t e m is u n c h e c k e d . Parameters
Description
Menu
Menu
identifier
Position
C o m m a n d I D or position of m e n u
Flags
O n e o f t h e mf _ Menu flags' c o n s t a n t s , mf_ByCommand o r m f _ B y P o s i t i o n
BitmapUnchecked
H B i t m a p t o b e d i s p l a y e d w h e n item n o t c h e c k e d or 0 to display nothing
item
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
691
Description
BitmapChecked
HBitmap t o b e d i s p l a y e d w h e n i t e m c h e c k e d o r 0 t o d i s p l a y n o t h i n g ; if BitmapUnchecked a n d BitmapChecked a r e 0, W i n d o w s u s e s d e f a u l t check mark
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
ThckPopupMenu function TrackPopupMenu(Menu: HMenu; Flags: Word; x, y, cx: Integer; Wnd: HWnd; var Rect: TRect): Bool; D i s p l a y s a f l o a t i n g p o p - u p m e n u a n d tracks i t e m s e l e c t i o n . Floating p o p - u p m e n u s can appear anywhere o n the screen. Parameters
Description
Menu
P o p - u p m e n u identifier
Flags
S e t t o 0, n o t u s e d
x, y
Upper-left position (in screen coordinates) o f m e n u
cx
M e n u w i d t h (in s c r e e n u n i t s ) o r 0 f o r d e f a u l t
Wnd
O w n i n g w i n d o w o f the p o p - u p m e n u , to receive wm_Command m e s s a g e s
Rect
TRect d e f i n i n g m o u s e a r e a w h e r e m e n u r e m a i n s visible if t h e u s e r r e l e a s e s t h e m o u s e b u t t o n
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
Message Procedures and Functions CallWindowProc DispatchMessage GetMessage GetMessagePos GetMessageTime InSendMessage PeekMessage PostAppMessage
692
Part I I I — R e f e r e n c e s
PostMessage PostQuitMessage ReplyMessage SendMessage SetMessageQueue TranslateAccelerator TranslateMDISysAccel TranslateMessage WaitMessage
CallVMowProc function CallWindowProc(PrevWndProc: TFarProc; Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint; S e n d s a m e s s a g e t o PrevWndProc. E n a b l e s w i n d o w s u b c l a s s i n g b y a l l o w i n g messages t o b e intercepted before they are sent t o t h e w i n d o w f u n c t i o n o f the class. Parameters
Description
PrevWndProc
Procedure-instance address o f the previous w i n d o w function
Wnd
W i n d o w that r e c e i v e s t h e m e s s a g e
Msg
Message identifier
wParam
Additional message-dependent information
lParam
Additional message-dependent information
Return Value: V a l u e f r o m call t o PrevWndProc.
DispatchMessage function DispatchMessage(var Msg: TMsg): Longint; Passes t h e m e s s a g e i n Msg t o t h e w i n d o w ' s w i n d o w f u n c t i o n . Parameters Msg
Description TMsg s t r u c t u r e
Return Value: A value returned from the w i n d o w function.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
GetMessage function GetMessage(var Msg: TMsg; Wnd: HWnd; MsgFilterMin, MsgFilterMax: Word): Bool; G e t s a m e s s a g e ( w i t h i n t h e filter r a n g e ) f r o m t h e a p p l i c a t i o n ' s m e s s a g e q u e u e . Y i e l d s c o n t r o l t o o t h e r a p p l i c a t i o n s if t h e r e a r e n o m e s s a g e s p e n d i n g , o r wm_Paint, o r wm_Timer is t h e n e x t m e s s a g e . Parameters
Description
Msg
R e c e i v i n g TMsg s t r u c t u r e
Wnd
M e s s a g e d e s t i n a t i o n w i n d o w o r 0 f o r all w i n d o w s i n applications
MsgFilterMin
0 for n o filtering o r wm_KeyFirst for k e y b o a r d o n l y o r wm_MouseFirst for m o u s e o n l y
MsgFilterMax
0 for n o filtering o r w m K e y L a s t for k e y b o a r d o n l y o r w m M o u s e L a s t for m o u s e o n l y
Return Value: N o n z e r o if n o t a w m Q u i t m e s s a g e ; e l s e 0.
GetMessagePos function GetMessagePos: Longint; G e t s t h e c u r s o r p o s i t i o n for t h e p r e v i o u s m e s s a g e o b t a i n e d f r o m GetMessage. Return
Value: X-coordinates in l o w word; Y-coordinates in high word.
GetMessagelime function GetMessageTime: Longint; G e t s t h e t i m e that h a s e l a p s e d s i n c e a s y s t e m r e b o o t for t h e last m e s s a g e o b t a i n e d f r o m GetMessage. Return Value: M e s s a g e t i m e (in m i l l i s e c o n d s ) .
693
694
Part I I I — R e f e r e n c e s
InSendMessage function InSendMessage: Bool; Decides whether the message being processed by the current w i n d o w function w a s s e n t t h r o u g h SendMessage. Return Value: N o n z e r o if t h e m e s s a g e w a s s e n t b y SendMessage; e l s e 0.
PeekMessage function PeekMessage(var Msg: TMsg; Wnd: HWnd; MsgFilterMin, MsgFilterMax, RemoveMsg: Word): Bool; C h e c k s t h e a p p l i c a t i o n q u e u e f o r a m e s s a g e a n d c o p i e s it t o Msg. If t h e r e a r e n o messages, the function returns immediately, giving control to W i n d o w s . Parameters
Description
Msg
R e c e i v i n g TMsg s t r u c t u r e
Wnd
Messages destination w i n d o w or 0 for any w i n d o w in application or - 1 for messages posted by PostAppMessage f u n c t i o n .
MsgFilterMin
L o w e s t m e s s a g e I D t o e x a m i n e , o r 0 f o r n o limit
MsgFilterMax
H i g h e s t m e s s a g e I D t o e x a m i n e , o r 0 f o r n o limit
RemoveMsg
O n e o r m o r e o f t h e pm_ Peek m e s s a g e o p t i o n s
Return
Value:
N o n z e r o if m e s s a g e a v a i l a b l e ; e l s e 0.
PostAppMessage function PostAppMessage(Task: THandle; Msg, wParam: Word; lParam: Longint): Bool; Posts a m e s s a g e t o a n a p p l i c a t i o n . T h e Wnd of t h e m e s s a g e is set t o 0. Parameters
Description
Task
Application to receive message
Msg
Message type
wParam
Additional message information
lParam
Additional message information
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
PostMessage function PostMessage(Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Bool; Posts a m e s s a g e t o a n application w i n d o w . Parameters Wnd
Description W i n d o w t o r e c e i v e m e s s a g e o r $ F F F F f o r all o v e r l a p p e d or pop-up windows
Msg
Message type
wParam
Additional message information
lParam
Additional message information
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
PostQuitMessage procedure PostQuitMessage(ExitCode:
Integer);
P o s t s a wm_Quit m e s s a g e u s u a l l y i n r e s p o n s e t o a w m D e s t r o y m e s s a g e . Parameters ExitCode
Description A p p l i c a t i o n exit c o d e (wParam o f wm_Quit m e s s a g e )
ReplyMessage procedure ReplyMessage(Reply: Longint); R e p l i e s t o a m e s s a g e s e n t byaSendMessagecall, a l l o w i n g b o t h t h e r e q u e s t e r o f t h e SendMessage a n d ReplyMessage t o c o n t i n u e p r o c e s s i n g . Parameters Reply
Description M e s s a g e - d e p e n d e n t r e t u r n result
695
696
Part I I I — R e f e r e n c e s
SendMessage function SendMessage(Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint; Sends a message to the w i n d o w function o f a specified w i n d o w . T h e function d o e s n ' t r e t u r n u n t i l t h e m e s s a g e is p r o c e s s e d . Parameters
Description
Wnd
W i n d o w t o r e c e i v e m e s s a g e o r $ F F F F t o s e n d t o all p o p u p w i n d o w s in system
Msg
Message type
wParam
Additional message information
lParam
Additional message information
Return Value: Value returned by the receiving w i n d o w function.
SetMessageQueue function SetMessageQueue(Msg:
Integer): Bool;
C r e a t e s a n e w a p p l i c a t i o n m e s s a g e q u e u e o f a s p e c i f i e d s i z e . T h e o l d q u e u e is deleted. Parameters Msg Return
Description Size o f q u e u e
Value:
N o n z e r o if s u c c e s s f u l ; e l s e 0.
ThmslateAccelerator function TranslateAccelerator(Wnd: HWnd; AccTable: THandle; var Msg: TMsg): Integer; T r a n s l a t e s a n y k e y b o a r d a c c e l e r a t o r s (wm_KeyUp a n d wm_KeyDown) i n t o m e n u c o m m a n d m e s s a g e s , w m C o m m a n d a n d wmSysCommand, which t h e n a r e s e n t directly t o t h e w i n d o w .
L — W i n d o w Manager Interface Procedures and Functions
Parameters
Description
Wnd
Window identifier
AccTable
Accelerator table identifier (returned by LoadAccelerators)
Msg
TMsg information retrieved from GetMessage or PeekMessage
Return Value: Nonzero if translation occurred; else 0.
TranslateMDISysAccel function TranslateMDISysAccel(Wnd: HWnd; var Msg: TMsg): Bool; Translates any keyboard accelerators for M D I child w i n d o w system-menu wm_SysCommand messages. These messages then are sent directly to the window. Parameters
Description
Wnd
MDI client parent w i n d o w
Msg
TMsg information retrieved from GetMessage or PeekMessage
Return Value: Nonzero if translation occurred; else 0.
IfonslateMessage function TranslateMessage(var Msg: TMsg): Bool; Translates wm_KeyDown/wm_KeyUp combinations to wm_Charor wm_DeadChar, and wm_SysKeyDown/wm_SysKeyllp combinations to w m _ S y s C h a r or wmSysDeadChar. Also posts the character message to the application queue. Parameters Msg
Description TMsg information retrieved from GetMessage or PeekMessage
Return Value: Nonzero if translation occurred; else 0.
697
698
Part I I I — R e f e r e n c e s
WaitMessage procedure WaitMessage; Yields control to other applications and does not return until a message appears in the application q u e u e .
Painting Procedures and Functions BeginPaint DrawFocusRect Drawlcon DrawText EndPaint ExcludeUpdateRgn FillRect FrameRect GetDC GetUpdateRect GetUpdateRgn GetWindowDC GrayString InvalidateRect InvalidateRgn InvertRect ReleaseDC UpdateWindow ValidateRect ValidateRgn
BeginPaint function BeginPaint(Wnd: HWnd; var Paint: TPaintStruct): HDC; P r e p a r e s a w i n d o w f o r p a i n t i n g i n r e s p o n s e t o a wm_Paint m e s s a g e . Fills Paint with the required information in order to paint. Parameters
Description
Wnd
W i n d o w to be repainted
Paint
TPaintStruct t o r e c e i v e p a i n t i n g i n f o r m a t i o n
Return Value. Device context identifier.
L — W i n d o w M a n a g e r Interface Procedures a n d F u n c t i o n s
DrawFocusRect procedure DrawFocusRect(DC: HDC; var Rect: TRect); Does XOR to d r a w a focus style rectangle. Parameters
Description
DC
Device context identifier
Rect
TRect to be d r a w n
Drawlcon function DrawIcon(DC: HDC; X, Y: Integer; Icon: HIcon): Bool; D r a w s an icon. Parameters
Description
DC
Device context identifier
X, Y
Upper-left corner of the icon
Icon
Icon to be d r a w n
Return Value: Nonzero if successful; else 0.
DrawText function DrawText(DC: HDC; Str: PChar; Count: Integer; var Rect: TRect; Format: Word): Integer; D r a w s formatted text w h o s e formatting is specified by Format. T h e text is clipped to the bounding rectangle, unless specified by dtNoClip. Parameters
Description
DC
Device-context identifier
Str
String to be drawn; if Count is - 1 , must be nullterminated
Count
N u m b e r of bytes in string
Rect
Bounding TRect of the text
Format
O n e or m o r e of the dt_ Text drawing formatting flags
Return Value: Text height.
699
700
Part I I I — R e f e r e n c e s
EndPaint procedure EndPaint(Wnd: HWnd; var Paint: TPaintStruct); D e n o t e s e n d of painting in Wnd. Parameters
Description
Wnd
Repainted window
Paint
TPaintStruct retrieved from BeginPaint function
ExcludeUpdateRgn function ExcludeUpdateRgn(DC: HDC; Wnd: HWnd): Integer; E x c l u d e s a w i n d o w ' s u p d a t e d region from a clipping region, drawing o u t s i d e the valid areas of the w i n d o w . Parameters
thus preventing
Description
DC
Device c o n t e x t
Wnd
Window
identifier
being u p d a t e d
Return Value: O n e of the Region flags' c o n s t a n t s .
FillRect function FillRect(DC: HDC; var Rect: TRect; Brush: HBrush): Integer; Fills a rectangle, Parameters
u s i n g Brush u p to the right a n d bottom borders. Description
DC
Device c o n t e x t identifier
Rect
TRect to be
Brush
Fill b r u s h
Return Value: Not used.
filled
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
701
FrameRect procedure
FrameRect(DC:
HDC; var Rect: TRect; Brush: HBrush):
Draws a border o n e logical unit wide a r o u n d a rectangle. Parameters
Description
DC
D e v i c e context identifier
Rect
TRect d e f i n i n g c o r n e r s o f t h e r e c t a n g l e
Brush
Framing brush
GetDC function GetDC(Wnd: HWnd): HDC; G e t s a display context for u s e by G D I functions in a w i n d o w ' s client area. Parameters Wnd
Description W i n d o w identifier
Return Value: D i s p l a y c o n t e x t i d e n t i f i e r ; 0 if e r r o r .
GetUpdateRect function GetUpdateRect(Wnd:
HWnd; var Rect: TRect;
Erase: Bool): Bool; G e t s the smallest enclosing rectangle o f a w i n d o w ' s u p d a t e region. Parameters
Description
Wnd
W i n d o w identifier
Rect
R e c e i v i n g TRect s t r u c t u r e
Erase
N o n z e r o to erase u p d a t e region b a c k g r o u n d
Return Value: N o n z e r o if n o n - e m p t y u p d a t e r e g i o n ; e l s e 0.
Integer;
702
Part I I I — R e f e r e n c e s
GetUpdateRgn function GetUpdateRgn(Wnd: HWnd; Rgn: HRgn; Erase: Bool): Integer; C o p i e s i n t o Rgn a w i n d o w ' s u p d a t e r e g i o n . Parameters
Description
Wnd
W i n d o w identifier
Rgn
Receiving update region
Erase
N o n z e r o if b a c k g r o u n d s h o u l d b e e r a s e d a n d c h i l d windows redrawn
Return Value: O n e o f t h e Region flags' c o n s t a n t s .
GetWindowDC function GetWindowDC(Wnd: HWnd): HDC; G e t s a d i s p l a y c o n t e x t u s u a l l y u s e d f o r p a i n t i n g n o n c l i e n t areas o f a w i n d o w . Parameters Wnd
Description W i n d o w identifier
Return Value: D i s p l a y c o n t e x t i d e n t i f i e r ; 0 if t h e r e ' s a n e r r o r .
GrayString function GrayString(DC: HDC; Brush: HBrush; OutputFunc: TFarProc; Data: Longint; Count, X, Y, Width, Height: Integer): Bool; D r a w s g r a y text ( u s i n g t h e c u r r e n t l y s e l e c t e d f o n t ) b y s e n d i n g a m e s s a g e t o OutputFunc that c o n t a i n s DC (with a bit m a p o f Height a n d Width s i z e ) , Data, a n d Count. Parameters
Description
DC
Device context identifier
Brush
HBrush u s e d f o r g r a y i n g
OutputFunc
D r a w f u n c t i o n p r o c e d u r e - i n s t a n c e a d d r e s s or n i l t o u s e TextOut
Data
D a t a t o p a s s t o OutputFunc or string if OutputFunc is 0
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
Description
Count
S i z e o f D a t a o r 0 a n d D a t a is a string t o c a l c u l a t e l e n g t h , o r - 1 a n d O u t p u t F u n c r e t u r n s 0 a n d i m a g e is d i s p l a y e d but not shown
X,Y
Starting logical position o f enclosing rectangle
Width
W i d t h (in l o g i c a l u n i t s ) o f e n c l o s i n g r e c t a n g l e , o r 0 a n d D a t a is a string t o c a l c u l a t e w i d t h
Height
H e i g h t (in l o g i c a l u n i t s ) o f e n c l o s i n g r e c t a n g l e , o r 0 a n d D a t a is a string t o c a l c u l a t e h e i g h t
Return Value: N o n z e r o if s u c c e s s f u l ; 0 if t h e o u t p u t f u n c t i o n r e t u r n e d 0 o r if i n s u f f i c i e n t m e m o r y t o c r e a t e t h e bit m a p .
InvalidateRect procedure
InvalidateRect(Wnd:
HWnd; R e c t :
LPRect;
Erase:
Bool);
Invalidates a w i n d o w ' s client area by a d d i n g R e c t to the w i n d o w ' s u p d a t e region. Parameters
Description
Wnd
W i n d o w identifier
Rect
T R e c t to b e a d d e d to u p d a t e region o r nil for the entire client area
Erase
N o n z e r o for B e g i n P a i n t to erase b a c k g r o u n d
InvalidateRgn procedure
InvalidateRgn(Wnd:
HWnd; R g n :
HRgn;
Erase:
Bool);
I n v a l i d a t e s a w i n d o w ' s c l i e n t a r e a b y a d d i n g Rg n t o t h e w i n d o w ' s u p d a t e r e g i o n . Parameters
Description
Wnd
W i n d o w identifier
Rgn
R e g i o n i d e n t i f i e r (in c l i e n t c o o r d i n a t e s )
Erase
N o n z e r o for B e g i n P a i n t t o e r a s e b a c k g r o u n d
703
704
Part I I I — R e f e r e n c e s
InvertRect procedure InvertRect(DC: HDC; var Rect: TRect); Inverts t h e c o l o r s o f t h e r e c t a n g l e s p e c i f i e d b y Rect. Parameters
Description
DC
Device context identifier
Rect
TRect s t r u c t u r e ( i n l o g i c a l c o o r d i n a t e s )
ReleaseDC function ReleaseDC(Wnd: HWnd; DC: HDC): Integer; R e l e a s e s a c o m m o n o r w i n d o w d e v i c e c o n t e x t , t h u s m a k i n g it available t o o t h e r applications. Parameters
Description
Wnd
W i n d o w identifier
DC
Device context identifier
Return Value: 1 if d e v i c e c o n t e x t r e l e a s e d ; e l s e 0.
UpdateWindow procedure UpdateWindow(Wnd: HWnd); S e n d s a w m P a i n t m e s s a g e d i r e c t l y t o a w i n d o w ' s window f u n c t i o n if t h e u p d a t e r e g i o n o f t h e w i n d o w is n o t e m p t y . Parameters Wnd
Description W i n d o w identifier
ValidateRect procedure ValidateRect(Wnd: HWnd; Rect: LPRect); V a l i d a t e s t h e c l i e n t a r e a b y r e m o v i n g Rect f r o m t h e w i n d o w ' s u p d a t e r e g i o n . Parameters
Description
Wnd
W i n d o w identifier
Rect
TRect ( i n c l i e n t c o o r d i n a t e s ) t o b e r e m o v e d f r o m u p d a t e region o r nil for entire client area
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
ValidateRgn procedure ValidateRgn(Wnd: HWnd; Rgn: HRgn); V a l i d a t e s t h e c l i e n t a r e a b y r e m o v i n g t h e r e g i o n s p e c i f i e d b y Rgn f r o m t h e window's update region. Parameters
Description
Wnd
W i n d o w identifier
Rgn
R e g i o n i d e n t i f i e r (in c l i e n t c o o r d i n a t e s )
Property Procedures and Functions EnumProps GetProp RemoveProp SetProp
EnumProps function EnumProps(Wnd: HWnd; EnumFunc: TFarProc): Integer; E n u m e r a t e s a w i n d o w ' s p r o p e r t y list s e n d i n g Wnd, nDummy, PSTR, a n d hData t o t h e callback. E n u m e r a t i o n e n d s if t h e callback r e t u r n s 0 o r if all p r o p e r t i e s are e n u m e r a t e d . Parameters
Description
Wnd
W i n d o w identifier
EnumFunc
Callback f u n c t i o n ' s p r o c e d u r e - i n s t a n c e a d d r e s s
Return Value: P r e v i o u s v a l u e r e t u r n e d b y callback; - 1 if w i n d o w h a s n o p r o p e r t i e s .
GetProp function GetProp(Wnd: HWnd; Str: PChar): THandle; G e t s t h e a s s o c i a t e d d a t a h a n d l e f r o m a w i n d o w ' s p r o p e r t y list.
705
706
Part I I I — R e f e r e n c e s
Parameters
Description
Wnd
W i n d o w identifier
Str
String (null-terminated) o r a t o m
Return Value: D a t a h a n d l e if p r o p e r t y list c o n t a i n s Str; e l s e 0.
RemoveProp function RemoveProp(Wnd: HWnd; Str: PChar): THandle; R e m o v e s a n e n t r y ( s p e c i f i e d b y Str) f r o m a w i n d o w ' s p r o p e r t y list. A n a p p l i c a t i o n is r e s p o n s i b l e f o r f r e e i n g t h e r e t u r n e d d a t a h a n d l e . Parameters
Description
Wnd
W i n d o w identifier
Str
String (null-terminated) o r an a t o m
Return Value: D a t a h a n d l e t o string; 0 if t h e string is n o t f o u n d .
SetProp function SetProp(Wnd: HWnd; Str: PChar; Data: THandle): Bool; A d d s o r c h a n g e s a n e n t r y ( s p e c i f i e d b y Str) t o a w i n d o w ' s p r o p e r t y list. Parameters
Description
Wnd
W i n d o w identifier
Str
String (null-terminated) o r a t o m value created by calling AddAtom
Data
Associated property data handle
Return Value: N o n z e r o if a d d e d ; e l s e 0.
Scrolling Procedures and Functions GetScrollPos GetScrollRange ScrollDC ScrollWindow
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
707
SetScrollPos SetScrollRange ShowScrollBar
GetScrollPos function
GetScrollPos(Wnd:
HWnd; B a r :
Integer):
Integer;
G e t s t h e c u r r e n t p o s i t i o n o f a scroll-bar t h u m b relative t o t h e c u r r e n t s c r o l l i n g range. Parameters
Description
Wnd
W i n d o w containing scroll bar
Bar
O n e of the s b _ S c r o l l bar constants
Return Value: C u r r e n t scroll-bar t h u m b p o s i t i o n .
GetScrollRange p r o c e d u r e G e t S c r o l l R a n g e ( W n d : HWnd; B a r : var MinPos, MaxPos: I n t e g e r ) ;
Integer;
G e t s a scroll bar's m i n i m u m a n d m a x i m u m positions. Parameters
Description
Wnd
W i n d o w containing scroll bar
Bar
O n e of the s b _ S c r o l l bar constants
MinPos
Integer to receive m i n i m u m position
MaxPos
Integer to receive m a x i m u m position
ScrollDC f u n c t i o n S c r o l l D C ( D C : HDC; d x , U p d a t e R g n : HRgn; U p d a t e R e c t :
dy: I n t e g e r ; var S c r o l l , LPRect): Bool;
S c r o l l s a r e c t a n g l e o f bits b y dx a n d dy u n i t s .
Clip:
TRect;
708
Part I I I — R e f e r e n c e s
Parameters
Description
DC
Device context identifier
dx
Horizontal scroll units
dy
Vertical scroll units
Scroll
T R e c t c o n t a i n i n g s c r o l l i n g rectangle containing clipping rectangle
UpdateRgn
S c r o l l D C region u n c o v e r e d b y t h e s c r o l l i n g p r o c e s s ; if n i l , u p d a t e region is n o t c o m p u t e d
UpdateRect
R e c e i v i n g T R e c t c o n t a i n i n g t h e b o u n d i n g rectangle of t h e s c r o l l u p d a t e region; if n i l , u p d a t e rectangle is n o t computed
Clip
TRect
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
SaollWmdow procedure ScrollWindow(Wnd: Rect,
ClipRect:
HWnd; X A m o u n t ,
YAmount:
Integer;
LPRect);
S c r o l l s a w i n d o w ' s c l i e n t a r e a b y XAmount a n d YAmount. T h e u n c o v e r e d a r e a is c o m b i n e d with the window's update regions Parameters
Description
Wnd
W i n d o w identifier
XAmount
Device units to scroll in x-direction
YAmount
Device units to scroll in y-direction
Rect
Client area T R e c t to b e scrolled or nil for the entire client area
ClipRect
C l i p p i n g T R e c t to b e scrolled or nil for the entire window
SetScrollPos function SetScrollPos(Wnd: Bool): Integer; Sets a scroll bar's t h u m b to P o s .
HWnd; B a r ,
Pos:
Integer;
Redraw:
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
N o t e : T h e s c r o l l b a r ' s " t h u m b " is t h e " S c r o l l B o x " i n a s c r o l l b a r that i n d i c a t e s y o u r p o s i t i o n i n a file. T h u s , y o u c a n set t h e " t h u m b " to any position.
Parameters
Description
Wnd
W i n d o w i d e n t i f i e r o r scroll-bar c o n t r o l i d e n t i f i e r if B a r is set t o s b _ C t l
Bar
O n e of the s b _ S c r o l l bar constants
Pos
N e w position
Redraw
N o n z e r o to redraw scroll bar
Return
Value:
Previous position o f scroll bar t h u m b .
SetScrollRange procedure Redraw:
SetScrollRange(Wnd: Bool);
HWnd; B a r ,
MinPos,
MaxPos:
Integer;
Sets a scroll bar's m i n i m u m a n d m a x i m u m position values. Parameters
Description
Wnd
W i n d o w i d e n t i f i e r o r s c r o l l b a r c o n t r o l i d e n t i f i e r if B a r is set t o s b _ C t l
Bar
O n e of the s b _ S c r o l l bar constants
MinPos
M i n i m u m scrolling position
MaxPos
M a x i m u m s c r o l l i n g p o s i t i o n o r 0 a n d M i n P o s set t o 0 t o h i d e the scroll bar
Redraw
N o n z e r o to redraw the scroll bar
ShowScrollBar procedure
ShowScrollBar(Wnd:
HWnd; B a r :
S h o w s o r h i d e s a s c r o l l b a r as s p e c i f i e d b y Show.
Word; Show:
Bool);
709
710
Part I I I — R e f e r e n c e s
Parameters
Description
Wnd
W i n d o w i d e n t i f i e r o r s c r o l l b a r c o n t r o l if B a r is set t o sb_Ctl
Bar
O n e o f t h e sb_ Scroll b a r c o n s t a n t s
Show
N o n z e r o t o s h o w t h e s c r o l l b a r o r 0 t o h i d e it
System Procedures and Functions GetCurrentTime GetSysColor GetSystemMetrics SetSysColors
GetCurrentTime function GetCurrentTime: Longint; G e t s the elapsed time since the system w a s rebooted. Return
Value:
C u r r e n t t i m e (in m i l l i s e c o n d s ) .
GetSysColor function GetSysColor(Index:
Integer): Longint;
Gets a W i n d o w s display element's current color. Parameters Index
Description Display element
Return Value: R G B color value.
GetSystemMetrics function GetSystemMetrics(Index:
Integer): Integer;
G e t s t h e s y s t e m m e t r i c s , s u c h as m o u s e s t a t u s , p i x e l w i d t h , a n d h e i g h t o f v a r i o u s display elements, a n d W i n d o w s d e b u g version.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters Index
Description O n e o f t h e sm_ S y s t e m m e t r i c s c o d e s ' c o n s t a n t s
Return Value: T h e requested system metric value.
SetSysColors procedure SetSysColors(Changes: Integer; var SysColor; var ColorValues); S e t s t h e s y s t e m c o l o r s f o r t h e d i s p l a y e l e m e n t s s p e c i f i e d i n SysColor. Parameters Change
SysColor
Description N u m b e r o f system colors to c h a n g e
I n t e g e r array w h o s e i n d e x e s a r e color_ System color codes
ColorValues
Longint array c o n t a i n i n g c o r r e s p o n d i n g R G B color v a l u e
f o r e a c h color i n d e x i n SysColor
Window-Creation Procedures and Functions Adj ustWindowRect Ad j ustWindowRectEx CreateWindow CreateWindowEx DefDlgProc DefFrameProc DefMDIChildProc DefWindowProc DestroyWindow GetClassInfo GetClassLong GetClassName GetClassWord GetLastActivePopup GetWindowLong GetWindowWord RegisterClass SetClassLong SetClassWord
711
712
Part I I I — R e f e r e n c e s
SetWindowLong SetWindowWord UnregisterClass
AdjustWindowRect procedure AdjustWindowRect(var
Rect: TRect; Style: Longint;
Menu: Bool); C o m p u t e s t h e size a w i n d o w r e c t a n g l e r e q u i r e s b a s e d o n Rect s i z e . Parameters
Description
Rect
TRect c o n t a i n i n g c l i e n t r e c t a n g l e c o o r d i n a t e s t o b e converted
Style
W i n d o w styles o f t h e w i n d o w w i t h a c l i e n t r e c t a n g l e that is t o b e c o n v e r t e d
Menu
N o n z e r o if w i n d o w h a s a m e n u
AdjustWindowRectEx procedure AdjustWindowRectEx(var Rect: TRect; Style: Longint; Menu: Bool; ExStyle: Longint); C o m p u t e s t h e size o f a w i n d o w r e c t a n g l e w i t h e x t e n d e d style b a s e d o n Rect size. A s s u m e s a s i n g l e r o w m e n u , if t h e r e ' s a m e n u . Parameters
Description
Rect
T R e c t structure containing client rectangle coordinates to be converted
Style
W i n d o w styles o f t h e w i n d o w w h o s e c l i e n t r e c t a n g l e w i l l be converted
Menu
N o n z e r o if t h e w i n d o w h a s a m e n u
ExStyle
E x t e n d e d style o f t h e w i n d o w b e i n g c r e a t e d
CreateWindow function CreateWindow(ClassName, WindowName: PChar; Style: Longint; X, Y, Width, Height: Integer; WndParent: HWnd; Menu: HMenu; Instance: THandle; Param: Pointer): HWnd; Creates a pop-up, overlapped, or child window.
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
713
Description
ClassName
W i n d o w class n a m e ( n u l l - t e r m i n a t e d ) o r a p r e d e f i n e d control-class n a m e
WindowName
W i n d o w caption or n a m e (null-terminated)
Style
O n e o r a c o m b i n a t i o n o f w i n d o w o r c o n t r o l style c o n stants: bs_ Button styles cbs_ Combo b o x styles ds_ Dialog styles es_ Edit c o n t r o l styles lbs_ List b o x styles sbs_ Scroll b a r styles ss_ Static c o n t r o l styles ws_ Window styles
X, Y
S t a r t i n g w i n d o w p o s i t i o n o r cwJJseDefault
Width
Starting w i n d o w w i d t h (in device units)
Height
Starting w i n d o w height (in device units)
WndParent
Owner window
Menu
M e n u o r c h i l d - w i n d o w identifier
Instance
Associated m o d u l e instance
Param
V a l u e p a s s e d i n TCreateStruct i n lParam o f t h e w m C r e a t e m e s s a g e ; this m u s t b e a p o i n t e r t o a TClientCreateStruct f o r MDI c l i e n t w i n d o w c r e a t i o n
Return Value: W i n d o w i d e n t i f i e r if s u c c e s s f u l ; e l s e 0 .
CreateWindowEx function CreateWindowEx(ExStyle: Longint; ClassName, WindowName: PChar; Style: Longint; X, Y, Width, Height: Integer; WndParent: HWnd; Menu: HMenu; Instance: THandle; Param: Pointer): HWnd; C r e a t e s a p o p - u p , o v e r l a p p e d , o r c h i l d w i n d o w w i t h a n e x t e n d e d style.
714
Part I I I — R e f e r e n c e s
Parameters
Description
ExStyle
O n e of t h e ws_ex_ Extended w i n d o w styles' c o n s t a n t s
ClassName
W i n d o w class n a m e ( n u l l - t e r m i n a t e d ) o r a p r e d e f i n e d control-class n a m e
WindowName
W i n d o w caption o r n a m e (null-terminated)
Style
O n e o r a c o m b i n a t i o n o f w i n d o w o r c o n t r o l style c o n stants: bs_ Button styles cbs_ Combo b o x styles ds_ Dialog styles es_ Edit c o n t r o l styles lbs_ List b o x styles sbs_ Scroll b a r styles ss_ Static c o n t r o l styles ws_ Window styles
X, Y
S t a r t i n g w i n d o w p o s i t i o n o r cw_UseDef ault
Width
S t a r t i n g w i n d o w w i d t h (in d e v i c e u n i t s )
Height
S t a r t i n g w i n d o w h e i g h t (in d e v i c e u n i t s )
WndParent
Owner window
Menu
M e n u o r child-window identifier
Instance
Associated m o d u l e instance
Param
V a l u e p a s s e d i n TCreateStruct i n lParam o f t h e wmCreate message, must be a pointer to a TClientCreateStruct f o r MDI c l i e n t w i n d o w c r e a t i o n
Return Value: W i n d o w identifier if s u c c e s s f u l ; e l s e 0.
DefDlgProc function DefDlgProc(Dig: HWnd; Msg, wParam: Word; lParam: Longint): Longint; H a n d l e s d e f a u l t p r o c e s s i n g f o r d i a l o g s w i t h a private w i n d o w class. Parameters
Description
Dig
D i a l o g b o x identifier
Msg
Message number
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
Description
wParam
Message-dependent information
lParam
Message-dependent information
Return Value: Result o f the message processing.
DefframeProc function DefFrameProc(Wnd, MDIClient: HWnd; Msg, wParam: Word; lParam: Longint): Longint; H a n d l e s d e f a u l t m e s s a g e p r o c e s s i n g f o r MDI f r a m e w i n d o w s . Parameters
Description
Wnd
MDI f r a m e w i n d o w
MDIClient
MDI c l i e n t w i n d o w
Msg
Message number
wParam
Message-dependent information
lParam
Message-dependent information
Return Value: Result o f message processing.
DeM)IChildProc function DefMDIChildProc(Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint; H a n d l e s d e f a u l t m e s s a g e p r o c e s s i n g f o r MDI c h i l d w i n d o w s . Parameters
Description
Wnd
MDI c h i l d w i n d o w
Msg
Message number
wParam
Message-dependent information
lParam
Message-dependent information
Return Value: Result o f the message processing.
715
716
Part H I — R e f e r e n c e s
DefVTindowProc function DefWindowProc(Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint; H a n d l e s default message processing for any messages n o t explicitly h a n d l e d b y an application. Parameters
Description
Wnd
W i n d o w identifier
Msg
Message number
wParam
Message-dependent information
lParam
Message-dependent information
Return Value: R e s u l t of t h e m e s s a g e p r o c e s s i n g .
Destroy^ndow function DestroyWindow(Wnd: HWnd): Bool; D e s t r o y s a w i n d o w or a m o d e l e s s d i a l o g box a n d a n y of its a s s o c i a t e d child windows. Parameters Wnd
Description Window
identifier
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
GetClassInfo function GetClassInfo(Instance: THandle; Classlnfo: PChar; var WndClass: TWndClass): Bool; G e t s class information for t h e s p e c i f i e d class .TWndClass fields .IpszClassName, IpszMenuName, a n d hlnstance are n o t returned. Parameters
Description
Instance
A p p l i c a t i o n i n s t a n c e that created t h e class or 0 for a p r e d e f i n e d Windows class ClassName C l a s s n a m e ( n u l l - t e r m i n a t e d ) or I D
WndClass
TWndClass to receive class information
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Return Value: N o n z e r o if s u c c e s s f u l ; 0 if m a t c h i n g class is n o t f o u n d .
GetClassLong function GetClassLong(Wnd: HWnd; Index: Integer): Longint; G e t s t h e l o n g v a l u e at I n d e x f r o m a w i n d o w ' s TWndClass s t r u c t u r e . Positive b y t e offsets ( f r o m 0) t o a c c e s s e x t r a class b y t e s . Parameters
Description
Wnd
W i n d o w identifier
Index
B y t e offset o r t h e c o n s t a n t gcl_WndProc
Return Value: Value retrieved.
GetClassName function GetClassName(Wnd: HWnd; ClassName: PChar; MaxCount: Integer): Integer; G e t s a w i n d o w ' s class n a m e . Parameters
Description
Wnd
W i n d o w identifier
ClassName
B u f f e r t o r e c e i v e class n a m e
MaxCount
Size o f buffer
Return Value: N u m b e r o f c h a r a c t e r s c o p i e d ; 0 if t h e r e ' s a n e r r o r .
GetClassWord function GetClassWord(Wnd: HWnd, Index: Integer): Word; G e t s t h e w o r d v a l u e at Index f r o m a w i n d o w ' s TWndClass s t r u c t u r e . Positive b y t e offsets ( f r o m 0) t o a c c e s s e x t r a class b y t e s .
717
718
Part I I I — R e f e r e n c e s
Parameters
Description
Wnd
W i n d o w identifier
Index
B y t e offset o r o n e o f t h e gcw_ Class field offsets' constants
Return Value: Value retrieved.
GetLastActivePopup function GetLastActivePopup(WndOwner: HWnd): HWnd; G e t s t h e m o s t r e c e n t l y active p o p - u p w i n d o w . Parameters WndOwner
Description O w n i n g parent w i n d o w o f pop-up.
Return Value: P o p - u p w i n d o w identifier; WndOwner.
GetWindowLong function GetWindowLong(Wnd: HWnd; Index: Integer): Longint; G e t s i n f o r m a t i o n about a w i n d o w o r a w i n d o w ' s e x t r a b y t e v a l u e s . Parameters
Description
Wnd
W i n d o w identifier
Index
B y t e oTbf f set o r o n e o f t h e gwl_ Window field offsets
Return Value: Specified w i n d o w information.
GetWindowWord function GetWindowWord(Wnd: HWnd; Index: Integer): Word; G e t s i n f o r m a t i o n a b o u t a w i n d o w o r window-class e x t r a b y t e v a l u e s .
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
Description
Wnd
W i n d o w identifier
Index
Positive b y t e offset o r o n e o f t h e gww_ Window offsets' c o n s t a n t s
field
Return Value: W o r d value.
RegisterClass function RegisterClass(var WndClass: TWndClass): Bool; Registers a w i n d o w class w h o s e attributes a r e s p e c i f i e d b y WndClass. Parameters WndClass
Description TWndClass s t r u c t u r e
Return Value: N o n z e r o if class r e g i s t e r e d ; e l s e 0.
SetClassLong function SetClassLong(Wnd: HWnd; Index: NewLong: Longint): Longint;
Integer;
Replaces the l o n g value specified by I n d e x in the w i n d o w ' s structure. Parameters
TWndClass
Description
Wnd
W i n d o w identifier
Index
O n e o f t h e gcl_ Class field offsets o r p o s i t i v e b y t e offset t o set e x t r a 4-byte v a l u e s
NewLong
Replacement value
Return Value: Previous value.
719
720
Part I I I — R e f e r e n c e s
SetClassWord function SetClassWord(Wnd: HWnd; Index: Integer; NewWord: Word): Word; R e p l a c e s t h e w o r d v a l u e s p e c i f i e d b y Index i n t h e w i n d o w ' s TWndClass structure. Parameters
Description
Wnd
W i n d o w identifier
Index
O n e of t h e gcw_ Class field o f f s e t s o r p o s i t i v e b y t e offset t o set e x t r a 2-byte v a l u e
NewWord
Replacement value
Return Value: Previous value.
SetWindowLong function SetWindowLong(Wnd: HWnd; Index: Integer; NewLong: Longint): Longint; R e p l a c e s a n attribute o f a w i n d o w ' s w i n d o w - c l a s s s t r u c t u r e w i t h a n e w v a l u e . Parameters
Description
Wnd
W i n d o w identifier
Index
O n e of t h e gwl_ Window f i e l d offsets o r p o s i t i v e b y t e offset t o a c c e s s e x t r a 4-byte v a l u e s
NewLong
Replacement value
Return Value: Previous value.
SetWindowWord function SetWindowWord(Wnd: HWnd; Index: Integer; NewWord: Word): Word; C h a n g e s t h e v a l u e of a n attribute ( s p e c i f i e d b y Index) i n a w i n d o w ' s w i n d o w class s t r u c t u r e .
L — W i n d o w M a n a g e r Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
721
Description
Wnd
W i n d o w identifier
Index
O n e of t h e gww_ Window f i e l d offsets o r p o s i t i v e b y t e offset t o a c c e s s e x t r a 2-byte v a l u e s
NewWord
Replacement value
Return Value: Previous value.
UnregisterClass function UnregisterClass(ClassName: PChar; Instance: THandle): Bool; D e l e t e s a w i n d o w class f r o m t h e w i n d o w - c l a s s t a b l e a n d frees a n y a s s o c i a t e d memory. Parameters
Description
ClassName
Class n a m e (null-terminated) o f a previously registered class
Instance
M o d u l e i n s t a n c e that c r e a t e d t h e class
Return Value: N o n z e r o if s u c c e s s f u l ; 0 if i n v a l i d ClassName.
M REFERENCE
SYSTEM SERVICES INTERFACE P R O C E D U R E S A N D FUNCTIONS
A l p h a b e t i c a l listing o f S y s t e m Services I n t e r f a c e p r o c e d u r e s a n d f u n c t i o n s :
Application-Execution Atom-Management Communication File I/O Initialization-File Memory-Management Module-Management
Operating-System Interrupt Resource-Management Segment Sound String-Manipulation Task Utility Macros
Application-Execution Functions LoadModule WinExec WinHelp
724
Part I I I — R e f e r e n c e s
LoadModule function
LoadModule(ModuleName:
PChar;
ParameterBlock:
Pointer):
Loads and runs a Windows application. Parameters
Description
ModuleName
A p p l i c a t i o n file n a m e ( n u l l - t e r m i n a t e d )
ParameterBlock
F o u r field s t r u c t u r e
EnvSeg
Word, e n v i r o n m e n t s e g m e n t a d d r e s s o r 0 f o r Windows environment
CmdLine
L o n g i n t , c o m m a n d line
CmdShow
L o n g i n t , t w o W o r d - l e n g t h s t r u c t u r e , first w o r d set t o 2 , s e c o n d set t o CmdShow o f ShowWindow
Reserved
L o n g i n t , must be 0
Return Value: Library m o d u l e i n s t a n c e i d e n t i f i e r (value g r e a t e r t h a n 32) if s u c c e s s f u l . If n o t , its v a l u e is less t h a n 3 2 , a n d o n e o f t h e f o l l o w i n g : (0) n o m e m o r y (5) a t t e m p t t o l i n k task (6) m u l t i p l e d a t a s e g m e n t s (10) i n v a l i d W i n d o w s v e r s i o n (11) i n v a l i d E X E file (12) O S / 2 a p p (13) D O S 4 . 0 a p p (14) i n v a l i d E X E t y p e (15) n o t p r o t e c t m o d e
WinExec function WinExec(CmdLine: PChar; CmdShow: Word): Word; E x e c u t e s a n a p p l i c a t i o n s p e c i f i e d b y CmdLine. Parameters CmdLine
Description C o m m a n d line to execute the application (null-terminated)
CmdShow
S p e c i f i e s how a n a p p l i c a t i o n w i n d o w is initially
displayed
THandle;
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
Return
Value:
V a l u e g r e a t e r t h a n 3 2 if s u c c e s s f u l ; o t h e r w i s e it r e t u r n s o n e o f t h e f o l l o w i n g : (0) n o m e m o r y (5) a t t e m p t e d t o d y n a m i c a l l y l i n k t o a task (6) library h a s m u l t i p l e d a t a s e g m e n t s (10) W i n d o w s v e r s i o n i n c o r r e c t (11) invalid E X E file (12) O S / 2 a p p l i c a t i o n (13) D O S 4 . 0 a p p l i c a t i o n (14) u n k n o w n E X E t y p e (15) n o t a p r o t e c t e d - m o d e a p p l i c a t i o n
WinHdp function WinHelp(Wnd: HWnd; HelpFile: PChar; Command: Word; Data: Longint): Bool; Invokes Windows
help engine w i t h a c o m m a n d specified by Command.
Parameters
Description
Wnd
Window
identifier
HelpFile
N a m e ( n u l l - t e r m i n a t e d ) o f help p a t h , if n e e d e d
Command
O n e of the help_ H e l p c o m m a n d s
Data
Context identifier n u m b e r if Command set to help_Context or help topic keyword ( n u l l t e r m i n a t e d ) if Command set to help_Key
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0
Atom-Management Procedures and Functions AddAtom DeleteAtom FindAtom
file
including
725
726
Part I I I — R e f e r e n c e s
GetAtomHandle GetAtomName GlobalAddAtom GlobalDeleteAtom GlobalFindAtom GlobalGetAtomName InitAtomTable MakelntAtom
AddAtom function AddAtom(Str: PChar): Atom; A d d s Str to t h e a t o m t a b l e . A reference count is m a i n t a i n e d for e a c h unique string i n s t a n c e . Parameters Str
Description Null-terminated character string
Return Value: U n i q u e a t o m i d e n t i f i e r if s u c c e s s f u l ; e l s e - 1 .
DeleteAtom function DeleteAtom(AnAtom: Atom): Atom; D e l e t e s an a t o m . If the Atom's reference count is zero, the a s s o c i a t e d string is removed from the a t o m t a b l e . Parameters AnAtom
Description A t o m identifier
Return Value: Zero if successful; else Atom.
FindAtom function FindAtom(Str: PChar): Atom; S e a r c h e s t h e atom t a b l e for t h e atom a s s o c i a t e d with Str. Parameters
Str
Description
Search string (null-terminated)
M — S y s t e m Services Interface Procedures and Functions
727
Return Value: A t o m associated w i t h S t r ; 0 if a t o m isn't f o u n d in table.
GetAtomHandle function
GetAtomHandle(AnAtom:
Atom):
THandle;
G e t s t h e string that c o r r e s p o n d s to a specified atom. Parameters AnAtom Return Value: Local m e m o r y handle
Description A t o m identifier
to atom string; 0 if t h e atom d o e s not exist.
GetAtomName function
GetAtomName(AnAtom:
Atom;
Buffer:
PChar;
Size:
Integer):
C o p i e s t h e associated a t o m string into B u f f e r . Parameters
Description
AnAtom
A t o m identifier
Buffer
Buffer to receive atom string
Size
Buffer size (in bytes)
Return Value: N u m b e r o f bytes c o p i e d into B u f f e r ; 0 if an invalid atom was specified.
GlobalAddAtom function
GlobalAddAtom(Str:
PChar):
Atom;
A d d s S t r to t h e atom table, t h u s creating a n e w global atom. Parameters Str
Description String (null-terminated)
Return Value: N e w l y created a t o m ; 0 if error.
Word;
728
Part III—References
GlobalDeleteAtom function GlobalDeleteAtom(AnAtom: Atom): Atom; Decreases a global atom's reference count by one, deleting the atom and its associated string from the atom table if the reference count becomes 0. Parameters
AnAtom Return
Description
A t o m identifier
Value:
Zero if successful; else AnAtom.
GlobalFindAtom function GlobalFindAtom(Str: PChar): Atom; Gets the global atom associated with Str. Parameters
Str Return
Description
Search string (null-terminated) Value:
Global atom; 0 if Str is not in the table.
GlobalGetAtomName function GlobalGetAtomName(AnAtom: Atom; Buffer: PChar; Size: Integer): Word; Copies the string associated with AnAtom into Buffer. Parameters
Description
AnAtom
A t o m identifier
Buffer
Receive buffer
Size
Size of Buffer
Return
Value:
N u m b e r of bytes copied; 0 if AnAtom is not valid.
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
InitAtomTable function InitAtomTable(Size: Integer): Bool; Initializes t h e a t o m h a s h t a b l e a n d sets its size. D e f a u l t is 3 7 . Parameters Size
Description N u m b e r o f table entries in a t o m hash table (should be a prime)
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0 .
MakelntAtom (type) MakelntAtom = PStr; U s e MakelntAtom f o r t y p e c a s t i n g i n t e g e r n u m b e r s i n t o a t o m s . T h i s is e q u i v a l e n t t o t y p e c a s t i n g i n t o t h e T u r b o Pascal t y p e PChar.
Communication Procedures and Functions BuildCommDCB ClearCommBreak CloseComm EscapeCommFunction FlushComm GetCommError GetCommEventMask GetCommState OpenComm ReadComm SetCommBreak SetCommEventMask SetCommState TransmitCommChar UngetCommChar WriteComm
729
730
Part I I I — R e f e r e n c e s
BuildCommDCB function BuildCommDCB(Def: PChar; var DCB: TDCB): Integer; T r a n s l a t e s Def i n t o a p p r o p r i a t e d e v i c e - c o n t r o l b l o c k c o d e s that are c o p i e d i n t o DCB. Parameters
Description
Def
D O S M O D E c o m m a n d line (null-terminated) of device-control information
DCB
R e c e i v i n g TDCB s t r u c t u r e
Return Value: Z e r o if Def is t r a n s l a t e d ; e l s e n e g a t i v e .
ClearCommBreak function ClearCommBreak(Cid:
Integer): Integer;
R e s t o r e s c h a r a c t e r t r a n s m i s s i o n a n d p l a c e s t h e l i n e i n a n o n - b r e a k state. Parameters Cid
Description C o m m u n i c a t i o n device to b e restored
Return Value: Z e r o , if s u c c e s s f u l ; n e g a t i v e if Cid is n o t a v a l i d d e v i c e .
CloseComm function CloseComm(Cid: Integer): Integer; C l o s e s Cid, f l u s h i n g t h e o u t p u t q u e u e . F r e e s a n y m e m o r y u s e d f o r t r a n s m i t a n d receive q u e u e s . Parameters Cid
Description C o m m u n i c a t i o n s device
Return Value: Z e r o if d e v i c e is c l o s e d ; n e g a t i v e if e r r o r .
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
EscapeCommFunction function EscapeCommFunction(Cid, Func: Integer): Integer; E x e c u t e s t h e e x t e n d e d f u n c t i o n s p e c i f i e d b y Func o n a c o m m u n i c a t i o n s d e v i c e . Parameters
Description
Cid
C o m m u n i c a t i o n s device
Func
O n e o f t h e EscapeComm c o n s t a n t s
Return Value: Z e r o if s u c c e s s f u l ; n e g a t i v e if ab i n v a l i d f u n c t i o n c o d e w a s s p e c i f i e d .
FlushComm function FlushComm(Cid, Queue: Integer): Integer; Flushes a c o m m u n i c a t i o n device's transmit o r receive q u e u e . Parameters Cid Queue
Description C o m m u n i c a t i o n s device to b e
flushed
Z e r o t o flush t r a n s m i t q u e u e o r 1 t o flush receive q u e u e
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0 .
GetCommError function GetCommError(Cid: Integer; var Stat: TComStat): Integer; Clears a device c o m m u n i c a t i o n s error. Parameters
Description
Cid
Communications device
Stat
TComStat t o r e c e i v e d e v i c e status i n f o r m a t i o n or nil
Return Value: O n e o f t h e ce_ Comm e r r o r flags' c o n s t a n t s .
731
732
Part III—References
GetCommEventMask function
GetCommEventMask(Cid,
EvtMask:
Integer):
Word;
G e t s a d e v i c e ' s c u r r e n t e v e n t m a s k , t h e n clears it. Parameters
Description
Cid
C o m m u n i c a t i o n s device
EvtMask
Events to be enabled
Return Value: Current event mask value.
GetCommState function
GetCommState(Cid:
Integer;
v a r DCB: T D C B ) :
Integer;
Gets a device's device control block. Parameters
Description
Cid
Communications device
DCB
TDCB t o r e c e i v e t h e c u r r e n t d e v i c e c o n t r o l block
Return Value: Z e r o if s u c c e s s f u l ; e l s e n e g a t i v e .
OpenComm function
OpenComm(ComName:
PChar;
InQueue,
OutQueue: Word):
Integer
O p e n s a c o m m u n i c a t i o n s d e v i c e . T h e d e v i c e is initialized t o a d e f a u l t c o n f i g u r a t i o n . T r a n s m i t a n d r e c e i v e q u e u e s are a l l o c a t e d . Parameters ComName
Description S t r i n g c o n t a i n i n g C O M n o r L P T n , w h e r e n is an integer
InQueue
R e c e i v e q u e u e size o r i g n o r e d f o r L P T p o r t s
OutQueue
T r a n s m i t q u e u e size o r i g n o r e d f o r L P T p o r t s
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
Return Value: Cid h a n d l e if s u c c e s s f u l ; e l s e n e g a t i v e e r r o r v a l u e ( o n e o f t h e ie_ c o m m u n i c a t i o n e r r o r flags).
733
Open
ReadComm function ReadComm(Cid: Integer; Buf: PChar, Size: Integer): Integer; R e a d s Cid a n d c o p i e s u p t o Size c h a r a c t e r s i n t o Buf. Parameters
Description
Cid
C o m m u n i c a t i o n s device
Buf
Receiving buffer
Size
Size o f Buffer
Return
Value:
N u m b e r o f c h a r a c t e r s r e a d ; 0 if n o c h a r a c t e r s a r e i n t h e r e c e i v e q u e u e ; n e g a t i v e if e r r o r .
SetCommBreak function SetCommBreak(Cid: Integer): Integer; Suspends character transmission a n d places the device's transmission line in a b r e a k state. Parameters Cid
Description C o m m u n i c a t i o n s device
Return Value: Z e r o if s u c c e s s f u l ; n e g a t i v e if i n v a l i d Cid.
SetCommEventMask function SetCommEventMask(Cid:
Integer; EvtMask: Word): PWord;
Activates a n d g e t s t h e c u r r e n t state o f a d e v i c e ' s e v e n t m a s k . Parameters Cid EvtMask
Description C o m m u n i c a t i o n s device A n y c o m b i n a t i o n of ev_ Comm e v e n t c o n s t a n t s
734
Part I I I — R e f e r e n c e s
Return
Value:
P o i n t e r t o a n e v e n t m a s k ; e a c h set bit i n d i c a t e s a n o c c u r r e n c e o f t h e e v e n t .
SetCommState function SetCommState(var DCB: TDCB): Integer; Reinitializes a c o m m u n i c a t i o n s d e v i c e s p e c i f i e d b y t h e Id field o f DCB t o t h e state s p e c i f i e d b y DCB. T r a n s m i t a n d r e c e i v e q u e u e s a r e n o t a f f e c t e d . Parameters DCB Return
Description TDCB s t r u c t u r e
Value:
Z e r o if s u c c e s s f u l ; e l s e n e g a t i v e .
TfonsmitCommChar function TransmitCommChar(Cid:
Integer; AChar: Char): Integer;
P u t s AChar at t h e h e a d o f t h e c o m m u n i c a t i o n d e v i c e ' s t r a n s m i t q u e u e f o r immediate transmission. Parameters
Description
Cid
C o m m u n i c a t i o n s device
AChar
Character t o transmit
Return
Value:
Z e r o if s u c c e s s f u l ; n e g a t i v e if t r a n s m i s s i o n is n o t p o s s i b l e b e c a u s e t h e p r e v i o u s character has n o t b e e n sent.
UngetCommChar function UngetCommChar(Cid: Integer; AChar: Char): Integer; P u t s AChar b a c k i n t o c o m m u n i c a t i o n d e v i c e ' s r e c e i v i n g q u e u e . Parameters
Description
Cid
C o m m u n i c a t i o n s device
AChar
Character to Un g et
Return Value: Z e r o if s u c c e s s f u l ; e l s e n e g a t i v e .
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
735
WriteComm f u n c t i o n WriteComm(Cid:
Integer;
Buf: PChar;
Size:
Integer):
Integer;
O u t p u t s the buffer specified by Buf to a c o m m u n i c a t i o n s device. Parameters
Description
Cid
C o m m u n i c a t i o n s device
Buf
Buffer containing characters t o b e written
Size
N u m b e r o f characters t o o u t p u t
Return Value: N u m b e r of characters written; negative if error has an absolute value that equals the n u m b e r of characters written before the error occurred.
File I/O Procedures and Functions GetDriveType GetSystemDirectory GetTempDrive GetTempFileName GetWindowsDirectory _lclose _lcreat _llseek _lopen _lread _lwrite OpenFile SetHandleCount
GetDriveType function GetDriveType(Drive: Integer): Word; Decides whether Drive is removeable, fixed, or remote. Parameters Drive
Description Drive to check (A is 0, B is 1, and so on.)
736
Part I I I — R e f e r e n c e s
Return
Value:
O n e of t h e drive_ Drive t y p e s c o n s t a n t s ; 0 if drive c a n n o t b e d e t e r m i n e d ; 1 if drive d o e s n o t exist.
GetSystemDirectory procedure GetSystemDirectory(Buffer:
PChar; Size: Word);
Gets the W i n d o w s system subdirectory path n a m e . Parameters
Description
Buffer
Receiving buffer
Size
S i z e o f B u f f e r (at least 144 c h a r a c t e r s )
GetTempDrive function GetTempDrive(DriveLetter: Char): Char; G e t s t h e d i s k d r i v e that h a s t h e o p t i m a l a c c e s s t i m e f o r t e m p o r a r y file operations. Parameters DriveLetter
Description D i s k drive letter o r 0 t o r e t u r n c u r r e n t drive
Return Value: D i s k drive letter.
GetTempFileName function GetTempFileName(DriveLetter:
Char; PrefixString: PChar;
Unique: Word; TempFileName: PChar): Integer; D e r i v e s a u n i q u e t e m p o r a r y file n a m e w i t h a p a t h n a m e of e i t h e r t h e r o o t d i r e c t o r y o r t h e d i r e c t o r y s p e c i f i e d b y t h e TEMP e n v i r o n m e n t v a r i a b l e . Parameters
Description
DriveLetter
S u g g e s t e d drive o r t f F o r c e D r i v e b i t - o r - e d with suggested drive o r 0 for default drive
PrefixString
File name t h r e e c h a r a c t e r p r e f i x ( n u l l terminated)
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters Unique
Description Base file-name n u m e r i c value, o r 0 for systemderived value
TempFileName
R e c e i v i n g p a t h - n a m e b u f f e r (at least 144 b y t e s long)
Return Value: File n a m e ' s n u m e r i c v a l u e .
Get^dowsDirectory function GetWindowsDirectory(Buffer:
PChar; Size: Word): Word;
G e t s the W i n d o w s directory path n a m e . Parameters
Description
Buffer
Receiving path n a m e buffer
Size
S i z e o f B u f f e r ( s h o u l d b e at least 144 b y t e s long)
Return Value: L e n g t h of t h e string c o p i e d i n t o Buffer.
Jclose function _lclose(FileHandle:
Integer): Integer;
C l o s e s a s p e c i f i e d file. Parameters FileHandle
Description D O S file h a n d l e
Return Value: Z e r o if s u c c e s s f u l ; e l s e - 1 .
lcreat function _lcreat(PathName: PChar; Attribute: O p e n s t h e s p e c i f i e d file.
Integer):Integer;
737
738
Part I I I — R e f e r e n c e s
Parameters
Description
Path n a m e
T h e D O S p a t h n a m e o f t h e file t o b e o p e n e d
Attribute
O n e of: (0) r e a d o r w r i t e , (1) r e a d o n l y , (2) h i d d e n , o r (3) s y s t e m file
Return
Value:
D O S file h a n d l e if s u c c e s s f u l ; e l s e - 1 .
Jlseek function _llseek(FileHandle: Integer; Offset: Longint; Origin: Integer): Longint; P o s i t i o n s t h e p o i n t e r i n a n o p e n file. Parameters
Description
FileHandle
D O S file h a n d l e
Offset
N u m b e r o f bytes t o m o v e the pointer
Origin
S p e c i f i e s t h e starting p o i n t a n d d i r e c t i o n o f t h e m o v e : (0) f o r w a r d f r o m t h e b e g i n n i n g , (1) f r o m t h e c u r r e n t p o s i t i o n , o r (2) b a c k f r o m t h e e n d o f t h e file
Return Value: T h e n e w offset o f t h e p o i n t e r ; - 1 if u n s u c c e s s f u l .
Jopen function _lopen(PathName: PChar; ReadWrite: Integer): Integer; O p e n s a file. Parameters
Description
Path n a m e
S t r i n g s p e c i f y i n g t h e p a t h a n d file n a m e
ReadWrite
Specifies the read a n d write access; o n e o f the f o l l o w i n g of _ Open file c o n s t a n t s : of_Read of_ReadWrite of Write
Return Value: T h e D O S file h a n d l e if s u c c e s s f u l ; e l s e - 1 .
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
Jread function _lread(FileHandle: Bytes: Integer): Word;
Integer; Buffer: PChar;
R e a d bytes f r o m a n o p e n file. Parameters
Description
FileHandle
T h e D O S file h a n d l e
Buffer
Receiving buffer
Bytes
T h e n u m b e r o f bytes t o read
Return Value: T h e n u m b e r o f b y t e s r e a d , if s u c c e s s f u l ; - 1 if n o t ; 0 if at t h e e n d o f file.
Jwrite function _lwrite(FileHandle: Bytes: Integer): Word;
Integer; Buffer: PChar;
W r i t e s d a t a f r o m Buffer i n t o t h e s p e c i f i e d file. Parameters
Description
FileHandle
D O S file h a n d l e
Buffer
H o l d s the data to b e written
Bytes
T h e n u m b e r o f bytes t o b e written
Return Value: T h e n u m b e r o f b y t e s w r i t t e n t o t h e file, if s u c c e s s f u l ; e l s e - 1 .
OpenFile function OpenFile(FileName: PChar; var ReOpenBuff: TOFStruct; Style: Word):
Integer;
C r e a t e s , o p e n s , r e o p e n s , o r d e l e t e s a file. Parameters
Description
File N a m e
T h e s p e c i f i e d file n a m e
ReOpenBuff
R e c e i v e s i n f o r m a t i o n a b o u t file w h e n o p e n e d
Style
S p e c i f i e s t h e a c t i o n ; o n e o f t h e of constants
Open file
739
740
Part I I I — R e f e r e n c e s
Return
Value:
D O S file h a n d l e if s u c c e s s f u l ; e l s e - 1 .
SetHandleCount function SetHandleCount(Number: Word): Word; C h a n g e s t h e n u m b e r o f file h a n d l e s available t o a task t o t h e v a l u e s p e c i f i e d b y Number. Parameters Number
Description N u m b e r o f r e q u i r e d file h a n d l e s ( m a x i m u m o f 255)
Return Value: N u m b e r o f file h a n d l e s a v a i l a b l e .
Initialization-File Procedures and Functions GetPrivateProfilelnt GetPrivateProfileString GetProfilelnt GetProfileString WritePrivateProfileString WriteProfileString
GetPrivateProfilelnt function GetPrivateProfilelnt(ApplicationName, Default: Integer; FileName: PChar): Word;
KeyName: PChar;
G e t s a n i n t e g e r k e y v a l u e f r o m a s p e c i f i e d i n i t i a l i z a t i o n file. Parameters
Description
ApplicationName
A p p l i c a t i o n h e a d i n g n a m e i n FileName
KeyName
Key n a m e i n FileName
Default
D e f a u l t v a l u e if KeyName n o t f o u n d
File N a m e
I n i t i a l i z a t i o n file n a m e i n W i n d o w s d i r e c t o r y
Return Value: Key v a l u e ; 0 if n e g a t i v e o r if Key v a l u e isn't a n i n t e g e r .
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
741
GetPrivateProfileString function GetPrivateProfileString(ApplicationName, KeyName, Default, ReturnedString: PChar; Size: Integer; FileName: PChar): Integer; G e t s a string k e y v a l u e f r o m a s p e c i f i e d i n i t i a l i z a t i o n file. Parameters
Description
ApplicationName
A p p l i c a t i o n h e a d i n g n a m e i n FileName
KeyName
Key n a m e i n FileName o r n i l t o o b t a i n list o f key names
Default
D e f a u l t v a l u e if KeyName n o t f o u n d
ReturnedString
Receiving buffer
Size
Size o f Buffer
File N a m e
I n i t i a l i z a t i o n file n a m e i n W i n d o w s d i r e c t o r y
Return
Value:
N u m b e r o f characters c o p i e d .
GetProfilelnt function GetProfilelnt(AppName,
KeyName: PChar; Default: Integer): Word;
G e t s a n i n t e g e r k e y v a l u e f r o m W i n d o w s W I N . I N I file. Parameters
Description
AppName
Application heading name
KeyName
Search key name
Default
D e f a u l t v a l u e if KeyName is n o t f o u n d
Return Value: K e y v a l u e ; 0 if n e g a t i v e o r if k e y v a l u e isn't a n i n t e g e r .
GetProfileString function GetProfileString(AppName, KeyName, Default, ReturnedString: PChar; Size: Integer): Integer;
742
Part I I I — R e f e r e n c e s
G e t s a string k e y v a l u e f r o m W i n d o w s W I N . I N I file Parameters AppName KeyName
Description Application heading name S e a r c h k e y n a m e o r n i l t o o b t a i n all k e y n a m e s a s s o c i a t e d w i t h AppName
Default
D e f a u l t v a l u e if KeyName n o t f o u n d
ReturnedString
Receiving buffer
Size
Size o f Buffer
Return Value: N u m b e r o f characters c o p i e d .
WritePrivateProfileString function WritePrivateProfileString(ApplicationName, KeyName, Str, FileName: PChar): Bool; S e a r c h e s FileName f o r a s p e c i f i e d a p p l i c a t i o n h e a d i n g a n d k e y n a m e ; t h e n r e p l a c e s t h e Key n a m e w i t h Str. Parameters
Description
ApplicationName
Application heading name
KeyName
Key n a m e appearing under the application heading n a m e o r nil to delete entire section
Str
N e w k e y n a m e string o r n i l t o d e l e t e k e y n a m e
File n a m e
I n i t i a l i z a t i o n file n a m e ( n u l l - t e r m i n a t e d )
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
WritePfoffleString function WriteProfileString(ApplicationName,
KeyName, Str: PChar): Bool;
Searches W I N . I N I for the specified application heading a n d key n a m e ; then r e p l a c e s t h e k e y n a m e w i t h St r.
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
Parameters
Description
ApplicationName
Application heading
KeyName
Key n a m e appearing u n d e r the application h e a d i n g n a m e , or nil to delete entire application section
Str
N e w key n a m e value or nil to delete key n a m e
Return Value: N o n z e r o if s u c c e s s f u l ; e l s e 0.
Memory-Management Procedures and Functions DefineHandleTable GetFreeSpace GetWinFlags GlobalAlloc GlobalCompact GlobalDiscard GlobalDosAlloc GlobalDosFree GlobalFlags GlobalFree GlobalHandle GlobalLock GlobalLRUNewest GlobalLRUOldest GlobalNotify GlobalReAlloc GlobalSize GlobalUnlock GlobalUnwire GlobalWire LimitEMSPages LocalAlloc LocalCompact LocalDiscard LocalFlags LocalFree LocalHandle
743
744
Part I I I — R e f e r e n c e s
Locallnit LocalLock LocalReAlloc LocalShrink LocalSize LocalUnlock LockData LockSegment SetSwapAreaSize SwitchStackBack SwitchStackTo UnlockData UnLockSegment
DefineHandleTable function
DefineHandleTable(Offset:
Word):
Bool;
C r e a t e s a private h a n d l e t a b l e i n t h e d e f a u l t d a t a s e g m e n t . T h e t a b l e h o l d s t h e a d d r e s s e s o f l o c k e d g l o b a l m e m o r y o b j e c t s , r e t u r n e d b y G l o b a l L o c k . If t h e s e m e m o r y o b j e c t s are m o v e d , W i n d o w s u p d a t e s t h e i r a d d r e s s e s w h e n r u n n i n g i n r e a l m o d e . A d d r e s s e s a r e n ' t u p d a t e d i n p r o t e c t e d m o d e s ( S t a n d a r d a n d 386Enhanced). T h e h a n d l e t a b l e c o n s i s t s o f t w o W o r d - t y p e v a l u e s f o l l o w e d b y a n array o f addresses. • T h e first w o r d is t h e n u m b e r o f e n t r i e s i n t h e t a b l e , w h i c h m u s t b e initialized b e f o r e t h e call t o D e f i n e H a n d l e T a b l e . • T h e s e c o n d is t h e n u m b e r o f e n t r i e s t o set t o 0 w h e n W i n d o w s u p d a t e s its list o f least r e c e n t l y u s e d m e m o r y . E i t h e r w o r d c a n b e c h a n g e d at a n y t i m e . T h e a d d r e s s e s i n t h e rest o f t h e t a b l e are r e t u r n e d b y G l o b a l L o c k . Parameters Offset
Description T h e offset o f t h e t a b l e f r o m t h e b e g i n n i n g o f t h e d a t a s e g m e n t . A v a l u e o f 0 i n d i c a t e s that W i n d o w s s h o u l d n o l o n g e r u p d a t e the table
Return
Value:
Z e r o if s u c c e s s f u l ; e l s e n o n z e r o .
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
GetFreeSpace function
GetFreeSpace(Flag:
Word):
Longint;
G e t s t h e a m o u n t o f free m e m o r y in t h e g l o b a l Parameters
Description
Flag
Return
heap.
T h e constant gmem_Not_Banked to scan below b a n k l i n e o r 0 t o s c a n a b o v e ; ignored f o r n o n E M S systems Value:
M e m o r y available (in b y t e s ) .
GetWinFlags function
GetWinFlags:
Longint;
G e t s t h e m e m o r y - c o n f i g u r a t i o n flags i n effect d u r i n g t h e c u r r e n t W i n d o w s session. Return Value: Flag mask specifying the current m e m o r y configuration; can include o n e of t h e f o l l o w i n g wf _ W i n d o w s m e m o r y c o n f i g u r a t i o n flags: wf_CPU286 wf_CPU386 wf_PMode wf_SmallFrame wf_Win286 wf
Win386
GlobalAlloc function
GlobalAlloc(Flags:
A l l o c a t e s requested Parameters Flags
Word;
Bytes:
Longint):
a m o u n t o f m e m o r y , at m i n i m u m , f r o m t h e g l o b a l Description F l a g m a s k ; o n e o r m o r e o f t h e gmem_ G l o b a l m e m o r y flags c o n s t a n t s
Bytes Return
THandle;
N u m b e r o f bytes to allocate Value:
A l l o c a t e d g l o b a l m e m o r y identifier;
0 if error.
heap.
745
746
Part I I I — R e f e r e n c e s
GlobalCompact function GlobalCompact(MinFree:
Longint): Longint;
C o m p a c t s global m e m o r y a n d , w h e n necessary a n d possible, d i s c a r d a b l e s e g m e n t s t o c r e a t e a MinFree size b l o c k . Parameters MinFree
Return
removes
Description D e s i r e d free b y t e s o r 0 t o r e t u r n largest free s e g m e n t , if all d i s c a r d a b l e s e g m e n t s a r e removed
Value:
S i z e o f largest free b l o c k .
GlobalDLscard function GlobalDiscard(Mem: THandle): THandle; D i s c a r d s t h e s p e c i f i e d g l o b a l m e m o r y b l o c k if t h e b l o c k is d i s c a r d a b l e a n d unlocked. Parameters Mem
Description T h e handle of the global memory block to discard
Return Value: H a n d l e o f t h e b l o c k if s u c c e s s f u l l y d i s c a r d e d ; e l s e 0.
GlobalDosAlloc function GlobalDosAlloc(Bytes: Longint): Longint; A l l o c a t e s g l o b a l m e m o r y i n t h e first m e g a b y t e o f l i n e a r a d d r e s s s p a c e that c a n be accessed by D O S . A v o i d u s i n g this f u n c t i o n , if p o s s i b l e , b e c a u s e l o w m e m o r y is a s c a r c e system resource. Parameters Bytes Return
Description T h e n u m b e r o f bytes t o allocate
Value:
Z e r o if m e m o r y c o u l d n o t b e a l l o c a t e d ; e l s e , t h e v a l u e is a p a r a g r a p h - s e g m e n t value in the high-order word a n d a selector in the low-order word.
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
In Real m o d e , the paragraph-segment value c a n b e u s e d to access the allocated memory. I n protected m o d e , the selector should not b e used.
GlobalDosFree function GlobalDosFree(Selector: Word): Word; F r e e s a b l o c k o f m e m o r y a l l o c a t e d b y GlobalDosAlloc. Parameters Selector
Description T h e s e l e c t o r o f t h e m e m o r y t o free
Return Value: Z e r o if s u c c e s s f u l ; e l s e Selector.
GlobalFlags function GlobalFlags(Mem: THandle): Word; G e t s i n f o r m a t i o n a b o u t Mem. Parameters Mem Return
Description G l o b a l m e m o r y b l o c k identifier
Value:
I n h i g h b y t e : em_Ddeshare, gmem_Discardable, gmem_Discarded, o r gmem_Not_Banked. I n l o w b y t e : lock r e f e r e n c e - c o u n t .
GlobalFree function GlobalFree(Mem: THandle): THandle; F r e e s a n u n l o c k e d g l o b a l m e m o r y b l o c k a n d i n v a l i d a t e s its h a n d l e . Parameters Mem
Description G l o b a l m e m o r y b l o c k identifier
Return Value: Z e r o if s u c c e s s f u l ; e l s e Mem.
747
748
Part I I I — R e f e r e n c e s
GlobalHandle function GlobalHandle(Mem: Word): Longint; Gets the handle o f a global m e m o r y object with the specified segment address. Parameters Mem Return
Description Segment address
Value:
H a n d l e a n d s e g m e n t a d d r e s s i n l o w - a n d h i g h - w o r d , r e s p e c t i v e l y ; 0 if Handle d o e s n ' t exist.
GlobalLock function GlobalLock(Mem: THandle): Pointer; Increments the reference count o f a global m e m o r y block a n d returns a p o i n t e r t o it. Parameters Mem
Description G l o b a l m e m o r y b l o c k identifier
Return Value: M e m o r y b l o c k a d d r e s s if s u c c e s s f u l ; e l s e n i l .
GlobalLRUNewest function GlobalLRUNewest(Mem: THandle): THandle; R e d u c e s t h e c h a n c e a g l o b a l m e m o r y o b j e c t w i l l b e d i s c a r d e d b y m o v i n g it i n t o t h e n e w e s t , least r e c e n t l y u s e d m e m o r y p o s i t i o n . Parameters Mem Return Value: Z e r o if i n v a l i d Mem.
Description G l o b a l m e m o r y object identifier
M — S y s t e m Services Interface P r o c e d u r e s a n d F u n c t i o n s
GlobalLRUOldest function GlobalLRUOldest(Mem: THandle): THandle; I n c r e a s e s t h e c h a n c e a g l o b a l m e m o r y o b j e c t w i l l b e d i s c a r d e d b y m o v i n g it i n t o t h e o l d e s t , least recently u s e d m