home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 30 fixes_v / 30-fixes_v.zip / vxrxc21c.zip / PROGGUID.INF (.txt) < prev    next >
OS/2 Help File  |  1995-06-06  |  573KB  |  9,458 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Introduction ΓòÉΓòÉΓòÉ
  3.  
  4. Watcom VX-REXX is an application development system for OS/2 REXX that provides 
  5. visual design and programming tools to help you create OS/2 applications that 
  6. have a graphical user interface. An application can be saved as an executable 
  7. file so that others can use your application without requiring a copy of 
  8. VX-REXX. The development system can also be used to create macro or script 
  9. files to be used with other applications. 
  10.  
  11. This chapter outlines how to use this manual to help you learn about VX-REXX. 
  12. It also includes a list of additional sources of information that may help you 
  13. in developing applications. 
  14.  
  15.  
  16. ΓòÉΓòÉΓòÉ 1.1. What you should know before starting ΓòÉΓòÉΓòÉ
  17.  
  18. This manual assumes you have installed and used OS/2. This includes: 
  19.  
  20. o How to use a mouse. You should know that OS/2 uses both mouse buttons 1 and 2 
  21.   and how to use a mouse to click, double-click and drag objects. 
  22.  
  23. o How to open, close and move a window. 
  24.  
  25. o How to open a menu and choose items. 
  26.  
  27. o How to select items from a list. 
  28.  
  29. o How to use an OS/2 notebook to change settings. 
  30.  
  31. o How to use a folder. 
  32.  
  33. o How to use a template. 
  34.  
  35. If you are not familiar with these topics you should browse the OS/2 Glossary 
  36. or try the OS/2 Tutorial. The glossary and tutorial are contained in the 
  37. Information folder that was created when you installed OS/2. 
  38.  
  39. This manual does not teach the REXX language. Sample REXX code is included in 
  40. the example programs and a brief introduction to the language is included in 
  41. the Appendices. You should refer to a REXX manual for more detailed 
  42. information. Some suggested manuals are listed at the end of this chapter. 
  43.  
  44.  
  45. ΓòÉΓòÉΓòÉ 1.2. How to use this manual ΓòÉΓòÉΓòÉ
  46.  
  47. This manual provides the information you need to create applications with 
  48. VX-REXX. 
  49.  
  50. Before you read this manual, you should install VX-REXX following the 
  51. instructions in the "Setting up" chapter. 
  52.  
  53.  
  54. ΓòÉΓòÉΓòÉ 1.2.1. Organization ΓòÉΓòÉΓòÉ
  55.  
  56. This manual is divided into four parts: 
  57.  
  58. Getting Started 
  59.  
  60. Chapter 1, Introduction, provides an overview of the book and other sources of 
  61. information. 
  62.  
  63. Chapter 2, Setting up, tells you how to install VX-REXX 
  64.  
  65. Chapter 3, A simple program, gets you started right away by taking you through 
  66. the creation of a simple VX-REXX program. 
  67.  
  68. Programmer's Guide 
  69.  
  70. Chapters 4 to 7, the first part of the Programmer's Guide, contain the 
  71. information you require to create and manipulate VX-REXX projects. The first 
  72. chapter, Creating and running projects, gives an overview of a project and 
  73. describes creating, saving, and running projects. The next three chapters, 
  74. Adding objects to a window, Changing object properties, and Adding and 
  75. modifying routines explain the mechanics of designing VX-REXX projects. 
  76.  
  77. Chapters 8 to 12 explain how to program with objects. Chapter 8, Programming 
  78. with objects, describes general techniques and functions used with objects. 
  79. Chapter 9, Using objects, presents detailed information on using specific types 
  80. of objects. Chapter 10, Bitmaps, icons and resources, shows how to add bitmaps 
  81. and icons to your project. Chapter 11, Drag and drop operations, shows how to 
  82. add drag and drop capabilities to your projects. Chapter 12, Adding menus to a 
  83. program, shows how to add menus to a window. 
  84.  
  85. Chapter 13 describes the dialog and system functions provided to simplify 
  86. application development. The dialog functions allow you to create and process 
  87. predefined dialogs to display messages, prompt for input, select a font, and 
  88. select a file. The system functions access file and system services such as 
  89. file renaming and deleting. 
  90.  
  91. Chapter 14, Creating custom dialogs, describes how to create your own custom 
  92. dialogs by using modal windows. 
  93.  
  94. Chapter 15, Secondary windows, explains how to create a user interface where 
  95. several modeless windows are made available at the same time. 
  96.  
  97. Chapter 16, Multiple file projects, explains how to create and manage projects 
  98. that consist of multiple source files. It also includes information on window 
  99. and code files, and exchanging information between source files. 
  100.  
  101. Chapter 17, Adding help to a program, explains how to add help to your 
  102. application. 
  103.  
  104. Chapter 18, Debugging a project, explains how to debug programs using the 
  105. VX-REXX interactive debugger. 
  106.  
  107. Chapter 19, Extending VXΓêÖREXX, explains how VX-REXX can be extended using 
  108. object libraries and external function libraries. 
  109.  
  110. Chapter 20, Database 2 OS/2 with VXΓêÖREXX, shows how to create database 
  111. applications with VX-REXX by using the REXX interface to IBM's DB2/2 or Watcom 
  112. SQL. The techniques shown here to access the database are similar to those you 
  113. can use to access any package that supports a REXX interface. 
  114.  
  115. Chapter 21, Writing multithreaded applications, discusses the way to write 
  116. multithreaded applications. 
  117.  
  118. Chapter 22, Controlling other programs, explains how you can control and 
  119. communicate with other applications from your VX-REXX project. 
  120.  
  121. Chapter 23, Creating objects at run time, explains how objects can be created 
  122. dynamically at run time. 
  123.  
  124. Chapter 24, VXΓêÖREXX design time macros, explains how the VX-REXX design 
  125. environment can be extended with macros. 
  126.  
  127. Chapter 25, Distributing your projects, explains what is needed to distribute 
  128. your projects. 
  129.  
  130. Chapter 26, Samples, summarizes the sample programs that come with VX-REXX. 
  131.  
  132. Reference 
  133.  
  134. Chapters 27 to 32 provide a summary of all VX-REXX objects, properties, events, 
  135. methods, predefined routines, and functions. 
  136.  
  137. In addition, a complete alphabetic reference for all objects, properties, 
  138. events, methods, predefined routines, and functions is found online in the 
  139. VXΓêÖREXX Reference. 
  140.  
  141. Appendices 
  142.  
  143. Appendix A is a glossary of terms used in this book. 
  144.  
  145. Appendix B is a quick introduction to REXX which you can use either to start 
  146. learning the REXX language or to refresh your REXX skills. 
  147.  
  148. Appendix C contains a brief summary of the REXX programming language. 
  149.  
  150.  
  151. ΓòÉΓòÉΓòÉ 1.2.2. Syntax conventions ΓòÉΓòÉΓòÉ
  152.  
  153. Several conventions are used when presenting syntax information. 
  154.  
  155. o Bold and normal text indicate words that you must enter as shown: 
  156.  
  157.   say, VRSet, BackColor, and Red. 
  158.  
  159.   Unless specifically mentioned, the words must be spelled as shown but can be 
  160.   entered in any combination of upper and lower case letters. 
  161.  
  162.   Word constants that are passed to functions must be quoted: 
  163.  
  164.   call VRSet object, "BackColor", "Red" 
  165.  
  166. o Italic letters indicate placeholders for information you supply: 
  167.  
  168.   value = VRInfo( type ) 
  169.  
  170.   You can always use your own name for the variable that receives the return 
  171.   value. 
  172.  
  173.   You can always use the call instruction to discard return values: 
  174.  
  175.   call VRInfo type 
  176.  
  177. o Optional arguments are enclosed in square brackets. For example, 
  178.  
  179.   fileInfo = VRDir( [ fileSpec ], [ output ], [ search ], [ mask ] ) 
  180.  
  181.   The commas between arguments are not required if all subsequent arguments are 
  182.   omitted: 
  183.  
  184.   fileInfo = VRDir( "*.*" ) 
  185.  
  186.  
  187. ΓòÉΓòÉΓòÉ 1.3. Online information ΓòÉΓòÉΓòÉ
  188.  
  189.  
  190. ΓòÉΓòÉΓòÉ 1.3.1. Online books ΓòÉΓòÉΓòÉ
  191.  
  192. All of this manual is provided online. It is divided into two online books: the 
  193. VX-REXX Programmer's Guide  and the VX-REXX Reference. The programmer's guide 
  194. contains the chapters from the Getting Started and Programmer's Guide parts of 
  195. this manual. The reference contains the chapters from the Reference and 
  196. Appendices as well as a complete alphabetical reference. You can browse either 
  197. book by double-clicking on the appropriate icon in the  VX-REXX folder. 
  198.  
  199. The online information for VX-REXX is fully hyper-linked. You can also search 
  200. (with or without wildcards) for text. The design environment includes several 
  201. features to quickly access online information from various locations. 
  202.  
  203.  
  204. ΓòÉΓòÉΓòÉ 1.3.2. REXX information ΓòÉΓòÉΓòÉ
  205.  
  206. The VX-REXX folder also contains an icon for the OS/2 REXX Information. You can 
  207. browse this document for information about REXX language statements. This REXX 
  208. documentation may have been installed when you installed OS/2. If it was not, 
  209. see Setting up for instructions on adding the REXX Information. 
  210.  
  211.  
  212. ΓòÉΓòÉΓòÉ 1.3.3. Context help at design time ΓòÉΓòÉΓòÉ
  213.  
  214. Context sensitive help is provided for the VX-REXX design environment. To see 
  215. help while you are located on a menu or object, press F1. 
  216.  
  217.  
  218. ΓòÉΓòÉΓòÉ 1.4. Technical notes ΓòÉΓòÉΓòÉ
  219.  
  220. From time to time, Watcom makes available technical information pertaining to 
  221. VX-REXX in the form of VX-REXX Tech Notes. Tech Notes are available 
  222. electronically from the Watcom bulletin board (see the contact information at 
  223. the front of this book) and on CompuServe (type GO WATCOM). As of this 
  224. printing, the following Tech Notes are available: 
  225.  
  226. vxtech01.zip        How to build external function libraries. Includes sample C 
  227.                     source code. 
  228.  
  229. vxtech02.zip        (Obsolete) Sending keystrokes to control other programs. 
  230.                     The material in this Tech Note has been superseded by the 
  231.                     "Controlling other programs" chapter. 
  232.  
  233. vxtech03.zip        How to use REXX queues to communicate with VIO applications 
  234.                     (applications that can only run in an OS/2 window or 
  235.                     full-screen session). 
  236.  
  237. vxtech04.zip        A simple introduction to REXX queues. 
  238.  
  239. vxtech05.zip        Customizing the VX-REXX executable stub. Includes sample C 
  240.                     source code. 
  241.  
  242. vxtech06.zip        Running and controlling other programs from a VX-REXX 
  243.                     program. Complements the material in chapter "Controlling 
  244.                     other programs". 
  245.  
  246. vxtech07.zip        How to build REXX-aware applications. Includes sample C 
  247.                     source code. 
  248.  
  249.  
  250. ΓòÉΓòÉΓòÉ 1.5. Other sources of information ΓòÉΓòÉΓòÉ
  251.  
  252. Many manuals are commercially available to help you learn about the REXX 
  253. language. Some of these include: 
  254.  
  255. Modern Programming Using REXX by R. P. O'Hara and D. R. Gomberg (ISBN 
  256. 0-13-579329-5). 
  257.  
  258. OS/2 REXX: From Bark to Byte from IBM, document #GG24-4199-00. 
  259.  
  260. OS/2 REXX Handbook by Hallette German. (ISBN 0-442-01734-0). 
  261.  
  262. Practical Usage of REXX by Anthony S. Rudd (ISBN 0-13-682790-X). 
  263.  
  264. Procedures Language 2/ REXX Reference V2.00 (S10G-6268) from the IBM OS/2 
  265. Technical Library. 
  266.  
  267. Procedures Language 2/ REXX User's Guide V2.00 (S10G-6269) from the IBM OS/2 
  268. Technical Library. 
  269.  
  270. Programming in REXX by C. Daney (ISBN 0-07-015305-1). 
  271.  
  272. The REXX Handbook by Gabriel Goldberg and Philip H. Smith III (ISBN 
  273. 0-07-028682-8). 
  274.  
  275. REXX -- Advanced Techniques for Programmers by Peter C. Kiesel. (ISBN 
  276. 0-07-034600-3). 
  277.  
  278. The REXX Language by M. F. Cowlishaw (ISBN 0-13-780651-5). 
  279.  
  280. REXX Reference Summary Handbook by Dick Goran. (ISBN 0-9639854-1-8). 
  281.  
  282. Writing OS/2 REXX Programs by Ronny Richardson. (ISBN 0-07-052372). 
  283.  
  284. If you want to learn more about OS/2 user interface design you may want to read 
  285. the IBM Systems Application Architecture manual Common User Access Advanced 
  286. Interface Design Reference (SC34-4290). It provides guidelines for when and how 
  287. to use the standard interface components. 
  288.  
  289.  
  290. ΓòÉΓòÉΓòÉ 2. Setting up ΓòÉΓòÉΓòÉ
  291.  
  292. The setup program for VX-REXX copies VX-REXX from the installation diskettes 
  293. onto your hard disk. It also creates a Workplace Shell folder with icons for 
  294. the design environment, the online books, samples, and design time macros. 
  295.  
  296.  
  297. ΓòÉΓòÉΓòÉ 2.1. Before you start ΓòÉΓòÉΓòÉ
  298.  
  299.  
  300. ΓòÉΓòÉΓòÉ 2.1.1. Check your VX-REXX package ΓòÉΓòÉΓòÉ
  301.  
  302. Check to make sure that your VX-REXX package contains the following materials: 
  303.  
  304. o Installation diskettes. If you have the VX-REXX Standard Edition there should 
  305.   be 3 diskettes. If you have the Client/Server Edition there should be 5 
  306.   diskettes. 
  307.  
  308. o The VX-REXX for OS/2 Programmer's Guide and Reference 
  309.  
  310. o The VX-REXX Client/Server Edition Objects Guide. This volume is made up of 
  311.   two books: the Database Object Guide and the Chart Object guide. These books 
  312.   are included with the Client/Server Edition only. 
  313.  
  314. o Your registration card 
  315.  
  316.  
  317. ΓòÉΓòÉΓòÉ 2.1.2. Check your machine ΓòÉΓòÉΓòÉ
  318.  
  319. Before installing, make sure your computer fulfills these requirements: 
  320.  
  321. o An IBM-compatible machine with a 386 (or higher) CPU 
  322.  
  323. o At least 8 megabytes of memory 
  324.  
  325. o At least 6 megabytes of hard disk space for the Standard Edition, and an 
  326.   additional 7 megabytes for the Client/Server Edition. 
  327.  
  328. o OS/2 2.0 or later 
  329.  
  330.   If you have OS/2 2.0, you must install the Service Pak before installing 
  331.   VX-REXX. You can obtain it from the IBM OS/2 BBS, CompuServe, or directly 
  332.   from IBM. The IBM number for the Service Pak is XR06055. Contact your IBM 
  333.   representative for more information. 
  334.  
  335. o The OS/2 REXX interpreter 
  336.  
  337.   If you are not sure whether the OS/2 REXX interpreter is installed, check 
  338.   your OS2\DLL directory for the following files: REXX.DLL, REXXAPI.DLL, 
  339.   REXXUTIL.DLL, and REXXINIT.DLL. If they are present, the interpreter has been 
  340.   installed. 
  341.  
  342. o The OS/2 Enhanced Editor (optional) 
  343.  
  344. o The OS/2 resource compiler (optional) 
  345.  
  346.  
  347. ΓòÉΓòÉΓòÉ 2.1.3. Installing OS/2 REXX, the Enhanced Editor and the resource compiler ΓòÉΓòÉΓòÉ
  348.  
  349. This section shows you how to install the OS/2 REXX interpreter, the OS/2 
  350. Enhanced Editor and the OS/2 resource compiler. If you have already installed 
  351. these, skip ahead to the next section. 
  352.  
  353. You must install the OS/2 REXX interpreter and the REXX information before 
  354. installing VX-REXX. 
  355.  
  356. In addition to using the OS/2 REXX interpreter, VX-REXX is also configured to 
  357. use the OS/2 Enhanced Editor. Although it is not required, you may wish to 
  358. install the Enhanced Editor to make sure you can use all of VX-REXX's features. 
  359.  
  360. For the following procedure you will need the OS/2 installation diskettes. 
  361.  
  362.  1. Open the OS/2 System folder. 
  363.  
  364.  2. Open the System Setup folder. 
  365.  
  366.  3. Open the Selective Install program. 
  367.  
  368.  4. Click on OK in the System Configuration window. 
  369.  
  370.  5. If you need to install the OS/2 REXX interpreter, click on the REXX 
  371.     checkbox. 
  372.  
  373.  6. If you wish to install the REXX online information,  click on the 
  374.     Documentation checkbox. Then click on the corresponding More button to open 
  375.     the Documentation window. Make sure REXX Information is checked, then click 
  376.     on OK. If other check boxes are checked, you can uncheck them by clicking 
  377.     on their respective check boxes. 
  378.  
  379.  7. If you wish to install the OS/2 Enhanced Editor, click on the Tools and 
  380.     Games check box. Then click on the corresponding More button to open the 
  381.     Tools and Games window. Make sure that the Enhanced Editor check box is 
  382.     checked, then click on OK. If other check boxes are checked, you can 
  383.     uncheck them by clicking on their respective check boxes. 
  384.  
  385.  8. Click on Install to start the installation. You will be instructed by the 
  386.     Selective Install program after this point. 
  387.  
  388. If you wish to bind resources to your projects, you must ensure that the OS/2 
  389. resource compiler is installed. It is part of the standard OS/2 installation. 
  390. To verify that the resource compiler is installed, open an OS/2 window, type rc 
  391. and press Enter. If a help screen is displayed, the resource compiler is 
  392. installed and in the default search path. 
  393.  
  394. You are now ready to install VX-REXX. 
  395.  
  396.  
  397. ΓòÉΓòÉΓòÉ 2.2. Installing VX-REXX ΓòÉΓòÉΓòÉ
  398.  
  399. The first VX-REXX diskette contains a program called SETUP.EXE which installs 
  400. the software. 
  401.  
  402. By default, the software will be installed in the directory called \VXREXX on 
  403. the hard disk with the OS/2 system installed, but you can name a different 
  404. directory. Note the instructions that follow assume that the VX-REXX directory 
  405. is C:\VXREXX. If you choose another drive or directory, then substitute that 
  406. directory for C:\VXREXX. 
  407.  
  408. The installation program will ensure that there is enough free disk space 
  409. before starting the actual installation. If there is insufficient free space, 
  410. the installer will prompt you to delete some files from your disk and then 
  411. restart the installer. 
  412.  
  413. The installation program requires a minimum of 1 megabyte of free space on the 
  414. OS/2 boot drive to start the install. 
  415.  
  416. If you already have a version of VX-REXX installed on your machine you must 
  417. ensure that it is not in use before installing the new version. You cannot 
  418. install VX-REXX if you are running either VX-REXX or a VX-REXX program or 
  419. macro. 
  420.  
  421. If you are upgrading VX-REXX we strongly recommend that you install the new 
  422. version of VX-REXX in the same directory as the previous version. The installer 
  423. will upgrade all the VX-REXX files but will leave the Projects directory and 
  424. any projects it contains intact. 
  425.  
  426. Note:  Only one version of VX-REXX can be running at one time. This includes 
  427. VX-REXX itself and any VX-REXX program or macro. However, all VX-REXX programs 
  428. and macros created with earlier versions of VX-REXX will run with the current 
  429. version without change. It is not necessary to regenerate either EXE or macro 
  430. files if you are upgrading. 
  431.  
  432. To install VX-REXX: 
  433.  
  434.  1. Open the OS/2 System folder. 
  435.  
  436.  2. Open the Command Prompts folder. 
  437.  
  438.  3. Open an OS/2 Window. 
  439.  
  440.  4. Insert the first Watcom VX-REXX diskette in a diskette drive (e.g. the A 
  441.     drive). 
  442.  
  443.  5. From the OS/2 command line, type: a:\setup. 
  444.  
  445. If you are installing the Client/Server Edition, the installer will ask you to 
  446. select the components you want to install. You can install the VX-REXX design 
  447. environment, the Client/Server objects, or both. Check the components you want 
  448. to install, then press OK 
  449.  
  450. The installer will prompt you for the drive and directory in which you want to 
  451. install VX-REXX. You can change the default values to any valid drive and 
  452. directory. If the directory does not exist, the installer will create it. 
  453.  
  454. After choosing the VX-REXX directory, the setup program will install the 
  455. software on your hard disk. From time to time, the installer will prompt you to 
  456. insert the next disk. When you see this message, remove the old disk, insert 
  457. the requested disk, then press OK. 
  458.  
  459. Once the files have been installed, you will be asked if you want your 
  460. CONFIG.SYS updated. If you select this option, the installer will update your 
  461. CONFIG.SYS so that the PATH, LIBPATH, HELP and BOOKSHELF variables include the 
  462. VX-REXX directory. It will also create a VXREXX variable set to the VX-REXX 
  463. directory. Your old CONFIG.SYS will be renamed CONFIG.BAK. 
  464.  
  465. If you do not select this option, the installer will create a copy of your 
  466. CONFIG.SYS with the changes it would have made. It writes this to the 
  467. CONFIG.VRX file in the C:\VXREXX directory. 
  468.  
  469. VX-REXX will not function properly until you update your CONFIG.SYS. Adding the 
  470. VX-REXX directory to the PATH allows you to start VX-REXX from an OS/2 command 
  471. line. The LIBPATH must be updated to run the executable and macro files 
  472. generated by VX-REXX. The HELP and BOOKSHELF variables must be updated to 
  473. access the VX-REXX context sensitive help. The VXREXX variable should be set to 
  474. the VX-REXX directory. Note that you must shutdown and restart OS/2 for changes 
  475. to your CONFIG.SYS file to take effect. 
  476.  
  477. When the installation is complete, you will be asked if you want to view the 
  478. Read Me First. This document contains important information that was not 
  479. available when the manual was printed, and is only available online. 
  480.  
  481. After the installer finishes, you will be returned to the OS/2 command line. 
  482. Type exit to close the OS/2 window. At this point you should reboot your 
  483. computer so that changes to the CONFIG.SYS file can take effect. 
  484.  
  485.  
  486. ΓòÉΓòÉΓòÉ 2.3. Send in your registration card ΓòÉΓòÉΓòÉ
  487.  
  488. You should fill out and mail or fax your registration card as soon as possible 
  489. to ensure you are informed of future upgrades and other special offers to 
  490. registered users. You must write the product registration number on this card 
  491. in the appropriate box. Your registration number is printed on the label of the 
  492. first diskette. You will need your registration number if you contact Watcom 
  493. Technical Support. 
  494.  
  495.  
  496. ΓòÉΓòÉΓòÉ 2.4. Watcom VX-REXX folder contents (Standard Edition) ΓòÉΓòÉΓòÉ
  497.  
  498. The installer creates a Watcom VX-REXX icon on your desktop. Open this folder 
  499. to view the VX-REXX contents. This section describes each of the icons the 
  500. folder contains. 
  501.  
  502. Note that the Watcom VX-REXX folder on your desktop only contains objects that 
  503. reference files in the VX-REXX directory. Deleting or moving this folder does 
  504. not delete or move the VX-REXX directory. If you accidentally delete the Watcom 
  505. VX-REXX folder, you can rebuild it with the BUILDVRX command which is described 
  506. later. 
  507.  
  508.  
  509. ΓòÉΓòÉΓòÉ 2.4.1. VX-REXX ΓòÉΓòÉΓòÉ
  510.  
  511. You can use the VX-REXX icon to open the VX-REXX development environment, 
  512. although usually you will open VX-REXX by opening a VX-REXX Project object. See 
  513. the section on the Projects folder in this document for more information. 
  514.  
  515.  
  516. ΓòÉΓòÉΓòÉ 2.4.2. Read Me First ΓòÉΓòÉΓòÉ
  517.  
  518. The Read Me First document contains information that was not available when the 
  519. Watcom VX-REXX for OS/2 Programmer's Guide and Reference went to press. Look in 
  520. this document for corrections to the manual and documentation for things not 
  521. covered in the printed manual. 
  522.  
  523.  
  524. ΓòÉΓòÉΓòÉ 2.4.3. VX-REXX Programmer's Guide ΓòÉΓòÉΓòÉ
  525.  
  526. VX-REXX Programmer's Guide is an online copy of the Programmer's Guide section 
  527. of the Watcom VX-REXX for OS/2 Programmer's Guide and Reference. You can read 
  528. this documentation to learn how to use VX-REXX and create VX-REXX applications. 
  529. You can also use the chapter "A simple program" as an online tutorial, actually 
  530. building the program in the VX-REXX development environment as you read through 
  531. the chapter. 
  532.  
  533. You should work through the tutorial before trying to create your own project. 
  534. It shows you how to examine the code and how to run a VX-REXX program. If you 
  535. need more information, the techniques outlined in the tutorial are expanded in 
  536. the first four chapters of the Programmer's Guide. 
  537.  
  538.  
  539. ΓòÉΓòÉΓòÉ 2.4.4. VX-REXX Reference ΓòÉΓòÉΓòÉ
  540.  
  541. The online VX-REXX Reference is a full alphabetical reference which lists all 
  542. objects, properties, methods, and functions in the Standard Edition of VX-REXX. 
  543. Use this documentation to get detailed information on any component of the 
  544. VX-REXX development system. 
  545.  
  546.  
  547. ΓòÉΓòÉΓòÉ 2.4.5. REXX Information ΓòÉΓòÉΓòÉ
  548.  
  549. REXX Information points to the online REXX language documentation which is 
  550. contained in the OS/2 Information folder. You can browse this information to 
  551. learn about the REXX language and the OS/2 REXX interpreter. 
  552.  
  553.  
  554. ΓòÉΓòÉΓòÉ 2.4.6. Samples ΓòÉΓòÉΓòÉ
  555.  
  556. This folder contains icons for the VX-REXX sample programs. The source for the 
  557. samples is in the Samples folder. The samples are described in the "Samples" 
  558. chapter. 
  559.  
  560. To run these sample programs, the LIBPATH and HELP environment variables must 
  561. include the VX-REXX directory. 
  562.  
  563.  
  564. ΓòÉΓòÉΓòÉ 2.4.7. Projects ΓòÉΓòÉΓòÉ
  565.  
  566. The Projects folder contains a shadow of the VX-REXX Project template. You use 
  567. this template to create new VX-REXX projects. Simply drag the template to the 
  568. folder in which you want to store the new project files. Open the VX-REXX 
  569. Project folder that is created, and open the  Project.VRP file to start VX-REXX 
  570. with the new project. 
  571.  
  572. The Projects folder is a shadow of the directory of the same name in the 
  573. VX-REXX directory. You can use this folder to safely store your projects as 
  574. they will remain intact even if the Watcom VX-REXX folder is accidentally 
  575. deleted. 
  576.  
  577.  
  578. ΓòÉΓòÉΓòÉ 2.4.8. Macros ΓòÉΓòÉΓòÉ
  579.  
  580. The Macros folder contains sample VX-REXX design time macros, and information 
  581. on developing your own macros. VX-REXX design time macros allow you to 
  582. customize the design environment by adding new commands to the VX-REXX pop-up 
  583. menu. 
  584.  
  585. Three sample macros are provided:  SetProps (another way to set properties), 
  586. Resize (force objects to the same size), and ObjList (list all objects on a 
  587. window). The source for these macros is included so you can modify and adapt 
  588. them to suit your own needs. 
  589.  
  590. Information on the sample macros and their installation instructions is 
  591. included in the Profile.VRM file located in the Macros folder. Details on 
  592. writing your own macros are contained in a later chapter in this book. 
  593.  
  594. The Macros folder is a shadow of the directory of the same name in the VX-REXX 
  595. directory. You can use this folder to safely store your macros as they will 
  596. remain intact even if the Watcom VX-REXX folder is accidentally deleted. 
  597.  
  598.  
  599. ΓòÉΓòÉΓòÉ 2.4.9. Color Palette ΓòÉΓòÉΓòÉ
  600.  
  601. The VX-REXX installation program creates a color palette Workplace Shell object 
  602. in the VX-REXX folder. You can use the palette to drag and drop colors onto 
  603. VX-REXX objects as an alternative to setting colors using a property notebook. 
  604.  
  605.  
  606. ΓòÉΓòÉΓòÉ 2.4.10. Font Palette ΓòÉΓòÉΓòÉ
  607.  
  608. The VX-REXX installation program creates a font palette Workplace Shell object 
  609. in the VX-REXX folder. You can use the palette to drag and drop fonts onto 
  610. VX-REXX objects as an alternative to setting fonts using a property notebook. 
  611.  
  612.  
  613. ΓòÉΓòÉΓòÉ 2.5. Watcom VX-REXX folder contents (Client/Server Edition) ΓòÉΓòÉΓòÉ
  614.  
  615.  
  616. ΓòÉΓòÉΓòÉ 2.5.1. Database Administrator ΓòÉΓòÉΓòÉ
  617.  
  618. Double click on the Database Administrator icon to start the database 
  619. administrator tool. 
  620.  
  621.  
  622. ΓòÉΓòÉΓòÉ 2.5.2. Chart samples ΓòÉΓòÉΓòÉ
  623.  
  624. The Chart samples folder contains a number of samples that demonstrate the 
  625. chart object. 
  626.  
  627.  
  628. ΓòÉΓòÉΓòÉ 2.5.3. Database samples ΓòÉΓòÉΓòÉ
  629.  
  630. The Chart samples folder contains a number of samples that demonstrate the 
  631. database objects. 
  632.  
  633.  
  634. ΓòÉΓòÉΓòÉ 2.5.4. Chart Object Guide ΓòÉΓòÉΓòÉ
  635.  
  636. This book is the programmer's guide and reference for the chart object. It is 
  637. an online copy of the printed Chart Object Guide. Corrections to the printed 
  638. book listed in the Read Me First have been made to the online version. 
  639.  
  640.  
  641. ΓòÉΓòÉΓòÉ 2.5.5. Database Objects Guide ΓòÉΓòÉΓòÉ
  642.  
  643. This book is the programmer's guide and reference for the database objects. It 
  644. is an online copy of the printed Database Objects Guide. Corrections to the 
  645. printed book listed in the Read Me First have been made to the online version. 
  646.  
  647.  
  648. ΓòÉΓòÉΓòÉ 2.6. Watcom VX-REXX directory contents ΓòÉΓòÉΓòÉ
  649.  
  650. In addition to the files and directories comprising the VX-REXX design 
  651. environment, the VX-REXX directory contains the following useful files. 
  652.  
  653.  
  654. ΓòÉΓòÉΓòÉ 2.6.1. Buildvrx.CMD ΓòÉΓòÉΓòÉ
  655.  
  656. This REXX script rebuilds the Workplace Shell objects for VX-REXX. If you 
  657. accidentally delete your Watcom VX-REXX folder, or if your desktop becomes 
  658. corrupted, you can run this command file from an OS/2 window. 
  659.  
  660.  
  661. ΓòÉΓòÉΓòÉ 2.6.2. Buildcso.CMD (Client/Server Edition only) ΓòÉΓòÉΓòÉ
  662.  
  663. This REXX script rebuilds the Workplace Shell objects for the Client/Server 
  664. Edition. If you accidentally delete your Watcom VX-REXX folder, or if your 
  665. desktop becomes corrupted, you can run this command file from an OS/2 window. 
  666.  
  667.  
  668. ΓòÉΓòÉΓòÉ 2.6.3. Bpatch.EXE ΓòÉΓòÉΓòÉ
  669.  
  670. The Watcom Patch Utility can be used to apply patches or bug fixes to VX-REXX. 
  671. As problems are reported and fixed, patches are released on the Watcom BBS and 
  672. FTP site. You can also order the patches on diskette from Watcom. 
  673.  
  674.  
  675. ΓòÉΓòÉΓòÉ 2.6.4. Recover.EXE ΓòÉΓòÉΓòÉ
  676.  
  677. If your computer crashes while running VX-REXX, you may be able to recover your 
  678. work using the RECOVER program. To run it, follow these steps: 
  679.  
  680.  1. Open an OS/2 window 
  681.  
  682.  2. Change to your VXREXX directory. Type cd c:\vxrexx (Replace "c:" with the 
  683.     actual drive letter). 
  684.  
  685.  3. Start the RECOVER program by typing RECOVER. 
  686.  
  687.  4. Select the directory which contains the source for your project. 
  688.  
  689.  5. Press the Recover button. 
  690.  
  691. For detailed help on the recovery process, press F1 while running the RECOVER 
  692. program. 
  693.  
  694.  
  695. ΓòÉΓòÉΓòÉ 3. A simple program ΓòÉΓòÉΓòÉ
  696.  
  697. This chapter provides a brief introduction to the VX-REXX development 
  698. environment through a tutorial. You will learn how to start and stop VX-REXX 
  699. and create, run, and save a simple application. In addition, the drag and drop 
  700. programming feature of VX-REXX will be used to reduce the time and effort 
  701. needed for writing code. The same steps used in this tutorial can be used to 
  702. develop all VX-REXX applications. Subsequent chapters provide more details 
  703. about each step. 
  704.  
  705. In this tutorial, you will create an application which consists of an entry 
  706. field, push button, and list box. When run, text typed in the entry field will 
  707. be added to the list box using the push button. 
  708.  
  709.  
  710. ΓòÉΓòÉΓòÉ 3.1. Starting VX-REXX ΓòÉΓòÉΓòÉ
  711.  
  712. You must install VX-REXX before working through this tutorial. During the 
  713. installation the Watcom VX-REXX folder is created on the OS/2 desktop. Open 
  714. that folder now. You will see several icons and a number of folders. 
  715.  
  716. To start a new VX-REXX project: 
  717.  
  718.  1. Open the Projects folder. 
  719.  
  720.  2. Drag the project template to a blank area in the Projects folder. A project 
  721.     folder will be created. 
  722.  
  723.  3. Open the folder. Three icons will be displayed. They represent the files in 
  724.     the new empty project. 
  725.  
  726.  4. Double click on the Project.VRP icon to start VX-REXX. 
  727.  
  728.  When VX-REXX has started, the screen will appear as in Figure 1: 
  729.  
  730. Figure 1  The initial VX-REXX screen.
  731.  
  732. The VX-REXX design environment consists of a menu bar, a tool palette, and a 
  733. project window containing a grid of dots. The menu bar contains the commands 
  734. that are used to create, save and run applications. The tool palette contains 
  735. the objects which can be placed in the project window to create the user 
  736. interface for an application. 
  737.  
  738.  
  739. ΓòÉΓòÉΓòÉ 3.2. Creating an application ΓòÉΓòÉΓòÉ
  740.  
  741. There are three basic steps to building a VX-REXX application: 
  742.  
  743.  1. Creating the user interface by adding objects to the project window. 
  744.  
  745.  2. Customizing each object's properties. 
  746.  
  747.  3. Attaching code to each object. 
  748.  
  749. You will go through these steps in the following sections to create a simple 
  750. application. 
  751.  
  752.  
  753. ΓòÉΓòÉΓòÉ 3.3. Creating the user interface ΓòÉΓòÉΓòÉ
  754.  
  755. Creating the user interface is the first step in building an application. The 
  756. interface to this application has three objects: an entry field, a push button, 
  757. and a list box. Start by adding the entry field to the window: 
  758.  
  759.  1. Click on the Tools menu and then choose EntryField. 
  760.  
  761.  2. Position the mouse pointer near the top left corner of the project window. 
  762.  
  763.     The cursor will change to a cross while it is positioned on the project 
  764.     window. 
  765.  
  766.  3. Hold down mouse button 1 and drag the mouse down and to the right until the 
  767.     entry field is approximately the size of the one shown in Figure 2. 
  768.  
  769.         Figure 2  The entry field added to the window.
  770.  
  771.  4. Release the mouse button. 
  772.  
  773. Add the push button to the window using a similar procedure: 
  774.  
  775.  1. Click on the Tools menu and then choose PushButton. 
  776.  
  777.  2. Position the pointer below the bottom left corner of the entry field. 
  778.  
  779.  3. Hold down mouse button 1 and drag the mouse down and to the right until the 
  780.     push button  is approximately the size of the one shown in Figure 3. 
  781.  
  782.         Figure 3  The push button added to the window.
  783.  
  784.  4. Release the mouse button. 
  785.  
  786. Repeat the above steps using the ListBox item from the Tools menu to make your 
  787. window similar in appearance to Figure 4. 
  788.  
  789. Figure 4  The entry field, push button and list box on the window.
  790.  
  791. Finally, to improve the appearance of the window, center the three objects on 
  792. the window as follows: 
  793.  
  794.  1. Position the pointer over the entry field. 
  795.  
  796.  2. Press and hold down mouse button 1. Sizing handles will appear along the 
  797.     border of the entry field. Move the pointer over the push button and then 
  798.     over the list box. Now all three objects will have sizing handles along 
  799.     their borders. The screen should look similar to  Figure 5. 
  800.  
  801.         Figure 5  The entry field, push button and list box are selected.
  802.  
  803.  3. Release mouse button 1. 
  804.  
  805.  4. Position the pointer on the entry field once again and press mouse button 2 
  806.     to invoke the VX-REXX pop-up menu. 
  807.  
  808.  5. Select the Align menu item using mouse button 1. A second menu will appear. 
  809.     From this menu, click on the menu item used for centering objects as shown 
  810.     in Figure 6. 
  811.  
  812.         Figure 6  The menu item used to centre objects.
  813.     The push button and the list box will now be centered underneath the entry 
  814.     field. 
  815.  
  816.  6. Move the pointer over the right border of the window. The pointer will 
  817.     change to a sizing arrow. 
  818.  
  819.  7. Hold down mouse button 1 and move the cursor left or right to adjust the 
  820.     width of the window until the objects are centered. 
  821.  
  822.  8. Click on the window background to deselect the objects. 
  823.  
  824. The screen should appear as in  Figure 7. 
  825.  
  826. Figure 7  The objects centred on the window.
  827.  
  828. All the objects you need have been created. Now their properties must be 
  829. customized. 
  830.  
  831.  
  832. ΓòÉΓòÉΓòÉ 3.4. Customizing object properties ΓòÉΓòÉΓòÉ
  833.  
  834. Each VX-REXX object has properties such as color and size which can be 
  835. customized. An object is given default property values when it is first 
  836. created. Often, these properties need to be changed. 
  837.  
  838. The entry field has a font property which determines the font used to display 
  839. text. The height of the entry field should be set according to the size of the 
  840. font being used. This step can be done automatically using the entry field's 
  841. Autosize property. If this property is set to 1, the height of the entry field 
  842. will be adjusted automatically based on the font being used. Initially, the 
  843. Autosize property is set to 0. Change it to 1 as follows: 
  844.  
  845.  1. Click mouse button 2 anywhere over the entry field. A pop-up menu will be 
  846.     displayed. 
  847.  
  848.  2. Choose the Open menu and then choose the Properties menu item. A property 
  849.     notebook will be displayed. 
  850.  
  851.  3. Click on the Size index tab. The Size page will be displayed as in Figure 
  852.     8. 
  853.  
  854.         Figure 8  The size page of the property notebook.
  855.  
  856.  4. Click on the check box marked Autosize. 
  857.  
  858.  5. Close the entry field's property notebook by double-clicking on the system 
  859.     menu in the title bar. 
  860.  
  861. The text which appears on a push button is called the caption and is determined 
  862. by the push button's Caption property. To set the caption of the push button to 
  863. Add Item: 
  864.  
  865.  1. Click mouse button 2 anywhere over the push button, choose Open and then 
  866.     choose Properties to open the push button's property notebook. 
  867.  
  868.  2. Click on the Text index tab. The Text page will be displayed as in Figure 
  869.     9. 
  870.  
  871.         Figure 9  The text page of the property notebook.
  872.  
  873.  3. Click on the Caption entry field and type: Add Item 
  874.  
  875.  4. Close the property notebook. The text Add Item will appear on the push 
  876.     button. 
  877.  
  878. Lines in a list box are displayed one below another, beginning at the top. The 
  879. last line in the list box may not appear completely, depending on the height of 
  880. the list box. The height must be adjusted if this characteristic is 
  881. undesirable. To have the height adjusted automatically, set the AdjustHeight 
  882. property of the list box as follows: 
  883.  
  884.  1. Open the property notebook for the list box using the same method as 
  885.     before. 
  886.  
  887.  2. Turn to the Size page by clicking on the Size index tab. 
  888.  
  889.  3. Click on the AdjustHeight check box. 
  890.  
  891. By default, items in a list box will be sorted in ascending order. For this 
  892. application, you want items to be listed in the order they are added to the 
  893. list box. The list box's Sort property must be changed: 
  894.  
  895.  1. With the list box property notebook open, turn to the List page by clicking 
  896.     on the List index tab. 
  897.  
  898.  2. Click on the scroll arrows in the Sort drop down combobox. 
  899.  
  900.  3. Choose none from the drop down list. 
  901.  
  902.  4. Close the property notebook by double-clicking on its system menu. 
  903.  
  904. Finally, set the text that will appear on the window title bar: 
  905.  
  906.  1. Open the property notebook for the window. Note that the pointer must be 
  907.     positioned on the window but not over any object in the window when 
  908.     pressing mouse button 2. 
  909.  
  910.  2. Turn to the Text page of the notebook. If an index tab for the Text page is 
  911.     not immediately visible, click on the arrow below the other index tabs to 
  912.     scroll through the page list. 
  913.  
  914.  3. Click on the Caption entry field and type: 
  915.  
  916.         Sample
  917.  
  918.  4. Close the property notebook. 
  919.  
  920. The first two steps in developing the sample application are complete: creating 
  921. the objects and customizing their properties. 
  922.  
  923.  
  924. ΓòÉΓòÉΓòÉ 3.5. A preliminary run ΓòÉΓòÉΓòÉ
  925.  
  926. Although the sample program is not finished you can run it to see what it will 
  927. look like when complete. To run it, click on the Run menu and choose Run 
  928. project. This will hide VX-REXX and run the application, which should appear 
  929. similar to Figure 10: 
  930.  
  931. Figure 10  A test run of the sample program.
  932.  
  933. Notice that the background of the window no longer contains a grid of dots. 
  934. Type text into the entry field to see how it will appear. Use the Tab key to 
  935. move between the objects. Click on the push button. Nothing happens because no 
  936. code has been attached to the push button. Attaching code to the objects in the 
  937. window is the next step in developing the sample application. 
  938.  
  939. Close the application by clicking the system menu and choosing Close. The 
  940. VX-REXX design environment will reappear. 
  941.  
  942.  
  943. ΓòÉΓòÉΓòÉ 3.6. Attaching code to objects ΓòÉΓòÉΓòÉ
  944.  
  945. In this application pressing the push button will copy the text from the entry 
  946. field to the list box. You will use the drag and drop programming feature of 
  947. VX-REXX to help write the code which will perform this task. First you must 
  948. obtain the text in the entry field. To attach this code to the push button: 
  949.  
  950.  1. Open the push button's property notebook and turn to the Event page. Code 
  951.     can be attached to the push button for any events which appear on this 
  952.     page. 
  953.  
  954.  2. Select Click and then click on Open to invoke an editor. The editor will 
  955.     contain a skeleton for an event routine, as shown in Figure 11. 
  956.  
  957.         Figure 11  Event routine skeleton
  958.  
  959.     The first line in the routine is a comment, the second is the name of the 
  960.     routine, and the last line contains a REXX return instruction which needs 
  961.     to be executed at the end of the routine. The REXX code you place in this 
  962.     routine will be executed when the push button is pressed. 
  963.  
  964.  3. At this point, you could write code manually but there is a much easier 
  965.     method. Press and hold down mouse button 2 over the entry field. Now move 
  966.     the mouse over the editor. The editor window and the application window may 
  967.     need to be moved apart before this step can be done. A line joining the 
  968.     mouse to the entry field will appear as in Figure 12: 
  969.  
  970.         Figure 12  Getting the text in the entry field.
  971.  
  972.  4. Release mouse button 2. A dialog will appear which lists descriptions of 
  973.     all the entry field methods which can be invoked and all the entry field 
  974.     properties which can be set or retrieved. 
  975.  
  976.  5. Click on the Value item under the Get property heading. You need to get the 
  977.     Value property because it contains the text in the entry field. Now click 
  978.     on OK. The following instruction is placed at the insertion point in the 
  979.     editor: 
  980.  
  981.         value = VRGet( "EF_1", "Value" )
  982.  
  983.     This instruction will assign the variable value with the text in the entry 
  984.     field. 
  985.  
  986. The automatic code generation feature of VX-REXX is called drag and drop 
  987. programming. Using this feature, you can create REXX applications without 
  988. having to memorize the syntax of VX-REXX functions and methods. 
  989.  
  990. To see the online information for VRGet, hold down the Ctrl key while double 
  991. clicking the mouse on the word. This technique may be used to view online 
  992. information for any VX-REXX function, event, property or method. 
  993.  
  994. The next step is to add the text to the list box: 
  995.  
  996.  1. Press and hold down mouse button 2 over the list box and then move the 
  997.     pointer over the editor window. A line joining the pointer to the list box 
  998.     will appear. 
  999.  
  1000.  2. Release mouse button 2. A dialog will appear listing all the list box 
  1001.     methods that can be invoked and all the list box properties which can be 
  1002.     set or retrieved. Click on the Add a string item under the Methods heading 
  1003.     and then press the OK button. 
  1004.  
  1005.  3. Another dialog, as shown in  Figure 13, will appear. 
  1006.  
  1007.         Figure 13  The Add a String dialog box.
  1008.  
  1009.  4. Click on the string field and type the following: 
  1010.  
  1011.         value
  1012.  
  1013.  5. Click on the Quoted string check box. Now it should not be checked. 
  1014.  
  1015.  6. Press the OK button. The REXX code to add the text to the list box will be 
  1016.     placed underneath the previous instruction, as shown in Figure 14. 
  1017.  
  1018. Figure 14  The event routine for the push button.
  1019.  
  1020. After getting the text, you should clear the entry field to allow new text to 
  1021. be entered: 
  1022.  
  1023.  1. Press and hold down mouse button 2 over the entry field and then move the 
  1024.     mouse over the editor window. 
  1025.  
  1026.  2. Release mouse button 2. A dialog will appear. 
  1027.  
  1028.  3. Click on the Value item under the Set property heading and then press the 
  1029.     OK button. 
  1030.  
  1031.  4. Click on OK from the second dialog. The editor window should now appear as 
  1032.     in  Figure 15. 
  1033.  
  1034.         Figure 15  The unfinished push button event routine.
  1035.  
  1036. The push button will have the focus when this routine is executed. You should 
  1037. set the focus to the entry field so that new text can be entered immediately: 
  1038.  
  1039.  1. Press and hold down mouse button 2 over the entry field and then move the 
  1040.     mouse over the editor window. 
  1041.  
  1042.  2. Release mouse button 2. 
  1043.  
  1044.  3. Click on the Set focus to object item underneath the Methods heading and 
  1045.     then press the OK button. A line of code will be inserted below the 
  1046.     previous lines in the editor window. 
  1047.  
  1048.  4. Close the editor window by double-clicking on its system menu icon. 
  1049.  
  1050. The push button event routine is now complete and is shown in Figure 16. Give 
  1051. the project a test run to see if it works correctly. 
  1052.  
  1053. Figure 16  The complete push button event routine.
  1054.  
  1055.  
  1056. ΓòÉΓòÉΓòÉ 3.7. A test run ΓòÉΓòÉΓòÉ
  1057.  
  1058. To run the application, click on the Run menu and choose Run project. The 
  1059. application window will look the same as it did during the first run. However, 
  1060. try clicking on the push button after typing text into the entry field. Now the 
  1061. text is added to the list box. Also, the entry field is cleared and is given 
  1062. the focus again. The push button click routine you created appears to be 
  1063. working as it should. 
  1064.  
  1065. Try adding more text to the list box. Also, try pressing the push button when 
  1066. there is no text in the entry field. It seems as though no action is performed. 
  1067. However, if more text is added to the list box, you can see that a blank line 
  1068. is inserted when the entry field is empty and the push button is pressed, as 
  1069. shown in Figure 17. 
  1070.  
  1071. Figure 17  Adding text to the list box.
  1072.  
  1073. This behavior is undesirable and needs to be prevented with the addition of 
  1074. more code. Also, to make the application easier to use, you should allow text 
  1075. to be added to the list box with the use of the Enter key. 
  1076.  
  1077.  
  1078. ΓòÉΓòÉΓòÉ 3.8. Improving the application ΓòÉΓòÉΓòÉ
  1079.  
  1080. A push button can be enabled or disabled. When enabled, a push button responds 
  1081. to events such as a click event. The push button in our application has always 
  1082. been enabled. When a push button is disabled it does not respond to any events 
  1083. and also appears grayed. In particular, a disabled push button cannot receive 
  1084. the focus and will not respond when pressed. The program will use this property 
  1085. of push buttons to prevent blank lines from being added to the list box: 
  1086.  
  1087.  1. Press mouse button 2 anywhere over the entry field to open the VX-REXX 
  1088.     pop-up menu. 
  1089.  
  1090.  2. Click on Events and then click on Change. The editor window will appear 
  1091.     with the skeleton of a routine, as shown in  Figure 18. 
  1092.  
  1093.         Figure 18  The entry field change routine.
  1094.  
  1095.     This routine will be executed whenever the contents of the entry field 
  1096.     change. It needs to determine if the entry field has become empty and if 
  1097.     this is the case, will disable the push button to prevent it from adding 
  1098.     any text to the list box. 
  1099.  
  1100.  3. Press and hold down mouse button 2 over the entry field, move the mouse 
  1101.     over the editor window and then release the mouse button. As before, a 
  1102.     dialog will appear. 
  1103.  
  1104.  4. Click on the Value item underneath the Get property heading and then press 
  1105.     OK. The code to get the contents of the entry field will be generated. 
  1106.  
  1107.  5. Add the following line of code at the insertion point: 
  1108.  
  1109.         if value = "" then do
  1110.  
  1111.     Press the Enter key and then the Tab key at the end of this line. 
  1112.  
  1113.  6. At this point, the code has determined that the entry field is empty so it 
  1114.     must disable the push button. Press and hold down mouse button 2 over the 
  1115.     push button, move the mouse over the editor window and then release the 
  1116.     mouse button. A dialog listing all methods and properties of a push button 
  1117.     will appear. 
  1118.  
  1119.  7. Click on the Enabled item under the Set property heading and then press OK. 
  1120.     A second dialog will appear, as shown in Figure 19. 
  1121.  
  1122.         Figure 19  The enabled property dialog box.
  1123.  
  1124.     Click on the Enabled check box so that it is not checked. Press OK. The 
  1125.     instruction to disable the push button is placed at the insertion point in 
  1126.     the editor window. 
  1127.  
  1128.  8. Now you have to add the code that will enable the push button when the 
  1129.     entry field is not empty. Add the following lines at the insertion point: 
  1130.  
  1131.         end
  1132.         else do
  1133.  
  1134.     Press Enter and then Tab at the end of the second line. The editor window 
  1135.     should appear as in Figure 20. 
  1136.  
  1137.         Figure 20  The incomplete entry field change routine.
  1138.  
  1139.     Press and hold down mouse button 2 over the push button, move the mouse 
  1140.     over the editor window and then release the mouse button. From the dialog 
  1141.     box click on the Enabled item under the Set property heading and then press 
  1142.     OK. Press OK again on the second dialog box which appears. The code to 
  1143.     enable the push button is inserted into the editor window. 
  1144.  
  1145.  9. One last line needs to be added to the routine: 
  1146.  
  1147.         end
  1148.  
  1149.     The complete routine is shown in Figure 21. 
  1150.  
  1151.         Figure 21  The complete entry field change routine.
  1152.  
  1153. Now you must make the push button disabled when the application is first run: 
  1154.  
  1155.  1. Open the push button's property notebook and turn to the Style page. Click 
  1156.     on the Enabled check box so that it is not checked. 
  1157.  
  1158.  2. Also on this page is the Default check box. Click on this check box so that 
  1159.     it becomes checked. Now, when the Enter key is pressed the push button 
  1160.     click routine will be executed, as though the push button had been pressed. 
  1161.     This behavior will allow text to be added to the list box by pressing the 
  1162.     Enter key. 
  1163.  
  1164. You can easily make another improvement to the application by adding hints to 
  1165. the objects: 
  1166.  
  1167.  1. Turn to the Hint page of the push button's property notebook. Type the 
  1168.     following in the Hint field: 
  1169.  
  1170.         Add the text to the list box.
  1171.  
  1172.  2. Open the entry field's property notebook, turn to the Hint page and type 
  1173.     the following: 
  1174.  
  1175.         Enter text.
  1176.  
  1177.  3. Open the window's property notebook, turn to the Hint page and click on the 
  1178.     ShowHints check box. Set the Status Area field. to Bottom. A status bar 
  1179.     will appear at the bottom of the window, as shown in Figure 22. 
  1180.  
  1181.         Figure 22  The status bar for showing hints.
  1182.  
  1183.     The status bar may overlap with the bottom of the list box. If this is the 
  1184.     case then the list box can be raised or its height can be decreased. 
  1185.  
  1186. The previous steps add hints to the application. When the mouse is moved over 
  1187. the push button, its hint text will be displayed in the status bar. Similarly, 
  1188. when the mouse is positioned over the entry field, its hint text will be 
  1189. displayed. You can now try out the improvements you have made. 
  1190.  
  1191.  
  1192. ΓòÉΓòÉΓòÉ 3.9. Running the application ΓòÉΓòÉΓòÉ
  1193.  
  1194. Run the application as before by clicking on the Run menu and choosing Run 
  1195. project. Move the mouse over the entry field and then the push button to see 
  1196. their hints. The application window is shown in  Figure 23. 
  1197.  
  1198. Figure 23  Running the finished application.
  1199.  
  1200. Try typing in text and adding it to the list box with the use of the Enter key 
  1201. as well as the push button. Notice that the push button becomes disabled 
  1202. whenever the entry field is empty. 
  1203.  
  1204. Although this is a simple application, it would take considerably more effort 
  1205. and expertise to create it with other languages and development tools. However, 
  1206. with VX-REXX features like as drag and drop programming, you have created it 
  1207. easily with little knowledge of OS/2 or the REXX language. 
  1208.  
  1209.  
  1210. ΓòÉΓòÉΓòÉ 3.10. Saving the application ΓòÉΓòÉΓòÉ
  1211.  
  1212. You should save the application now that it is complete: 
  1213.  
  1214.  1. Click on the Project menu. 
  1215.  
  1216.  2. Choose Save. The project will be saved in its project folder. 
  1217.  
  1218.  
  1219. ΓòÉΓòÉΓòÉ 3.11. Stopping VX-REXX ΓòÉΓòÉΓòÉ
  1220.  
  1221. To exit VX-REXX and return to the OS/2 desktop, click on the VX-REXX system 
  1222. menu icon and choose Close or double-click on the system menu icon. 
  1223.  
  1224. In this tutorial, you have seen the following techniques: 
  1225.  
  1226.  1. Adding objects to a window. 
  1227.  
  1228.  2. Modifying an object's properties. 
  1229.  
  1230.  3. Using the VX-REXX drag and drop programming feature to add code. 
  1231.  
  1232.  4. Testing a project. 
  1233.  
  1234.  5. Saving a project. 
  1235.  
  1236. These are the basics. The following chapters expand on these basics to show how 
  1237. to create and maintain complex as well as simple applications. 
  1238.  
  1239.  
  1240. ΓòÉΓòÉΓòÉ 4. Creating and running projects ΓòÉΓòÉΓòÉ
  1241.  
  1242. VX-REXX is a complete REXX programming system, not just a set of libraries that 
  1243. adds features to the REXX language. Its project management facilities, 
  1244. described in this chapter, allow you to easily design and maintain 
  1245. applications. 
  1246.  
  1247. There are three basic steps to building a VX-REXX application. Building the 
  1248. user interface is the first step. You create the interface by placing control 
  1249. objects such as push buttons in a window. Once they are in place you can easily 
  1250. move and resize them until you are satisfied with their position and 
  1251. appearance. When you have finished designing your window, you have completed 
  1252. the first step and have a prototype for your application. The next chapter 
  1253. shows you how to add objects to a window. 
  1254.  
  1255.  The second step is to assign properties to the objects. The properties of an 
  1256. object determine both how it appears and how it functions. When you create an 
  1257. object, it will have default values for its properties. The chapter  Changing 
  1258. object properties shows you how to change the default values. 
  1259.  
  1260. The third step attaches code to the objects to provide action for your 
  1261. application. As well as properties, each object has a set of events to which 
  1262. you can attach REXX routines. An event routine is run when you trigger the 
  1263. event, for example, by clicking on a button. The chapter  Adding and modifying 
  1264. routines shows you how to do this. 
  1265.  
  1266.  
  1267. ΓòÉΓòÉΓòÉ 4.1. Projects ΓòÉΓòÉΓòÉ
  1268.  
  1269. A VX-REXX project is a set of one or more window or code files that are 
  1270. combined to form a standalone application. You work on a single project at a 
  1271. time, designing the windows and attaching REXX code to the objects on the 
  1272. windows, testing and debugging the project as necessary. You can generate a 
  1273. standalone executable file at any point in the process. You can run an 
  1274. executable on any machine that has the VX-REXX run time libraries installed. 
  1275.  
  1276. It is important to distinguish between design mode and run mode. You are in 
  1277. design mode when you are working on a VX-REXX project. You are in run mode when 
  1278. you are testing or debugging a project, or when running a standalone 
  1279. executable. A project can only be modified at design time, but new objects can 
  1280. be created and object properties modified at run time. Some objects also have 
  1281. properties that are only available at run time. 
  1282.  
  1283. There are several files associated with a VX-REXX project. We recommend that 
  1284. you keep all the files for one project together in a single directory or 
  1285. folder. This will happen automatically if you create your projects by dragging 
  1286. and dropping the VX-REXX project template. 
  1287.  
  1288. Each project consists of a project file (extension VRP) and one or more source 
  1289. files (extension VRX). Some VRX files require an additional information file. 
  1290. These files have the same name as the VRX file but end with the extension VRY. 
  1291.  
  1292. Generally you will not need to worry about the details of the files in a 
  1293. project as VX-REXX will maintain them for you. You must be careful, however, 
  1294. when copying or backing up a project to copy or backup all required files. 
  1295.  
  1296.  
  1297. ΓòÉΓòÉΓòÉ 4.2. VX-REXX and the Workplace Shell ΓòÉΓòÉΓòÉ
  1298.  
  1299. When VX-REXX is installed, a VX-REXX folder is created on the desktop. This 
  1300. folder contains several icons and two folders: Samples and Projects. You can 
  1301. start VX-REXX simply by double clicking on the VX-REXX icon, but the preferred 
  1302. method is to drag and drop a project template. This procedure is outlined in 
  1303. the next section which describes how to create a project. 
  1304.  
  1305. When installed, VX-REXX also creates Workplace Shell associations between 
  1306. projects and VX-REXX project files. In particular, files with the extension VRP 
  1307. are assumed to be VX-REXX projects. The Workplace Shell will start VX-REXX when 
  1308. such a file is opened. Projects may also be opened by dragging the project file 
  1309. (VRP) onto the VX-REXX program icon. 
  1310.  
  1311. If you accidentally delete the VX-REXX folder, or must reinstall the OS/2 
  1312. desktop, the online Read Me First contains instructions on recreating the 
  1313. VX-REXX Workplace Shell objects. 
  1314.  
  1315.  
  1316. ΓòÉΓòÉΓòÉ 4.3. Creating a project ΓòÉΓòÉΓòÉ
  1317.  
  1318. There are two ways to start a new project. The best method is to open the 
  1319. VX-REXX Projects folder and drag and drop the project template contained within 
  1320. it. A new project folder will be created. Open the folder and double click on 
  1321. Project.VRP to edit the new project. 
  1322.  
  1323. Be careful when dragging a project template. It is best to use a folder on one 
  1324. of your Drives objects as the target. This ensures that the project is not lost 
  1325. if your desktop must be reinstalled. The VX-REXX folder in particular is not a 
  1326. good choice, since its contents will be replaced completely if a new version of 
  1327. VX-REXX is installed. The Projects folder inside the VX-REXX folder is safe, 
  1328. however, because it is a shadow of a physical directory on the drive where you 
  1329. installed VX-REXX. Once you have created a project in a safe location, you may 
  1330. of course place a shadow of the project folder wherever you wish. 
  1331.  
  1332. You can also create projects from within VX-REXX by selecting New from the 
  1333. Project menu. This creates a new project in a temporary working directory. No 
  1334. permanent copy of your project will be created until you save it. At that time, 
  1335. VX-REXX will prompt you for the directory and filenames to use. The directory 
  1336. you specify must already exist, so you should create it before trying to save 
  1337. your project. 
  1338.  
  1339.  
  1340. ΓòÉΓòÉΓòÉ 4.4. Opening an existing project ΓòÉΓòÉΓòÉ
  1341.  
  1342. You can open an existing project from the Workplace Shell by opening its 
  1343. project folder and double clicking on the project file (VRP). You can also open 
  1344. projects from within VX-REXX by selecting Open from the Project menu, which 
  1345. will prompt you for the path of the project. If you were editing another 
  1346. project and have not saved the project since the last change, VX-REXX will 
  1347. allow you to save the current project before proceeding. 
  1348.  
  1349.  
  1350. ΓòÉΓòÉΓòÉ 4.5. Saving a project ΓòÉΓòÉΓòÉ
  1351.  
  1352. You can save an open project to disk at any time by selecting Save or Save as 
  1353. from the Project menu. Saving a project saves the source files and the project 
  1354. file. Save saves the files using their current filenames. However, if you 
  1355. created the project using the New menu item and have not yet saved it, you will 
  1356. be asked to specify the path for the project as if you had chosen Save as. The 
  1357. Save as item displays a dialog allowing you to set the location and names of 
  1358. each of the project files. You usually keep all of the files for a project in 
  1359. one directory, but each file can be saved in a different directory. 
  1360.  
  1361.  
  1362. ΓòÉΓòÉΓòÉ 4.6. Running a project ΓòÉΓòÉΓòÉ
  1363.  
  1364. You can test your project at any time in the design process by selecting Run 
  1365. project from the Run menu. The project is then compiled into an executable form 
  1366. in a temporary working directory (the original project is not changed). VX-REXX 
  1367. hides itself while the program runs. 
  1368.  
  1369. It may be necessary to use the Run menu item in the Options menu to set some 
  1370. initial parameters for the test run, such as the working directory or initial 
  1371. arguments to pass to the program. 
  1372.  
  1373. If a REXX error occurs while your program runs, it will stop running. VX-REXX 
  1374. will appear and describe the type and location of the error and let you edit 
  1375. the procedure that is in error. 
  1376.  
  1377. You can also debug your project by selecting the Debug project menu item from 
  1378. the Run menu. See the chapter  Debugging a project for more information. 
  1379.  
  1380. Before testing or debugging a program, it is always a good idea to save the 
  1381. project. 
  1382.  
  1383.  
  1384. ΓòÉΓòÉΓòÉ 4.7. Making an executable ΓòÉΓòÉΓòÉ
  1385.  
  1386. Once you are satisfied with your project, you can generate a standalone program 
  1387. by selecting Make EXE file from the Project menu. You will be prompted for a 
  1388. path and the project will be compiled into an executable file which you can 
  1389. then run on any machine on which the VX-REXX run time libraries have been 
  1390. installed. See the online Read Me First that came with VX-REXX for information 
  1391. about the run time libraries. 
  1392.  
  1393.  
  1394. ΓòÉΓòÉΓòÉ 4.8. Command line options ΓòÉΓòÉΓòÉ
  1395.  
  1396. The VX-REXX design environment accepts the following options: 
  1397.  
  1398. /o projectname      Opens the project projectname. 
  1399.  
  1400. /x exename          Makes the executable file exename from the currently open 
  1401.                     project. 
  1402.  
  1403. /m macroname        Makes the macro file macroname from the currently open 
  1404.                     project. 
  1405.  
  1406. /q                  Quit. If omitted, the design environment remains open. 
  1407.  
  1408. These options can be used to automatically re-generate project executables from 
  1409. the OS/2 command line. For example: 
  1410.  
  1411. vrxedit /o myproj.vrp /x myproj.exe /q
  1412.  
  1413. This example starts VRXEDIT.EXE (the design environment), opens the project 
  1414. MYPROJ.VRP, makes the executable file MYPROJ.EXE from the project and then 
  1415. quits. 
  1416.  
  1417.  
  1418. ΓòÉΓòÉΓòÉ 5. Adding objects to a window ΓòÉΓòÉΓòÉ
  1419.  
  1420. When you start VX-REXX, an empty project window appears to which you can add 
  1421. objects such as data entry fields, push buttons and list boxes. This chapter 
  1422. shows you how to create and modify these objects to design your application 
  1423. user interface. 
  1424.  
  1425.  
  1426. ΓòÉΓòÉΓòÉ 5.1. Introduction to objects ΓòÉΓòÉΓòÉ
  1427.  
  1428. An object is a basic building block for your application interface. An object 
  1429. consists of properties (its data), and methods (the functions it can perform). 
  1430. Your program interacts with objects by creating them, setting and getting their 
  1431. properties, and invoking their methods. Objects interact with your program by 
  1432. sending it events to which the program responds. 
  1433.  
  1434. The PushButton is a typical object. You create one by drawing it in a window. 
  1435. You can set the text on it by setting its Caption property. You specify what 
  1436. happens when the button is clicked by defining a Click event routine. The event 
  1437. routine is run when the button is clicked. 
  1438.  
  1439. Some special objects, for example menus and  windows, are created with commands 
  1440. on a window's pop-up menu and on the Windows menu. These objects are described 
  1441. in separate chapters (Adding menus to a program, Multiple file projects, 
  1442. Secondary windows). 
  1443.  
  1444. Other objects are invisible. You cannot create or see them but you can use 
  1445. them; these objects are created for you. One of them is the Application object. 
  1446. You can use it to pass information from one file to another within an 
  1447. application, and to start and control execution threads. The Screen object is 
  1448. another such object. These objects are described in the online VXΓêÖREXX 
  1449. Reference. 
  1450.  
  1451.  
  1452. ΓòÉΓòÉΓòÉ 5.2. Creating objects ΓòÉΓòÉΓòÉ
  1453.  
  1454. When VX-REXX is started on a new project, an empty project window appears. In 
  1455. Figure 24 the window containing rows of dots is the project window. You create 
  1456. the visual interface to your application in this window. 
  1457.  
  1458. Figure 24  The VX-REXX design environment
  1459.  
  1460. You begin to create an application by adding objects to the empty project 
  1461. window. The Tools menu contains the objects you can use to design your 
  1462. application interface. 
  1463.  
  1464. To add one of these objects such as a push button to the project window, 
  1465. proceed as follows: 
  1466.  
  1467.  1. Click on the Tools menu and choose the object from the list. 
  1468.  
  1469.  2. Position the mouse pointer in the project window where the upper left 
  1470.     corner of the object is to be placed. 
  1471.  
  1472.  3. Hold down mouse button 1 and drag the mouse until the outline of the object 
  1473.     is the size you want. 
  1474.  
  1475.  4. Release the mouse button. 
  1476.  
  1477. Use this procedure to add a push button to the upper left hand corner of the 
  1478. empty  window. Your project window will look similar to Figure 25. 
  1479.  
  1480. Figure 25  Object added to a project window
  1481.  
  1482.  
  1483. ΓòÉΓòÉΓòÉ 5.3. Using the tool palette ΓòÉΓòÉΓòÉ
  1484.  
  1485. Each of the objects listed in the Tools menu has a corresponding icon in the 
  1486. tool palette as in Figure 26. This allows you to select objects more quickly. 
  1487.  
  1488. Figure 26  Tool palette
  1489.  
  1490. The tool palette is displayed on the right side of your project window when you 
  1491. start VX-REXX. To add an object using the tool palette, click on the object 
  1492. icon to select it  and then add the object to your window by positioning and 
  1493. dragging the mouse. 
  1494.  
  1495. Unless you close it, the tool palette will remain displayed during the current 
  1496. session. When you become familiar with the icons, you may find that the tool 
  1497. palette is more convenient and faster to use than the Tools menu. 
  1498.  
  1499.  
  1500. ΓòÉΓòÉΓòÉ 5.4. Sizing and moving an object ΓòÉΓòÉΓòÉ
  1501.  
  1502. After an object is created, you may find that it is not the exact size that you 
  1503. want or that it is not positioned correctly. You can easily resize and move 
  1504. objects using the mouse. 
  1505.  
  1506. To resize an object, select it by clicking on it with mouse button 1. When you 
  1507. select an object you will see small black squares located on the corners and 
  1508. sides as in Figure 27. 
  1509.  
  1510. Figure 27  Sizing handles
  1511.  
  1512.  These black squares are called sizing handles and are used to resize the 
  1513. object. The handles at the corners of the object  let you change the height and 
  1514. width simultaneously. The handles in the middle of the sides let you resize one 
  1515. dimension at a time. 
  1516.  
  1517. For example, to enlarge both the width and height of an object: 
  1518.  
  1519.  1. Position the mouse pointer on the bottom right corner sizing handle. You 
  1520.     are positioned correctly when the mouse pointer changes to an arrow with a 
  1521.     point at both ends. 
  1522.  
  1523.  2. Use mouse button 1 to drag the mouse down and to the right. Notice the 
  1524.     outline for the new size of the object. 
  1525.  
  1526.  3. Release the mouse button. The object will be redrawn to the new size. 
  1527.  
  1528. You can use a similar technique to resize the project window. Windows do not 
  1529. have sizing handles as objects do, but if you move the mouse pointer  to the 
  1530. edge or corner of the window you will notice that the pointer changes to an 
  1531. arrow with a point at both ends. You can then resize the window by dragging the 
  1532. mouse using mouse button 1, until the window is the size that you want. 
  1533.  
  1534. To move an object, position the mouse pointer anywhere within the object and 
  1535. use mouse button 2 to drag it to the new location. If you want to move two or 
  1536. more objects at the same time you must select  them both. To do this, position 
  1537. the mouse above and to the left of the first object and, using mouse button 1, 
  1538. drag the mouse to enclose all of them in a box. For example, to move two push 
  1539. buttons together as in Figure 28: 
  1540.  
  1541.  1. Position the mouse pointer slightly above and to the left of the first push 
  1542.     button. 
  1543.  
  1544.  2. Use mouse button 1 to drag the mouse down and to the right, surrounding 
  1545.     both of  the objects. 
  1546.  
  1547.  3. Release the mouse button. 
  1548.  
  1549. Figure 28  Selecting two objects
  1550.  
  1551. Both of the objects within the outlined region will be selected and their 
  1552. sizing handles visible. The sizing handles will be gray rather than black. You 
  1553. can now move both push buttons as you would one object by positioning the mouse 
  1554. on either object and dragging the objects to the new location. 
  1555.  
  1556. You can also select multiple objects by pressing and holding the Ctrl key while 
  1557. clicking on the objects that you want to select. Use this technique to select 
  1558. objects that cannot  be enclosed in a boxed region. 
  1559.  
  1560.  
  1561. ΓòÉΓòÉΓòÉ 5.5. Selecting objects ΓòÉΓòÉΓòÉ
  1562.  
  1563. There are two ways of selecting objects: marquee selection and swipe selection. 
  1564. You have already seen marquee selection in a previous section -- this technique 
  1565. involves dragging a rectangle around an object or a group of objects. When you 
  1566. release the mouse, all objects in the rectangle are selected. 
  1567.  
  1568. You can also select objects by swiping the mouse across a number of objects 
  1569. while holding down the mouse button. This is called swipe selection. The 
  1570. following steps show you how to swipe select the two push buttons from the 
  1571. previous section. 
  1572.  
  1573.  1. Position the mouse over the first push button. 
  1574.  
  1575.  2. Press and hold down mouse button 1. The first push button will be selected. 
  1576.  
  1577.  3. Without releasing the mouse button, move the mouse over the second push 
  1578.     button. Now both push buttons will be selected. 
  1579.  
  1580.  4. Release the mouse button. 
  1581.  
  1582.  
  1583. ΓòÉΓòÉΓòÉ 5.6. Copying and deleting objects ΓòÉΓòÉΓòÉ
  1584.  
  1585. You can remove and copy objects in your project window with the Cut, Copy, 
  1586. Paste, and Delete commands found in the object pop-up menu. Cut, Copy and Paste 
  1587. use an internal clipboard to copy objects within a window or between windows 
  1588. within one project. 
  1589.  
  1590. For example, to add three identical push buttons to your project window: 
  1591.  
  1592.  1. Create the first push button. 
  1593.  
  1594.  2. Click mouse button 2 anywhere within the object to display the object's 
  1595.     pop-up menu. 
  1596.  
  1597.  3. Choose Copy. A copy of the push button will be added to the clipboard. 
  1598.  
  1599.  4. Click mouse button 2 on the location in your program window where you want 
  1600.     the copy to be placed. The window pop-up menu will appear. 
  1601.  
  1602.  5. Choose Paste. The top left corner of the pasted object will be located 
  1603.     where you clicked in the program window. 
  1604.  
  1605.  6. To add the third push button, repeat steps 4 and 5. 
  1606.  
  1607. Using cut, copy and paste, objects can be moved between project windows within 
  1608. an application. You will learn how to create applications with multiple windows 
  1609. in the chapters Multiple file projects and Secondary windows. 
  1610.  
  1611. Figure 29  Copying objects
  1612.  
  1613. Delete removes an object from a window. It cannot be pasted back. For example, 
  1614. to remove an object from your project window, move the mouse pointer over the 
  1615. object and click mouse button 2. Choose Delete from the pop-up menu as shown in 
  1616. Figure 30. 
  1617.  
  1618. Figure 30  Delete an object
  1619.  
  1620. The object will be removed from the project window. 
  1621.  
  1622.  
  1623. ΓòÉΓòÉΓòÉ 5.7. Duplicating an object ΓòÉΓòÉΓòÉ
  1624.  
  1625. Duplicate creates a duplicate copy of an object. The objects are identical 
  1626. except for their location in the window. The duplicate object is created 
  1627. slightly offset from the original. 
  1628.  
  1629. You should duplicate objects only when you want them to share the same event 
  1630. code. For example, you may want to use duplicate push buttons for the numeric 
  1631. buttons in a calculator program. 
  1632.  
  1633. For example, to add three identical push buttons to your window: 
  1634.  
  1635.  1. Create the first push button. 
  1636.  
  1637.  2. Click mouse button 2 anywhere within the object to display the object's 
  1638.     pop-up menu. 
  1639.  
  1640.  3. Choose Duplicate. The duplicated object will appear offset from the 
  1641.     original object. 
  1642.  
  1643.  4. Use mouse button 2 to drag the new object to its new location in your 
  1644.     project window. 
  1645.  
  1646.  5. To add the third push button, repeat steps 2, 3 and 4. 
  1647.  
  1648. When you duplicate an object, the clipboard is not used; the clipboard contents 
  1649. remain unchanged. 
  1650.  
  1651.  
  1652. ΓòÉΓòÉΓòÉ 5.8. Aligning objects ΓòÉΓòÉΓòÉ
  1653.  
  1654. The background of the program window is covered with a pattern of regularly 
  1655. spaced dots. These dots form an alignment grid that you can use to ensure that 
  1656. objects are aligned vertically or horizontally. The grid is used whenever 
  1657. objects are created, resized or moved. For example, as you add an object to a 
  1658. window, the size of the outline changes in "jump-steps" rather than in a smooth 
  1659. motion. 
  1660.  
  1661. The grid helps you align objects when you are moving or resizing them. The 
  1662. Align command in the object pop-up menu lets you align objects more easily. You 
  1663. can use this command to align two or more objects on the left or right, at the 
  1664. top or bottom, or vertically or horizontally on the centre of one of the 
  1665. objects. 
  1666.  
  1667. For example, if you have created a window with three push buttons you could 
  1668. align their left edges, as follows: 
  1669.  
  1670.  1. Select all three push buttons either by pressing the Ctrl key while 
  1671.     clicking on each object or by enclosing the objects in a box using mouse 
  1672.     button 1. 
  1673.  
  1674.  2. Click mouse button 2 anywhere within one of the buttons to display its 
  1675.     pop-up menu. This button will be the target for the alignment. 
  1676.  
  1677.  3. Choose Align from the pop-up menu. The Align menu will be displayed as 
  1678.     shown in Figure 31. 
  1679.  
  1680.         Figure 31  Align menu
  1681.  
  1682.  4. Click on the icon that shows a vertical dotted line to the left of three 
  1683.     fields. 
  1684.  
  1685. The objects will be aligned on the left side of the target push button, as in 
  1686. Figure 32. 
  1687.  
  1688. Figure 32  Push buttons aligned
  1689.  
  1690.  
  1691. ΓòÉΓòÉΓòÉ 5.9. Grouping objects ΓòÉΓòÉΓòÉ
  1692.  
  1693. VX-REXX objects exist in groups. For example, all objects added to a window 
  1694. belong to a group. The GroupBox object allows you to create other groups within 
  1695. a window. Any object that can be placed in a window can be put in a group box, 
  1696. including other group boxes. If you draw a group box around an existing set of 
  1697. objects, the objects will be added to the new group box. Objects may also be 
  1698. added by cutting and pasting them into the group box. 
  1699.  
  1700. Group boxes are most commonly used to group radio buttons. Since only one radio 
  1701. button can be set at one time, you must group them if you have more than one 
  1702. set of radio buttons in a window. This allows the groups of buttons to function 
  1703. independently. 
  1704.  
  1705. The group boxes in  Figure 33 contain two groups of independent radio buttons. 
  1706.  
  1707. Figure 33  Sample group boxes
  1708.  
  1709. You can also use group boxes just to emphasize the relationship among  the 
  1710. grouped objects, or to enhance the appearance of your window. Also, since 
  1711. objects in a group move together when you move the group, you can use groups to 
  1712. simplify designing windows. 
  1713.  
  1714.  
  1715. ΓòÉΓòÉΓòÉ 5.10. Moving objects to the front and back ΓòÉΓòÉΓòÉ
  1716.  
  1717. Objects on a window or in a group box are drawn in a particular order, 
  1718. sometimes referred to as the z-order or sibling order. The sibling order is 
  1719. only important if two objects in the same window or group box overlap. If both 
  1720. objects have the ClipSiblings property set to 1, they draw themselves so that 
  1721. the object with the lower sibling order is on "top" of the other object. 
  1722.  
  1723. The sibling order of an object is changed at design time using the Bring to 
  1724. front and Send to back commands on the object pop-up menu. (If an object is 
  1725. already at the top of the sibling order, the Bring to front command is removed 
  1726. from the menu; similarly, if an object is at the bottom of the sibling order, 
  1727. the Send to back command is removed from the menu.)  You may also select 
  1728. several objects and send them to the front or back as a group. 
  1729.  
  1730. To change the sibling order of an object at run time, use the SiblingOrder 
  1731. property. 
  1732.  
  1733. Remember that changing the sibling order of an object may appear to have no 
  1734. effect unless the ClipSiblings property is set. ClipSiblings is not set by 
  1735. default, because some objects (notably the DropDownComboBox object) do not 
  1736. behave as expected if it is set. 
  1737.  
  1738.  
  1739. ΓòÉΓòÉΓòÉ 6. Changing object properties ΓòÉΓòÉΓòÉ
  1740.  
  1741. Each object in your project's user interface has properties which determine 
  1742. both how it appears and how it functions. You can change property values at 
  1743. both design time and run time. This chapter shows you how to change property 
  1744. values when designing the user interface. 
  1745.  
  1746. When an object is created, default values are assigned to its associated 
  1747. properties. At design time, you can change the values using the object's 
  1748. property notebook. For example, you can add a caption to a push button. You can 
  1749. also examine and change the values of many properties while the application is 
  1750. running. For example, you may want to disable a push button once it is pressed. 
  1751. VX-REXX provides functions to query and change property values at run time. Run 
  1752. time  procedures are described in the chapter named  Programming with objects. 
  1753.  
  1754.  
  1755. ΓòÉΓòÉΓòÉ 6.1. Property notebook ΓòÉΓòÉΓòÉ
  1756.  
  1757. When you add an object to your project window, initial values are set for its 
  1758. properties. You change an object's properties using its property notebook, 
  1759. which is opened by selecting the Properties item from the Open menu in the 
  1760. object's pop-up menu. To open an object's pop-up menu, click mouse button 2 
  1761. anywhere within the object. The property notebook for a push button is 
  1762. displayed in Figure 34. 
  1763.  
  1764. Figure 34  A push button's property notebook
  1765.  
  1766. In this example the first page of the notebook shows the values of the color 
  1767. properties associated with the push button. The index tabs are the names of all 
  1768. of the property groups for this object. 
  1769.  
  1770. A few properties, such as Name, are common to every object. Others, such as 
  1771. BackColor and ForeColor, apply only to certain objects. Only properties which 
  1772. apply to the current object are shown. 
  1773.  
  1774. You can open the online information for any property by clicking on its value 
  1775. in the property notebook and then pressing F1. 
  1776.  
  1777.  
  1778. ΓòÉΓòÉΓòÉ 6.2. Changing property values ΓòÉΓòÉΓòÉ
  1779.  
  1780. You can change a property value either by entering a value or by choosing an 
  1781. option from the property's notebook page. For example, to change the caption 
  1782. property of a push button, open its property notebook, click on the Text index 
  1783. tab, then click on the entry field for Caption and type the value, such as Push 
  1784. Me, as in Figure 35. 
  1785.  
  1786. Figure 35  Text properties
  1787.  
  1788. When you press Enter the caption appears on the button. 
  1789.  
  1790. A property change is applied to the object as soon as you make the choice. You 
  1791. can leave the notebook open but your screen will be less cluttered if you close 
  1792. it when you have finished making property changes. 
  1793.  
  1794. Like the objects on a window, the window itself has properties. For example, 
  1795. the title which appears on the title bar corresponds to the window's Caption 
  1796. property. There is no caption set for a window when you first create it. 
  1797.  
  1798. To add or change a caption: 
  1799.  
  1800.  1. Click mouse button 2 on an empty location in the window. The window 
  1801.     object's pop-up menu will be displayed. 
  1802.  
  1803.  2. Click on the Open menu and then the Properties item. The window's property 
  1804.     notebook will be displayed. 
  1805.  
  1806.  3. Choose the Text index tab. 
  1807.  
  1808.  4. Click on the Caption entry field and enter a value such as First 
  1809.     Application. 
  1810.  
  1811.  5. Press Enter to make the change. 
  1812.  
  1813. You will notice that the caption is displayed in the title bar of the window. 
  1814.  
  1815. Some properties, such as the caption, are text strings. Some others can only 
  1816. have two values, 1 or 0. These appear as check boxes, as shown in the following 
  1817. example of the Border property for the push button. 
  1818.  
  1819. Figure 36  Making a choice in a notebook
  1820.  
  1821. If you examine the push button's Border property on the Style page you will 
  1822. find that it is checked, indicating that the push button has a border. If you 
  1823. click on the check box, the border on the push button is removed. The push 
  1824. button caption is all that remains visible. Most of the time you will want the 
  1825. border to be set for a push button. 
  1826.  
  1827. Other properties are set by selecting a value from a list. For example, Figure 
  1828. 37 shows the list used to change the BackColor property on the Color notebook 
  1829. page. 
  1830.  
  1831. Figure 37  Choosing a property value from a list
  1832.  
  1833. In some cases, a separate dialog is used to set a value. For example, the Font 
  1834. property is defined by a number of characteristics including a font name, style 
  1835. and size. You select a font by clicking on the Edit button on the Text page of 
  1836. the property notebook to display the Font window as in Figure 38. 
  1837.  
  1838. Figure 38  Changing the Font property
  1839.  
  1840. You can select values from the drop down lists and the check boxes to choose 
  1841. the appropriate font. The changes are reflected in the Sample box. The font 
  1842. changes in the project window when you click on Ok. If you decide to not change 
  1843. the font, you can click on Cancel. 
  1844.  
  1845.  
  1846. ΓòÉΓòÉΓòÉ 6.3. Properties of copied and deleted objects ΓòÉΓòÉΓòÉ
  1847.  
  1848. All property values for an object are cut, copied, pasted, duplicated or 
  1849. deleted when you cut, copy, paste, duplicate or delete an object in your 
  1850. window. 
  1851.  
  1852.  When you cut or copy an object it is saved to the clipboard along with its 
  1853. properties. You can then paste the object into the current window or into 
  1854. another window within the same project. 
  1855.  
  1856. When an object is pasted, the following properties are changed automatically so 
  1857. that the values are unique for the new object: 
  1858.  
  1859. o Top and Left are changed to the location of the pasted object. 
  1860.  
  1861. o TabIndex is changed to add the new object to the end of the tab order. 
  1862.  
  1863. o Name is changed if necessary to give the new object a unique name. 
  1864.  
  1865. The other properties remain the same. 
  1866.  
  1867. When you duplicate an object, it is not copied to the clipboard. Any 
  1868. information previously copied to the clipboard remains. Duplicating an object 
  1869. is the same as copying and pasting except that the name of the new object 
  1870. remains identical to the original object. Because they have the same name, 
  1871. duplicate objects share event routines; i.e., the same event routine is used 
  1872. for both objects. 
  1873.  
  1874. If you cut or copy one of a set of duplicate objects to the clipboard and then 
  1875. paste it, its name will change. It will no longer be a duplicate object. If you 
  1876. select several duplicate objects and then copy them to the clipboard, their 
  1877. names will change to the same value when pasted. They will be a new set of 
  1878. duplicate objects. 
  1879.  
  1880. When you delete an object both the object and its properties are deleted. You 
  1881. cannot paste it back in the project window. 
  1882.  
  1883.  
  1884. ΓòÉΓòÉΓòÉ 6.4. Direct editing ΓòÉΓòÉΓòÉ
  1885.  
  1886. Direct editing may be used to at design time to edit the text of an object with 
  1887. a Caption or Value property. To start direct editing, click on the object while 
  1888. pressing the Alt key. An entry field will appear. Enter or modify the text. 
  1889. Click outside the entry field to terminate the editing and save the new text, 
  1890. or press the Esc key to cancel the editing. 
  1891.  
  1892.  
  1893. ΓòÉΓòÉΓòÉ 7. Adding and modifying routines ΓòÉΓòÉΓòÉ
  1894.  
  1895. The third and final step in creating a program in VX-REXX is attaching the REXX 
  1896. code. The previous two chapters described procedures for creating objects and 
  1897. setting their properties. This chapter describes the procedures to create and 
  1898. attach routines to the objects. It also describes the creation and use of 
  1899. general routines that are not attached to any particular object. 
  1900.  
  1901.  
  1902. ΓòÉΓòÉΓòÉ 7.1. Introduction to routines ΓòÉΓòÉΓòÉ
  1903.  
  1904. There are two types of routines used in VX-REXX: event routines and general 
  1905. routines. Event routines are called automatically when the user triggers the 
  1906. event, such as clicking the mouse on an object, while general routines are 
  1907. called explicitly by other routines within your application. 
  1908.  
  1909.  
  1910. ΓòÉΓòÉΓòÉ 7.1.1. Event routines ΓòÉΓòÉΓòÉ
  1911.  
  1912. Similar to properties, each object has a set of events associated with it. Each 
  1913. object type has a unique set of events to which you can attach REXX routines. 
  1914. These routines are called event routines. When an object is created, its event 
  1915. routines are empty. If an action should be executed when the event is 
  1916. triggered, you add code to that event routine. 
  1917.  
  1918. At run time, when you trigger an event for an object, the corresponding event 
  1919. routine is run automatically. 
  1920.  
  1921.  
  1922. ΓòÉΓòÉΓòÉ 7.1.2. General routines ΓòÉΓòÉΓòÉ
  1923.  
  1924. Programs usually have other collections of routines which are not directly tied 
  1925. to events. These routines are called general routines. General routines allow 
  1926. programs to be factored into logical units and allow you to reuse common code 
  1927. segments. 
  1928.  
  1929. Event and general routines are both just normal REXX routines. Within one file 
  1930. (window file or code file), any routine can call any other routine. However, it 
  1931. is best not to call event routines directly as this will make your code harder 
  1932. to understand and maintain. Also, if you delete or rename the object 
  1933. corresponding to an event routine the event routine will be deleted or renamed. 
  1934. Instead of calling an event routine directly, you should factor out the common 
  1935. code and place it in a general routine and call it. 
  1936.  
  1937.  
  1938. ΓòÉΓòÉΓòÉ 7.2. Introduction to sections ΓòÉΓòÉΓòÉ
  1939.  
  1940. VX-REXX adds the concept of sections of routines within a file to standard 
  1941. REXX. A standard REXX program consists of a file containing routines. You edit 
  1942. the entire file at once. For very large REXX programs, maintaining this file 
  1943. can be difficult. VX-REXX uses sections within a file to group routines into 
  1944. more manageable components. When using VX-REXX, you can choose to edit your 
  1945. application section-by-section or to edit the entire file. 
  1946.  
  1947. A section is a named set of related routines. The name of the section is 
  1948. normally the same as the name of the first routine in the section, though this 
  1949. is strictly only necessary for sections containing event routines. There can be 
  1950. multiple routines in a section. A section is not a callable entity in the REXX 
  1951. language, it only provides modularization of the REXX routines within a file. 
  1952. Sections have no effect on the scope of names; all names are global within the 
  1953. containing file. 
  1954.  
  1955. A new section is created automatically whenever a new event routine is created. 
  1956. A section statement in a REXX file has the following form. 
  1957.  
  1958. /*:VRX     name */
  1959.  
  1960. The name would be the same as the label of the first routine in the section. 
  1961.  
  1962.  
  1963. ΓòÉΓòÉΓòÉ 7.3. Editing sections ΓòÉΓòÉΓòÉ
  1964.  
  1965.  
  1966. ΓòÉΓòÉΓòÉ 7.3.1. Editing event routine sections ΓòÉΓòÉΓòÉ
  1967.  
  1968. You can think of an event routine as another type of property that is 
  1969. associated with an object. Creating or changing an event routine is similar to 
  1970. setting other properties. 
  1971.  
  1972. Use the following procedure to create a new section for an object's event 
  1973. routine or to edit an existing event routine. 
  1974.  
  1975.  1. Click mouse button 2 anywhere within the object to view the pop-up menu. 
  1976.  
  1977.  2. Choose Open... and then choose Properties to display the object's property 
  1978.     notebook. 
  1979.  
  1980.  3. Choose Event to view the list of possible events for the object. 
  1981.  
  1982.  4. Select the event name from the list of items and click on Open, or double 
  1983.     click on the name. 
  1984.  
  1985.     This opens the VX-REXX section editor which you can use to create or edit 
  1986.     the event routine. 
  1987.  
  1988.  5. Enter the REXX instructions. 
  1989.  
  1990.  6. Close the section editor, if you are finished with it. 
  1991.  
  1992. When you open an event routine which has not been previously created, VX-REXX 
  1993. automatically generates a new section which contains the event routine name and 
  1994. a REXX return statement similar to the following: 
  1995.  
  1996. /*:VRX  PB_OK_Click */
  1997. PB_OK_Click:
  1998.  
  1999. return
  2000.  
  2001.  You need only fill in the body of the routine. If the event routine already 
  2002. exists, the section which contains the existing routine is loaded. 
  2003.  
  2004.  
  2005. ΓòÉΓòÉΓòÉ 7.3.2. Event routine names ΓòÉΓòÉΓòÉ
  2006.  
  2007. VX-REXX generates names for event routines. An event routine name is the 
  2008. object's name followed by an underscore followed by the name of the event. For 
  2009. example, the click event routine for a push button with the name PB_OK would be 
  2010. PB_OK_Click. 
  2011.  
  2012.  
  2013. ΓòÉΓòÉΓòÉ 7.3.3. General routines ΓòÉΓòÉΓòÉ
  2014.  
  2015. General routines are not automatically created and named by VX-REXX. You create 
  2016. them as needed using the Sections window. The next section describes how to use 
  2017. this window. 
  2018.  
  2019.  
  2020. ΓòÉΓòÉΓòÉ 7.3.4. Using the section list ΓòÉΓòÉΓòÉ
  2021.  
  2022. The Sections window lists all of the sections in a file. From the Sections 
  2023. window, you can create new sections containing general routines,  and edit and 
  2024. delete existing sections. This provides an alternate way to edit sections 
  2025. containing event routines. You must always create event routines using the 
  2026. property notebook. 
  2027.  
  2028. To open the Sections window, select Section list from the Windows menu. The 
  2029. section list will remain open until you close it. 
  2030.  
  2031. Figure 39  The Section list
  2032.  
  2033.  
  2034. ΓòÉΓòÉΓòÉ 7.3.5. Creating a new section ΓòÉΓòÉΓòÉ
  2035.  
  2036. The following procedure creates a new section. 
  2037.  
  2038.  1. In the Sections window, choose New from the Section menu. 
  2039.  
  2040.     A dialog will prompt you for the name of the new section. 
  2041.  
  2042.  2. Enter the name of the new section, for example, DoIt. 
  2043.  
  2044.  3. Click the OK button. 
  2045.  
  2046.     The new section name, in this case DoIt, will be added to the section list. 
  2047.     Also, a section editor will be opened containing the new section. VX-REXX 
  2048.     automatically generates a skeleton routine consisting of the routine name 
  2049.     (which is the same as the section name), and a REXX return statement. You 
  2050.     need only to fill in the body of the routine. The new routine will look 
  2051.     like this: 
  2052.  
  2053.         /*:VRX  DoIt */
  2054.         DoIt:
  2055.  
  2056.         return
  2057.  
  2058.  4. Enter the REXX instructions. 
  2059.  
  2060.  5. Close the section editor, if you are finished with it. 
  2061.  
  2062.  
  2063. ΓòÉΓòÉΓòÉ 7.3.6. Default section header ΓòÉΓòÉΓòÉ
  2064.  
  2065. A default section header may be defined using the Editor options dialog. To 
  2066. open the dialog, select the Editor... item from the Settings menu under the 
  2067. Options menu. One of the groups on this dialog defines the default header to 
  2068. use when creating new sections. This header is a string which is appended to 
  2069. the end of the first label in the section. For example, if the default header 
  2070. is procedure, sections will be created in this form: 
  2071.  
  2072. /*:VRX  DoIt */
  2073. DoIt: procedure
  2074.  
  2075. return
  2076.  
  2077. Headers are only used if Create new sections with this header is checked. 
  2078.  
  2079. If a default header is defined, it applies to any new section created in any 
  2080. project. 
  2081.  
  2082.  
  2083. ΓòÉΓòÉΓòÉ 7.3.7. Editing a section ΓòÉΓòÉΓòÉ
  2084.  
  2085. To edit an existing section: 
  2086.  
  2087.  1. In the Sections window, select the section name from the list of names. 
  2088.  
  2089.  2. Choose Open from the Section menu, or double click on the name. 
  2090.  
  2091.     This opens a section editor containing the section. 
  2092.  
  2093.  3. Enter or change the REXX instructions. 
  2094.  
  2095.  4. Close the section editor, if you are finished with it. 
  2096.  
  2097.  
  2098. ΓòÉΓòÉΓòÉ 7.3.8. Deleting a section ΓòÉΓòÉΓòÉ
  2099.  
  2100. To delete a section: 
  2101.  
  2102.  1. In the Sections window, select the section name from the list. 
  2103.  
  2104.  2. Choose Delete from the Section menu. 
  2105.  
  2106. The section name will be removed from the section list and the related routines 
  2107. will be deleted from the program. To delete an event routine, you delete its 
  2108. section. 
  2109.  
  2110.  
  2111. ΓòÉΓòÉΓòÉ 7.4. Using the section editor ΓòÉΓòÉΓòÉ
  2112.  
  2113. Sections are entered and modified in an editor. You can choose to edit sections 
  2114. using an external editor, such as the OS/2 Enhanced Editor, as described in the 
  2115. next section, or using VX-REXX's built-in section editor. 
  2116.  
  2117. The built-in section editor provides standard editing capabilities including 
  2118. Cut, Copy, Paste, and Delete commands. The Cut, Copy, and Paste commands use 
  2119. the OS/2 clipboard so you can move code between applications. The section 
  2120. editor also provides Search, Replace and Go to line commands. 
  2121.  
  2122.  
  2123. ΓòÉΓòÉΓòÉ 7.4.1. Searching ΓòÉΓòÉΓòÉ
  2124.  
  2125. The Search command searches for a target string starting from the current 
  2126. position in the section to the end of the section. The following steps describe 
  2127. how to use the Search command. 
  2128.  
  2129.  1. Select Search from the Edit menu. The Search dialog will be displayed. 
  2130.  
  2131.  2. Enter the string you want to find. 
  2132.  
  2133.  3. Click on the Find button. The next occurrence of the target search string 
  2134.     will be highlighted. 
  2135.  
  2136.  4. To find the next occurrence, repeat step 3. 
  2137.  
  2138.  5. Click Cancel to close the search dialog. 
  2139.  
  2140.  
  2141. ΓòÉΓòÉΓòÉ 7.4.2. Replacing ΓòÉΓòÉΓòÉ
  2142.  
  2143. The Replace command searches for a target string starting from the current 
  2144. position in the section to the end of the section. You can replace the target 
  2145. string or continue to the next occurrence of the target string. The following 
  2146. steps describe how to use the Replace command. 
  2147.  
  2148.  1. Select Replace from the Edit menu. The dialog will appear as in Figure 40. 
  2149.  
  2150.         Figure 40  Replace dialog
  2151.  
  2152.  2. Enter the string you want to find. 
  2153.  
  2154.  3. Enter the replacement string. 
  2155.  
  2156.  4. Click the Find button. The editor will find the next occurrence of the 
  2157.     target string. 
  2158.  
  2159.  5. To replace the current occurrence, click the Replace button. The string 
  2160.     will be changed to the new value. 
  2161.  
  2162.  6. To find and replace the next occurrence, repeat steps 4 and 5. 
  2163.  
  2164.  7. Click Cancel to close the search dialog. 
  2165.  
  2166. The Replace command can also replace all occurrences of the target string in 
  2167. the section with the replacement string. The following steps describe how to 
  2168. replace all occurrences. 
  2169.  
  2170.  1. Position the edit insertion point at the top of the file so that all 
  2171.     occurrences will be found. 
  2172.  
  2173.  2. Select Replace from the Edit menu. The replace dialog will appear. 
  2174.  
  2175.  3. Enter the string you want to find. 
  2176.  
  2177.  4. Enter the replacement string. 
  2178.  
  2179.  5. Click the Replace All button. All occurrences of the string will be 
  2180.     replaced with the new string. 
  2181.  
  2182.  6. Click Cancel to close the search dialog. 
  2183.  
  2184.  
  2185. ΓòÉΓòÉΓòÉ 7.4.3. Moving to a line ΓòÉΓòÉΓòÉ
  2186.  
  2187. The Go command moves the edit insertion point to the beginning of a specified 
  2188. line number. The following steps describe how to use the Go command. 
  2189.  
  2190.  1. Select Go from the Edit menu. The Go To Line dialog will appear. 
  2191.  
  2192.  2. Enter the line number. 
  2193.  
  2194.  3. Click the OK button. The edit insertion point will be positioned at the 
  2195.     beginning of the line that you entered. 
  2196.  
  2197.  
  2198. ΓòÉΓòÉΓòÉ 7.4.4. Accessing online information ΓòÉΓòÉΓòÉ
  2199.  
  2200. You can open online information on VX-REXX and REXX topics directly from the 
  2201. editor in three ways. 
  2202.  
  2203. The first way is to select a word with the mouse and then click mouse button 2 
  2204. to bring up the editor pop-up menu. Select the Help on item to search the 
  2205. online information for the topic corresponding to the selected word. 
  2206.  
  2207. The second way is to hold the Ctrl key while double clicking with mouse button 
  2208. 1 on a word. The word will be selected, and the topic will be searched for in 
  2209. the online help. 
  2210.  
  2211. The third was is to open an online book by picking one of the books listed in 
  2212. the Help menu. The VX-REXX programmer's guide and reference, and the REXX 
  2213. language reference are all in this menu. 
  2214.  
  2215. You can use these technique to view the reference information for all VX-REXX 
  2216. objects, properties, events, and methods as well as all REXX functions and 
  2217. keywords. 
  2218.  
  2219.  
  2220. ΓòÉΓòÉΓòÉ 7.4.5. Jumping to another routine ΓòÉΓòÉΓòÉ
  2221.  
  2222. Similar methods can be used to quickly switch from one editor to another if the 
  2223. text in one editor refers to a procedure in another editor. Select the text and 
  2224. invoke the pop-up menu as before, but select the View item instead, or hold 
  2225. down the Alt key while double clicking on the word. 
  2226.  
  2227.  
  2228. ΓòÉΓòÉΓòÉ 7.5. Using an external editor ΓòÉΓòÉΓòÉ
  2229.  
  2230. You can choose to edit any section using either the built-in section editor or 
  2231. an external editor such as the OS/2 Enhanced Editor. To use an external editor, 
  2232. use the External editor menu item or push button instead of the Open menu item 
  2233. or push button. 
  2234.  
  2235. You can set the external editor to the editor of your choice. By default, the 
  2236. external editor is set to the OS/2 Enhanced Editor. Use the following procedure 
  2237. to use a different external editor. 
  2238.  
  2239.  1. Select Settings from the Options menu. 
  2240.  
  2241.  2. Select Editor from the Settings menu. 
  2242.  
  2243.  3. Enter the command to be used to start your editor. 
  2244.  
  2245.  4. Check the appropriate radio button. 
  2246.  
  2247.  5. Click the OK button. 
  2248.  
  2249. The command you enter is interpreted by REXX, so enter the command as you would 
  2250. enter it in a REXX command file, including any required quotation marks. You 
  2251. can enter a single command or enter a number of statements separated by 
  2252. semicolons. You can also call an external REXX command file by using the call 
  2253. instruction in your command. You can even use the say and trace instructions if 
  2254. you call VRRedirectStdIO first. 
  2255.  
  2256. There are three variables available that you can use in your command: 
  2257.  
  2258. VREFileName         The path and name of the file to edit. 
  2259.  
  2260. VRELineNumber       The line in the file where the insertion point should be 
  2261.                     placed. 
  2262.  
  2263. VREWindow           The internal name of the VX-REXX primary window (you can 
  2264.                     use this as the parent window if you invoke a dialog in 
  2265.                     your procedure). 
  2266.  
  2267. The default command starts the OS/2 Enhanced Editor (EPM): 
  2268.  
  2269. "start epm.exe" VREFileName "'"VRELineNumber"'"
  2270.  
  2271. The OS/2 start command is used to start the editor in a separate process so 
  2272. that VX-REXX and the editor both run at the same time. 
  2273.  
  2274. Note:  When using an external editor you must be careful to save your work 
  2275. before saving or running your project. This is because VX-REXX cannot command 
  2276. your editor to save its contents when they are needed. If your current work is 
  2277. not saved the project will be saved or run with the old code. The updating of 
  2278. sections is handled automatically when you use the built-in section editor. 
  2279.  
  2280.  
  2281. ΓòÉΓòÉΓòÉ 7.6. Event routines of copied or deleted objects ΓòÉΓòÉΓòÉ
  2282.  
  2283. The cut, copy, paste, duplicate, and delete commands operate on an object as a 
  2284. whole, which includes the object, its properties, and sections containing its 
  2285. event routines. For instance, deleting an object removes the object, properties 
  2286. of the object, and sections of the object (all sections that start with the 
  2287. name of the object). 
  2288.  
  2289. The paste command checks for a duplicate object name. If the object name is 
  2290. unique (e.g. the object was cut), the object, its properties, and its events 
  2291. are pasted as is into the program. If an object with the same name already 
  2292. exists (e.g. the object was copied), the Name property is automatically 
  2293. renamed, as described in the previous chapter, before the object is pasted into 
  2294. the program. The sections and event routines for the object are also renamed. 
  2295.  
  2296. For instance, a push button named PB_1 would have a click event routine named 
  2297. PB_1_Click in a section named PB_1_Click. Copying this object using a copy and 
  2298. paste operation would generate a new push button with a new name, such as PB_2, 
  2299. with a click event routine named PB_2_Click in the section named PB_2_Click. 
  2300.  
  2301. The duplicate command copies the object, its properties and its sections. 
  2302. However, unlike pasted objects, the name of the new object remains the same as 
  2303. the original object. Any event routines created for one of the duplicate 
  2304. objects are shared by all of the duplicate objects. If you delete an event 
  2305. routine from the section list, it is deleted from all of the duplicate objects. 
  2306.  
  2307. If you rename one duplicate object, it will no longer share any of the event 
  2308. routines. You must create new ones for that object. However, if you copy a 
  2309. duplicate object to the clipboard and then paste it, the pasted object will 
  2310. have a new name and the events associated with it will be copied and renamed. 
  2311. You can also select and copy a set of duplicate objects to the clipboard. When 
  2312. you paste them, all of them will have the same new name and share the copied 
  2313. events. 
  2314.  
  2315.  
  2316. ΓòÉΓòÉΓòÉ 7.7. Sharing sections ΓòÉΓòÉΓòÉ
  2317.  
  2318. A shared section is a file containing one or more routines that are to be 
  2319. shared by several files in a project (see "Multiple file projects") or by files 
  2320. in different projects. 
  2321.  
  2322.  
  2323. ΓòÉΓòÉΓòÉ 7.7.1. Adding shared sections ΓòÉΓòÉΓòÉ
  2324.  
  2325. To add a shared section, select Add... from the Section menu in the Sections 
  2326. window. Enter the name of the file containing the routines that are to be 
  2327. shared. Absolute or relative file paths may be used. The shared section will be 
  2328. added to the front of the section list, as in: 
  2329.  
  2330. <d:\vxrexx\projects\shared\common.vrx>
  2331. Fini
  2332. Halt
  2333. Init
  2334. Main
  2335. Quit
  2336.  
  2337. When the project is run, or an executable or macro command file is made, the 
  2338. contents of the shared section will be appended (added to the end) to the file. 
  2339.  
  2340.  
  2341. ΓòÉΓòÉΓòÉ 7.7.2. Editing shared sections ΓòÉΓòÉΓòÉ
  2342.  
  2343. Shared sections are edited like normal sections:  double-click on the section 
  2344. name or select the section and choose Open from the Section menu. 
  2345.  
  2346. You may create new shared sections using your favorite text editor or using the 
  2347. section editor. To create new files using the section editor, simply create a 
  2348. new section in the current project, select all the text in the section editor, 
  2349. export it to an external file, delete the section and add the new file as a 
  2350. shared section. 
  2351.  
  2352.  
  2353. ΓòÉΓòÉΓòÉ 7.7.3. Deleting shared sections ΓòÉΓòÉΓòÉ
  2354.  
  2355. Shared sections are deleted from the current file by choosing Delete from the 
  2356. Section menu. The shared section is not actually deleted, but simply removed 
  2357. from the current file. 
  2358.  
  2359.  
  2360. ΓòÉΓòÉΓòÉ 7.7.4. Search order ΓòÉΓòÉΓòÉ
  2361.  
  2362. If a relative path is used when adding a shared section to a file, the 
  2363. following search order is used to locate the shared section: 
  2364.  
  2365.  1. The project folder. 
  2366.  
  2367.  2. The paths specified in the VXINCLUDE environment variable, if it exists. 
  2368.  
  2369.  3. The directory specified in the VXREXX environment variable. 
  2370.  
  2371.  
  2372. ΓòÉΓòÉΓòÉ 8. Programming with objects ΓòÉΓòÉΓòÉ
  2373.  
  2374. To create a VX-REXX application you position objects on a window and attach 
  2375. event routines to the objects. The routines attached to the objects are 
  2376. performed when the application is running and the user interacts with the 
  2377. objects. Previous chapters showed you how to add objects and code to a window. 
  2378. This chapter gives an overview of the structure and execution of VX-REXX 
  2379. projects and explains the general techniques used in writing event routines. 
  2380.  
  2381.  
  2382. ΓòÉΓòÉΓòÉ 8.1. The structure of a VX-REXX project ΓòÉΓòÉΓòÉ
  2383.  
  2384.  
  2385. ΓòÉΓòÉΓòÉ 8.1.1. Code files ΓòÉΓòÉΓòÉ
  2386.  
  2387. Not all VX-REXX applications include a graphical user interface. A simple 
  2388. VX-REXX project can consist of a single code file that contains a standard REXX 
  2389. program. A code-only application can be created by selecting New code file from 
  2390. the Project menu after creating a new project. (A new project is created when 
  2391. New is selected from the Project menu or when VX-REXX is started by double 
  2392. clicking on its icon). 
  2393.  
  2394. A new code file consists of an empty Main routine in a Main section. The code 
  2395. in the Main section is placed at the start of the REXX file and so is the code 
  2396. that is run first when the file is invoked. Since a section can contain many 
  2397. routines, all of the code in a project can be placed in the Main section. 
  2398. However it is easier to edit and maintain a large project if you use several 
  2399. sections. 
  2400.  
  2401. The advantage of multiple sections is that they allow you to edit your program 
  2402. in smaller pieces. However, multiple sections have no effect on the way your 
  2403. program is run: all of the code runs as a single REXX file. This means that 
  2404. routine and variable names are subject to the usual rules for a single REXX 
  2405. file. Since routine names are global, any routine can call any other routine 
  2406. and the names of all routines must be unique. Similarly, because variable names 
  2407. are global, any variable can be used or set in any routine, unless the REXX 
  2408. keyword procedure is added to the routine label. 
  2409.  
  2410.  
  2411. ΓòÉΓòÉΓòÉ 8.1.2. Window files ΓòÉΓòÉΓòÉ
  2412.  
  2413. Normally VX-REXX applications do include a graphical user interface. For 
  2414. example, a new VX-REXX project consists of a single window file. There are two 
  2415. parts to a window file: the window definition and the REXX code. The window 
  2416. definition lists the objects that form the user interface. The code is divided 
  2417. into sections for editing but is run as a single REXX file. 
  2418.  
  2419. Every object has a name. A default name is generated when the object is 
  2420. created,  but you can change the name by changing the Name property using the 
  2421. object's property notebook. Object names are global within the window file: any 
  2422. routine in the file can refer to any object in the file using its name. Object 
  2423. names are used to get and set the value of an object's properties at run time. 
  2424. The name is also used to associate the object with its event routines. For 
  2425. example, the routine for the Click event of a push button with name PB_1 would 
  2426. be named PB_1_Click. 
  2427.  
  2428. The code in a window file is divided into event routines and general routines. 
  2429.  
  2430. The event routines are defined by entering code in an edit window opened on an 
  2431. event property of an object. The code in an event routine is standard REXX 
  2432. code, except that special VX-REXX functions are used to access the objects. 
  2433. These special routines are explained in  Interacting with objects from a 
  2434. program. 
  2435.  
  2436. In addition to event routines, a window file includes general routines that are 
  2437. called by the event routines or on start up. Putting code in general routines 
  2438. allows you to share code between objects and to keep general purpose routines 
  2439. separate from any object-specific code. For example, to handle two different 
  2440. events in the same way, create a general routine that is called from both event 
  2441. routines. This is better than calling one event routine from another as it 
  2442. reduces the chance that renaming or deleting an object introduces an error into 
  2443. the program. 
  2444.  
  2445.  
  2446. ΓòÉΓòÉΓòÉ 8.1.3. Predefined routines ΓòÉΓòÉΓòÉ
  2447.  
  2448. A new window file consists of an empty window and a set of predefined routines: 
  2449. Main, Halt, Init, Window1_Close, Quit, and Fini (each routine is in a section 
  2450. of the same name). The routine called Main is the first routine that is run 
  2451. when the window file is run. It loads the window and processes its events. You 
  2452. should not modify the Main routine as its definition may be changed in future 
  2453. versions of VX-REXX. Instead,  modify the other predefined routines. They have 
  2454. been provided to allow you to connect to the start up and shutdown of a window. 
  2455.  
  2456. When a window file is executed, the Main routine gathers up any arguments 
  2457. passed to the window file and places them in the global compound variable 
  2458. InitArgs. InitArgs.0 is set to the number of arguments, and each of InitArgs.1 
  2459. to InitArgs.n is set to each of the n arguments in turn. If the window file is 
  2460. the main or only file in a project, the arguments passed to it are the 
  2461. arguments entered on the command line that started the project. (The command 
  2462. line itself is also available from the CommandLine property of the Application 
  2463. object). If the window file is called from another file, the first argument is 
  2464. assumed to be a window name. In this case, the window name is used as the 
  2465. parent window and the remaining arguments are placed in InitArgs. This is 
  2466. explained more fully in  Multiple file projects. 
  2467.  
  2468. The Main routine then loads the associated window and calls the Init routine. 
  2469. On entry to the Init routine, the window has been loaded but is not visible. 
  2470. The default Init routine sets the window to be visible and returns. You can add 
  2471. code to the Init routine to initialize your application. If your initialization 
  2472. is short you might like to complete it and then make the window visible. If you 
  2473. have a long initialization you might like to make the window visible right 
  2474. away, but disable it until your initialization is complete. See the online 
  2475. VXΓêÖREXX Reference for information on the Visible and Enabled window properties. 
  2476.  
  2477. After returning from the Init routine, the Main routine enters a loop which 
  2478. waits for an event and then runs the corresponding event routine. The events 
  2479. are processed one at a time. Events that occur while an event routine is 
  2480. running will be queued and processed when the current event routine is 
  2481. finished. If an event routine takes a long time to complete, the user can queue 
  2482. many events. If you want to prevent the user from creating events, you can 
  2483. disable the window until the current processing is complete. You may also want 
  2484. to start a separate thread to handle long computations to allow your event 
  2485. routine to return right away. See the StartThread method in the online VXΓêÖREXX 
  2486. Reference for information on starting a separate thread. 
  2487.  
  2488. The predefined routine Window1_Close is the event routine for the close event 
  2489. of the window. The event is triggered when the user selects Close from the 
  2490. window's system menu. This routine calls the Quit routine to shut down the 
  2491. window. 
  2492.  
  2493. The event processing loop is stopped when the window's ShutDown property 
  2494. becomes 1. The Quit routine sets the window ShutDown property to 1. You can 
  2495. call the Quit routine from any of your routines to close the window. You can 
  2496. also change the Quit routine so that it allows the user to confirm or cancel 
  2497. the close. If the user decides not to close the window, just return from the 
  2498. Quit routine without setting the ShutDown property, and your project will 
  2499. continue to run. 
  2500.  
  2501. Note that if you determine in the Init routine that the project should quit 
  2502. right away you can call the Quit routine before returning. This will prevent 
  2503. the event loop from running at all. 
  2504.  
  2505. After exiting from the event processing loop, the Fini routine is called. At 
  2506. this point it is too late to prevent the window from being closed, but the 
  2507. window still exists. This allows you to get the final value of radio buttons, 
  2508. entry fields, etc. so you can set a return value for the window file. The value 
  2509. returned by the Fini routine is the value returned by the window file. For this 
  2510. reason, the Fini routine must return a value. The default return value is 0. 
  2511. See  Multiple file projects for more information on the return value of a 
  2512. window file. 
  2513.  
  2514.  
  2515. ΓòÉΓòÉΓòÉ 8.1.4. Multiple files and windows ΓòÉΓòÉΓòÉ
  2516.  
  2517. More complex VX-REXX projects consist of several files. These files can be any 
  2518. combination of code and window files. One file invokes another by calling it 
  2519. with the REXX call instruction or by invoking it as a REXX function. Each file 
  2520. in a project executes as a separate REXX program file. This means that all of 
  2521. the labels and variables in one file are hidden when executing another file. In 
  2522. addition all object names in one file are hidden when executing another. This 
  2523. allows you to use the same names in different files without fear of conflict. 
  2524. Data is passed between files using REXX arguments and return values, or by 
  2525. using the PutVar and GetVar methods of the Application object. Using multiple 
  2526. files is explained in  Multiple file projects. 
  2527.  
  2528. Each window file has its own event queue and event processing loop. This means 
  2529. that, if one file calls another, it is not possible to process the events from 
  2530. two windows in two different files at once. This is because only one of the 
  2531. event processing loops will be running. This is not a problem if the called 
  2532. window is a modal dialog that the user must finish before returning to the 
  2533. calling window. Sometimes, however, it is necessary to provide access to 
  2534. multiple windows at the same time. Although this can be dealt with by using 
  2535. multiple threads, it is usually more straightforward to handle this by defining 
  2536. multiple modeless windows within a single window file. One event loop 
  2537. dispatches events for all the windows so none are disabled. Also, since all of 
  2538. the event routines have access to all of the object names and variables, it is 
  2539. quite simple to share information between windows. See  Secondary windows for 
  2540. more information. 
  2541.  
  2542.  
  2543. ΓòÉΓòÉΓòÉ 8.2. Interacting with objects from a program ΓòÉΓòÉΓòÉ
  2544.  
  2545. A program interacts with an object by its events, properties, and methods. 
  2546. Events are messages the object can send to the program. The program can receive 
  2547. these messages and respond to them by executing an appropriate routine. The 
  2548. properties of an object are its data and state information. A program can get 
  2549. and set an object's properties, so it can read and change the object's state. 
  2550. The methods of an object are its functions. A program invokes a method of an 
  2551. object to cause the object to perform a function. 
  2552.  
  2553. The following sections explain how to refer to an object, and how VX-REXX 
  2554. programs interact with objects by responding to events, getting and setting 
  2555. properties, and invoking methods. 
  2556.  
  2557.  
  2558. ΓòÉΓòÉΓòÉ 8.2.1. Referring to an object ΓòÉΓòÉΓòÉ
  2559.  
  2560. Every object has a Name property which is assigned a unique value when it is 
  2561. created. The assigned name is the name or initials of the object type followed 
  2562. by a number generated by VX-REXX. For example, the assigned name of a push 
  2563. button may be PB_1. You can change the default name using the General page of 
  2564. the property notebook. 
  2565.  
  2566. Object names are global within a file. Any routine in any section can refer to 
  2567. an object in the same file by its name. Object names are hidden between files. 
  2568. Objects in different files can have the same name without conflict. While it is 
  2569. not possible to refer to an object in another file by its name, it is possible 
  2570. to refer to objects in other files by using internal names, as explained below. 
  2571.  
  2572. Duplicate objects are objects in one file with the same name that share the 
  2573. same event routines. They can only be created by using the Duplicate item on an 
  2574. object's pop-up menu. It is not possible to refer to an individual duplicate 
  2575. object by its name, as there is more than one object with that name. It is 
  2576. however possible to refer to duplicate objects by using internal names. 
  2577.  
  2578. In addition to the Name property, every object has a unique internal name 
  2579. assigned when it is created. An object's internal name is always unique, and is 
  2580. unique over the entire VX-REXX project. Whenever an object name is required as 
  2581. a parameter to a VX-REXX function you can use either the value of the Name 
  2582. property (the external name), if it's unique, or the object's internal name, 
  2583. which is always unique. 
  2584.  
  2585. The Self property of an object contains its internal name. It is not available 
  2586. at design time because the internal name of an object is only assigned when the 
  2587. object is created at run time. The Self property can be used to obtain the 
  2588. internal name of an object to pass to another file. 
  2589.  
  2590. The VRInfo function can be used to return the internal name of the object that 
  2591. triggered an event. The VRInfo function can only be used within event routines 
  2592. as it returns information about the current event. It can be used within event 
  2593. routines to get the internal name of duplicate objects. A typical function call 
  2594. is: 
  2595.  
  2596. object = VRInfo( "Object" )
  2597.  
  2598. The VRWindow function returns the internal name of the current primary window 
  2599. (the window automatically loaded when the window file was invoked). It is most 
  2600. often used with the dialog functions which require the name of the window to be 
  2601. disabled during the dialog. The following shows VRWindow used with the 
  2602. VRMessage function. 
  2603.  
  2604. call VRMessage VRWindow(), "Time to go home!", "Time reminder", "I"
  2605.  
  2606.  Using dialog and system functions documents the VRMessage function, among 
  2607. others. 
  2608.  
  2609.  
  2610. ΓòÉΓòÉΓòÉ 8.2.2. Renaming an object ΓòÉΓòÉΓòÉ
  2611.  
  2612. If you are going to refer to an object in a program, you should give that 
  2613. object a more meaningful name -- for example PB_Start rather than PB_1. If you 
  2614. change the names, it will be easier for you to remember them and easier to read 
  2615. and understand the code. 
  2616.  
  2617. When an object is renamed, references to that object are updated in the REXX 
  2618. code. The object must have a name of the form prefix_suffix where prefix is an 
  2619. alphanumeric string. The following strings are changed in the REXX code: 
  2620.  
  2621. o Literal strings 
  2622. o Labels 
  2623. o call instructions 
  2624.  
  2625. For example, if the object PB_1 is renamed to PB_Start, the following code 
  2626.  
  2627. PB_1_Click:
  2628.     if( VRSet( "PB_1", "Caption" \= "" ) ) then signal PB_1_Click_End
  2629.     call VRSet "PB_1", "Caption", "Clicked"
  2630. PB_1_Click_End:
  2631. return
  2632.  
  2633. is updated to 
  2634.  
  2635. PB_Start_Click:
  2636.     if( VRSet( "PB_Start", "Caption" \= "" ) ) then signal PB_Start_Click_End
  2637.     call VRSet "PB_Start", "Caption", "Clicked"
  2638. PB_Start_Click_End:
  2639. return
  2640.  
  2641.  
  2642. ΓòÉΓòÉΓòÉ 8.2.3. Implicit and relative naming ΓòÉΓòÉΓòÉ
  2643.  
  2644. Objects can also be referred to using relative naming, where the name that 
  2645. identifies the object is a combination of names belonging to the object and one 
  2646. or more of its parent objects. The names are separated using periods. 
  2647.  
  2648. For example, consider a window Window1 with a group box GB_1 and a push button 
  2649. PB_1 inside that group box. The push button can be referred to as: 
  2650.  
  2651. PB_1
  2652. GB_1.PB_1
  2653. Window1.PB_1
  2654. Window1.GB_1.PB_1
  2655.  
  2656. If a second group box GB_2 containing another push button PB_1 is added to the 
  2657. window, then PB_1 by itself is ambiguous, but the following are not: 
  2658.  
  2659. GB_1.PB_1
  2660. GB_2.PB_1
  2661. Window1.GB_1.PB_1
  2662. Window1.GB_2.PB_1
  2663.  
  2664. Two objects with the same name may exist within a single file, which can cause 
  2665. ambiguity. This is a common situation when the same secondary window is loaded 
  2666. twice or more by a project. 
  2667.  
  2668. Each component of a relative name can be a simple name or an internal name. 
  2669.  
  2670. VX-REXX also implements a form of relative naming called implicit naming which 
  2671. is useful for files that load two or more copies of the same secondary window. 
  2672. Implicit naming is on by default, but it can be turned off using the VROptions 
  2673. function. The internal name of the current event window (the window returned by 
  2674. passing the Window parameter to VRInfo) is implicitly prefixed to the name of 
  2675. an object to form a relative name. In other words, when implicit naming is on 
  2676. the following code: 
  2677.  
  2678. call VRSet "PB_1", "Enabled", 0
  2679.  
  2680. is equivalent to the following code when implicit naming is off: 
  2681.  
  2682. win = VRInfo( "Window" )
  2683. call VRSet win || "." || "PB_1", "Enabled", 0
  2684.  
  2685. If implicit naming is on and the object is not found, the object is searched 
  2686. for again without the implicit prefix. 
  2687.  
  2688.  
  2689. ΓòÉΓòÉΓòÉ 8.2.4. Responding to events ΓòÉΓòÉΓòÉ
  2690.  
  2691. Events are usually caused by a user interacting with an object. For example a 
  2692. user can click on a button. Many objects handle events automatically. For 
  2693. instance, clicking a check box automatically toggles the state of that object 
  2694. for you. This includes checking or unchecking the box on the screen as well as 
  2695. updating the Set property. No programming is needed for this to happen. 
  2696. However, after updating the internal state, the check box will queue a Click 
  2697. event so that your program can respond to it. 
  2698.  
  2699. There is usually more than one way to generate a particular event. For example, 
  2700. the Click event for a push button can be generated by clicking on the push 
  2701. button or by pressing the space bar when the push button has the focus. The 
  2702. object does the work of the low-level interaction with the user and only passes 
  2703. on "interesting" events to the program. 
  2704.  
  2705. The correct response to an event depends on the object, the event, and on the 
  2706. purpose of the program. The next chapter  Using objects shows how to deal with 
  2707. some specific objects and events. In addition to standard REXX programming, the 
  2708. event routines set and get object properties and invoke object methods, as 
  2709. described in the next section. 
  2710.  
  2711.  
  2712. ΓòÉΓòÉΓòÉ 8.2.5. Getting and setting properties ΓòÉΓòÉΓòÉ
  2713.  
  2714. Two functions are provided to get and set the properties of an object: VRGet 
  2715. and VRSet. Each property is identified by a name. Most properties appear in the 
  2716. object's property notebook, however some properties (such as Self) are not 
  2717. available at design time. It is always possible to get a property's value, but 
  2718. some properties are read-only at run time and cannot be set. 
  2719.  
  2720. The valid values for each property depend on the property. Typically a value 
  2721. must be a logical value (0 or 1), a number (such as for the size or position of 
  2722. an object), one of a set of values (e.g. Red for BackColor), or any text string 
  2723. (Caption). Property names and values that are one of a set of values are always 
  2724. case insensitive. 
  2725.  
  2726. Property values are always stored and returned in canonical form. This means, 
  2727. for example, that logical values are always returned as 0 or 1, and values that 
  2728. are one of a set are always returned in mixed case, such as Red. 
  2729.  
  2730.  Summary of properties contains a complete list of property names. The online 
  2731. VXΓêÖREXX Reference contains a detailed description of each property. 
  2732.  
  2733. The function VRGet returns the current value of a property. This function 
  2734. requires two parameters: the object name and the property name. 
  2735.  
  2736. objectCaption = VRGet( "PB_PushMe", "Caption")
  2737.  
  2738. In this example, the value of the Caption property for the object named 
  2739. PB_PushMe is assigned to the REXX variable objectCaption. 
  2740.  
  2741. The VRSet function changes the current value of a property to the specified 
  2742. value. This function requires three parameters: the object name, the property 
  2743. name, and the new property value. More than one property can be changed at once 
  2744. by including multiple property names and their values as pairs of arguments. 
  2745. Changing more than one value at once can improve the performance of the change. 
  2746. For example, it is better to change the Height and Width properties together so 
  2747. the object will only be redrawn once. An example of VRSet follows. 
  2748.  
  2749. call VRSet "PB_PushMe", "Caption", "Push Me", "BackColor", "Red"
  2750.  
  2751. In this example, the value of the caption property for the object named 
  2752. PB_PushMe is changed to Push Me, and the BackColor to Red. 
  2753.  
  2754. You can check the results of VRSet as follows: 
  2755.  
  2756. rc = VRSet( "PB_PushMe", "Caption", "Push Me", "BackColor", "Red" )
  2757.  
  2758. The value returned in the variable rc indicates whether the property was set 
  2759. successfully (1 is returned) or not (0 is returned). 
  2760.  
  2761. Some of the most common uses of run time property editing are: 
  2762.  
  2763. o To enable and disable push buttons. The following disables the push button 
  2764.   named PB_PushMe. 
  2765.  
  2766.     call VRSet "PB_PushMe", "Enabled", 0
  2767.  
  2768. o To set the value of an entry field. The following sets the value of the entry 
  2769.   field named EF_Text to the value <none>. 
  2770.  
  2771.     call VRSet "EF_Text", "Value", "<none>"
  2772.  
  2773. o To toggle a radio button or check box. The following changes the Set property 
  2774.   of the radio button named RB_1 to show that it is selected. 
  2775.  
  2776.     call VRSet "RB_1", "Set", 1
  2777.  
  2778.  
  2779. ΓòÉΓòÉΓòÉ 8.2.6. Using object methods ΓòÉΓòÉΓòÉ
  2780.  
  2781. Each object type has special built-in operations which act upon the object. 
  2782. These operations are called methods. For a complete list of methods, refer to 
  2783. the chapter  Summary of methods. 
  2784.  
  2785. A method is invoked using the VX-REXX function VRMethod. This function requires 
  2786. at least two parameters, the object reference, the method name, and then any 
  2787. other parameters required by the particular method. In the individual method 
  2788. descriptions in the online VXΓêÖREXX Reference, the other parameters are 
  2789. described as the method's arguments. 
  2790.  
  2791. In the following example, the method named GetSelectedStringList is invoked for 
  2792. the list box object named LB_Color and passed the argument color. 
  2793.  
  2794. call VRMethod "LB_Color", "GetSelectedStringList", "color."
  2795.  
  2796. The method GetSelectedStringList returns the selected strings from the list box 
  2797. LB_Color in the compound variable color. 
  2798.  
  2799.  
  2800. ΓòÉΓòÉΓòÉ 9. Using objects ΓòÉΓòÉΓòÉ
  2801.  
  2802. This chapter explains how to use VX-REXX objects in your project. For the more 
  2803. common objects, it describes the object and gives programming instructions for 
  2804. certain object-specific tasks. The first part of the chapter shows you some 
  2805. operations that you can perform on most objects. They are: disabling and hiding 
  2806. objects, setting the input focus, and setting the tab order. 
  2807.  
  2808. For complete information on all the VX-REXX objects refer to the online VX-REXX 
  2809. Reference. 
  2810.  
  2811.  
  2812. ΓòÉΓòÉΓòÉ 9.1. Common operations on objects ΓòÉΓòÉΓòÉ
  2813.  
  2814.  
  2815. ΓòÉΓòÉΓòÉ 9.1.1. Disabling objects ΓòÉΓòÉΓòÉ
  2816.  
  2817. There are times when you want an object to be visible, but you do not want to 
  2818. allow the user do anything with that object. For example, if you have a window 
  2819. with an entry field and a push button you may not want  the user to push the 
  2820. button before entering a value in the entry field. You want to disable the push 
  2821. button while the entry field is empty. 
  2822.  
  2823. You can disable an object by setting its Enabled property to 0. You can enable 
  2824. an object by setting its Enabled property back to 1. By default, all objects 
  2825. are created with their Enabled property set to 1. 
  2826.  
  2827. You should never disable the main window for your project! If you do, you will 
  2828. not be able to close the window or quit the project except perhaps by using the 
  2829. OS/2 Window List. 
  2830.  
  2831.  
  2832. ΓòÉΓòÉΓòÉ 9.1.2. Hiding objects ΓòÉΓòÉΓòÉ
  2833.  
  2834. There may be times when you want to hide an object. You can control the 
  2835. visibility of any object using its Visible property. To hide an object, set its 
  2836. Visible property to 0. To show it again, set the property to 1. By default, all 
  2837. objects are visible. 
  2838.  
  2839.  
  2840. ΓòÉΓòÉΓòÉ 9.1.3. Getting and setting the focus ΓòÉΓòÉΓòÉ
  2841.  
  2842. The object which is currently the target of any input is said to have the 
  2843. focus. When an object gains or loses the focus, an  event occurs for that 
  2844. object. These events are GotFocus and LostFocus, respectively. Usually these 
  2845. events occur in pairs; the object that loses the focus receives a LostFocus 
  2846. event, then the object which is receiving the focus gets a GotFocus event. 
  2847.  
  2848. You should not use the GotFocus and LostFocus events to perform user input 
  2849. validation. The reason is that these events can be caused by actions that have 
  2850. nothing to do with user input. For example, if the user activates a different 
  2851. application, then a LostFocus event is generated, regardless of whether the 
  2852. user was finished entering data or not. Use the Verify event instead, as 
  2853. described below. 
  2854.  
  2855. You can use the SetFocus method to move the focus to a given object. Suppose 
  2856. you have written a dialog that validates the input received from a user. If the 
  2857. data is invalid, the program should alert the user, then set the focus to the 
  2858. object which contains the errant data. 
  2859.  
  2860. To determine which object (if any) in your project currently has the input 
  2861. focus, use the following code: 
  2862.  
  2863. GetFocusObject: procedure
  2864.     focus = VRMethod( "Screen", "GetFocusWindow" )
  2865.     if( focus \= "" )then do
  2866.         focus = VRGet( focus, "Object" )
  2867.     end
  2868. return focus
  2869.  
  2870. The routine returns the internal name of the object with focus, or a null 
  2871. string if no object in the project has the input focus. 
  2872.  
  2873.  
  2874. ΓòÉΓòÉΓòÉ 9.1.4. Input validation ΓòÉΓòÉΓòÉ
  2875.  
  2876. A Verify event exists for the EntryField, DropDownComboBox, ComboBox, 
  2877. MultiLineEntryField and SpinButton objects. This event occurs when the input 
  2878. focus moves to another object on the same window, allowing you to validate the 
  2879. contents of the Value property and if necessary reset the focus. See the 
  2880. description for Verify for more details. 
  2881.  
  2882.  
  2883. ΓòÉΓòÉΓòÉ 9.1.5. Setting the tab order ΓòÉΓòÉΓòÉ
  2884.  
  2885. In a window, the user can press the Tab or Backtab keys to move the focus from 
  2886. object to object. The order in which each object gets the focus is called the 
  2887. tab order. 
  2888.  
  2889. You can set the tab order by setting the TabIndex property for each object in a 
  2890. given window. Initially, the object that has TabIndex set to 1 has the focus. 
  2891. When the user presses Tab, the focus moves to the object with TabIndex equal to 
  2892. 2, and so on. 
  2893.  
  2894. If you do not want to include an object in the tab order, set its TabStop 
  2895. property to 0. Most objects have TabStop set to 1 by default. Radio buttons and 
  2896. group boxes are created with TabStop cleared. A radio button is only included 
  2897. in the tab order if it is selected so only one of the buttons in a group is 
  2898. included in the tab order. Group boxes are never included in the tab order. 
  2899.  
  2900. The TabStop and TabIndex properties are set automatically when you add an 
  2901. object to a group or window. 
  2902.  
  2903. To aid in setting the tab order of a window, a tab editor is available in the 
  2904. design environment. Click on the window with mouse button 2 and select the Tab 
  2905. Editor from the Open item on the pop-up menu. 
  2906.  
  2907.  
  2908. ΓòÉΓòÉΓòÉ 9.2. Windows ΓòÉΓòÉΓòÉ
  2909.  
  2910. Figure 41  A window
  2911.  
  2912. Users communicate with your project through windows. Each window presents a 
  2913. view of the project. More than one window can be used at the same time to show 
  2914. different views. 
  2915.  
  2916. A window is a rectangular area on the screen. It consists of a frame and any 
  2917. number of other objects which appear in the window. The frame may be a simple 
  2918. border, or it may also include a title bar, a system menu, minimize, maximize 
  2919. and hide buttons. 
  2920.  
  2921.  
  2922. ΓòÉΓòÉΓòÉ 9.2.1. Setting the border type ΓòÉΓòÉΓòÉ
  2923.  
  2924. A window can have one of three borders: dialog, sizeable, or thin. Use a dialog 
  2925. border for modal or system modal windows. Use a sizeable border if you want to 
  2926. let the user resize the window. Use a thin border for all other cases. 
  2927.  
  2928. To set the border type, set the BorderType property. You must set this property 
  2929. at design time. 
  2930.  
  2931.  
  2932. ΓòÉΓòÉΓòÉ 9.2.2. Setting the caption ΓòÉΓòÉΓòÉ
  2933.  
  2934. You can change a window's caption by setting its Caption property. The caption 
  2935. appears in the title bar. If the caption is longer than the width of the 
  2936. window, only the leftmost portion will be visible. 
  2937.  
  2938.  
  2939. ΓòÉΓòÉΓòÉ 9.2.3. Adding minimize, hide, and maximize buttons ΓòÉΓòÉΓòÉ
  2940.  
  2941. By default a window is created without maximize, minimize, or hide buttons. To 
  2942. add a minimize button, set the MinimizeButton property of the window. To add a 
  2943. maximize button, set the MaximizeButton property. To add a hide button, set 
  2944. HideButton to 1. 
  2945.  
  2946. A window can have either a hide button or a minimize button, but not both. As a 
  2947. result, if MinimizeButton is 1, you cannot set HideButton to 1 until you set 
  2948. MinimizeButton to 0. 
  2949.  
  2950. If you include a maximize, minimize, or hide button, the corresponding items in 
  2951. the system menu are enabled. 
  2952.  
  2953. You must set the MinimizeButton, MaximizeButton, and HideButton properties at 
  2954. design time. Setting them at run time will have no effect. 
  2955.  
  2956.  
  2957. ΓòÉΓòÉΓòÉ 9.2.4. Removing the system menu ΓòÉΓòÉΓòÉ
  2958.  
  2959. By default, a window is created with a system menu. Since the system menu can 
  2960. be used to close a window, it is a good idea to always include one. If you 
  2961. remove it, you must provide some other object, such as a push button, to close 
  2962. the window. You need to call the Quit routine from the push button's Click 
  2963. event. 
  2964.  
  2965. To remove the system menu, reset the window's SystemMenu property. You must set 
  2966. or clear this property at design time. 
  2967.  
  2968.  
  2969. ΓòÉΓòÉΓòÉ 9.2.5. Removing the title bar ΓòÉΓòÉΓòÉ
  2970.  
  2971. By default, a window is created with a title bar. To remove the title bar, 
  2972. reset the window's TitleBar property. 
  2973.  
  2974.  
  2975. ΓòÉΓòÉΓòÉ 9.2.6. Resizing objects in windows ΓòÉΓòÉΓòÉ
  2976.  
  2977. If you want the contents of a window to automatically resize themselves when 
  2978. the window is sized, you may be able to use the LayoutStyle property of the 
  2979. window. If the window contains a single object and some push buttons, set the 
  2980. LayoutStyle property to SimpleDialog. The window will then automatically resize 
  2981. the object it contains, and will place the push buttons appropriately. If the 
  2982. window has more objects on it, then the program must reposition or resize 
  2983. objects. An ideal place to do the sizing is the Resize event. 
  2984.  
  2985.  
  2986. ΓòÉΓòÉΓòÉ 9.2.7. Getting and setting the window state ΓòÉΓòÉΓòÉ
  2987.  
  2988. You can determine whether a window is minimized or maximized by calling the 
  2989. VRGet function on the WindowState property. The value of the property will be 
  2990. one of Minimized, Maximized, or Normal (in the case that the window is neither 
  2991. minimized or maximized). Likewise, you can minimize, maximize, or return a 
  2992. window to normal size by using the VRSet function in conjunction with this 
  2993. property. 
  2994.  
  2995. A Resize event is generated whenever a window is minimized, maximized or 
  2996. restored. 
  2997.  
  2998.  
  2999. ΓòÉΓòÉΓòÉ 9.2.8. Setting the OS/2 window list title ΓòÉΓòÉΓòÉ
  3000.  
  3001. By default, only the main window of an application is added to the OS/2 window 
  3002. list. The WindowListTitle property is used to add a window to the window list 
  3003. or to remove it from the window list. 
  3004.  
  3005.  
  3006. ΓòÉΓòÉΓòÉ 9.2.9. Hints ΓòÉΓòÉΓòÉ
  3007.  
  3008. Hints are single-line messages displayed in a special status area at the top or 
  3009. bottom of a window. When an object receives the keyboard focus or the pointer 
  3010. moves over the object, the hint for that object is displayed in the window's 
  3011. status area. The hint text for an object is defined by the HintText property. 
  3012.  
  3013. To add hint support, set the ShowHints property to 1 and set the StatusArea 
  3014. property to Top or Bottom. If hints are to be displayed for menu items, Bottom 
  3015. is recommended. 
  3016.  
  3017. The font used by the status area is changed using the StatusFont property. 
  3018.  
  3019.  
  3020. ΓòÉΓòÉΓòÉ 9.2.10. Displaying a background picture ΓòÉΓòÉΓòÉ
  3021.  
  3022. A background picture may be displayed in a window by setting the PicturePath 
  3023. property. See the "Bitmaps, icons and resources" chapter for more information. 
  3024.  
  3025.  
  3026. ΓòÉΓòÉΓòÉ 9.3. Push buttons ΓòÉΓòÉΓòÉ
  3027.  
  3028. A push button is used to initiate an action which is associated with that 
  3029. object. 
  3030.  
  3031. There are two ways to press a push button: 
  3032.  
  3033. o Click on the button using mouse button 1. 
  3034.  
  3035. o If the push button has the input focus, press the SpaceBar or the Enter key. 
  3036.  
  3037. When it is clicked at run time a push button object gives the illusion of being 
  3038. pressed. 
  3039.  
  3040.  
  3041. ΓòÉΓòÉΓòÉ 9.3.1. Setting the caption ΓòÉΓòÉΓòÉ
  3042.  
  3043. To change the caption for a push button, set the Caption property. If the 
  3044. AutoSize property is 1, the push button will automatically resize itself so 
  3045. that the entire caption is visible. If AutoSize is 0, and the caption is longer 
  3046. than the width of the button, the caption will be clipped. 
  3047.  
  3048.  
  3049. ΓòÉΓòÉΓòÉ 9.3.2. Creating a default button ΓòÉΓòÉΓòÉ
  3050.  
  3051. In a window, the default button is automatically clicked when the focus is on 
  3052. another object (other than another push button) and you press Enter. To specify 
  3053. a default button, set its Default property to 1 at design time. 
  3054.  
  3055.  
  3056. ΓòÉΓòÉΓòÉ 9.3.3. Creating a cancel button ΓòÉΓòÉΓòÉ
  3057.  
  3058. In a window, the cancel button is automatically clicked when you press Esc. To 
  3059. specify a cancel button, set its Cancel property to 1 at design time. 
  3060.  
  3061.  
  3062. ΓòÉΓòÉΓòÉ 9.3.4. Using the Click event ΓòÉΓòÉΓòÉ
  3063.  
  3064. Typically, you will add code to a push button's Click event in order to perform 
  3065. an action. The following example shows the click routine for a button named 
  3066. PB_PushMe which toggles the background color of the button between red and 
  3067. green. 
  3068.  
  3069. PB_PushMe_Click:
  3070.     color = VRGet( "PB_PushMe", "BackColor" )
  3071.     if color = "Red" then do
  3072.         call VRSet "PB_PushMe", "BackColor", "Green"
  3073.     end
  3074.     else do
  3075.         call VRSet "PB_PushMe", "BackColor", "Red"
  3076.     end
  3077. return
  3078.  
  3079.  
  3080. ΓòÉΓòÉΓòÉ 9.4. Radio buttons ΓòÉΓòÉΓòÉ
  3081.  
  3082. Figure 42  A radio button
  3083.  
  3084. Radio buttons are used to present multiple related options from which only one 
  3085. can be specified. Clicking one radio button selects that object and clears the 
  3086. previously selected radio button. A radio button is set when a solid circle is 
  3087. displayed in the circle to the left of the button's caption. 
  3088.  
  3089. There are two ways to press a radio button: 
  3090.  
  3091. o Click on the radio button using mouse button 1. 
  3092.  
  3093. o If the radio button has the focus, press the SpaceBar. 
  3094.  
  3095. RadioButton objects can be grouped so that each group operates independently of 
  3096. the other. That is, clicking a radio button within one group only affects other 
  3097. radio buttons within the same group. 
  3098.  
  3099.  
  3100. ΓòÉΓòÉΓòÉ 9.4.1. Setting the caption ΓòÉΓòÉΓòÉ
  3101.  
  3102. To change the caption for a radio button, set the Caption property. The button 
  3103. will automatically enlarge if the caption is larger than the button, and the 
  3104. AutoSize property is 1. If the caption is larger than the button, but AutoSize 
  3105. is 0, then the button will not resize and the caption will be clipped. 
  3106.  
  3107.  
  3108. ΓòÉΓòÉΓòÉ 9.4.2. Setting and getting the button state ΓòÉΓòÉΓòÉ
  3109.  
  3110. To set a radio button, set its Set property to 1. All other radio buttons in 
  3111. the same group box or window will be reset automatically. You can set a radio 
  3112. button both at design time, and at run time. 
  3113.  
  3114. To find out if a radio button is set, use VRGet to retrieve the Set property. 
  3115. If it is 1, then the button is set. 
  3116.  
  3117.  
  3118. ΓòÉΓòÉΓòÉ 9.4.3. Using the Click event ΓòÉΓòÉΓòÉ
  3119.  
  3120. While it is not necessary to process the Click event for radio buttons, you may 
  3121. want to do so if some object on the window should be updated immediately as a 
  3122. result of the selection. 
  3123.  
  3124. For example, suppose a window contains two radio buttons (named RB_Red and 
  3125. RB_Green) and a line of descriptive text (named DT_Sample). The color of the 
  3126. descriptive text is to be red if the RB_Red radio button is set, and green if 
  3127. RB_Green is set. To do this, include a click event routine for each radio 
  3128. button. Each routine updates the color of the descriptive text. 
  3129.  
  3130. The click event routines for the push buttons would be: 
  3131.  
  3132. RB_Red_Click:
  3133.     call VRSet "DT_Sample", "ForeColor", "Red"
  3134. return
  3135.  
  3136. RB_Green_Click:
  3137.     call VRSet "DT_Sample", "ForeColor", "Green"
  3138. return
  3139.  
  3140.  
  3141. ΓòÉΓòÉΓòÉ 9.5. Check boxes ΓòÉΓòÉΓòÉ
  3142.  
  3143. Figure 43  A check box
  3144.  
  3145. Check boxes are used to present multiple options from which one or more options 
  3146. can be selected independently of the other options available. Clicking one 
  3147. check box has no automatic effect on any other check box. Each click on a check 
  3148. box toggles its state between set and clear. A check box is set when a check 
  3149. mark is displayed in the box to the left of the object's caption. 
  3150.  
  3151. There are two ways to press a check box: 
  3152.  
  3153. o Click on the check box using mouse button 1. 
  3154.  
  3155. o If the check box has the focus, press the SpaceBar. 
  3156.  
  3157.  
  3158. ΓòÉΓòÉΓòÉ 9.5.1. Setting the caption ΓòÉΓòÉΓòÉ
  3159.  
  3160. To change the caption for a check box, set the Caption property. The button 
  3161. will automatically enlarge if the caption is larger than the button, and the 
  3162. AutoSize property is 1. If the caption is larger than the button, but AutoSize 
  3163. is 0, then the button will not resize and the caption will be clipped. 
  3164.  
  3165.  
  3166. ΓòÉΓòÉΓòÉ 9.5.2. Setting and clearing a check box ΓòÉΓòÉΓòÉ
  3167.  
  3168. To set a check box, set its Set property to 1. You can set a check box both at 
  3169. design time and at run time. To find out if a check box is set, use VRGet to 
  3170. retrieve the Set property. If it is 1, then the check box is set. 
  3171.  
  3172. To clear a check box, set its Set property to 0. 
  3173.  
  3174.  
  3175. ΓòÉΓòÉΓòÉ 9.5.3. Using the Click event ΓòÉΓòÉΓòÉ
  3176.  
  3177. While it is not necessary to process the Click event for check boxes, you may 
  3178. want to do so if some object on the window should be updated immediately as a 
  3179. result of the selection. 
  3180.  
  3181.  
  3182. ΓòÉΓòÉΓòÉ 9.6. Descriptive text ΓòÉΓòÉΓòÉ
  3183.  
  3184. Figure 44  Descriptive text
  3185.  
  3186. DescriptiveText objects are typically used to display titles, prompts, and 
  3187. other static text in a window. This object can show one or more lines of 
  3188. information. Unlike the other text objects, you cannot select or copy 
  3189. descriptive text. Since there is no user interaction with DescriptiveText 
  3190. objects, there are no events associated with them. 
  3191.  
  3192.  
  3193. ΓòÉΓòÉΓòÉ 9.6.1. Setting the text ΓòÉΓòÉΓòÉ
  3194.  
  3195. To change the text for a DescriptiveText object, set the Caption property. If 
  3196. the text is wider than the object, one of two things will happen, depending on 
  3197. the value of the AutoSize property: 
  3198.  
  3199. o If AutoSize is 0, the text will word wrap at the right edge of the object. 
  3200.   You may have to increase the object's height to make the entire caption 
  3201.   visible. 
  3202.  
  3203. o If AutoSize is 1, the object will make itself wider so that the caption will 
  3204.   all fit on one line. The height of the object will not be changed. 
  3205.  
  3206. The Caption property can be changed both at design time and at run time. For 
  3207. example, changing the text at run time allows you to create a window that 
  3208. monitors and displays changing information. 
  3209.  
  3210.  
  3211. ΓòÉΓòÉΓòÉ 9.7. Entry field ΓòÉΓòÉΓòÉ
  3212.  
  3213. Figure 45  An entry field
  3214.  
  3215. Use an entry field when you want the user to type in a single line of text. If 
  3216. you want multiple lines of text, use a multiline entry field. 
  3217.  
  3218. At design time, you can set an entry field's Value property to define text that 
  3219. will appear in the entry field when the application is run. Usually you enter 
  3220. data in an entry field at run time. You can enter and edit text using the 
  3221. normal cut, copy, and paste techniques. You can retrieve and change the value 
  3222. entered. 
  3223.  
  3224. If you want to allow the user to enter more text than the width of the entry 
  3225. field, you should set the AutoScroll property at design time. When you enter 
  3226. text at run time, the field will scroll automatically allowing you to enter or 
  3227. read all of the text. 
  3228.  
  3229. You can mask entered text to support input of private data such as passwords. 
  3230. When you type text in a masked entry field an asterisk appears for each 
  3231. character typed. 
  3232.  
  3233. You can define an entry field to be read-only. In this case, you can view but 
  3234. not modify the information. The entry field will be similar to descriptive text 
  3235. except that text selections can be copied. 
  3236.  
  3237.  
  3238. ΓòÉΓòÉΓòÉ 9.7.1. Setting and getting the value ΓòÉΓòÉΓòÉ
  3239.  
  3240. To change the value of an entry field, set the Value property. An entry field 
  3241. never changes size to accommodate its value. Use VRGet to retrieve the contents 
  3242. of its Value property. 
  3243.  
  3244. The length of the value is limited by the TextLimit property. If you want the 
  3245. entry field to contain more text, then set the TextLimit to a larger number 
  3246. (the default is 255). A text limit of -1 means "unlimited". 
  3247.  
  3248.  
  3249. ΓòÉΓòÉΓòÉ 9.7.2. Masking the value ΓòÉΓòÉΓòÉ
  3250.  
  3251. There may be times when you want the user to enter some text without it being 
  3252. displayed on the screen. If the user types a password, for example, you may 
  3253. want to hide it. To do this, set the Masked property of the entry field to 1. A 
  3254. mask character appears for each character that you type. You can still set and 
  3255. get the value. 
  3256.  
  3257. You must set the Masked property at design time. Setting it at run time has no 
  3258. effect. 
  3259.  
  3260.  
  3261. ΓòÉΓòÉΓòÉ 9.7.3. Write-protecting an entry field ΓòÉΓòÉΓòÉ
  3262.  
  3263. To write-protect an entry field, set its ReadOnly property to 1. When 
  3264. write-protected, you cannot change the entry field value, although it is still 
  3265. possible to copy its value and paste it elsewhere. 
  3266.  
  3267.  
  3268. ΓòÉΓòÉΓòÉ 9.7.4. Using cut, copy, and paste and delete ΓòÉΓòÉΓòÉ
  3269.  
  3270. Entry fields support the usual OS/2 key sequences to cut, copy, paste, and 
  3271. delete text. The keys are listed in the following table. 
  3272.  
  3273. Cut                 Shift+Delete 
  3274.  
  3275. Copy                Ctrl+Insert 
  3276.  
  3277. Paste               Shift+Insert 
  3278.  
  3279. Delete              Delete 
  3280.  
  3281. If the entry field has ReadOnly set to 1, only the copy operation is allowed. 
  3282.  
  3283.  
  3284. ΓòÉΓòÉΓòÉ 9.7.5. Using default and cancel push buttons ΓòÉΓòÉΓòÉ
  3285.  
  3286. If an entry field is on the same window as a default push button, the button's 
  3287. Click event is called whenever the Enter key is pressed while the entry field 
  3288. has the focus. After, the focus will be left on the push button. 
  3289.  
  3290. Similarly, if there is a cancel button on the window, its Click event will be 
  3291. called when the Esc key is pressed while the entry field has focus. 
  3292.  
  3293.  
  3294. ΓòÉΓòÉΓòÉ 9.8. Multi line entry field ΓòÉΓòÉΓòÉ
  3295.  
  3296. Figure 46  A multiline entry field
  3297.  
  3298. Use a MultiLineEntryField (MLE) when you want the user to enter several lines 
  3299. of text. If you want to enter single lines, you should use an entry field. At 
  3300. run time, you can enter and edit text using the normal cut, copy, and paste 
  3301. techniques. 
  3302.  
  3303. MLEs can be write-protected in which case you can view but not modify the 
  3304. information. However, you can copy text selections. 
  3305.  
  3306. MultiLineEntryFields show multiple lines of text. You can scroll the text 
  3307. horizontally and vertically if it cannot be viewed entirely within the object. 
  3308. MLEs also support an option to word wrap if horizontal scrolling is not 
  3309. enabled. 
  3310.  
  3311.  
  3312. ΓòÉΓòÉΓòÉ 9.8.1. Adding text to an MLE ΓòÉΓòÉΓòÉ
  3313.  
  3314. To change the value of an MLE, set its Value property. Use VRGet to retrieve 
  3315. the contents of its Value property. 
  3316.  
  3317. If you want to add text as several lines rather than a single line, separate 
  3318. the lines by a carriage return-line feed pair. The following code adds three 
  3319. lines with line breaks to an MLE: 
  3320.  
  3321. CR_LF = "0d0a"x
  3322. value = "This little piggy went to market" || CR_LF || ,
  3323.         "This little piggy stayed home" || CR_LF || ,
  3324.         "This little piggy programmed all through the night"
  3325. call VRSet "MLE_1", "Value", value
  3326.  
  3327. Note:  A comma at the end of a line is the REXX line continuation character. 
  3328.  
  3329. The length of the value is limited by the TextLimit property. When you create 
  3330. an MLE, the text limit is set to -1 which means unlimited. If you want the MLE 
  3331. to limit the amount of text, set the TextLimit to the appropriate  number. 
  3332.  
  3333.  
  3334. ΓòÉΓòÉΓòÉ 9.8.2. Using scroll bars and word wrap ΓòÉΓòÉΓòÉ
  3335.  
  3336. If you add a line of text that is longer than the MLE, it will be word wrapped 
  3337. by default. If you want to preserve the line breaks in the text, you can turn 
  3338. word wrap off by setting the WordWrap property to 0. By default, word wrap is 
  3339. enabled. 
  3340.  
  3341. While you can always scroll through the MLE text using the cursor keys, you can 
  3342. also use scroll bars to make the task easier. When you create an MLE, the 
  3343. vertical scroll bar property (VertScroll) is set. To add a horizontal scroll 
  3344. bar, set the HorizScroll property of the MLE. Note that if word wrap is 
  3345. enabled, you do not need a horizontal scroll bar. The WordWrap property is set 
  3346. when you create an MLE. 
  3347.  
  3348. You must set the HorizScroll and VertScroll properties at design time. Setting 
  3349. them at run time has no effect. 
  3350.  
  3351.  
  3352. ΓòÉΓòÉΓòÉ 9.8.3. Write-protecting an MLE ΓòÉΓòÉΓòÉ
  3353.  
  3354. To write-protect an MLE, set its ReadOnly property to 1. When it is 
  3355. write-protected, you cannot change the MLE contents at run time. You can, 
  3356. however,  copy the text value and paste it elsewhere. 
  3357.  
  3358.  
  3359. ΓòÉΓòÉΓòÉ 9.8.4. Using cut, copy, and paste and delete ΓòÉΓòÉΓòÉ
  3360.  
  3361. The MLE object supports the usual OS/2 key sequences to cut, copy, paste, and 
  3362. delete text. The keys are listed in the following table. 
  3363.  
  3364. Cut                 Shift+Delete 
  3365.  
  3366. Copy                Ctrl+Insert 
  3367.  
  3368. Paste               Shift+Insert 
  3369.  
  3370. Delete              Delete 
  3371.  
  3372. If the MLE has ReadOnly set to 1, only the copy operation is allowed. 
  3373.  
  3374.  
  3375. ΓòÉΓòÉΓòÉ 9.8.5. Using MLEs with a cancel button ΓòÉΓòÉΓòÉ
  3376.  
  3377. If an MLE is on the same window as a cancel push button, the button's Click 
  3378. event is called whenever the Esc key is pressed while the entry field has the 
  3379. focus. After, the focus will be left on the push button. 
  3380.  
  3381. There is no special interaction between an MLE and a default push button. 
  3382.  
  3383.  
  3384. ΓòÉΓòÉΓòÉ 9.9. Lists ΓòÉΓòÉΓòÉ
  3385.  
  3386. Figure 47  A ListBox, ComboBox, and DropDownComboBox
  3387.  
  3388. VX-REXX provides three list objects: ListBox, ComboBox, and DropDownComboBox. 
  3389. In general, these objects present lists of items from which the user can 
  3390. choose. The list can be sized to show a set number of items. If there are more 
  3391. items than can be displayed, a scroll bar is automatically attached to the 
  3392. list. Selected entries are highlighted. 
  3393.  
  3394. Use list boxes to display a list of options from which the user can select one 
  3395. or more items. Generally, you use a list box with a push button which, when 
  3396. clicked, performs an action on selected items. 
  3397.  
  3398. A combo box is a combination of a list box and an entry field. Use a combo box 
  3399. when you want to either select from a list or type in a new value. When you 
  3400. select an item from the list, its text is copied to the entry field part of the 
  3401. combo box, replacing the current value. 
  3402.  
  3403. Drop down combo boxes are similar to combo boxes except that the list portion 
  3404. of the object is not displayed until requested. Normally, only the entry field 
  3405. part and the drop down arrow are visible. Clicking the arrow indicator makes 
  3406. the list portion visible (but only if the height of the object is larger than 
  3407. the height of a single line of text). Once you select an item from the list, or 
  3408. type in a new value, the drop down list disappears. Drop down combo boxes can 
  3409. be made read-only so that you can only select one of the list items. 
  3410.  
  3411.  
  3412. ΓòÉΓòÉΓòÉ 9.9.1. Setting the sort order ΓòÉΓòÉΓòÉ
  3413.  
  3414. You can specify that a list should be sorted automatically when items are added 
  3415. to the list. If you want a list to be sorted, set the Sort property to 
  3416. Ascending or Descending. If you set Sort to None, then the list will be 
  3417. unsorted. 
  3418.  
  3419. You must set the sort order at design time. Setting the Sort property at run 
  3420. time will have no effect. 
  3421.  
  3422.  
  3423. ΓòÉΓòÉΓòÉ 9.9.2. Adding items to the list ΓòÉΓòÉΓòÉ
  3424.  
  3425. You can add items to a list at both design time and at run time. To add items 
  3426. at design time, set the InitialList property. The property is made up of a 
  3427. separator character followed by list items, separated by the separator 
  3428. character. For example, to set the list to be "Red", "Green", and "Blue",  set 
  3429. InitialList to ",Red,Green,Blue". The leading comma indicates that list items 
  3430. are separated by commas. 
  3431.  
  3432. To add single items at run time, use the AddString method. The following 
  3433. statement adds the item "White" to list box LB_1 as the third item: 
  3434.  
  3435. call VRMethod "LB_1", "AddString", "White", 3
  3436.  
  3437. If you omit the position argument, the item is added to the end of the list. 
  3438. The position is ignored in a sorted list, the new item is always added 
  3439. according to the sort order. 
  3440.  
  3441. To add many items at run time, use the AddStringList method. For example, to 
  3442. add "Red", "Green", and "Blue" to list box LB_1, you would write code similar 
  3443. to: 
  3444.  
  3445. items.0 = 3
  3446. items.1 = "Red"
  3447. items.2 = "Green"
  3448. items.3 = "Blue"
  3449. call VRMethod "LB_1", "AddStringList", "items."
  3450.  
  3451. Since no position parameter was given, the items will be added to the end of 
  3452. the list. 
  3453.  
  3454.  
  3455. ΓòÉΓòÉΓòÉ 9.9.3. Selecting and deselecting list items ΓòÉΓòÉΓòÉ
  3456.  
  3457. You have control over selected items only in list boxes. In combo boxes or drop 
  3458. down combo boxes the selected item is automatically entered into the entry 
  3459. field part. The contents of the entry field are available as the Value 
  3460. property. The index of the selected item is available as the Selected property. 
  3461.  
  3462. You can configure a list box to allow either single or multiple selection with 
  3463. the MultiSelect property. If MultiSelect is 1, then the user can select more 
  3464. than one item in the list. The MultiSelect property can be set at design time 
  3465. or at run time. 
  3466.  
  3467. For single selection list boxes, the current selection is reflected by the 
  3468. Selected and SelectedString properties. To select an item at run time, set the 
  3469. Selected property to the item number. For example, if you want to select the 
  3470. third item, set Selected to 3. Similarly, if you want to find out which item is 
  3471. selected, use VRGet to retrieve the value of the Selected property. If you want 
  3472. the text of the selected item, retrieve the value of the SelectedString 
  3473. property. 
  3474.  
  3475. For multiple selection list boxes, you can use the GetSelectedList and 
  3476. SetSelectedList methods to select and deselect list items. 
  3477.  
  3478.  
  3479. ΓòÉΓòÉΓòÉ 9.9.4. Removing list items ΓòÉΓòÉΓòÉ
  3480.  
  3481. To remove a list item, use the Delete, DeleteString or DeleteList methods. To 
  3482. remove all list items, use the Clear method. 
  3483.  
  3484. To restore a list to its initial state, use the Reset method. 
  3485.  
  3486. List boxes, combo boxes, and drop down combo boxes support the Clear, Reset, 
  3487. Delete, DeleteString and DeleteList methods. 
  3488.  
  3489.  
  3490. ΓòÉΓòÉΓòÉ 9.9.5. Write-protecting drop down combo boxes ΓòÉΓòÉΓòÉ
  3491.  
  3492. You can make a drop down combo box read-only to prevent you from typing a value 
  3493. at run time. You can only select an item from the list. In this case, the drop 
  3494. down combo box acts more like a list box which only allows a single selection. 
  3495. You may want to use the read-only drop down combo box instead of a list box to 
  3496. save space in your window since the list appears only when you want to make a 
  3497. selection. 
  3498.  
  3499.  
  3500. ΓòÉΓòÉΓòÉ 9.9.6. Per-item data ΓòÉΓòÉΓòÉ
  3501.  
  3502. User-defined strings can be added on a per-item basis to list boxes, combo 
  3503. boxes and drop down combo boxes. See the AddString, AddStringList, GetString 
  3504. and GetStringList methods. 
  3505.  
  3506.  
  3507. ΓòÉΓòÉΓòÉ 9.9.7. Sizing drop down combo boxes ΓòÉΓòÉΓòÉ
  3508.  
  3509. The height of a drop down combo box is the combined height of the list box part 
  3510. and the entry field part that make up the DDCB. If the height is too small, the 
  3511. list box part will not appear when the drop down arrow is pressed. 
  3512.  
  3513.  
  3514. ΓòÉΓòÉΓòÉ 9.9.8. Using the Click event ΓòÉΓòÉΓòÉ
  3515.  
  3516. List boxes, combo boxes, and drop down combo boxes generate a Click event when 
  3517. you select an item. The event does not occur for each actual mouse click, only 
  3518. for each new selection, including those done via the keyboard. 
  3519.  
  3520. When handling a click event for a combo box or drop down combo box, use the 
  3521. Selected and SelectedString properties to find out which item was selected, as 
  3522. the Value property is not updated immediately. 
  3523.  
  3524.  
  3525. ΓòÉΓòÉΓòÉ 9.9.9. Using the Change event ΓòÉΓòÉΓòÉ
  3526.  
  3527. When the contents of the entry field portion change in a combo box or drop down 
  3528. combo box, a Change event occurs. In the event routine, use the Value property 
  3529. to get the new value of the entry field portion. 
  3530.  
  3531.  
  3532. ΓòÉΓòÉΓòÉ 9.9.10. Using the DoubleClick event ΓòÉΓòÉΓòÉ
  3533.  
  3534. List boxes and combo boxes generate a DoubleClick event when you double click 
  3535. on a list item or press the Enter key. The DropDownComboBox object does not 
  3536. have a DoubleClick event; double clicking in that object activates the default 
  3537. push button. 
  3538.  
  3539.  
  3540. ΓòÉΓòÉΓòÉ 9.9.11. Using lists with default and cancel push buttons ΓòÉΓòÉΓòÉ
  3541.  
  3542. If a combo box is on the same window as a cancel push button, the button's 
  3543. Click event is called whenever the Esc key is pressed while the combo box has 
  3544. the focus. After, the focus will be left on the push button. Drop down combo 
  3545. boxes also have this behavior. 
  3546.  
  3547. Pressing Enter in a drop down combo box causes the Click routine of a default 
  3548. button to be called. However, there is no special interaction between combo 
  3549. boxes and default push buttons. 
  3550.  
  3551.  
  3552. ΓòÉΓòÉΓòÉ 9.10. Spin buttons ΓòÉΓòÉΓòÉ
  3553.  
  3554. Figure 48  A spin button
  3555.  
  3556. The SpinButton object lets the user choose one from a set of choices, or to 
  3557. type values directly into an entry field. Only one item from the spin button's 
  3558. list of items is displayed at a time, so the items should always be in a 
  3559. logical sequence, like a range of numbers or an alphabetized list of names, or 
  3560. the days of the week. If the items do not have a logical sequence, use a 
  3561. ComboBox or DropDownComboBox, both of which provide a list of items and an 
  3562. entry field, but allow the viewing of several items at a time. 
  3563.  
  3564.  
  3565. ΓòÉΓòÉΓòÉ 9.10.1. Using spin buttons with numbers ΓòÉΓòÉΓòÉ
  3566.  
  3567. Using spin buttons to let the user select a number is very easy, since VX-REXX 
  3568. already knows the sequence of integers. To set the spin button to cycle through 
  3569. a set of numbers, set its first list item to a string of the form 
  3570.  
  3571. <Min to Max by Step> 
  3572.  
  3573. You can do this at design time by setting the InitialList property, or at run 
  3574. time using the SetStringList method. Min is the minimum numeric value, Max is 
  3575. the maximum numeric value, and Step is the increment between items. For 
  3576. example, <10 to 50 by 10> would produce the list 10,20,30,40,50. If Min is 
  3577. greater than Max, the Min and Max parameters are reversed. If Step is negative, 
  3578. it is made positive. 
  3579.  
  3580.  
  3581. ΓòÉΓòÉΓòÉ 9.10.2. Using spin buttons with a list of items ΓòÉΓòÉΓòÉ
  3582.  
  3583. Presenting non-numeric list items with a spin button involves a similar 
  3584. procedure to that used for making list boxes. Type the list of items into the 
  3585. spin button's InitialList property, remembering that the first character in the 
  3586. string is used as a separator character. Use that character to separate one 
  3587. item from the next. The separator character cannot occur in any of the items. 
  3588. For example, the InitialList property for a spin button to display the days of 
  3589. the week may look like: 
  3590.  
  3591. ;Saturday;Friday;Thursday;Wednesday;Tuesday;Monday;Sunday
  3592.  
  3593. Or you could replace the semicolon with any other character that does not 
  3594. appear in the items themselves. 
  3595.  
  3596. You can also set the list of items at run time with the SetStringList method. 
  3597. This method works like the GetStringList method in reverse. You supply a stem 
  3598. variable containing the items, and they become the spin button's list of items, 
  3599. replacing whatever the list used to be. 
  3600.  
  3601. The CUA guidelines suggest that if a spin button displays only numeric values, 
  3602. that the up arrow causes the next higher value to be displayed. This is the 
  3603. behavior of the VX-REXX spin button. The guidelines also suggest that if the 
  3604. spin button displays a list of ordered strings, that pressing the down arrow 
  3605. should display the next string. To get this effect, you should list values in 
  3606. the InitialList property in reverse alphabetical order. 
  3607.  
  3608.  
  3609. ΓòÉΓòÉΓòÉ 9.10.3. Using the ReadOnly and NumericOnly properties ΓòÉΓòÉΓòÉ
  3610.  
  3611. By default, a spin button will not allow the user to type a value directly into 
  3612. its entry field. If you set the ReadOnly property to 0, the user will be able 
  3613. to enter values directly into the entry field. If you set the NumericOnly 
  3614. property to 1, only numbers can be typed in. 
  3615.  
  3616.  
  3617. ΓòÉΓòÉΓòÉ 9.10.4. Using default and cancel push buttons ΓòÉΓòÉΓòÉ
  3618.  
  3619. If a spin button is on the same window as a default push button, the push 
  3620. button's Click event is called whenever the Enter key is pressed while the spin 
  3621. button has the focus. After, the focus will be left on the push button. 
  3622.  
  3623. Similarly, if there is a cancel button on the window, its Click event will be 
  3624. called when the Esc key is pressed while the spin button has focus. 
  3625.  
  3626.  
  3627. ΓòÉΓòÉΓòÉ 9.11. Pictures ΓòÉΓòÉΓòÉ
  3628.  
  3629. VX-REXX provides three picture objects: PictureBox, ImagePushButton and 
  3630. ImageRadioButton. These objects are used to display pictures (icons or 
  3631. bitmaps). 
  3632.  
  3633. A picture box is a rectangular area for displaying a picture. A border can be 
  3634. drawn around the picture. 
  3635.  
  3636. An image push button is a push button that displays a picture instead of text. 
  3637. When the user clicks on the image push button, the image it displays is briefly 
  3638. inverted. 
  3639.  
  3640. An image radio button is a radio button that displays a picture instead of 
  3641. text. When the image radio button is set, its image is inverted. As with radio 
  3642. buttons, only a single radio button in a group (see below) can be set at a 
  3643. time. The VX-REXX tool palette is a collection of image radio buttons. 
  3644.  
  3645.  
  3646. ΓòÉΓòÉΓòÉ 9.11.1. Setting the picture path ΓòÉΓòÉΓòÉ
  3647.  
  3648. The picture displayed by a picture object is set using the PicturePath 
  3649. property. The PicturePath can be set to the name of a bitmap or icon file, or 
  3650. the resource identifier of a bitmap or icon resource. See the "Bitmaps, icons 
  3651. and resources" chapter for more information. 
  3652.  
  3653.  
  3654. ΓòÉΓòÉΓòÉ 9.11.2. Creating 3-D effects ΓòÉΓòÉΓòÉ
  3655.  
  3656. You can create 3-D effects for use with the image push button and image radio 
  3657. button objects by including a border as part of the icon or bitmap itself. For 
  3658. example, the image radio buttons in the VX-REXX tool palette all use icons with 
  3659. a white border on the top and left sides, a dark grey border on the bottom and 
  3660. right sides, and a medium grey interior. 
  3661.  
  3662.  
  3663. ΓòÉΓòÉΓòÉ 9.12. Groups ΓòÉΓòÉΓòÉ
  3664.  
  3665. Figure 49  A group box
  3666.  
  3667. Group boxes and windows are containers for objects. All objects added to a 
  3668. window belong to one group. If you need more than one group in a window then 
  3669. you must use a GroupBox object. You should use group boxes for these purposes: 
  3670.  
  3671. o To group radio buttons and image radio buttons 
  3672.  
  3673.   All radio buttons (or image radio buttons) within a given group box are 
  3674.   mutually exclusive. If you want to put more than one set of radio buttons on 
  3675.   a window, you should put each set in its own group box. 
  3676.  
  3677.   Note that all radio buttons which are not in any group box are considered to 
  3678.   be in a group. If you are designing a window which uses only one set of radio 
  3679.   buttons, you do not need to put them in a group box, although you can for 
  3680.   aesthetic reasons. 
  3681.  
  3682. o To emphasize the relationship among a group of objects 
  3683.  
  3684.   A group box usually implies that the objects it contains have a common 
  3685.   purpose. You can put any type of object into a group box -- even other group 
  3686.   boxes. 
  3687.  
  3688.  
  3689. ΓòÉΓòÉΓòÉ 9.12.1. Setting a group box caption ΓòÉΓòÉΓòÉ
  3690.  
  3691. The group box caption is displayed on the top line of the group box near the 
  3692. upper left corner. When you create a group box, its caption is the null string. 
  3693. To change the caption, set the Caption property to the new caption. If the 
  3694. caption is longer than the width of the group box, only the leftmost portion of 
  3695. the caption will be visible. 
  3696.  
  3697.  
  3698. ΓòÉΓòÉΓòÉ 9.12.2. Adding objects to a group ΓòÉΓòÉΓòÉ
  3699.  
  3700. Objects are added to a group in one of three ways: 
  3701.  
  3702.  1. Selecting an object from the tool palette and then clicking and dragging in 
  3703.     the group box. 
  3704.  
  3705.  2. Cutting or copying an object from elsewhere and pasting it into the group 
  3706.     box. 
  3707.  
  3708.  3. When the group box is created, any objects it entirely overlaps are 
  3709.     automatically added to the group box. 
  3710.  
  3711.  
  3712. ΓòÉΓòÉΓòÉ 9.12.3. Removing objects from a group ΓòÉΓòÉΓòÉ
  3713.  
  3714. Objects can only be removed from a group by cutting them from the group box and 
  3715. pasting them elsewhere. 
  3716.  
  3717.  
  3718. ΓòÉΓòÉΓòÉ 9.12.4. Disabling objects in a group ΓòÉΓòÉΓòÉ
  3719.  
  3720. When you disable a group box or a window, all of the objects it contains are 
  3721. also disabled, though they will not be grayed out. Similarly, enabling a group 
  3722. box or window enables all of its child objects. However, if a child object's 
  3723. Enabled property is 0, then the object is always disabled, regardless of 
  3724. whether its parent is enabled or not. 
  3725.  
  3726.  
  3727. ΓòÉΓòÉΓòÉ 9.13. Notebooks ΓòÉΓòÉΓòÉ
  3728.  
  3729. Figure 50  A notebook
  3730.  
  3731. Use notebooks to present information to the user using a book metaphor. The 
  3732. notebook has a number of pages, on which you can place other objects. Pages can 
  3733. have tabs which let the user turn the pages quickly. Notebooks are often used 
  3734. to present settings to the user; OS/2 does this for Workplace Shell objects, 
  3735. and VX-REXX does this for changing object properties at design time. 
  3736.  
  3737. The parts of a notebook are listed below: 
  3738.  
  3739. binding             The binding is the spine of the notebook. It can be shown 
  3740.                     either as solid or spiral. The notebook in Figure 50 has a 
  3741.                     spiral binding. 
  3742.  
  3743. back pages          The pages under the top page make up the back pages. They 
  3744.                     are drawn along the right and bottom edges in Figure 50. 
  3745.  
  3746. page buttons        The arrows in the corner where the recessed pages meet 
  3747.                     select the previous and next page. 
  3748.  
  3749. page window         The contents of each page is made up of a page window. A 
  3750.                     page window is an ordinary VX-REXX window that is used like 
  3751.                     a secondary window. 
  3752.  
  3753. status text         The text near the bottom edge of the page in Figure 50 is 
  3754.                     called status text. Each page can have its own status text. 
  3755.  
  3756. tabs                A tab is an extension to a page that the user can click on 
  3757.                     to select that page. There are two types of tabs: major and 
  3758.                     minor. Major tabs are always drawn opposite the binding. 
  3759.                     Minor tabs are shown along the other edge with back pages. 
  3760.  
  3761.                     In Figure 50, the words Value, Style, Name, and Info appear 
  3762.                     on major tabs; these words are the tab text. If there were 
  3763.                     pages with minor tabs, the tabs would appear along the 
  3764.                     bottom. 
  3765.  
  3766.                     When a user clicks on a tab, that page is brought to the 
  3767.                     front. 
  3768.  
  3769. tab scroll buttons  If the notebook does not have room to display all of the 
  3770.                     tabs, it creates tab scroll buttons that the user can press 
  3771.                     to scroll through the list of tabs. 
  3772.  
  3773.  
  3774. ΓòÉΓòÉΓòÉ 9.13.1. Changing the notebook binding ΓòÉΓòÉΓòÉ
  3775.  
  3776. Figure 51  Notebooks with solid and spiral binding
  3777.  
  3778. You can change the notebook binding by setting the Binding property to either 
  3779. Spiral or Solid. By default, notebooks have a spiral binding. The two styles 
  3780. are shown in Figure 51. The notebook on the left has solid binding, while the 
  3781. one on the right has spiral binding. 
  3782.  
  3783. This property can be set at design time using the property notebook for the 
  3784. notebook object, and at run time using the VRSet and VRGet functions. 
  3785.  
  3786.  
  3787. ΓòÉΓòÉΓòÉ 9.13.2. Changing the tab shape ΓòÉΓòÉΓòÉ
  3788.  
  3789. The appearance of tabs is determined by the TabShape property which can be set 
  3790. to Square, Rounded, or Polygonal. The notebook in Figure 50 has square tabs. By 
  3791. default, pages have square tabs. 
  3792.  
  3793. This property can be set at design time using the property notebook for the 
  3794. notebook object, and at run time using VRSet. For example, the following 
  3795. statement causes notebook "NB_1" to display rounded tabs: 
  3796.  
  3797. call VRSet "NB_1", "TabShape", "Rounded"
  3798.  
  3799.  
  3800. ΓòÉΓòÉΓòÉ 9.13.3. Using the MajorTabPos and BackPages properties ΓòÉΓòÉΓòÉ
  3801.  
  3802. The BackPages property controls the orientation of the back pages. You can set 
  3803. it at design time and at run time to any of: TopLeft, TopRight, BottomLeft, or 
  3804. BottomRight. The BackPages property determines the allowed values for the 
  3805. MajorTabPos property. MajorTabPos can only be one of the two values that make 
  3806. up the BackPages property. For example, if BackPages is BottomRight, then 
  3807. MajorTabPos can be either Bottom or Right. 
  3808.  
  3809. The binding is always drawn opposite the major tabs. So if MajorTabPos is 
  3810. Bottom, then the binding will be drawn along the top edge of the notebook. 
  3811.  
  3812. Minor tabs are always placed on the side with recessed pages that does not have 
  3813. major tabs. For example, in Figure 51, the minor tabs would appear along the 
  3814. bottom. 
  3815.  
  3816. The BackPages and MajorTabPos properties can be set at design time using the 
  3817. property notebook for the notebook object, and at run time using VRSet. For 
  3818. example, the following statements put back pages at the bottom right, major 
  3819. tabs along the bottom, and the binding along the top. 
  3820.  
  3821. call VRSet "NB_1", "BackPages", "BottomRight"
  3822. call VRSet "NB_1", "MajorTabPos", Bottom"
  3823.  
  3824.  
  3825. ΓòÉΓòÉΓòÉ 9.13.4. Adding pages at design time ΓòÉΓòÉΓòÉ
  3826.  
  3827. Notebook pages are made up of secondary windows. These windows can be 
  3828. automatically loaded and added to a notebook by listing their names in the 
  3829. notebook's InitialPageList property. 
  3830.  
  3831. To create a secondary window, select New Window from the window list. Add 
  3832. objects to this new window, and write event routines for the objects as you 
  3833. normally would. Then, add the name of the window to the InitialPageList 
  3834. property. 
  3835.  
  3836. The InitialPageList property is made up of a number of page descriptors, 
  3837. separated by a delimiter which must be the first character of the string. The 
  3838. page descriptors have the following syntax: 
  3839.  
  3840. windowName [ ( + | - ) tabText ]
  3841.  
  3842. where windowName is the name of the window, and tabText is the tab text for 
  3843. that page. If you omit the tab text, the page will have no tab. See the 
  3844. description of the InitialPageList property for more information. 
  3845.  
  3846. The initial page list is processed from left to right. The first window becomes 
  3847. page 1, the second becomes page 2, and so on. Many of the notebook methods take 
  3848. a page number as a parameter. The page number is a whole number from 1 to n 
  3849. where n is the number of pages in the notebook. There is no fixed limit on the 
  3850. number of pages that a notebook can hold. 
  3851.  
  3852. Notebooks process the initial page list property in the main event loop of the 
  3853. window file. This means that the pages will not be loaded when the Init routine 
  3854. is called. If you need to perform some initialization on the notebook pages, 
  3855. you should put your initialization code for a given page in that window's 
  3856. Create event routine. Your code will be called when the window is loaded. 
  3857.  
  3858. For an example of how to use the InitialPageList property, recall the notebook 
  3859. in Figure 50 which has four pages. The secondary windows that are the pages of 
  3860. the notebooks are named SW_1, SW_2, SW_3, and SW_4. The InitialPageList string 
  3861. to add these pages with their tab text would be: 
  3862.  
  3863. ;SW_1+Value;SW_2+Style;SW_3+Name;SW_4+Info
  3864.  
  3865. Note that secondary windows are displayed slightly differently when they are 
  3866. added to a notebook. You should be aware of the following points: 
  3867.  
  3868. o Secondary windows are positioned in the upper left corner of the page. If the 
  3869.   window is larger than the page, only the top left portion of the window will 
  3870.   be visible. The user can make the rest of the window visible by making the 
  3871.   notebook larger. 
  3872.  
  3873. o Page windows have no frame, so the BorderType, MaximizeButton, 
  3874.   MinimizeButton, HideButton, SystemMenu and WindowState properties have no 
  3875.   effect. 
  3876.  
  3877. o The WindowMode property of the window is ignored. 
  3878.  
  3879. Menus, however, will be displayed. 
  3880.  
  3881.  
  3882. ΓòÉΓòÉΓòÉ 9.13.5. Setting the page tab text ΓòÉΓòÉΓòÉ
  3883.  
  3884. To change the tab text for a page, use the SetTabText method. The notebook will 
  3885. automatically resize the tabs to fit the longest tab text. The GetTabText 
  3886. method returns the tab text for a given page. 
  3887.  
  3888.  
  3889. ΓòÉΓòÉΓòÉ 9.13.6. Setting the page status text ΓòÉΓòÉΓòÉ
  3890.  
  3891. To change the status text for a page, use the SetStatusText method. The 
  3892. GetStatusText method returns the status text for a given page. The status text 
  3893. can be set only at run time. 
  3894.  
  3895.  
  3896. ΓòÉΓòÉΓòÉ 9.13.7. Turning to a given page ΓòÉΓòÉΓòÉ
  3897.  
  3898. To set the current page number, use VRSet to change the Selected property. Set 
  3899. the property to 1 to turn to the first page. To turn to the last page, use 
  3900. VRGet to retrieve the number of pages in the Count property, then turn to that 
  3901. page. 
  3902.  
  3903. While Selected can be set and retrieved at run time, the Count property is 
  3904. read-only at run time. 
  3905.  
  3906.  
  3907. ΓòÉΓòÉΓòÉ 9.13.8. Adding pages at run time ΓòÉΓòÉΓòÉ
  3908.  
  3909. Notebooks automatically insert all pages listed in the InitialPageList property 
  3910. when they are created. To add more pages at run time, use either the 
  3911. InsertBlankPage method or the InsertPage method. Use InsertBlankPage if the 
  3912. page window has not been loaded yet; use InsertPage if the window is already 
  3913. loaded. 
  3914.  
  3915. InsertBlankPage reserves a page for a window in the notebook. When that page is 
  3916. selected, the notebook will automatically load the page window (see the 
  3917. PageLoad section in the Reference) 
  3918.  
  3919.  
  3920. ΓòÉΓòÉΓòÉ 9.13.9. Preloading notebook pages ΓòÉΓòÉΓòÉ
  3921.  
  3922. By default, the notebook loads a page window when the page is initially 
  3923. selected. This scheme results in better performance than loading all of the 
  3924. page windows when the notebook is created. If your program requires that all 
  3925. page windows be loaded on startup, set the PreloadPages property to 1. By 
  3926. default, PreloadPages is 0. 
  3927.  
  3928.  
  3929. ΓòÉΓòÉΓòÉ 9.13.10. Loading pages under program control ΓòÉΓòÉΓòÉ
  3930.  
  3931. By default, notebooks load page windows automatically. If the application needs 
  3932. to perform the loading itself, it must define a PageLoad event for the 
  3933. notebook. When a page is selected for the first time, this event is generated. 
  3934. The event handler must call VRLoad to load the window, then invoke the 
  3935. SetPageWindow method to associate the window's internal name with the notebook 
  3936. page. 
  3937.  
  3938. The following PageLoad event is equivalent to the notebook's default behavior: 
  3939.  
  3940. NB_1_PageLoad:
  3941.     name = VRInfo( "WindowName" )
  3942.     page = VRGet( "NB_1", "Selected" )
  3943.     w = VRLoad( "NB_1", VRWindowPath(), name )
  3944.     if w \= "" then do
  3945.         call VRMethod "NB_1", "SetPageWindow", page, w
  3946.     end
  3947. return
  3948.  
  3949. Note:  Do not use VRLoadSecondary to load notebook page windows. 
  3950. VRLoadSecondary does not make the loaded window a child of the notebook. It 
  3951. also makes the window visible as soon as it is loaded, which may cause the 
  3952. window to flash as it is added to the notebook. 
  3953.  
  3954.  
  3955. ΓòÉΓòÉΓòÉ 9.13.11. Removing pages at run time ΓòÉΓòÉΓòÉ
  3956.  
  3957. Pages can be deleted using the DeletePage method. (This does not destroy the 
  3958. page window.)  When a notebook is destroyed, it automatically deletes and 
  3959. destroys all of its pages. 
  3960.  
  3961.  
  3962. ΓòÉΓòÉΓòÉ 9.14. Containers ΓòÉΓòÉΓòÉ
  3963.  
  3964. Figure 52  A container
  3965.  
  3966. A container shows a view of a set of records. The view may consist of icons, 
  3967. bitmaps, text, or a combination of these. All records have attributes such as 
  3968. an icon, caption, and its position within the container. 
  3969.  
  3970. Records have a hierarchical structure. A record may be the parent of a number 
  3971. of other records. This parent-child relationship can be shown using the 
  3972. container tree views. 
  3973.  
  3974. Containers support drag and drop interactions. A user can do the following, 
  3975. among others: 
  3976.  
  3977. o Drag files onto containers 
  3978. o Drag records onto the Workplace Shell Shredder 
  3979. o Drag records onto Workplace Shell printers 
  3980.  
  3981. OS/2 uses containers in the Workplace Shell; the desktop and folder objects are 
  3982. containers. The icon, tree, and detail views used by the Workplace Shell are 
  3983. fundamental container properties that you can use in your VX-REXX programs. 
  3984.  
  3985.  
  3986. ΓòÉΓòÉΓòÉ 9.14.1. Setting the view ΓòÉΓòÉΓòÉ
  3987.  
  3988. The type of view that a container displays is set using the View property. The 
  3989. following sections describe each view. 
  3990.  
  3991. Icon view 
  3992.  
  3993. Figure 53  A container in icon view
  3994.  
  3995. In icon view, the icon and caption for each record are shown together. Icons 
  3996. can be positioned anywhere in the container workspace. If there is not enough 
  3997. room to display all the records at once, the container adds horizontal and 
  3998. vertical scroll bars where necessary. 
  3999.  
  4000. Name view 
  4001.  
  4002. Figure 54  A container in name view
  4003.  
  4004. In name view, the icon and caption for each record are shown side by side. 
  4005. Records are listed in a single column, unless the Flowed property is set, in 
  4006. which case the column wraps horizontally. 
  4007.  
  4008. Text view 
  4009.  
  4010. Figure 55  A container in text view
  4011.  
  4012. In text view, only the record captions are displayed. Records are listed in a 
  4013. single column, unless the Flowed property is set, in which case the column 
  4014. wraps horizontally. 
  4015.  
  4016. Detail view 
  4017.  
  4018. Figure 56  A container in detail view
  4019.  
  4020. The detail view presents the records in tabular form. The columns are made of 
  4021. fields which the REXX program creates, while each row contains information for 
  4022. a given record. Fields can contain icons, text, numbers, dates, and times. 
  4023.  
  4024. The record icon and caption are not shown in the detail view. 
  4025.  
  4026. The detail view can be optionally split into left and right halves. The two 
  4027. halves share the same vertical scroll bar, but can be scrolled horizontally 
  4028. independently. See the SplitBarLeft and LastSplitField properties for more 
  4029. information. 
  4030.  
  4031. Tree views 
  4032.  
  4033. Figure 57  A container in icon tree view
  4034.  
  4035. Records can be organized in a hierarchical structure with parent and child 
  4036. records. Child records are displayed in the following views: icon tree, name 
  4037. tree, and text tree. Child records are never displayed in icon, name, text, or 
  4038. detail views. 
  4039.  
  4040.  Figure 57 shows a container whose View property is set to IconTree. The BIN 
  4041. record has two child records: WINCTRL.ICO and WINCTRL.EXE. 
  4042.  
  4043. In the icon tree or text tree views, a graphic indicator appears to the left of 
  4044. each parent record to indicate that the record has children. If the children 
  4045. are not displayed, the parent record is said to be collapsed. When the children 
  4046. are showing, the parent is expanded. No indicator appears in name tree view, 
  4047. although clicking on the parent record makes the children visible. 
  4048.  
  4049. A line connects the child and parent records. This line can be suppressed by 
  4050. setting the ShowTreeLine property to 0. The thickness of the line can is set by 
  4051. the TreeLine property, while the amount of indentation used to display child 
  4052. records is set using the TreeIndent property. 
  4053.  
  4054.  
  4055. ΓòÉΓòÉΓòÉ 9.14.2. Creating detail view fields ΓòÉΓòÉΓòÉ
  4056.  
  4057. In the detail view, the record caption and icon are not displayed. Instead the 
  4058. container shows records in a tabular form. Each row contains information 
  4059. associated with a given record. The information is broken up horizontally into 
  4060. a number of fields. 
  4061.  
  4062. Detail view fields are only visible in the detail view. If a container is never 
  4063. used in detail view, there is no need to define fields or to set field data. 
  4064. You may want to do so however, in order to store user defined information about 
  4065. records. 
  4066.  
  4067. It is up to the REXX program to create each field and to set the field data for 
  4068. each record. Fields are created using the AddField method. When you add a 
  4069. field, you must declare both the field caption and the type of data that the 
  4070. field will hold. For example: 
  4071.  
  4072. nameField = VRMethod( "CN_1", "AddField", "String", "Name", "NameField" )
  4073.  
  4074. adds a field with the caption "Name"; the field holds strings. The last 
  4075. parameter NameField is the symbolic name for the new field. The AddField method 
  4076. returns a field handle which uniquely identifies the field. The method that 
  4077. sets field data for records takes the field handle as a parameter. You can also 
  4078. use the symbolic name wherever you use a field handle. 
  4079.  
  4080. Note:  You must define all fields before adding any records to the container. 
  4081.  
  4082. Fields have a number of attributes which can be set using the SetFieldAttr 
  4083. method. The REXX program can configure a field's visibility, text 
  4084. justification, and read/write status. For example, the following statement 
  4085. makes the name field created above read only. 
  4086.  
  4087. call VRMethod "CN_1", "SetFieldAttr", nameField, "ReadOnly", 1
  4088.  
  4089. The default field attribute values are listed in the SetFieldAttr section in 
  4090. the reference guide. 
  4091.  
  4092.  
  4093. ΓòÉΓòÉΓòÉ 9.14.3. Record emphasis ΓòÉΓòÉΓòÉ
  4094.  
  4095. Several types of record emphasis are available. Each emphasis type may be set 
  4096. using SetRecordAttr and retrieved using GetRecordAttr: 
  4097.  
  4098. Visible             If set, the record will be shown. 
  4099.  
  4100. Cursored            If set, a thin dotted line is drawn around the record. The 
  4101.                     cursored record is the record with input focus. The cursor 
  4102.                     keys can be used to move to cursor to another record. 
  4103.                     Pressing the space bar will select the cursored record. 
  4104.  
  4105. Selected            If set, a solid background is used for the record. 
  4106.                     Selection is done using the space bar (to select the 
  4107.                     cursored record) or by clicking on the record with mouse 
  4108.                     button 1. Record selection is influenced by the container's 
  4109.                     MultiSelect and ExtendSelect properties. If both properties 
  4110.                     are 0, only a single record can be selected at a time. If 
  4111.                     MultiSelect is 1, any number of records can be selected and 
  4112.                     clicking on the record either selects it (if it was 
  4113.                     deselected) or deselects it (if it was selected). If 
  4114.                     MultiSelect is 0 but ExtendSelect is 1, clicking on a 
  4115.                     record will select it and deselect the rest unless the Ctrl 
  4116.                     is down, in which case the click selects or deselects the 
  4117.                     record without affecting the other selected records. Swipe 
  4118.                     selection is also enabled if either MultiSelect or 
  4119.                     ExtendSelect is 1. 
  4120.  
  4121. InUse               If set, a hatched emphasis is used for the record. This is 
  4122.                     the same emphasis used by Workplace Shell objects to 
  4123.                     indicate a view has been opened. This emphasis can only be 
  4124.                     set by the program. 
  4125.  
  4126. Source              If set, a heavy dotted line surrounds the record. This 
  4127.                     emphasis is set by VX-REXX when a pop-up menu is displayed 
  4128.                     in a container and is used to indicate which records are to 
  4129.                     be acted on by the commands in the pop-up menu. If the 
  4130.                     record you clicked on to open the pop-up (see the 
  4131.                     ContextMenu event) is selected, source emphasis will be set 
  4132.                     on all selected records. Otherwise only the record you 
  4133.                     clicked on has the source emphasis set. 
  4134.  
  4135. The GetRecordList method is used to obtain a list of records in a container 
  4136. that have a given emphasis. 
  4137.  
  4138. Pull-down menus should only operate on the selected records in a container. 
  4139. Pop-up menus should only operate on the records with source emphasis. The 
  4140. SourceOrSelected parameter may be passed to GetRecordList to obtain the correct 
  4141. list of records. Also, if an item is selected from a pop-up menu, it is your 
  4142. project's responsibility to remove the source emphasis from any records. 
  4143.  
  4144.  
  4145. ΓòÉΓòÉΓòÉ 9.14.4. Adding records ΓòÉΓòÉΓòÉ
  4146.  
  4147. Use the AddRecord or AddRecordList methods to add records to a container. When 
  4148. you add a record, you can give its initial position in the container workspace, 
  4149. its caption, and its icon. You can later change any of this information using 
  4150. the SetRecordAttr method. 
  4151.  
  4152. If you use the AddRecord method, detail view data must be specified later with 
  4153. the SetFieldData method. If you use AddRecordList, you can create the records 
  4154. and initialize the field data all at once. See the AddRecordList method for 
  4155. details. 
  4156.  
  4157. The AddRecord method returns a record handle which is an identifier for the new 
  4158. record. The record handle is passed to many of the container methods. 
  4159.  
  4160. You do not have to add records to each particular view. Records are added to 
  4161. the container, and the container displays its records in some particular view. 
  4162.  
  4163. The following sample code creates a record with the caption Anaconda. It uses 
  4164. the icon in file SNAKE.ICO. 
  4165.  
  4166. record = VRMethod( "CN_1", "AddRecord", "", "Last",,
  4167.                    "Anaconda", "SNAKE.ICO" )
  4168.  
  4169. The null string in the third parameter above indicates that the record has no 
  4170. parent. If this had been a child record, this parameter would have been the 
  4171. record handle of its parent. 
  4172.  
  4173. The fourth parameter to VRMethod is Last, meaning that the record should be 
  4174. added at the end of the container's record list. In the name, text, and detail 
  4175. views records are listed in the order in which they were added. 
  4176.  
  4177. The trailing comma on the first line in the above example is the REXX line 
  4178. continuation character. 
  4179.  
  4180. The following sample shows how to use AddRecordList to add a number of records 
  4181. all at once. 
  4182.  
  4183. info.0 = 3             /* Create 3 records */
  4184. info.1 = ";Apple;APPLE.ICO"
  4185. info.2 = ";Orange;ORANGE.ICO"
  4186. info.3 = ";Grape;GRAPE.ICO"
  4187. ok = VRMethod( "CN_1", "AddRecordList", , , "info." )
  4188.  
  4189. Note:  Once you add the first record to a container, you can no longer add any 
  4190. fields. 
  4191.  
  4192.  
  4193. ΓòÉΓòÉΓòÉ 9.14.5. Removing records ΓòÉΓòÉΓòÉ
  4194.  
  4195. Use the RemoveRecord method to remove a record. You do not have to remove 
  4196. records from each view because the record belongs to the container, not the 
  4197. individual views. If the AutoPosition property is 1, the container will 
  4198. automatically adjust the other records' positions as a result of the deletion. 
  4199.  
  4200.  
  4201. ΓòÉΓòÉΓòÉ 9.14.6. Selecting records ΓòÉΓòÉΓòÉ
  4202.  
  4203. You can control the way records are selected in a container by setting the 
  4204. ExtendSelect and MultiSelect properties. The three selection modes are 
  4205. described below. 
  4206.  
  4207. Single selection (ExtendSelect=0, MultiSelect=0) 
  4208.  
  4209. You can select one record at a time. Select a record by clicking on it, or by 
  4210. moving the cursor to the record then pressing Ctrl+Spacebar. 
  4211.  
  4212. Multiple selection (ExtendSelect=0, MultiSelect=1) 
  4213.  
  4214. You can select one or more records at a time in any order. Clicking on a record 
  4215. toggles its selected state without deselecting other records. 
  4216.  
  4217. Multiple selection is not available in any of the tree views. 
  4218.  
  4219. Extended selection (ExtendSelect=1, MultiSelect=0) 
  4220.  
  4221. You can select one or more records at a time in any order. Clicking on a record 
  4222. automatically deselects all other selected records. To add a record to the 
  4223. selected list, hold the Ctrl key while clicking. 
  4224.  
  4225. Extended selection is not available in any of the tree views. 
  4226.  
  4227. Note:  The container ExtendSelect and MultiSelect properties operate 
  4228. differently than those on list boxes and combo boxes. 
  4229.  
  4230.  
  4231. ΓòÉΓòÉΓòÉ 9.14.7. Setting detail view information ΓòÉΓòÉΓòÉ
  4232.  
  4233. To set the detail view information, use the SetFieldData method. If you do not 
  4234. set the field data for a given record, the field will be left blank if it is a 
  4235. string, or 0 otherwise. 
  4236.  
  4237. The following code sets the name field for record rh to "Cattran": 
  4238.  
  4239. ok = VRMethod( "CN_1", "SetFieldData", rh, nameField, "Cattran" )
  4240.  
  4241.  
  4242. ΓòÉΓòÉΓòÉ 9.14.8. Making fields invisible ΓòÉΓòÉΓòÉ
  4243.  
  4244. You cannot remove fields from a container, although it is possible to hide 
  4245. fields, which has the appearance of removing fields. 
  4246.  
  4247. Sometimes you may want to associate extra information with each record, but you 
  4248. do not want that information displayed. In this case, you can store the 
  4249. information in an invisible field. You can make fields invisible by setting the 
  4250. field attribute Visible to 0. 
  4251.  
  4252.  
  4253. ΓòÉΓòÉΓòÉ 9.14.9. Positioning records ΓòÉΓòÉΓòÉ
  4254.  
  4255. In icon view, records are positioned according to their Left and Bottom 
  4256. attributes. These two attributes give the record's location relative to the 
  4257. container's workspace. The workspace is a logical area equal to the rectangle 
  4258. that is just large enough to enclose all records in icon view. If the workspace 
  4259. is smaller than the container object, scroll bars appear to let the user scroll 
  4260. through the workspace. 
  4261.  
  4262. You can change the position of a record using the SetRecordAttr method. The 
  4263. following statement moves the record whose handle is in rh 200 twips above the 
  4264. bottom of the workspace, and 500 twips to the right of the left edge: 
  4265.  
  4266. call VRMethod "CN_1", "SetRecordAttr", rh, "Bottom", 200, "Left", 500
  4267.  
  4268. In icon view, use the Arrange method to reposition records according to the CUA 
  4269. guidelines. Records are put in a row near the top of the workspace. Once the 
  4270. row is full, a new row is started under the first row, and so on. If the 
  4271. AutoPosition property is 1, then the container automatically positions records 
  4272. in icon view. The records' Left and Bottom attributes are ignored in that case. 
  4273.  
  4274. In the other views, records are displayed in the order they are added. This 
  4275. order can be changed by sorting the records. 
  4276.  
  4277.  
  4278. ΓòÉΓòÉΓòÉ 9.14.10. Sorting records ΓòÉΓòÉΓòÉ
  4279.  
  4280. Container records can be sorted at run time. To sort records, follow these 
  4281. steps: 
  4282.  
  4283.  1. Set the Sort property to indicate the ordering you want. 
  4284.  
  4285.  2. If you are sorting while the detail view is shown, set the DetailSort 
  4286.     property to the field handle which contains the sort key. 
  4287.  
  4288.  3. Invoke the SortRecords method. 
  4289.  
  4290. If the container is not showing the detail view, sorting is done on the 
  4291. records' caption attribute. 
  4292.  
  4293. If the AutoSort property is 1, then the container automatically sorts records 
  4294. as they are inserted. 
  4295.  
  4296.  
  4297. ΓòÉΓòÉΓòÉ 9.14.11. Searching records ΓòÉΓòÉΓòÉ
  4298.  
  4299. Like items in a list, records can be searched for a particular text string. Use 
  4300. the FindRecord method to do this. 
  4301.  
  4302.  
  4303. ΓòÉΓòÉΓòÉ 9.14.12. Sharing records between multiple containers ΓòÉΓòÉΓòÉ
  4304.  
  4305. Once you create a record using the AddRecord method, you can then add it to 
  4306. other containers using the AddSharedRecord method. The record is then said to 
  4307. be shared. While the record's caption, icon, and field data are shared between 
  4308. all containers, each container keeps track of the record's position separately. 
  4309. For example, if you change the Caption attribute of a shared record in one 
  4310. container, that change will be reflected in all of the containers. However, 
  4311. changing the Left or Bottom attributes in one container does not affect any of 
  4312. the other containers. 
  4313.  
  4314. You remove shared records in the usual way with the RemoveRecord method. The 
  4315. record will not actually be destroyed until it is removed from all of the 
  4316. containers it has been added to. 
  4317.  
  4318.  
  4319. ΓòÉΓòÉΓòÉ 9.14.13. Moving a record from one container to another ΓòÉΓòÉΓòÉ
  4320.  
  4321. You can use AddSharedRecord to move records from one container to another while 
  4322. preserving the detail field information. The following DragDrop event routine 
  4323. illustrates how to do this: 
  4324.  
  4325. CN_1_DragDrop:
  4326.     srcCtn = VRInfo( "SourceObject" )
  4327.     srcRec = VRInfo( "SourceRecord" )
  4328.     targetCtn = VRInfo( "TargetObject" )
  4329.     left = VRInfo( "Left" )
  4330.     bottom = VRInfo( "Bottom" )
  4331.  
  4332.     ok = VRMethod( targetCtn, "AddSharedRecord", srcRec )
  4333.     if ok then do
  4334.         ok = VRMethod( targetCtn, "SetRecordAttr", srcRec,,
  4335.                        "Left", left, "Bottom", bottom )
  4336.         ok = VRMethod( srcCtn, "RemoveRecord", srcRec )
  4337.     end
  4338.  
  4339. return
  4340.  
  4341. You can also use the AddRecord method to create a new record in the target 
  4342. container, then delete the source record. The disadvantage to this technique is 
  4343. that none of the detail field values are preserved. Also, it is up to the REXX 
  4344. programmer to preserve the record's Caption and Icon attributes. 
  4345.  
  4346.  
  4347. ΓòÉΓòÉΓòÉ 9.14.14. Direct editing of records ΓòÉΓòÉΓòÉ
  4348.  
  4349. A user can modify the records' caption text and field data by clicking mouse 
  4350. button 1 over the text while holding down the Alt key. This action opens an 
  4351. editing field over the record in which the user can type new data. A direct 
  4352. editing field can also be opened by invoking the OpenEdit method. 
  4353.  
  4354. The user finishes a direct editing operation by clicking on another record to 
  4355. accept the changes, or by cancelling the operation. Any of the following 
  4356. actions will cancel the operation and restore the record data to its previous 
  4357. value: 
  4358.  
  4359. o Press the Esc key 
  4360. o Drag the record being edited 
  4361. o Click on another record while holding the Alt key 
  4362. o Scroll the container 
  4363.  
  4364. Invoking the CloseEdit method will close the direct editing field without 
  4365. losing the changes. 
  4366.  
  4367. If the AutoEdit property is 1, the user can tab between fields while direct 
  4368. editing. This feature is available only in detail view. 
  4369.  
  4370. A BeginEdit event occurs when a direct editing operation starts. If AutoEdit is 
  4371. 0, the event occurs for each field being edited. When AutoEdit is 1, the event 
  4372. occurs only once for each record being edited. Similarly, the EndEdit event 
  4373. occurs when the direct editing operation finishes. If AutoEdit is 0, an EndEdit 
  4374. event occurs for each field. Otherwise, it occurs for the record as a whole. 
  4375.  
  4376. To prevent direct editing of the record's caption, set the record's ReadOnly 
  4377. attribute to 1. If the container's ReadOnly property is 1, no direct editing is 
  4378. allowed on any record, regardless of the record's ReadOnly attribute. In detail 
  4379. view, direct editing is also inhibited if the field's ReadOnly attribute is 1. 
  4380.  
  4381. Note:  Direct editing is supported for string fields only. You cannot direct 
  4382. edit a field of type Date, Icon, or Time. 
  4383.  
  4384.  
  4385. ΓòÉΓòÉΓòÉ 9.14.15. Checking if a record is in a container ΓòÉΓòÉΓòÉ
  4386.  
  4387. To check if a record is in a container, use the ValidateRecord method. The 
  4388. following sample code tests if the record whose handle is stored in record is 
  4389. currently in container CN_1: 
  4390.  
  4391. if( VRMethod( "CN_1", "ValidateRecord", record ) = 1 ) then do
  4392.     say "The record is in the container."
  4393. end
  4394.  
  4395.  
  4396. ΓòÉΓòÉΓòÉ 9.14.16. Using the container ContextMenu event ΓòÉΓòÉΓòÉ
  4397.  
  4398. When the user causes a ContextMenu event by clicking mouse button 2, it 
  4399. automatically sets the Source attribute for the records and the Source property 
  4400. for the container to indicate the records to which the ContextMenu event 
  4401. applies. If the user does not select a menu item from the pop-up menu, the 
  4402. source emphasis is removed automatically. If the user clicks on a menu item, it 
  4403. is up to the menu item Click routine to reset the Source emphasis. 
  4404.  
  4405. The container applies the source emphasis according to the following rules: 
  4406.  
  4407. o If the user clicks mouse button 2 on an unselected record, only that record 
  4408.   will have its Source attribute set to 1. 
  4409.  
  4410. o If the user clicks on a selected record, all selected records will have the 
  4411.   Source attribute set to 1. 
  4412.  
  4413. o If the user does not click on a record, the container's Source property is 
  4414.   set to 1. The Source attribute for all records is reset to 0. 
  4415.  
  4416. For an sample menu click routine, see Using pop-up menus with containers. 
  4417.  
  4418.  
  4419. ΓòÉΓòÉΓòÉ 9.14.17. Dragging and dropping records ΓòÉΓòÉΓòÉ
  4420.  
  4421. For a description of drag and drop operations in general, see the "Drag and 
  4422. drop operations" chapter. The information presented below describes the drag 
  4423. and drop support available to containers, which is similar (but not exactly the 
  4424. same) to the drag and drop support available to other objects. 
  4425.  
  4426. Overview 
  4427.  
  4428. Users can drag and drop container records in the same way that they drag and 
  4429. drop VX-REXX objects and Workplace Shell objects. In general, VX-REXX supports 
  4430. the following drag/drop operations: 
  4431.  
  4432. o Records can be dropped on any other object (including records in other 
  4433.   containers) in the same program. 
  4434.  
  4435. o Records can be dropped onto containers or records from other programs if the 
  4436.   records represent actual OS/2 files (they must have the Filename attribute 
  4437.   set). 
  4438.  
  4439. o Records can be dropped onto Workplace Shell objects or containers in other 
  4440.   programs if the records represent actual OS/2 files (they must have the 
  4441.   Filename attribute set). 
  4442.  
  4443. o Records can be dropped on the Workplace Shell Shredder and any Workplace 
  4444.   Shell printer object. 
  4445.  
  4446. o OS/2 files and other objects can be dropped on containers and records. 
  4447.  
  4448. The REXX program can prevent drag/drop operations in the following ways: 
  4449.  
  4450. o You can specify the types of things that can be dropped onto a given record 
  4451.   by setting the record's Target attribute. 
  4452.  
  4453. o You can specify the types of things that can be dropped onto a container by 
  4454.   setting the container's DragTarget property. 
  4455.  
  4456. o Records cannot be dropped onto a read only container. 
  4457.  
  4458. o The user cannot drag records that have the AllowDrag attribute set to 0. 
  4459.  
  4460. o Records in a container with the AllowDrag property set to 0 cannot be 
  4461.   dragged, regardless of the records' AllowDrag attribute setting. 
  4462.  
  4463. In all of the cases listed above, it is the responsibility of the REXX program 
  4464. to respond to container events to perform the action requested by the drop 
  4465. operation. For example, if the user drags a record from one container to 
  4466. another, the REXX program must add the record to the target container then 
  4467. delete it from the first container. 
  4468.  
  4469. Drag/drop operations 
  4470.  
  4471. When the user drops a record, there is an implied action associated with the 
  4472. drop. It is one of: Copy, Link, or Move. The default operation when dragging 
  4473. records between containers in the same VX-REXX program is Move. The user can 
  4474. change the operation by holding down the Shift and Ctrl keys while dragging, as 
  4475. outlined below: 
  4476.  
  4477. Copy                The Ctrl key was held down. The dragged icon appears 
  4478.                     partially transparent. 
  4479.  
  4480. Link                The Ctrl and Shift keys were held down. A line is drawn 
  4481.                     between the record and the mouse while dragging to indicate 
  4482.                     the link operation. 
  4483.  
  4484. Move                The Shift key was held down. The dragged icon is drawn 
  4485.                     normally. 
  4486.  
  4487. The REXX program can retrieve the operation type by passing Operation to VRInfo 
  4488. in the following events: DragDrop, DragFile, and MoveRecord. The REXX program 
  4489. can provide a default operation by invoking the StartDrag method from within a 
  4490. DragStart event. 
  4491.  
  4492. Describing eligible drag/drop sources 
  4493.  
  4494. You can program the container to define the types of objects that can be 
  4495. dropped onto it. The list of accepted objects is stored in the container's 
  4496. DragTarget property. By default, this property is set to All, meaning that 
  4497. container records, Workplace Shell files and other VX-REXX objects can be 
  4498. dropped onto the container. If you want only records to be dropped, set 
  4499. DragTarget to Records. If you do not want the user to drop anything on the 
  4500. container, set DragTarget to None. 
  4501.  
  4502. You can also restrict the types of objects that are dropped onto a given 
  4503. record. To do this, set the record's Target attribute using SetRecordAttr. 
  4504.  
  4505. Note that the container's DragTarget property applies only to the "white space" 
  4506. of the container, not the records it contains. 
  4507.  
  4508. Using the Source attribute in drag/drop operations 
  4509.  
  4510. The container automatically sets the Source attribute for dragged records. This 
  4511. forms a visual cue to the user which highlights the records that are about to 
  4512. be dragged. If the user drags an unselected record, then only that record will 
  4513. have the Source attribute set. (Another way of saying this is that the record 
  4514. has the Source emphasis.) If the user drags a selected record, then all 
  4515. selected records get the Source emphasis. Any records that are not involved in 
  4516. the drag/drop operation have the Source attribute reset to 0. 
  4517.  
  4518. When records are dropped onto a container, the target container receives a 
  4519. DragDrop event for each record that was dropped. It is then up to the DragDrop 
  4520. event to turn off the Source attribute for each dropped record. If it is more 
  4521. appropriate to process all dropped records at once rather than one at a time, 
  4522. the target can use the GetRecordList method to list all records in the source 
  4523. container that have the Source attribute turned on. The DragDrop event can then 
  4524. process all the records at once. 
  4525.  
  4526. It is up to the program to turn off the source attributes of dragged records. 
  4527.  
  4528. The following sample DragDrop event causes all records that are dropped onto 
  4529. its container to be deleted, just like the OS/2 Shredder. The routine processes 
  4530. all of the dropped records at once. Note that the target container will receive 
  4531. a DragDrop event for each dropped record. However, since we turn the Source 
  4532. attribute off for all of the dropped records when the first event occurs, 
  4533. nothing will happen in the remaining events. The other DragDrop events still 
  4534. occur, but the GetRecordList method will return an empty list of records. 
  4535.  
  4536. CN_1_DragDrop:
  4537.     container = VRInfo( "SourceObject" )
  4538.     call VRMethod container, "GetRecordList", "Source", "reclist."
  4539.     do i = 1 to reclist.0
  4540.         call VRMethod container, "SetRecordAttr", reclist.i, ,
  4541.                                  "Source", 0
  4542.         call VRMethod container, "RemoveRecord", reclist.i
  4543.     end
  4544. return
  4545.  
  4546. If you wanted to purge the remaining DragDrop events from the event queue, you 
  4547. could use the VRFlush function. 
  4548.  
  4549. Programming with the MoveRecord event 
  4550.  
  4551. The MoveRecord event occurs when the user drags a record to a new position 
  4552. within the same container. The event occurs if the user drags a record onto the 
  4553. container white space, or onto another record. If the record's Target attribute 
  4554. does not include records, no MoveRecord event will be generated. Similarly, if 
  4555. the container's DragTarget property does not include records, dropping a record 
  4556. on the container's white space will not generate an event. 
  4557.  
  4558. If the container is in a linear view (the View property is set to Name, Text, 
  4559. or Detail), and no MoveRecord event is defined, the dragged records will be 
  4560. automatically moved. If the container is not in a linear view, or if a 
  4561. MoveRecord event has been defined for the container, no reordering occurs; it 
  4562. is up to the REXX program to reorder the records by setting the Previous record 
  4563. attribute using the SetRecordAttr method. 
  4564.  
  4565. Suppose you wanted the drag and drop operation to reparent the dropped records, 
  4566. similar to dropping files into a folder in the Workplace Shell. The following 
  4567. MoveRecord event code does this by setting the Parent attribute of the dragged 
  4568. record to the target record. 
  4569.  
  4570. CN_1_MoveRecord:
  4571.     srcRec = VRInfo( "SourceRecord" )
  4572.     targetRec = VRInfo( "TargetRecord" )
  4573.     if( targetRec \= "" ) then do
  4574.         call VRMethod "CN_1", "SetRecordAttr", srcRec, ,
  4575.                       "Parent", targetRec
  4576.     end
  4577. return
  4578.  
  4579. The record reordering behavior for linear views is equivalent to the following 
  4580. code: 
  4581.  
  4582. CN_1_MoveRecord:
  4583.     srcRec = VRInfo( "SourceRecord" )
  4584.     targetRec = VRInfo( "TargetRecord" )
  4585.     if( targetRec = "" ) then do
  4586.         targetRec = "Last"
  4587.     end
  4588.     call VRMethod "CN_1", "SetRecordAttr", srcRec, ,
  4589.                   "Previous", targetRec
  4590. return
  4591.  
  4592. Note that for the above event routine, dropping a record on the container white 
  4593. space moves the record to the end of the list. 
  4594.  
  4595. A MoveRecord event is generated for each record that is moved. If you need the 
  4596. entire list of dragged records, you can get it by defining a DragStart event: 
  4597.  
  4598. CN_1_DragStart:
  4599.     call VRMethod "CN_1", "GetRecordList", "Source", "Globals.!RecList"
  4600.     call VRMethod "CN_1", "StartDrag"
  4601. return
  4602.  
  4603. The above code uses the GetRecordList method to get the list of records that 
  4604. are about to be dragged. The list is stored in the REXX variable 
  4605. Gloabls.!RecList. In the MoveRecord event, you can use the list to manipulate 
  4606. the dragged records. You cannot get the list of dragged records in the 
  4607. MoveRecord event because the container automatically turns off the Source 
  4608. attribute when records are dragged within the same container. Note that the 
  4609. Source attribute is left on when records are dragged from one container to 
  4610. another, or to the Workplace Shell. 
  4611.  
  4612. Programming with the DragDrop event 
  4613.  
  4614. The DragDrop event is generated when the user drops a record from another 
  4615. container or a Workplace Shell file into a container or one of its records. The 
  4616. target container receives the DragDrop event. 
  4617.  
  4618. The DragDrop event is similar to the MoveRecord event, but has the following 
  4619. differences: 
  4620.  
  4621. o A DragDrop event is generated if the items being dropped are not records from 
  4622.   the same container. Dragging and dropping records within a single container 
  4623.   causes a MoveRecord event, not a DragDrop event. 
  4624.  
  4625. o No automatic record reparenting or reordering occurs under any circumstance 
  4626.   when a DragDrop event occurs. 
  4627.  
  4628. It is the responsibility of the REXX program to take some appropriate action in 
  4629. response to a DragDrop event. 
  4630.  
  4631. The following sample event routine copies or moves a record from the source 
  4632. container to the target container. 
  4633.  
  4634. CN_1_DragDrop:
  4635.     /* Get information about the drag drop source and target
  4636.     */
  4637.     srcCtn = VRInfo( "SourceObject" )
  4638.     srcRec = VRInfo( "SourceRecord" )
  4639.     targetCtn = VRInfo( "TargetObject" )
  4640.     left = VRInfo( "Left" )
  4641.     bottom = VRInfo( "Bottom" )
  4642.     operation = VRInfo( "Operation" )
  4643.  
  4644.     /* Add the record to the target container
  4645.     */
  4646.     call VRMethod targetCtn, "AddSharedRecord", srcRec
  4647.     call VRMethod targetCtn, "SetRecordAttr", srcRec,,
  4648.                   "Left", left, "Bottom", bottom
  4649.  
  4650.     /* If moving the record, remove it from the source container
  4651.     */
  4652.     if( operation = "Move" ) then do
  4653.         call VRMethod srcCtn, "RemoveRecord", srcRec
  4654.     end
  4655. return
  4656.  
  4657.  
  4658. ΓòÉΓòÉΓòÉ 9.14.18. Interacting with the Workplace Shell ΓòÉΓòÉΓòÉ
  4659.  
  4660.  
  4661.  
  4662. Dropping files onto a container 
  4663.  
  4664. The user can drop Workplace Shell file icons onto containers or records. When 
  4665. this happens, a DragDrop event is generated. The REXX program must respond to 
  4666. this event in the same way as if a record had been dropped onto the container. 
  4667. The program can get the name of the file by calling VRInfo in the DragDrop 
  4668. routine. 
  4669.  
  4670. The following DragDrop event routine prints the names of files dropped onto it. 
  4671.  
  4672. CN_1_DragDrop:
  4673.     filename = VRInfo( "SourceFile" )
  4674.     if filename \= "" then do
  4675.         say "File" filename "was dropped onto me."
  4676.     end
  4677. return
  4678.  
  4679. You can program the container to accept only certain types of files by setting 
  4680. the DragTarget property of the container. By default, any file can be dropped. 
  4681. If you set the DragTarget property to a file mask (e.g. "*.TXT"), then only 
  4682. files whose names match the mask can be dropped on the container. 
  4683.  
  4684. You can also restrict the types of files that are dropped onto a given record. 
  4685. To do this, set the record's Target attribute using SetRecordAttr. 
  4686.  
  4687. Dropping records onto Workplace Shell objects 
  4688.  
  4689. The user can drag records onto Workplace Shell folders or applications as long 
  4690. as the records represent actual OS/2 files. To tell the container about the 
  4691. file a record represents, set the record's Filename attribute to the name of 
  4692. the file including path and drive information. The record icon will change to 
  4693. the one that would be shown in a Workplace Shell folder for that file. 
  4694.  
  4695. The following sample code adds a record to a container, then sets its Filename 
  4696. attribute to C:\CONFIG.SYS. At run time, the user can drop the record onto EPM 
  4697. to view the file. (EPM is the OS/2 Enhanced Editor, and is initially installed 
  4698. in the Productivity folder which is in the OS/2 System folder.) 
  4699.  
  4700. record = VRMethod( "CN_1", "AddRecord",,, "CONFIG.SYS" )
  4701. call VRMethod "CN_1", "SetRecordAttr", record, "Filename", ,
  4702.               "FileName", "C:\CONFIG.SYS"
  4703.  
  4704. When a record is dropped onto a Workplace Shell folder or application, the 
  4705. source container receives a DragFile event. If the REXX program does not define 
  4706. a DragFile event, and the target moves or deletes the file that record 
  4707. represents, then the record is automatically removed from the container. If a 
  4708. DragFile event is defined, it is up to the event routine to remove the record. 
  4709.  
  4710. The default container action is equivalent to the following DragFile event: 
  4711.  
  4712. CN_1_DragFile:
  4713.     record = VRInfo( "SourceRecord" )
  4714.     file = VRInfo( "SourceFile" )
  4715.  
  4716.     if( \VRFileExists( file ) ) then do
  4717.         call VRMethod "CN_1", "RemoveRecord", record
  4718.     end
  4719. return
  4720.  
  4721.  
  4722. Displaying file icons 
  4723.  
  4724. In an OS/2 folder, files are displayed with a certain icon. You set the icon 
  4725. for a record to the same icon that is displayed for a given file. To do this, 
  4726. set the Icon attribute to the name of the file with path and drive information. 
  4727.  
  4728. For example, the following code creates a record whose icon is the same for the 
  4729. OS/2 Chess program. Note that the record does not represent the file since the 
  4730. Filename attribute is not set. This means that the user cannot drag the record 
  4731. to Workplace Shell folders or applications. 
  4732.  
  4733. record = VRMethod( "CN_1", "AddRecord",,,"Chess",,
  4734.                    "C:\OS2\APPS\OS2CHESS.EXE" )
  4735.  
  4736. If you want to use a container to display a number of files, use the 
  4737. FillFromDir method to add records based on the contents of a directory. The 
  4738. method adds a record for each file that matches a file mask in the given 
  4739. directory. If no detail view fields have been defined, it creates the same ones 
  4740. that are in the detail view for Workplace Shell folders -- icon, name, size, 
  4741. date, and so on. The fields are created with symbolic names that correspond to 
  4742. the field headings: FileIcon, FileName, FileSize, FileWriteDate, FileWriteTime, 
  4743. FileAccessDate, FileAccessTime, FileCreateDate, FileCreateTime, and FileFlags. 
  4744. If you define a field with one of these names before calling the FillFromDir, 
  4745. the method will use your field instead of creating one. The method also sets 
  4746. the record Caption, Icon, and Filename attributes automatically. 
  4747.  
  4748. The following code fills a container with records for all the executable files 
  4749. in the "D:\VXREXX" directory: 
  4750.  
  4751. call VRMethod "CN_1", "FillFromDir",, "D:\VXREXX", "*"
  4752.  
  4753.  
  4754. Programming with the DragDiscard event 
  4755.  
  4756. If the user drops a record on a Workplace Shell Shredder object, the container 
  4757. to which the record belongs is sent a DragDiscard event. The container does not 
  4758. automatically delete the record; the event routine must do this. If no 
  4759. DragDiscard event is defined, then nothing happens. 
  4760.  
  4761. The following sample event routine deletes a record when it is dropped on the 
  4762. Shredder. 
  4763.  
  4764. CN_1_DragDiscard:
  4765.     record = VRInfo( "Record" )
  4766.     call VRMethod "CN_1", "RemoveRecord", record
  4767. return
  4768.  
  4769.  
  4770. Programming with the DragPrint event 
  4771.  
  4772. If the user drops a record on a Workplace Shell printer object, the container 
  4773. to which the record belongs is sent a DragPrint event. The container does not 
  4774. automatically print the record; the event routine must do this. If no DragPrint 
  4775. event is defined, then nothing happens. 
  4776.  
  4777.  
  4778. ΓòÉΓòÉΓòÉ 9.14.19. Programming with the DragStart event ΓòÉΓòÉΓòÉ
  4779.  
  4780. By default, when the user starts to drag a record (or records), the drag 
  4781. operation starts right away -- that is, the user sees the record move with the 
  4782. mouse pointer. Your program can get control between the time the user clicks 
  4783. mouse button 2 and the time the records are actually dragged by defining a 
  4784. DragStart event. 
  4785.  
  4786. If your program defines a DragStart event, it is up to your program to actually 
  4787. start the drag operation by invoking the StartDrag method. If this method is 
  4788. not used, the records will not be dragged. The default container action is 
  4789. equivalent to the following DragStart event: 
  4790.  
  4791. CN_1_DragStart:
  4792.     call VRMethod "CN_1", "StartDrag"
  4793. return
  4794.  
  4795. StartDrag only causes records with the Source emphasis to be dragged. The 
  4796. DragStart event can get the list of records that have the source emphasis using 
  4797. the GetRecordList method. It can then reset the Source attribute if the record 
  4798. should now be dragged, or it can set the Source attribute of some other record 
  4799. so that it will be dragged. All of the Source attribute manipulation must be 
  4800. done before invoking the StartDrag method. 
  4801.  
  4802. The DragStart event is also a convenient time to set the Filename attribute for 
  4803. the dragged records. Suppose that the container is full of records that 
  4804. represent information in a database. The intent is for the user to drag one of 
  4805. the icons to EPM in order to view the information. In order to drag a record to 
  4806. EPM, the record must represent an OS/2 file, that is, the Filename attribute 
  4807. must be set. Rather than build and update files for all of the records, you can 
  4808. create a file when the user drags the record. This approach is more efficient 
  4809. because files are created only for the records that the user wants to view. 
  4810.  
  4811. The following sample shows a DragStart event that creates a file for each 
  4812. dragged record, then sets the Filename attribute for the records. The files 
  4813. created in this example hold some dummy text; in a real program you would put 
  4814. more meaningful data. 
  4815.  
  4816. CN_1_DragStart:
  4817.     /*  Create a file for each record
  4818.     */
  4819.     call VRMethod "CN_1", "GetRecordList", "Source", "reclist."
  4820.     do i = 1 to reclist.0
  4821.         filename = "TMP" || i
  4822.         call Lineout filename, "Dummy text for record" i
  4823.         call VRMethod "CN_1", "SetRecordAttr", reclist.i, ,
  4824.                       "Filename", filename
  4825.     end
  4826.  
  4827.     /*  Start the drag operation
  4828.     */
  4829.     call VRMethod "CN_1", "StartDrag"
  4830. return
  4831.  
  4832.  
  4833. ΓòÉΓòÉΓòÉ 9.15. Sliders ΓòÉΓòÉΓòÉ
  4834.  
  4835. Figure 58  A slider
  4836.  
  4837. A Slider object is used to let the user select a value from a range of values. 
  4838. The slider also shows the current value relative to the entire range of values. 
  4839. The slider can also be used as a status display, to indicate progress during a 
  4840. long operation such as copying a large number of files. 
  4841.  
  4842. Interacting with a slider is much like interacting with a scroll bar. The user 
  4843. moves the slider arm by dragging it, or by clicking on the slider shaft or 
  4844. slider buttons. 
  4845.  
  4846.  
  4847. ΓòÉΓòÉΓòÉ 9.15.1. Setting up the slider ticks ΓòÉΓòÉΓòÉ
  4848.  
  4849. To specify the number of ticks on the slider, set the Ticks property to the 
  4850. number of ticks you want. Labels for the ticks are taken from the TickList 
  4851. property. If there are fewer ticks than labels in the TickList, then the rest 
  4852. of the labels are ignored. 
  4853.  
  4854. To leave a tick unlabeled, add an empty item in the tick list. For example, if 
  4855. you wanted to have 3 ticks where the first is labeled 0, the last is labeled 
  4856. 100, and the middle tick is unlabeled, you would set Ticks to 3 and TickList to 
  4857. ;0;;100. 
  4858.  
  4859.  
  4860. ΓòÉΓòÉΓòÉ 9.15.2. Setting and getting the slider value ΓòÉΓòÉΓòÉ
  4861.  
  4862. There are two properties that set the slider value: Percentile and TickIndex. 
  4863. Percentile sets the slider value as a percentage (in whole numbers) of the 
  4864. distance between the home position and the opposite end. TickIndex sets the 
  4865. slider to a given tick. You can set these properties at both design time and at 
  4866. run time. 
  4867.  
  4868. Percentile and TickIndex are updated as the user moves the slider. Percentile 
  4869. always indicates the slider value, in whole numbers, on a scale of 0 to 100. 
  4870. Getting the TickIndex value returns the number of the closest tick to the 
  4871. current slider position. You can get the value of these properties using VRGet. 
  4872.  
  4873.  
  4874. ΓòÉΓòÉΓòÉ 9.15.3. Using a slider as a progress indicator ΓòÉΓòÉΓòÉ
  4875.  
  4876. You can use a slider to indicate progress for some action. To do this, set the 
  4877. ReadOnly property to 0; this hides the slider arm. Then set RibbonStrip to 1; 
  4878. this causes the slider to fill in the slider shaft with the color specified by 
  4879. the RibbonColor property. 
  4880.  
  4881.  
  4882. ΓòÉΓòÉΓòÉ 9.15.4. Responding to the Track event ΓòÉΓòÉΓòÉ
  4883.  
  4884. If your application needs to perform some action as the user drags the slider 
  4885. arm, then do it in the Track event for the slider. 
  4886.  
  4887.  
  4888. ΓòÉΓòÉΓòÉ 9.16. Value sets ΓòÉΓòÉΓòÉ
  4889.  
  4890. Figure 59  A value set
  4891.  
  4892. ValueSet objects present you with a set of choices arranged in a grid, one of 
  4893. which is selected at all times. Value set items can be bitmaps, colors, icons, 
  4894. or text. 
  4895.  
  4896.  
  4897. ΓòÉΓòÉΓòÉ 9.16.1. Setting the number of rows and columns ΓòÉΓòÉΓòÉ
  4898.  
  4899. Set the Rows and Columns properties to configure the number of rows and columns 
  4900. that the value set displays. You must set the rows and columns at design time; 
  4901. you cannot set them at run time. 
  4902.  
  4903.  
  4904. ΓòÉΓòÉΓòÉ 9.16.2. Setting item types ΓòÉΓòÉΓòÉ
  4905.  
  4906. To set the types of all items at once, change the ItemType property. You can 
  4907. also set the types for a set of items using the SetAttributes method. 
  4908.  
  4909. You can set the ItemType at design time or at run time. 
  4910.  
  4911.  
  4912. ΓòÉΓòÉΓòÉ 9.16.3. Setting item values ΓòÉΓòÉΓòÉ
  4913.  
  4914. At design time, you can set the item values using the InitialList property. The 
  4915. syntax of each list item depends on the item type. See the ItemType section in 
  4916. the reference guide for a list of item types and allowable values. 
  4917.  
  4918. At run time, you can set item values using the SetAttributes method. 
  4919.  
  4920.  
  4921. ΓòÉΓòÉΓòÉ 9.16.4. Handling the Click event ΓòÉΓòÉΓòÉ
  4922.  
  4923. When a new value set item is selected, a Click event is generated. The index of 
  4924. the selected item is in the Selected property. 
  4925.  
  4926.  
  4927. ΓòÉΓòÉΓòÉ 9.17. Timers ΓòÉΓòÉΓòÉ
  4928.  
  4929. You can use Timer objects to generate events as settable intervals. While 
  4930. enabled, a timer will continuously post Trigger events at the interval set in 
  4931. the Delay property. 
  4932.  
  4933.  
  4934. ΓòÉΓòÉΓòÉ 9.17.1. Setting the delay interval ΓòÉΓòÉΓòÉ
  4935.  
  4936. To set the delay interval, set the Delay property to the number of milliseconds 
  4937. to wait before a Trigger event is posted. You can set this property at design 
  4938. time and at run time. 
  4939.  
  4940.  
  4941. ΓòÉΓòÉΓòÉ 9.17.2. Starting and stopping timers ΓòÉΓòÉΓòÉ
  4942.  
  4943. A timer is started and stopped by setting its Enabled property. Initially 
  4944. timers are disabled, meaning that they will not generate Trigger events. To 
  4945. start a timer, set the Enabled property to 1. To stop a timer, set Enabled to 
  4946. 0. If you set the Delay property while a timer is enabled, the previous delay 
  4947. is ignored and a Trigger event occurs once the new delay expires. 
  4948.  
  4949.  
  4950. ΓòÉΓòÉΓòÉ 9.17.3. Responding to  ΓòÉΓòÉΓòÉ
  4951.  
  4952. Trigger events 
  4953.  
  4954. Trigger events occur after the delay interval has elapsed, measured from when 
  4955. the delay was set or when the timer was enabled. Because the OS/2 system may be 
  4956. engaged in some modal or time critical activities when the delay expires, your 
  4957. program may not process the Trigger event until some time after the delay has 
  4958. elapsed. As a result, your program should not count Trigger events as a way to 
  4959. keep track of time. 
  4960.  
  4961. The following Trigger event routine changes the timer's Caption to the current 
  4962. time and date. 
  4963.  
  4964. Trigger:
  4965.     caption = Time("N") Date("N")
  4966.     call VRSet "TM_1", "Caption", caption
  4967. return
  4968.  
  4969.  
  4970. ΓòÉΓòÉΓòÉ 9.18. Dynamic Data Exchange (DDE) Client ΓòÉΓòÉΓòÉ
  4971.  
  4972. DDE (Dynamic Data Exchange) is an OS/2 facility that allows applications to 
  4973. exchange data. Two applications engage in a DDE conversation, with one 
  4974. application being the DDE client (the one requesting the data), and the other a 
  4975. DDE server (the one responding to requests). 
  4976.  
  4977. VX-REXX provides a DDE client, which allows your programs to talk to other 
  4978. applications, such as spreadsheets and word processors. It is possible, for 
  4979. example, to write a VX-REXX program that extracts data from a spreadsheet, then 
  4980. inserts that data into a word processing document. 
  4981.  
  4982. For more information on the DDE client object, see Dynamic Data Exchange 
  4983. client. 
  4984.  
  4985.  
  4986. ΓòÉΓòÉΓòÉ 9.19. The VX-REXX console ΓòÉΓòÉΓòÉ
  4987.  
  4988. VX-REXX includes a simple console window to which the output of say 
  4989. instructions and OS/2 commands is redirected. (I.e. output directed to the 
  4990. standard output devices STDOUT and STDERR is redirected to the VX-REXX 
  4991. console.) Although it handles most output the console is not intended to be 
  4992. equivalent to an OS/2 window or full-screen session. It does not handle special 
  4993. escape sequences of commands to position the cursor. 
  4994.  
  4995. There is only one console window object per program, and it is referred to by 
  4996. its name, Console. 
  4997.  
  4998.  
  4999. ΓòÉΓòÉΓòÉ 9.19.1. Turning off the console ΓòÉΓòÉΓòÉ
  5000.  
  5001. A VX-REXX program includes console support by default. The VRRedirectStdIO 
  5002. function is used to disable console support: 
  5003.  
  5004. call VRRedirectStdio "Off"
  5005.  
  5006. The console cannot be referred to if it is disabled. 
  5007.  
  5008. VRRedirectStdIO is also used to re-enable the console and/or to log its output 
  5009. to a file. If the console output is being generated by an OS/2 command, it may 
  5010. be more appropriate to prevent the command from writing to standard output 
  5011. rather than disabling the console window. For more information on redirecting 
  5012. the output from OS/2 commands see the chapter "Controlling other programs". 
  5013.  
  5014.  
  5015. ΓòÉΓòÉΓòÉ 9.19.2. Hiding, moving and clearing the console ΓòÉΓòÉΓòÉ
  5016.  
  5017. If console support is enabled, the console window can be moved or sized as you 
  5018. would any other object: 
  5019.  
  5020. call VRSet "Console", "Left", 2000, "Top", 1000
  5021. call VRSet "Console", "Width", 1500, "Height", 1000
  5022.  
  5023. To clear the console: 
  5024.  
  5025. call VRMethod "Console", "Clear"
  5026.  
  5027. The console is temporarily hidden by setting its Visible property: 
  5028.  
  5029. call VRSet "Console", "Visible", 0
  5030.  
  5031. Note, however, that the console will reappear as soon as a line of output is 
  5032. added. 
  5033.  
  5034.  
  5035. ΓòÉΓòÉΓòÉ 9.19.3. Removing the console from the OS/2 window list ΓòÉΓòÉΓòÉ
  5036.  
  5037. The console may be removed from the OS/2 window list by setting its 
  5038. WindowListTitle property: 
  5039.  
  5040. call VRSet "Console", "WindowListTitle", ""
  5041.  
  5042.  
  5043. ΓòÉΓòÉΓòÉ 9.19.4. Console input ΓòÉΓòÉΓòÉ
  5044.  
  5045. The console is also used for user input, but it must be made visible before the 
  5046. input is to occur. To do so, either set the Visible property to 1 or output a 
  5047. line of text using a say statement. 
  5048.  
  5049.  
  5050. ΓòÉΓòÉΓòÉ 10. Bitmaps, icons, and resources ΓòÉΓòÉΓòÉ
  5051.  
  5052. This chapter explains how to add bitmaps and icons to your project. 
  5053.  
  5054.  
  5055. ΓòÉΓòÉΓòÉ 10.1. Loading bitmap and icon files ΓòÉΓòÉΓòÉ
  5056.  
  5057. To display a bitmap file (.BMP) or icon file (.ICO) an object must support the 
  5058. PicturePath property. For bitmap files, PicturePath is the path of the bitmap 
  5059. to load, and must end in a .BMP extension. For example: 
  5060.  
  5061. call VRSet VRWindow(), "PicturePath", "D:\OS2\BITMAP\OS2LOGO.BMP"
  5062.  
  5063. For icon files, PicturePath is the path of the icon to load, which must end in 
  5064. a .ICO extension. For example: 
  5065.  
  5066. call VRSet "IPB_1", "PicturePath", "D:\OS2\MDOS\WINOS2\WINOS2.ICO"
  5067.  
  5068. The icon associated with a non-icon file (executable files, for example) may 
  5069. also be loaded: 
  5070.  
  5071. call VRSet "IPB_1", "PicturePath", "D:\OS2\E.EXE"
  5072.  
  5073. The icon associated with a file is determined by OS/2. You can associate an 
  5074. icon with a file by defining a .ICON extended attribute for the file or by 
  5075. placing a .ICO file with the same filename in the file's directory. You can 
  5076. also associate an icon with a Workplace Shell file by using the General page of 
  5077. the file's Settings notebook. 
  5078.  
  5079. The WindowIcon, Pointer, DefaultIcon and DragIcon properties are also used to 
  5080. load icons (and bitmaps in the case of DragIcon), using the same syntax as 
  5081. PicturePath. 
  5082.  
  5083.  
  5084. ΓòÉΓòÉΓòÉ 10.2. System icons and pointers ΓòÉΓòÉΓòÉ
  5085.  
  5086. OS/2 defines a set of system icons that your project can use by simply setting 
  5087. PicturePath (or any of the other picture properties) to one of the following 
  5088. values: 
  5089.  
  5090. Application         The OS/2 application icon. 
  5091.  
  5092. Information         The OS/2 information icon. 
  5093.  
  5094. Question            The OS/2 question icon. 
  5095.  
  5096. Error               The OS/2 error icon. 
  5097.  
  5098. Warning             The OS/2 warning icon. 
  5099.  
  5100. Illegal             The OS/2 illegal operation icon. 
  5101.  
  5102. File                An icon representing a single file. 
  5103.  
  5104. MultipleFiles       An icon representing multiple files. 
  5105.  
  5106. Folder              An icon representing a folder. 
  5107.  
  5108. Program             A smaller icon for representing applications. 
  5109.  
  5110. Arrow               The default pointer icon. 
  5111.  
  5112. Text                The I-beam pointer icon (for text editing). 
  5113.  
  5114. Wait                The watch icon (for long operations). 
  5115.  
  5116. Move                A four-headed arrow. 
  5117.  
  5118. SizeNWSE            Two arrows, pointing northwest and southeast. 
  5119.  
  5120. SizeNESW            Two arrows, pointing northeast and southwest. 
  5121.  
  5122. SizeWE              Two arrows, pointing west and east. 
  5123.  
  5124. SizeNS              Two arrows, pointing north and south. 
  5125.  
  5126.  
  5127. ΓòÉΓòÉΓòÉ 10.3. Loading bitmap and icon resources ΓòÉΓòÉΓòÉ
  5128.  
  5129. Bitmaps and icons can also be loaded from resources bound to an executable file 
  5130. (.EXE) or dynamic link library (.DLL). (A resource is binary data that has been 
  5131. appended to a file. A later section describes how to bind resources to your 
  5132. project).  To load the resource you need to know what kind it is (bitmap or 
  5133. icon), its resource number (an integer from 1 to 65000) and where it is located 
  5134. (in the executable or in a DLL). 
  5135.  
  5136. For a bitmap resource, set PicturePath to the following format: 
  5137.  
  5138. #resourceID[:DLLName]
  5139.  
  5140. For an icon resource, use the format: 
  5141.  
  5142. $resourceID[:DLLName]
  5143.  
  5144. In both formats resourceID is the resource number and DLLName is the name of a 
  5145. DLL (do not include path information -- the DLL must be in the LIBPATH). If 
  5146. DLLName is omitted, then the resource is assumed to be in the project's 
  5147. executable (.EXE) file. 
  5148.  
  5149. For example, to load bitmap with a resource number of 1899 from a DLL called 
  5150. JHUTT.DLL: 
  5151.  
  5152. #1899:JHUTT
  5153.  
  5154. To load an icon with a resource number of 100 from the project executable: 
  5155.  
  5156. $100
  5157.  
  5158. Resources can be used with any of the picture properties. 
  5159.  
  5160.  
  5161. ΓòÉΓòÉΓòÉ 10.4. Adding resources to your project ΓòÉΓòÉΓòÉ
  5162.  
  5163. Resources can be added to a project by using the VX-REXX resource editor and 
  5164. the OS/2 resource compiler. 
  5165.  
  5166.  
  5167. ΓòÉΓòÉΓòÉ 10.4.1. Using the resource editor ΓòÉΓòÉΓòÉ
  5168.  
  5169. The resources to be added to a project must be defined in a resource file (.RC) 
  5170. in the project directory. This file is then processed by the OS/2 resource 
  5171. compiler to generate a binary resource file (.RES) that is later used by 
  5172. VX-REXX when creating an executable file from the project. 
  5173.  
  5174. The VX-REXX resource editor is a simple text editor that allows you to edit a 
  5175. resource file. The resource file is a standard OS/2 resource file containing 
  5176. bitmap and icon definitions. A bitmap resource is defined as: 
  5177.  
  5178. bitmap id filepath
  5179.  
  5180. For example: 
  5181.  
  5182. bitmap 100 d:\os2\bitmap\os2logo.bmp
  5183.  
  5184. Icons are defined using a similar format: 
  5185.  
  5186. icon id filepath
  5187.  
  5188. For example: 
  5189.  
  5190. icon 342 d:\vxrexx\watcom2.ico
  5191.  
  5192. In either case, id is a number from 1 to 64000 that identifies the resource and 
  5193. filepath is the path of the bitmap or icon file. 
  5194.  
  5195. To run the VX-REXX resource editor, select the Open menu after clicking mouse 
  5196. button 2 on a window, or select the Resource editor item in the Project menu. 
  5197.  
  5198. The VX-REXX resource editor creates a file in the project's source directory, 
  5199. so it will not work on a project that was not created from a template and has 
  5200. never been saved. You must save such projects before running the resource 
  5201. editor. 
  5202.  
  5203. If you do not wish to edit the resource file directly, click mouse button 2 on 
  5204. the resource editor to invoke its pop-up menu and choose Insert resource to 
  5205. display a dialog that prompts you for the necessary information. You may also 
  5206. drag bitmap and icon files from the Workplace Shell and drop them on the 
  5207. resource editor. 
  5208.  
  5209. After making modifications, save the resource file to disk and compile it with 
  5210. the resource compiler by selecting Save and compile from the File menu. If 
  5211. errors occur, correct them and repeat the process. 
  5212.  
  5213.  
  5214. ΓòÉΓòÉΓòÉ 10.4.2. Resource binding ΓòÉΓòÉΓòÉ
  5215.  
  5216. Once a binary resource file (.RES) has been created in your project directory, 
  5217. VX-REXX will bind that file to your project when an executable is made. The 
  5218. resources will then be available to the executable when it is run, using the 
  5219. syntax described in the previous section. 
  5220.  
  5221. Resources are also available when testing a project using Run project. 
  5222.  
  5223. In both cases, VX-REXX displays a message box describing the resource binding 
  5224. process while it occurs. 
  5225.  
  5226. Resources are not available to your project when Debug project is used. 
  5227.  
  5228.  
  5229. ΓòÉΓòÉΓòÉ 10.4.3. Editing bitmaps and icons ΓòÉΓòÉΓòÉ
  5230.  
  5231. OS/2 includes an icon editor in the Productivity folder in the OS/2 System 
  5232. folder. (Or type iconedit at the OS/2 command prompt). This is the same editor 
  5233. that is used to edit Workplace Shell icons. 
  5234.  
  5235. Small bitmaps can also be edited using the icon editor. For larger bitmaps, you 
  5236. must use another application. One possibility is the Microsoft Windows Paint 
  5237. Brush application -- VX-REXX can load Windows bitmaps as well as OS/2 bitmaps. 
  5238.  
  5239.  
  5240. ΓòÉΓòÉΓòÉ 10.4.4. A note about icon formats ΓòÉΓòÉΓòÉ
  5241.  
  5242. An icon file or resource can contain icons for various screen resolutions and 
  5243. color palettes. At least one of these formats will be the "Independent Color 
  5244. Form" that will be used when there is no exact match for the screen resolution. 
  5245. However OS/2 will not display your bitmap in all cases unless you include at 
  5246. least two formats. The "8514 - 16 colors" is a good choice for the second 
  5247. format. 
  5248.  
  5249.  
  5250. ΓòÉΓòÉΓòÉ 10.4.5. The executable icon ΓòÉΓòÉΓòÉ
  5251.  
  5252. If your project's resources include at least one icon, the Workplace Shell will 
  5253. use the icon with the lowest resource number as the default icon when its 
  5254. executable is displayed in a folder or on the desktop. 
  5255.  
  5256.  
  5257. ΓòÉΓòÉΓòÉ 11. Drag and drop operations ΓòÉΓòÉΓòÉ
  5258.  
  5259. This chapter explains how to add drag and drop support to your project. Drag 
  5260. and drop operations are available on most objects. 
  5261.  
  5262.  
  5263. ΓòÉΓòÉΓòÉ 11.1. Drag and drop definitions ΓòÉΓòÉΓòÉ
  5264.  
  5265. Drag and drop is a form of direct manipulation where the user selects an 
  5266. object, drags it across the screen and drops it on another object. The drag 
  5267. operation is usually started by pressing mouse button 2 over an object, moving 
  5268. the mouse to drag the object, and then releasing mouse button 2 to drop the 
  5269. object. The Workplace Shell uses drag and drop operations extensively, and 
  5270. these capabilities are easily added to your own project. 
  5271.  
  5272. Before adding drag and drop support, it is important that you understand the 
  5273. terminology that will be used throughout this chapter. 
  5274.  
  5275.  
  5276. ΓòÉΓòÉΓòÉ 11.1.1. Basic terminology ΓòÉΓòÉΓòÉ
  5277.  
  5278. A drag item  is something being dragged. There is at least one drag item in 
  5279. every drag and drop operation, though there may be more than one. Each drag 
  5280. item represents a thing to be dragged -- an object in your program, or a record 
  5281. in a container, or a Workplace Shell object, or a file, or something else. 
  5282.  
  5283. A drag source  is something that allows a drag operation to start. The user 
  5284. presses mouse button 2 on the drag source to start a drag and drop operation. 
  5285. Most VX-REXX objects can act as drag sources through the use of the AllowDrag 
  5286. property. 
  5287.  
  5288. A drag target  is something that allows a drag item or items to be dropped on 
  5289. it. Not all drag items can be dropped on all drag targets -- the drag target 
  5290. chooses which are allowable. Most VX-REXX objects can act as drag targets 
  5291. through the use of the DragTarget property. 
  5292.  
  5293. The operation type  defines the drag and drop operation that is taking place. 
  5294. Drag items can be moved, copied or linked. The definition of each operation 
  5295. type depends on the drag source, the drag target and the format of the drag 
  5296. items. If the drag items, drag source and drag target are all Workplace Shell 
  5297. objects, a move operation relocates an object, a copy operation replicates the 
  5298. object, and a link operation shadows the object. Users can specify a particular 
  5299. operation by holding down the Ctrl and/or Shift keys. If no key is pressed, a 
  5300. default operation is chosen by the drag target. The visual appearance of drag 
  5301. items changes depending on the operation. 
  5302.  
  5303.  
  5304. ΓòÉΓòÉΓòÉ 11.2. Adding drag targets to your project ΓòÉΓòÉΓòÉ
  5305.  
  5306. Most VX-REXX objects are drag targets. The DragTarget property describes the 
  5307. kinds of drag items that can be dropped on an object. If a drag item is 
  5308. dropped, the drag target receives a DragDrop event. 
  5309.  
  5310. The user cannot drop drag items onto an object if those items do not match the 
  5311. criteria defined by the DragTarget property. Items can only be dropped if they 
  5312. match the DragTarget settings of the drag target and the drag target has a 
  5313. DragDrop event defined. 
  5314.  
  5315. An object can also explicitly refuse any drops by setting its DragTarget 
  5316. property to None. 
  5317.  
  5318.  
  5319. ΓòÉΓòÉΓòÉ 11.2.1. Files, records and objects ΓòÉΓòÉΓòÉ
  5320.  
  5321. The three most common settings for DragTarget are: 
  5322.  
  5323. Files="*"           Accepts all files, either from Workplace Shell objects 
  5324.                     corresponding to a file, or container records that have the 
  5325.                     Filename attribute set. One or more filemasks (using the 
  5326.                     usual OS/2 wildcard characters * and ?) can be specified, 
  5327.                     and only files which match those masks will be allowed to 
  5328.                     be dropped on the object. 
  5329.  
  5330.                     For example, use Files="*" to allow all files. Use 
  5331.                     Files="*.C","*.H" to allow all files ending in .C and .H 
  5332.                     extensions. 
  5333.  
  5334. Records             Accepts records dragged from a container in the same 
  5335.                     project. 
  5336.  
  5337. Objects             Accepts drag items generated by other objects in the same 
  5338.                     project. 
  5339.  
  5340. You can combine any or all three using semicolons. For example, 
  5341. Files="*"semi.Records accepts all files and all container records. The setting 
  5342. All is equivalent to Files="*";Records;Objects and is the default value for 
  5343. DragTarget. 
  5344.  
  5345. If the Files setting is specified, the Types setting may also be specified to 
  5346. allow only files with certain OS/2 file types to be dropped. For example, the 
  5347. setting Files="*";Types="Plain text","OS/2 Command File" only allows text and 
  5348. command files to be dropped. 
  5349.  
  5350.  
  5351. ΓòÉΓòÉΓòÉ 11.2.2. Default and supported operations ΓòÉΓòÉΓòÉ
  5352.  
  5353. The default operation in a drop is determined solely by the drag target. If not 
  5354. specified, Move is assumed to be the default operation. A different default 
  5355. operation (Copy or Link) may be specified in the DragTarget using the form 
  5356. Default=Link or Default=Copy. For example: 
  5357.  
  5358. Files="*.TXT";Default=Copy
  5359.  
  5360. The drag target may also limit the allowable operations using Operations: 
  5361.  
  5362. Records;Default=Copy;Operations=Move,Copy
  5363.  
  5364. All operations are supported by default. 
  5365.  
  5366.  
  5367. ΓòÉΓòÉΓòÉ 11.2.3. Other formats ΓòÉΓòÉΓòÉ
  5368.  
  5369. If none of the formats listed above are sufficient, you may specify the exact 
  5370. OS/2 rendering formats the target will accept using the Formats keyword. When 
  5371. specifying a rendering format, you may not specify Files, Records or Objects. 
  5372. If you wish to handle objects of these types, you must ensure that your Formats 
  5373. string specifies the appropriate underlying rendering formats. 
  5374.  
  5375. The rendering format describes how the drag source and the drag target are to 
  5376. exchange the data that the drag item represents. The rendering format is 
  5377. actually a string of pairs of data. Each pair describes a mechanism for 
  5378. exchanging data and a format  to use with that mechanism. The DRM_OS2FILE is 
  5379. the most common mechanism, representing an OS/2 file. VX-REXX also defines a 
  5380. DRM_VXREXX_OBJECT mechanism. Drag items with the DRM_PRINT and DRM_DISCARD 
  5381. mechanisms may be dropped on Workplace Shell printer and shredder objects, 
  5382. respectively. 
  5383.  
  5384. The syntax for rendering mechanisms and formats is either a list of pairs: 
  5385.  
  5386. <mech1,format1>,<mech2,format2>,...
  5387.  
  5388. or a cross-product: 
  5389.  
  5390. (mech1,mech2,...)x(format1,format2,...)
  5391.  
  5392. For example, a Workplace Shell folder is represented as: 
  5393.  
  5394. <DRM_OS2FILE,DRF_UNKNOWN>,<DRM_OBJECT,DRF_OBJECT>
  5395.  
  5396. To accept any and all Workplace Shell objects, even those that do not represent 
  5397. files, you may specify the string: 
  5398.  
  5399. Formats=(DRM_OS2FILE,DRM_OBJECT)x(DRF_UNKNOWN)
  5400.  
  5401. The default rendering format for VX-REXX objects other than containers is: 
  5402.  
  5403. (DRM_VXREXX_OBJECT,DRM_PRINT,DRM_DISCARD)x(DRF_UNKNOWN)
  5404.  
  5405. More detailed information on types, mechanisms and formats can be found in the 
  5406. programming guides for OS/2. 
  5407.  
  5408.  
  5409. ΓòÉΓòÉΓòÉ 11.2.4. Passing the drop to the parent object ΓòÉΓòÉΓòÉ
  5410.  
  5411. If there are several objects that you wish to designate as drag targets, it may 
  5412. be more convenient to set their DragTarget properties to Parent instead. The 
  5413. parent object will then control and receive the result of any drag and drop 
  5414. operations. You must also define the DragTarget property and DragDrop event on 
  5415. the parent object. The internal name of the actual target object will be 
  5416. available in the DragDrop event. 
  5417.  
  5418.  
  5419. ΓòÉΓòÉΓòÉ 11.2.5. Container restrictions ΓòÉΓòÉΓòÉ
  5420.  
  5421. Each record in a Container object is a drag target. You may further restrict 
  5422. the types of drag items that may be dropped on a record by setting its Target 
  5423. attribute using SetRecordAttr. The syntax for Target is similar to that of 
  5424. DragTarget except that the Formats, Parent, Default and Operations values may 
  5425. not be specified. If the Target attribute of a record is not set, it defaults 
  5426. to All. 
  5427.  
  5428.  
  5429. ΓòÉΓòÉΓòÉ 11.3. Handling drops ΓòÉΓòÉΓòÉ
  5430.  
  5431. Each drag item that is dropped on an object is really a request to perform an 
  5432. action. It is the responsibility of your program to recognize, interpret and 
  5433. act on the request. There is one exception to this rule:  when a record is 
  5434. dragged to a new position in the same container, the record is automatically 
  5435. repositioned unless a MoveRecord event has been defined. 
  5436.  
  5437.  
  5438. ΓòÉΓòÉΓòÉ 11.3.1. Programming with the DragDrop event ΓòÉΓòÉΓòÉ
  5439.  
  5440. When a DragDrop event occurs, use VRInfo to retrieve information about the drag 
  5441. item that was dropped. See the online VX-REXX Reference section for DragDrop 
  5442. for a complete list of available information. Here are some tips: 
  5443.  
  5444. o SourceObject identifies the object in your program that was the drag source. 
  5445.   If it is null, then the drag source was not part of your project. 
  5446.  
  5447. o Object identifies the object processing the DragDrop event. TargetObject 
  5448.   identifies the object underneath the drop point. They are usually the same 
  5449.   unless the Parent setting for DragTarget is used. 
  5450.  
  5451. o If the drag source is a container in your project, then SourceRecord 
  5452.   identifies the record that is being dragged. 
  5453.  
  5454. o If the drag source is a ListBox, ComboBox or ValueSet in your project, then 
  5455.   SourceIndex identifies the item being dragged. 
  5456.  
  5457. o If the drag target is a Container, then TargetRecord identifies the record 
  5458.   underneath the drop point. 
  5459.  
  5460. o If the drag target is a ListBox, ComboBox or ValueSet, then TargetIndex 
  5461.   identifies the item underneath the drop point. 
  5462.  
  5463. By carefully choosing the values for DragTarget, programming the DragDrop event 
  5464. is quite simple. For example, you can add the ability to drop files onto a 
  5465. multiline entry field by setting DragTarget to Files and using the following 
  5466. DragDrop event routine: 
  5467.  
  5468. MLE_1_DragDrop:
  5469.     file = VRInfo( "SourceFile" )
  5470.     if( VRFileExists( file ) ) then do
  5471.         contents = CharIn( file, 1, Chars( file ) )
  5472.         call Stream file, "C", "Close"
  5473.         call VRMethod "MLE_1", "Insert", contents
  5474.     end
  5475. return
  5476.  
  5477. The Insert method is used to insert the text of the file into the MLE. 
  5478.  
  5479. See the section on dragging and dropping records in the "Using objects" chapter 
  5480. for information on using the DragDrop event with Container objects. 
  5481.  
  5482.  
  5483. ΓòÉΓòÉΓòÉ 11.3.2. Programming with the MoveRecord event ΓòÉΓòÉΓòÉ
  5484.  
  5485. The MoveRecord event occurs when the user drags a record to a new position 
  5486. within the same container. For more information on the MoveRecord, see the 
  5487. "Using objects" chapter. 
  5488.  
  5489.  
  5490. ΓòÉΓòÉΓòÉ 11.4. Adding drag sources to your project ΓòÉΓòÉΓòÉ
  5491.  
  5492. Most VX-REXX objects can also act as drag sources by setting the AllowDrag 
  5493. property to 1. Then when the user clicks mouse button 2 on the object and moves 
  5494. the mouse, a DragStart event occurs. If you have defined a DragStart event, the 
  5495. drag operation will start when you call the StartDrag method. If no DragStart 
  5496. event is defined, the drag operation will start immediately. 
  5497.  
  5498. If a Container object is to be a drag source, please refer to the "Using 
  5499. objects" chapter. The remainder of this section applies only to objects other 
  5500. than the container. 
  5501.  
  5502.  
  5503. ΓòÉΓòÉΓòÉ 11.4.1. The StartDrag method ΓòÉΓòÉΓòÉ
  5504.  
  5505. For objects other than containers, the StartDrag method can be used to fully 
  5506. describe a drag item and to start the drag operation. Although the StartDrag 
  5507. method has many arguments which allow you to specify details such as the 
  5508. default operation, drag icon, and rendering format, you will usually be able to 
  5509. use the default values. 
  5510.  
  5511. The StartDrag method returns a value which indicates whether or not the drag 
  5512. item was dropped on a drag target, and if so identifies the target. 
  5513.  
  5514. For full information on the StartDrag method, see the online VXΓêÖREXX Reference. 
  5515.  
  5516.  
  5517. ΓòÉΓòÉΓòÉ 11.4.2. Dragging objects ΓòÉΓòÉΓòÉ
  5518.  
  5519. Objects in your project can be dragged onto other objects in your project with 
  5520. very little work. The objects that are to act as drag targets should include 
  5521. Objects in their DragTarget property and define an appropriate DragDrop event. 
  5522. The objects that are to be drag sources need only set AllowDrag to 1. 
  5523.  
  5524. If you specify the rendering format when calling the StartDrag method, you must 
  5525. include the pair: 
  5526.  
  5527. <DRM_VXREXX_OBJECT,DRF_UNKNOWN>
  5528.  
  5529. If this format is not specified, the drag targets will not recognize the drag 
  5530. item as a VX-REXX object from the same project. 
  5531.  
  5532.  
  5533. ΓòÉΓòÉΓòÉ 11.4.3. Dragging files ΓòÉΓòÉΓòÉ
  5534.  
  5535. A drag item that represents a file can be dragged onto drag targets in other 
  5536. applications and on the Workplace Shell. The StartDrag method must be invoked 
  5537. with the following values: 
  5538.  
  5539. o The container name argument (not to be confused with a container object) must 
  5540.   be set to the drive and directory containing the file, including the trailing 
  5541.   backslash. For example, "D:\OS2\BITMAP\". 
  5542.  
  5543. o The source name must be set to the physical name of the file. (The physical 
  5544.   name of a file may be different than its folder name on systems that do not 
  5545.   support long filenames). For example, "OS2LOGO.BMP". 
  5546.  
  5547. o The target name must be set to the suggested name of the file. (On systems 
  5548.   that do not support long filenames at the file level, this should be the long 
  5549.   version of the filename. On other systems it is usually the same as the 
  5550.   source name).  For example, "OS2LOGO.BMP". 
  5551.  
  5552. o The rendering format must include the DRM_OS2FILE mechanism. For example, 
  5553.   <DRM_OS2FILE,DRF_TEXT>. Including DRM_PRINT and DRM_DISCARD allows the file 
  5554.   to be dropped on printer and shredder objects. 
  5555.  
  5556. o The type describes the type of the file. (If type is unknown or not 
  5557.   important, use "Unknown"). For example, "Plain Text". 
  5558.  
  5559. Here is an example: 
  5560.  
  5561. PB_1_DragStart:
  5562.     call VRMethod "PB_1", "StartDrag", "Move", "File", ,
  5563.         "<DRM_OS2FILE,DRF_BITMAP>", "Bitmap", ,
  5564.         "D:\OS2\BITMAP\", "OS2LOGO.BMP", "OS2LOGO.BMP"
  5565. return
  5566.  
  5567. What happens to the file after it has been dropped depends on the drag target. 
  5568. The return value from the StartDrag method lets you know if the drag item was 
  5569. dropped or the drag operation was cancelled. If a drop occurred, it is the drag 
  5570. target's responsibility to handle the file. 
  5571.  
  5572.  
  5573. ΓòÉΓòÉΓòÉ 11.4.4. Dragging to the shredder and printer ΓòÉΓòÉΓòÉ
  5574.  
  5575. Drag items may be dropped on the Workplace Shell shredder object if the 
  5576. DRM_DISCARD rendering format is used, and on Workplace Shell printer objects if 
  5577. the DRM_PRINT rendering format is used. Unlike other drag targets, dropping a 
  5578. drag item on these objects does not generate a DragDrop event. A DragDiscard 
  5579. event occurs if an item is dropped on the shredder and a DragPrint event occurs 
  5580. if an item is dropped on a printer object. 
  5581.  
  5582. Dropping an item on the shredder or a printer object only results in a 
  5583. notification being sent to your project. You are responsible for doing any 
  5584. actual discarding or printing using the information provided in the DragDiscard 
  5585. and DragPrint events. 
  5586.  
  5587.  
  5588. ΓòÉΓòÉΓòÉ 12. Adding menus to a program ΓòÉΓòÉΓòÉ
  5589.  
  5590. Many applications have menus from which you can choose options or actions. For 
  5591. example, you have used the Tools menu in VX-REXX to choose objects and the 
  5592. Project menu to save a project. This chapter shows you how to add a menu to a 
  5593. window using the VX-REXX menu editor. 
  5594.  
  5595.  
  5596. ΓòÉΓòÉΓòÉ 12.1. Types of menus ΓòÉΓòÉΓòÉ
  5597.  
  5598.  
  5599. ΓòÉΓòÉΓòÉ 12.1.1. Menu bar and pull-down menus ΓòÉΓòÉΓòÉ
  5600.  
  5601. Typical application windows have a menu bar which contains one or more 
  5602. pull-down menus. The menu bar is displayed immediately below the window title 
  5603. bar. For example, Figure 60 shows the VX-REXX menu bar. 
  5604.  
  5605. Figure 60  VX-REXX menu bar
  5606.  
  5607. Pull-down menus such as Help are common to many applications. Other pull-down 
  5608. menus such as Tools and Run in VX-REXX are application specific. 
  5609.  
  5610. To open a pull-down menu, click on the menu name. This drops down a list of 
  5611. menu items. For example, if you click on the VX-REXX Project menu, the menu 
  5612. shown in  Figure 61 appears. 
  5613.  
  5614. Figure 61  VX-REXX Project menu
  5615.  
  5616. An underlined letter in a menu name or menu item is called a mnemonic. It is a 
  5617. the key that can be pressed to choose the menu or menu item instead of using 
  5618. the mouse. To choose a menu using a mnemonic you must first activate the menu 
  5619. bar by pressing the Alt key. To use a mnemonic to choose a menu item you must 
  5620. first open the menu that contains the item. 
  5621.  
  5622. A key called an accelerator may be shown to the right of a menu item. An 
  5623. accelerator is similar to a mnemonic in that it allows the user to press a key 
  5624. instead of clicking on the menu item. It is different in that the menu does not 
  5625. have to be open for the accelerator to work. This can save a lot of mouse 
  5626. clicking for users familiar with an application. 
  5627.  
  5628. The horizontal lines are separator bars, and are used to group choices to make 
  5629. menus easier to read. Choosing a separator does not result in any action. 
  5630.  
  5631. Some items in a menu perform an action immediately when chosen; for example, 
  5632. Save saves the current project. By convention, a menu item which contains an 
  5633. ellipsis (...), such as Save as..., indicates that a dialog will appear when 
  5634. the item is chosen, instead of an immediate action. 
  5635.  
  5636.  
  5637. ΓòÉΓòÉΓòÉ 12.1.2. Pop-up or context menus ΓòÉΓòÉΓòÉ
  5638.  
  5639. Pop-up menus (also called context menus) are similar to pull-down menus except 
  5640. that they are not attached to a menu bar. Pop-up menus can be positioned 
  5641. anywhere on a window. Usually pop-up menus are associated with a specific 
  5642. object such as a record in a container, and are displayed when you click on the 
  5643. object with mouse button 2 or when you press Shift+F10 when the object has the 
  5644. focus. 
  5645.  
  5646. Figure 62 shows a pop-up menu. 
  5647.  
  5648. Figure 62  A pop-up menu
  5649.  
  5650.  
  5651. ΓòÉΓòÉΓòÉ 12.1.3. Cascaded menus ΓòÉΓòÉΓòÉ
  5652.  
  5653. A menu item that contains an arrow pointing to the right indicates that a 
  5654. cascaded menu will drop down when the item is chosen. The cascaded menu is 
  5655. displayed beside the chosen item as in the sample menu shown in  Figure 63. 
  5656.  
  5657. Figure 63  Cascaded menu
  5658.  
  5659. A cascaded menu is used to reduce the length of a menu by grouping related 
  5660. choices. Although you can display up to 5 levels of cascaded menus, using more 
  5661. than 3 levels will make the menus difficult to use. 
  5662.  
  5663. If the arrow in a menu item is two dimensional, then the menu is an 
  5664. unconditional cascaded menu. This means that the menu automatically becomes 
  5665. visible when the item is selected. If the arrow is three dimensional, then the 
  5666. menu is a conditional cascaded menu. For these menu items, the cascaded menu 
  5667. does not appear automatically. The three dimensional button indicates that one 
  5668. of the cascaded menu items is preselected. Choosing the menu item with the 
  5669. arrow is the same as choosing the preselected item. The user can display a 
  5670. conditional cascaded menu by clicking on the arrow button. 
  5671.  
  5672.  Figure 64 shows a conditional cascaded menu after the arrow button has been 
  5673. clicked. The menu item General help has been preselected, as indicated by the 
  5674. check mark. 
  5675.  
  5676. Figure 64  Conditional cascaded menu
  5677.  
  5678.  
  5679. ΓòÉΓòÉΓòÉ 12.2. Menu properties ΓòÉΓòÉΓòÉ
  5680.  
  5681. In VX-REXX, a menu is made of objects. The menu bar itself is a MenuBar object. 
  5682. It contains Menu objects which in turn contain MenuItem objects and possibly 
  5683. other Menu objects (in cascaded menus). At design time, menus are created and 
  5684. modified using a menu editor, which is described later in this chapter. At run 
  5685. time the properties of the menu objects, described below, can be changed using 
  5686. the VRSet and VRGet functions. This is also described later in this chapter. 
  5687.  
  5688. Accelerator         The Accelerator property is a string value which represents 
  5689.                     the keyboard equivalent for a given menu item. VX-REXX has 
  5690.                     many strings to represent special keys, such as {Alt} for 
  5691.                     Alt, and {Ctrl} for Ctrl. A complete list of these key 
  5692.                     strings is available in the description of the KeyString 
  5693.                     property in the online VXΓêÖREXX Reference. To change 
  5694.                     accelerators at run time, change the Accelerator property 
  5695.                     and then invoke the InstallAccelerators method. 
  5696.  
  5697. Caption             The Caption property is the text that appears on the menu 
  5698.                     bar or within a menu. The position of items on a menu bar 
  5699.                     and the width of menus is automatically adjusted to fit the 
  5700.                     captions. The order of items in a menu bar or within a menu 
  5701.                     is controlled by the order in which the items are created. 
  5702.                     This is managed for you by the menu editor. 
  5703.  
  5704.                     To define a character in a caption as a mnemonic, precede 
  5705.                     the character with a tilde (~). To create a menu separator, 
  5706.                     set the caption to a single hyphen (-). 
  5707.  
  5708. Checked             The Checked property is used to indicate that an option is 
  5709.                     in effect. A menu item that is checked has a check mark 
  5710.                     displayed beside it when the menu is dropped down. The 
  5711.                     values of both the enabled and checked properties can be 
  5712.                     queried and changed at run time. 
  5713.  
  5714. DefaultItem         The DefaultItem is used to indicate the default selection 
  5715.                     for a conditional cascaded menu. The default item is 
  5716.                     automatically checked. 
  5717.  
  5718. Enabled             The Enabled property controls whether the menu item can be 
  5719.                     chosen when the application is run. Menu items are enabled 
  5720.                     by default. You may want to disable a menu item to prevent 
  5721.                     an action until another action is  performed. A disabled 
  5722.                     menu item is dimmed as a visual cue that its action cannot 
  5723.                     be chosen. 
  5724.  
  5725. HelpTag, HelpText, HintText You can provide help for your menu items as you can 
  5726.                     for most objects. The HelpTag, HelpText, and HintText 
  5727.                     properties are all editable from within the menu editor. 
  5728.  
  5729. Name                The Name property can be used to refer to a menu or menu 
  5730.                     item from a routine. A default name will be generated when 
  5731.                     you create each item. You can change the default name to 
  5732.                     make your program more readable. 
  5733.  
  5734. Visible             Menu objects can be made invisible by setting their Visible 
  5735.                     property to 0. You may want to do this to hide a menu which 
  5736.                     is only used as a pop-up menu. 
  5737.  
  5738.  
  5739. ΓòÉΓòÉΓòÉ 12.3. Menu editor ΓòÉΓòÉΓòÉ
  5740.  
  5741. You create menus in VX-REXX using the menu editor. To open the editor, display 
  5742. a window's pop-up menu, select Open... and choose Menu editor. The menu editor 
  5743. is shown in  Figure 65. 
  5744.  
  5745. Figure 65  Menu editor
  5746.  
  5747. The entry fields and check boxes are used to create the menus and set the 
  5748. properties. The Change, Insert and Delete push buttons modify, add or remove 
  5749. items from the menu structure displayed in the list box. The four arrow push 
  5750. buttons let you move the order and level of menu items displayed in the Menu 
  5751. Layout list box. The Edit event push button opens the edit window so that you 
  5752. can add code to a menu item. The Close button saves the changes to your project 
  5753. window and closes the menu editor. 
  5754.  
  5755. Pull-down menus, pop-up menus, menu items, and cascaded menus are all created 
  5756. using the menu editor. You create each one by entering a caption and choosing a 
  5757. level. For example, the caption of an item created at level 1 is the name of a 
  5758. drop-down menu that will appear in the menu bar. The items in the drop down 
  5759. menu will be the items added at level 2 underneath the level 1 item. 
  5760.  
  5761. The following sections show, by example, how to use the menu editor. 
  5762.  
  5763.  
  5764. ΓòÉΓòÉΓòÉ 12.4. Creating a menu ΓòÉΓòÉΓòÉ
  5765.  
  5766. This section describes how to create the sample drop-down menu Options shown in 
  5767. Figure 66. 
  5768.  
  5769. Figure 66  Options menu
  5770.  
  5771. The sample menu contains commands to change the caption and color of a push 
  5772. button. The menu has three items: Set caption..., Set color and Reset default. 
  5773. The ellipsis (...) following Set caption indicates that a dialog is displayed 
  5774. when you choose this item. The arrow beside Set color indicates that a cascaded 
  5775. menu appears when this item is chosen. When the user chooses Reset default an 
  5776. action is immediately run; in this case the push button's caption and color are 
  5777. reset to the default values. 
  5778.  
  5779. To create this menu: 
  5780.  
  5781.  1. Display the window's pop-up menu. 
  5782.  
  5783.  2. Choose Menu editor. 
  5784.  
  5785.  3. Type ~Options in the Caption entry field. The tilde character (~) signifies 
  5786.     that when the menu is displayed, the character which follows will be 
  5787.     underlined. Pressing that key is the keyboard equivalent to clicking on the 
  5788.     item to choose it. 
  5789.  
  5790.  4. Move to the Name entry field and type MenuOptions. You can enter any value 
  5791.     for the name, but choosing a name related to its use makes it easier to 
  5792.     remember and makes the code more readable. If you do not enter a name, a 
  5793.     default name will be generated when it is inserted in the menu structure. 
  5794.  
  5795.  5. Press Enter or click on Change to add it to the list box with default 
  5796.     values for all other properties. When it is added to the list box, the 
  5797.     caption and name fields are cleared and a new blank entry is added to the 
  5798.     end of the list in the list box. 
  5799.  
  5800. By default the menu is added at level 1 which means its caption will appear on 
  5801. the window's menu bar. Also, it is enabled and is not checked by default. 
  5802.  
  5803. The next steps add the items to the drop-down menu. They will be entered at 
  5804. level 2. The three items are Set caption, Set color and Reset default. A 
  5805. separator line is to be included between Set color and Reset default. 
  5806.  
  5807.  1. Type Set ~caption... in the Caption entry field. 
  5808.  
  5809.  2. Move to the Name entry field and type MenuOptionsCaption. 
  5810.  
  5811.  3. Move to the Level entry field and replace the current value with 2. 
  5812.  
  5813.  4. Move to the Accelerator field, and type {Ctrl}C. This accelerator string 
  5814.     means that the event routine associated with clicking on the Set caption 
  5815.     menu item can be executed even when the Options menu is not opened by 
  5816.     pressing the Ctrl key, and the letter C. 
  5817.  
  5818.  5. Press Enter or click on Change. The menu item is added to the list box. The 
  5819.     item will be indented below the first item to visually denote its level. 
  5820.  
  5821.  6. Type Set co~lor in the Caption entry field. Because the key "c" is the 
  5822.     mnemonic key for Set caption, a different key must be selected for Set 
  5823.     color. In this case the letter "l". 
  5824.  
  5825.  7. Press Enter or click on Change. No Name property was entered so a default 
  5826.     name will be generated. The generated name will be "Menu" concatenated with 
  5827.     a number to create a unique name (e.g. Menu3). The default name is 
  5828.     satisfactory because no click event will be associated with this menu item. 
  5829.     When the item is clicked a cascaded menu appears. 
  5830.  
  5831.  8. Type - (hyphen) in the Caption entry field. A hyphen adds a separator 
  5832.     between menu items. No Name property is set because the item cannot be 
  5833.     manipulated. 
  5834.  
  5835.  9. Press Enter or click on Change. 
  5836.  
  5837. 10. Repeat steps 1 through 4 setting the caption to ~Reset default, the name to 
  5838.     MenuOptionsReset, and the accelerator to {Ctrl}R. 
  5839.  
  5840. The menu editor window should look like Figure 67. 
  5841.  
  5842. Figure 67  Level 1 and 2 menu items
  5843.  
  5844. To complete the menu you need to add a cascaded menu for the menu item Set 
  5845. color. It contains a list of colors from which you can choose one. The items in 
  5846. the menu will be at level 3 and are inserted between Set color and the 
  5847. separator. Items are inserted before the item currently selected in the list 
  5848. box. 
  5849.  
  5850. To add the Set color menu: 
  5851.  
  5852.  1. Click on the separator line (hyphen) in the list box. The Caption entry 
  5853.     field will contain a "-". You will add the level 3 items above this item. 
  5854.  
  5855.  2. Replace the caption with ~Green. 
  5856.  
  5857.  3. Move to the Name entry field and replace the name with MenuOptionsGreen. 
  5858.  
  5859.  4. Move to the Level entry field and replace the value with 3. 
  5860.  
  5861.  5. Click Insert. A new entry will be added to the list box. This entry will be 
  5862.     identical to the entry that was selected when the Insert button was 
  5863.     pressed. 
  5864.  
  5865.  6. Repeat steps 2 through 5 for the colors Red and Yellow adding a ~ at the 
  5866.     beginning of each color name and adding the appropriate name entry. 
  5867.  
  5868. When all of the colors have been added the menu structure is complete. Because 
  5869. Set color is followed by level 3 menu items, an arrow will automatically be 
  5870. displayed beside its caption when the application is run. 
  5871.  
  5872. As yet, none of the menu items perform any action. The next section shows you 
  5873. how to add code to the menu items. 
  5874.  
  5875.  
  5876. ΓòÉΓòÉΓòÉ 12.5. Adding code to menu items ΓòÉΓòÉΓòÉ
  5877.  
  5878. Code is attached to objects to handle events. The Click event is the only event 
  5879. available for a menu item. 
  5880.  
  5881. You add code to menu items in the same way as you add code to objects except 
  5882. that you open the section editor from the menu editor. Instead of selecting an 
  5883. object in a window, you select a menu item from the list box in the menu 
  5884. editor. To edit code for that item's Click event, press the Edit event button, 
  5885. or double click on the menu item. The editor will contain the event routine for 
  5886. the selected item. You can then edit the event routine. 
  5887.  
  5888. For example, to add code for the Reset default item: 
  5889.  
  5890.  1. Select Reset default from the list. 
  5891.  
  5892.  2. Click on Edit event. The section editor is opened as in Figure 68. 
  5893.  
  5894.         Figure 68  Edit a menu event
  5895.  
  5896. The section name is generated from the menu item name, MenuOptionsReset, and 
  5897. the event name, Click. 
  5898.  
  5899. You add the code for the event between the section name and the return 
  5900. statement. For example, the code for this menu item sets the caption on the 
  5901. push button with the name PB_PushMe to the default value Push Me! and the color 
  5902. of the push button to the system default color. The code added is: 
  5903.  
  5904.   call VRSet "PB_PushMe", "BackColor", "<default>"
  5905.   call VRSet "PB_PushMe", "Caption", "Push Me!"
  5906.  
  5907. After you add the code, close the section editor and return to the menu editor. 
  5908.  
  5909. The code for each of the items in the cascaded menu is similar since each one 
  5910. performs the same action; that is, it sets the color of the push button. The 
  5911. code for MenuOptionsGreen is: 
  5912.  
  5913. call VRSet "PB_PushMe", "BackColor", "Green"
  5914.  
  5915. The VRSet procedure sets the push button's color. The code for the click events 
  5916. for each of the other colors would be the same, replacing Green with Red and 
  5917. Yellow. 
  5918.  
  5919. When you are finished creating your menu, click on Close to apply the changes 
  5920. and close the menu editor window. 
  5921.  
  5922.  
  5923. ΓòÉΓòÉΓòÉ 12.6. Creating a pop-up menu ΓòÉΓòÉΓòÉ
  5924.  
  5925. Any menu can be displayed as a pop-up menu. To do this, invoke the Popup method 
  5926. on the menu. Usually, your program will do this in response to a ContextMenu 
  5927. event which is generated when the user clicks mouse button 2 on an object. 
  5928.  
  5929. The user can either choose one of the menu items or dismiss the menu by 
  5930. clicking outside the menu or pressing Esc. If the user clicks on a menu item, a 
  5931. Click event is generated for that menu item in the same way as if the menu was 
  5932. attached to a menu bar. 
  5933.  
  5934. The following ContextMenu event routine displays the menu created in the 
  5935. previous section as a pop-up menu. 
  5936.  
  5937. PB1_ContextMenu:
  5938.     call VRMethod "MenuOptions", "Popup"
  5939. return
  5940.  
  5941. All menus that you use as pop-up menus must be associated with some window's 
  5942. menu bar. If you do not want these menus to appear on the menu bar, uncheck the 
  5943. Visible box for that menu in the menu editor. This will remove the menu from 
  5944. the menu bar, although you can still use it as a pop-up menu. If none of the 
  5945. menus attached to a menu bar are visible, the menu bar itself will be 
  5946. invisible. 
  5947.  
  5948.  
  5949. ΓòÉΓòÉΓòÉ 12.7. Responding to a pop-up menu ΓòÉΓòÉΓòÉ
  5950.  
  5951. In the Click event for a menu item, the internal name of the object for which 
  5952. the ContextMenu event was generated is available. To get it, pass the keyword 
  5953. Source to VRInfo. The action on the menu item should be applied to the source 
  5954. object. For example, the Popup sample program changes the BackColor property of 
  5955. a button with the following code: 
  5956.  
  5957. MI_BackGreenClick:           /* menu item click routine */
  5958.     call SetColor "Green"
  5959. return
  5960.  
  5961. SetColor: procedure
  5962.     parse arg color
  5963.  
  5964.     button = VRInfo( "Source" )
  5965.     call VRSet button, "BackColor", color
  5966. return
  5967.  
  5968. In the SetColor routine, the call to VRInfo gets the name of the button on 
  5969. which the user clicked mouse button 2. 
  5970.  
  5971.  
  5972. ΓòÉΓòÉΓòÉ 12.8. Using pop-up menus with containers ΓòÉΓòÉΓòÉ
  5973.  
  5974. If the user caused a ContextMenu event for a container, then the menu item 
  5975. Click routine is more involved. The container automatically marks the records 
  5976. to which the pop-up menu should apply. The Click event can get the list of 
  5977. records by using the GetRecordList container method to list all records that 
  5978. have the source emphasis (ie. the Source attribute set 1.) The Click event code 
  5979. must reset the Source attribute back to 0. 
  5980.  
  5981. If no records have the source emphasis, the Click routine must check if the 
  5982. container itself has the source emphasis. It can do this by getting the 
  5983. container's Source property. If the container itself has the source emphasis, 
  5984. then the menu action does not apply to any particular record, but rather to the 
  5985. container as a whole. Again, the Click routine must turn off the Source 
  5986. property if it is on. 
  5987.  
  5988. For example, suppose you have a pop-up menu that has two items: Open and Help. 
  5989. The program uses the Popup method to display the menu in response to a 
  5990. ContextMenu event on a container. If the user picks the Open menu item and the 
  5991. user clicked on a record, then information about that record is displayed. If 
  5992. the user picked Help, then help for that record is displayed. If the user 
  5993. clicks mouse button 2 on the container white space, then picking Open does 
  5994. nothing, but picking Help brings up some general help. 
  5995.  
  5996. Here are the two menu item click routines that would implement this behavior: 
  5997.  
  5998. MI_Open_Click:
  5999.     ctn = VRInfo( "Source" )
  6000.  
  6001.     /*  Get the list of records with source emphasis
  6002.     */
  6003.     call VRMethod ctn, "GetRecordList", "Source", "reclist."
  6004.     do i = 1 to reclist.0
  6005.  
  6006.         /*
  6007.            ... display information about the record ...
  6008.         */
  6009.  
  6010.         /*  Reset the record's source attribute
  6011.         */
  6012.         call VRMethod ctn, "SetRecordAttr", reclist.i, "Source", 0
  6013.     end
  6014.  
  6015.     /*  Turn off source emphasis for the container in case
  6016.         it is currently on.
  6017.     */
  6018.     call VRSet ctn, "Source", 0
  6019.  
  6020. return
  6021.  
  6022. MI_Help_Click:
  6023.     ctn = VRInfo( "Source" )
  6024.  
  6025.     /*  Get the list of records with source emphasis
  6026.     */
  6027.     call VRMethod ctn, "GetRecordList", "Source", "reclist."
  6028.     do i = 1 to reclist.0
  6029.  
  6030.         /*
  6031.            ... display help for the record ...
  6032.         */
  6033.  
  6034.         /*  Reset the record's source attribute
  6035.         */
  6036.         call VRMethod ctn, "SetRecordAttr", reclist.i, "Source", 0
  6037.     end
  6038.  
  6039.     /*  Turn off source emphasis for the container in case
  6040.         it is currently on.
  6041.     */
  6042.     if VRGet( ctn, "Source" ) = 1 then do
  6043.  
  6044.         /* ... display help for the record ...
  6045.         */
  6046.  
  6047.         /*  Reset the container's Source property
  6048.         */
  6049.         call VRSet ctn, "Source", 0
  6050.     end
  6051.  
  6052. return
  6053.  
  6054. For details on the way containers set the Source attribute see 
  6055.  
  6056. You can use a menu both as a pop-up and a pull-down menu if you make the 
  6057. following change to your code: instead of getting the list of records that have 
  6058. the source emphasis, get the list of records that have either source or the 
  6059. selected emphasis. From the example above, you would change: 
  6060.  
  6061. call VRMethod ctn, "GetRecordList", "Source", "reclist."
  6062.  
  6063. to 
  6064.  
  6065. call VRMethod ctn, "GetRecordList", "SourceOrSelected", "reclist."
  6066.  
  6067. Getting the SourceOrSelected list returns the records that have the source 
  6068. emphasis, or if there are none, then the records that are selected. Remember 
  6069. that pull-down menus should apply only to the selected records. 
  6070.  
  6071.  
  6072. ΓòÉΓòÉΓòÉ 12.9. Creating a conditional cascaded menu ΓòÉΓòÉΓòÉ
  6073.  
  6074. To make a cascaded menu into a conditional cascaded menu, set the DefaultItem 
  6075. property for that menu to the name of the default menu item. You do not have to 
  6076. check any of the menu items; the menu will automatically check the default 
  6077. item. A Click event for the default item is generated if the user clicks the 
  6078. menu item without displaying the cascaded portion. 
  6079.  
  6080. You can set the DefaultItem for a menu using the menu editor. 
  6081.  
  6082.  
  6083. ΓòÉΓòÉΓòÉ 12.10. Changing menus at run time ΓòÉΓòÉΓòÉ
  6084.  
  6085. The Caption, Checked, Enabled, and Visible properties can be changed at run 
  6086. time. This enables you to change your menus to reflect a change in the state of 
  6087. the program. For example, you can disable a menu item when it is not possible 
  6088. to perform that action for some reason. 
  6089.  
  6090. A convenient place to put the code to enable and disable menu items is in the 
  6091. Click event for the menu containing the items. This event will occur whenever 
  6092. the menu is displayed. 
  6093.  
  6094.  
  6095. ΓòÉΓòÉΓòÉ 12.10.1. Checking menu items ΓòÉΓòÉΓòÉ
  6096.  
  6097. Menu item properties are accessed with VRGet and VRSet just like any other 
  6098. object's properties. For example, to set a check mark beside the Green option 
  6099. in our sample menu you would use the following code: 
  6100.  
  6101. call VRSet "MenuOptionsGreen", "Checked", 1
  6102.  
  6103. At the same time you would uncheck the other items: 
  6104.  
  6105. call VRSet "MenuOptionsRed", "Checked", 0
  6106. call VRSet "MenuOptionsYellow", "Checked", 0
  6107.  
  6108.  
  6109. ΓòÉΓòÉΓòÉ 12.10.2. Installing accelerators at run time ΓòÉΓòÉΓòÉ
  6110.  
  6111. The Accelerator properties of the menu items are ineffective until the window 
  6112. builds an accelerator table. This is an internal data structure which the 
  6113. window uses to control the use of accelerator keys. To create this table, you 
  6114. must use the window object's InstallAccelerators method. All applications 
  6115. created in the VX-REXX environment automatically call this method at run time. 
  6116. You only have to call this method if you wish to change the accelerators for a 
  6117. menu item, or add new menu items with accelerators. 
  6118.  
  6119.  
  6120. ΓòÉΓòÉΓòÉ 13. Using built-in dialogs and system functions ΓòÉΓòÉΓòÉ
  6121.  
  6122. In addition to providing functions like VRGet and VRSet for manipulating 
  6123. objects, VX-REXX also defines functions for displaying dialogs and for file 
  6124. system manipulation. 
  6125.  
  6126.  
  6127. ΓòÉΓòÉΓòÉ 13.1. Predefined dialogs ΓòÉΓòÉΓòÉ
  6128.  
  6129. Four functions are available for displaying predefined dialogs: 
  6130.  
  6131. o VRFileDialog displays an OS/2 file dialog, to prompt the user for one or more 
  6132.   file names 
  6133.  
  6134. o VRFontDialog displays an OS/2 font dialog, to prompt the user for a font name 
  6135.   and style 
  6136.  
  6137. o VRMessage displays a message and waits for user confirmation 
  6138.  
  6139. o VRPrompt prompts the user for a string 
  6140.  
  6141. These functions do not return until the dialog is dismissed. The first 
  6142. parameter is the name of the window that is to own the dialog -- the owner and 
  6143. any of its children will be disabled while the dialog is active. 
  6144.  
  6145. Each of these functions along with their parameters is described in the online 
  6146. VXΓêÖREXX Reference. Predefined dialogs can save you programming time. They also 
  6147. help you maintain a consistent look in your applications. The following 
  6148. sections describe these dialogs and show how you may use them. 
  6149.  
  6150.  
  6151. ΓòÉΓòÉΓòÉ 13.1.1. File selection dialog ΓòÉΓòÉΓòÉ
  6152.  
  6153. The file selection dialog (VRFileDialog) is used to obtain a file specification 
  6154. for file operations such as reading or writing. Figure 69 shows a sample file 
  6155. dialog. 
  6156.  
  6157. Figure 69  File dialog with default values
  6158.  
  6159. The dialog displays several fields related to the file: its name, type, and 
  6160. location. The REXX code to display the dialog is: 
  6161.  
  6162. path = VRFileDialog( VRWindow(), "Sample File Dialog" )
  6163.  
  6164. VRFileDialog provides default values for all of the fields. By default, all 
  6165. files in the project's working directory are displayed in the file list box. 
  6166. The only parameters that must be supplied are the reference to the window to 
  6167. which the dialog is attached and a title for the dialog. In this example, the 
  6168. reference to the window is obtained using the function VRWindow and the dialog 
  6169. title is Sample File Dialog. The full path and name of the chosen file is 
  6170. returned. 
  6171.  
  6172. If the default values are not appropriate for your application, you can include 
  6173. parameters to override them. For example, you may want the dialog to display 
  6174. only files with a particular extension. The following sample code for an open 
  6175. file dialog includes the dialog type and initial path parameters so that only 
  6176. files in the project working directory with an extension BMP are listed. Note 
  6177. that the comma at the end of the first line is the REXX line continuation 
  6178. character. 
  6179.  
  6180. path = VRFileDialog( VRWindow(), "Select a Bitmap file", ,
  6181.                      "Open", "*.BMP" )
  6182.  
  6183. The dialog type parameter sets the string that is displayed above the file name 
  6184. entry field. In this example the string is "Open filename:". The initial path 
  6185. determines the mask for the file name and the values displayed for the drive, 
  6186. directory and file boxes. If no path is included, the application's working 
  6187. directory is assumed. If the working directory is not suitable, you can include 
  6188. a complete path name for this parameter. For example, 
  6189.  
  6190. path = VRFileDialog( VRWindow(), "Select a Bitmap file", ,
  6191.                      "Open", "E:\OS2\BITMAP\*.BMP" )
  6192.  
  6193. would produce the dialog shown in Figure 70. 
  6194.  
  6195. Figure 70  Sample file dialog overriding default parameters
  6196.  
  6197. The initial type parameter lets you set the initial value displayed for Type of 
  6198. file. The default is all types. The file type is different from the file 
  6199. extension of the file name. The file type is saved in the file's extended 
  6200. attribute. File types in OS/2 let you create a special link between program 
  6201. objects and data file objects. When objects are linked, you can open a data 
  6202. file and a program at the same time. OS/2 defines a number of data types, such 
  6203. as Assembler Code, C Code, Executable and Icon. A program can also add its own 
  6204. data type. For more information about file types see the OS/2 online "Master 
  6205. Help Index". 
  6206.  
  6207. Other parameters include the drive list and type list. These two parameters let 
  6208. you limit the values displayed for the drive and type fields. Both require 
  6209. compound variables. The file dialog can also allow for multiple file selection. 
  6210. A detailed description of the parameters is contained in the Alphabetical 
  6211. Reference. If you do not want to change a default parameter, omit it by leaving 
  6212. a blank between the commas. 
  6213.  
  6214.  
  6215. ΓòÉΓòÉΓòÉ 13.1.2. Font selection dialog ΓòÉΓòÉΓòÉ
  6216.  
  6217. The font selection dialog (VRFontDialog) is used to obtain a font specification 
  6218. for use with the Font property and anywhere else a font string can be used. 
  6219.  
  6220. An initial font can be specified as a parameter to VRFontDialog, as well as a 
  6221. title string: 
  6222.  
  6223. font = VRFontDialog( VRWindow(), "10.Helv.Bold", ,
  6224.                      "Choose a font!" )
  6225.  
  6226. If the user selects a font, the string describing the font is returned. A null 
  6227. string is returned if the Cancel button is selected. 
  6228.  
  6229. The font string is returned in the format described in the Font property 
  6230. section of the Reference. 
  6231.  
  6232.  
  6233. ΓòÉΓòÉΓòÉ 13.1.3. Message dialog ΓòÉΓòÉΓòÉ
  6234.  
  6235. The message dialog VRMessage displays information. The message could be an 
  6236. error condition, descriptive information or a query. For example, the following 
  6237. code 
  6238.  
  6239. call VRMessage VRWindow(), "Welcome to the world of VX-REXX"
  6240.  
  6241. would display the message dialog in Figure 71. 
  6242.  
  6243. Figure 71  Message dialog with default parameters
  6244.  
  6245. The two required parameters are the window to which the dialog is attached, and 
  6246. the message to be displayed. In this example the window is obtained using the 
  6247. function VRWindow and the message is "Welcome to the world of VX-REXX". 
  6248. Additional parameters let you change the title, add an icon, add buttons and 
  6249. set default and cancel buttons. For example, the following code would display 
  6250. the message shown in Figure 72. Note that a comma at the end of a line is the 
  6251. REXX line continuation character. 
  6252.  
  6253. button.0 = 2
  6254. button.1 = "OK"
  6255. button.2 = "Cancel"
  6256. call VRMessage VRWindow(), "Welcome to the world of VX-REXX", ,
  6257.                "VX-REXX", "I", "button.", 1, 2
  6258.  
  6259. Figure 72  Message dialog with user defined buttons
  6260.  
  6261. The third argument sets the title for the dialog to "VX-REXX". The fourth 
  6262. argument displays the information icon; you can choose from several icons such 
  6263. as a question mark, exclamation mark, or asterisk. A list of icons is included 
  6264. in the VRMessage description in the online VXΓêÖREXX Reference. The stem variable 
  6265. defines buttons to be displayed in the message box. Notice that the compound 
  6266. variable parameter has a period (.) at the end of the name. The last two 
  6267. arguments  indicate which two buttons should be activated if the Enter or Esc 
  6268. keys are pressed. Pressing Esc or Enter will close the dialog. 
  6269.  
  6270.  
  6271. ΓòÉΓòÉΓòÉ 13.1.4. Multiline message dialog ΓòÉΓòÉΓòÉ
  6272.  
  6273. The multiline message dialog VRMessageStem is used to display a message that 
  6274. requires more than one line. The arguments are the same as those for VRMessage 
  6275. except for the second argument which defines the text for the message dialog 
  6276. using a compound variable. For example, the following code would display the 
  6277. message window shown in Figure 73. Note that a comma at the end of a line is 
  6278. the REXX line continuation character. 
  6279.  
  6280. message.0 = 3
  6281. message.1 = "Version 1.00"
  6282. message.2 = "Copyright (c) 1993 WATCOM International Corporation"
  6283. message.3 = "WATCOM is a trademark of WATCOM International"
  6284. button.0 = 1
  6285. button.1 = "OK"
  6286. call VRMessageStem VRWindow(), "message.", ,
  6287.                    "VX-REXX - Product information", "N", ,
  6288.                    "button.", 1, 1
  6289.  
  6290. Figure 73  Multiline message dialog
  6291.  
  6292. This message displays the same information as the Product information item from 
  6293. the VX-REXX Help menu. Notice that the dialog box adjusts its size to fit the 
  6294. long lines. 
  6295.  
  6296. The reference to the window object and the message are the only required 
  6297. parameters. The additional values set the title and add the buttons. 
  6298.  
  6299.  
  6300. ΓòÉΓòÉΓòÉ 13.1.5. Prompt dialog ΓòÉΓòÉΓòÉ
  6301.  
  6302. The prompt dialog VRPrompt lets you display a simple input dialog to request 
  6303. data. The arguments for the function are similar to those for the message 
  6304. function. An additional parameter is provided for saving the user's response. 
  6305. For example, the following code will display the prompt window shown in Figure 
  6306. 74. 
  6307.  
  6308. userName = ""
  6309. button.0 = 2
  6310. button.1 = "OK"
  6311. button.2 = "Cancel"
  6312. call VRPrompt VRWindow(), "Please enter your user name:", ,
  6313.               "userName", "Logon", "button.", 1, 2
  6314. if result = 2 then userName = ""
  6315.  
  6316. Figure 74  Prompt dialog
  6317.  
  6318. In this example the value that the user enters is returned in the variable 
  6319. userName. There are two buttons: OK and Cancel. Pressing Enter is equivalent to 
  6320. clicking OK and pressing Esc is equivalent to clicking Cancel. 
  6321.  
  6322. The value returned by VRPrompt indicates which button was pressed. In this 
  6323. example the program checks to see if Cancel was chosen (result = 2). If it was, 
  6324. any value entered is ignored. 
  6325.  
  6326.  
  6327. ΓòÉΓòÉΓòÉ 13.2. INI files ΓòÉΓòÉΓòÉ
  6328.  
  6329. OS/2 stores configuration and profile data in INI files. VX-REXX provides 
  6330. several functions for manipulating those files: VRDelIni, VRGetIni, and 
  6331. VRSetIni. 
  6332.  
  6333. INI files are used to efficiently store text and binary data. User preferences 
  6334. are often stored in INI files, for example. If possible, it is best for an 
  6335. application to use its own private INI file rather than one of the OS/2 system 
  6336. INI files. Ideally this file should exist in the same directory as the program 
  6337. executable. You can use the Application object in conjunction with the 
  6338. VRParseFileName function to determine where your executable is: 
  6339.  
  6340. exePath = VRGet( "Application", "Program" )
  6341. iniDir  = VRParseFileName( exePath, "DP" )
  6342. iniFile = iniDir || "\myini.ini"
  6343.  
  6344. If the INI file does not exist or is missing data, your application should 
  6345. create a new INI file with reasonable default values. 
  6346.  
  6347.  
  6348. ΓòÉΓòÉΓòÉ 13.3. File system manipulation ΓòÉΓòÉΓòÉ
  6349.  
  6350. File system manipulation in REXX is limited to a few built-in functions and 
  6351. relies mostly on the use of commands to the CMD host environment. VX-REXX 
  6352. defines a complete set of file system functions for performing common tasks: 
  6353.  
  6354. o File and directory creation, deletion and copying: VRCopyFile, VRCreateFile, 
  6355.   VRDeleteFile, VRFileExists, VRIsDir, VRMkDir, VRRenameFile, VRRmDir 
  6356.  
  6357. o Getting and changing the current drive and/or directory: VRChDir, VRChDrive, 
  6358.   VRCurrDir, VRCurrDrive, VRDir 
  6359.  
  6360. o Setting file attributes: VRChAttr, VRFileDate 
  6361.  
  6362. o Retrieving disk information: VRDiskInfo, VRDiskLabel, VRFindFile 
  6363.  
  6364. o Parsing and expanding file paths: VRExpandFileName, VRParseFileName 
  6365.  
  6366.  
  6367. ΓòÉΓòÉΓòÉ 14. Creating custom dialogs ΓòÉΓòÉΓòÉ
  6368.  
  6369. In a previous chapter, you have seen how to use built-in dialogs. This chapter 
  6370. describes how to create your own custom dialogs using window files. 
  6371.  
  6372. Window files behave the same way as the built-in dialog functions -- you call 
  6373. them, the window appears, the user closes the window, then the calling program 
  6374. continues. Windows that operate in this way are called modal. A modal window 
  6375. automatically disables its parent and any sibling windows. The calling window 
  6376. file is also suspended while the called window is active. When a modal window 
  6377. closes, it enables its parent and sibling windows, and execution of the calling 
  6378. window file continues. Your program should use a modal window whenever it has 
  6379. to get user input before continuing. 
  6380.  
  6381. In contrast, a modeless window is part of the window file that loads it. A 
  6382. modeless window does not suspend the code that loaded it, nor does it disable 
  6383. any other windows. You can use modeless windows to allow your user to work with 
  6384. several windows at the same time. This type of window is covered in the 
  6385. "Secondary windows"  chapter, and is not discussed here. 
  6386.  
  6387. Modal windows do not have to be separate window files. You can also create 
  6388. modal windows in the same file using the techniques discussed in the "Secondary 
  6389. windows" chapter. This chapter, however, is only concerned with the case where 
  6390. a modal window is a separate window file. 
  6391.  
  6392. The sections in this chapter take you through the process of creating a sample 
  6393. modal dialog which prompts the user for two pieces of data: a name and a 
  6394. password. 
  6395.  
  6396.  
  6397. ΓòÉΓòÉΓòÉ 14.1. Calling the modal window file ΓòÉΓòÉΓòÉ
  6398.  
  6399. In this example, we will create a simple modal dialog that asks the user for 
  6400. some information. The dialog will be kept in a second window file. The first 
  6401. file calls the second file which returns a name and password. 
  6402.  
  6403. When windows are saved in separate files, one window is activated from another 
  6404. window by calling it with the file name as in: 
  6405.  
  6406. values = Window2( VRWindow() )
  6407.  
  6408. where Window2 is the file name of the second window file. The VX-REXX function 
  6409. VRWindow, which returns the internal name of the current primary window, must 
  6410. be passed as the first argument. The second window file needs the name of the 
  6411. current window in order to disable it and all of its child windows (if any). 
  6412. The second window disables its parent automatically; you do not have to add any 
  6413. REXX code to do this. 
  6414.  
  6415. On your main window add a push button, then modify the button's click event to 
  6416. the following: 
  6417.  
  6418. PB_1_Click:
  6419.     values = Window2( VRWindow() )
  6420.     if values \= "" then do
  6421.         parse var values name "," password
  6422.         say "Name =" name ", Password = " password
  6423.     end
  6424.     else do
  6425.         say "The dialog was canceled."
  6426.     end
  6427. return
  6428.  
  6429. This code assumes Window2 will return the name and password in a single comma 
  6430. delimited string. If the user closes the window or presses the cancel button, 
  6431. Window2 will return the null string. 
  6432.  
  6433.  
  6434. ΓòÉΓòÉΓòÉ 14.2. Creating a new window file ΓòÉΓòÉΓòÉ
  6435.  
  6436. To create a new window file, choose the New window file item from the Project 
  6437. menu. When you do this, the current file is closed and a new window file is 
  6438. created and displayed. At the same time, the file list window will appear. This 
  6439. window is discussed in the "Multiple file projects" chapter. 
  6440.  
  6441. The new window is automatically given a unique file name of the form Window 
  6442. followed by a number; for example, Window2. To rename this window, choose the 
  6443. Save as item from the File menu. VX-REXX will then prompt you for the new name 
  6444. of the window file. 
  6445.  
  6446. The name of the new file is added to the file list. If the section list window 
  6447. is open, you will see that sections have been generated for the window as they 
  6448. were for the first window -- Fini, Init, Main, Quit and Window2_Close. 
  6449.  
  6450. Set the window's Caption property to Logon. Then add two entry fields, some 
  6451. descriptive text, and OK and Cancel buttons to the new window so that it 
  6452. resembles Figure 75. 
  6453.  
  6454. Figure 75  A custom dialog
  6455.  
  6456.  
  6457. ΓòÉΓòÉΓòÉ 14.3. Returning a value ΓòÉΓòÉΓòÉ
  6458.  
  6459. Window2 returns a name and password in a single comma delimited string. The 
  6460. value returned by the Fini routine in Window2 is the value that is passed back 
  6461. to Window1. The Fini section is automatically generated when you create a new 
  6462. window file. It returns 0 by default. 
  6463.  
  6464. For our example, Fini returns the Retcode variable which we will set in the OK 
  6465. button's click routine. First, edit the PB_1_Click routine in Window2 to match 
  6466. the following code. 
  6467.  
  6468. PB_1_Click:
  6469.     name = VRGet( "EF_1", "Value" )
  6470.     pswd = VRGet( "EF_2", "Value" )
  6471.     Retcode = name || "," || pswd
  6472.     call Quit
  6473. return
  6474.  
  6475. The Click routine calls Quit to terminate the dialog. 
  6476.  
  6477. Note:  If you have changed the names of the entry fields, replace EF_1 and EF_2 
  6478. with the actual names of the entry fields. 
  6479.  
  6480. Next, modify the Click event for the cancel button to close the dialog window 
  6481. without changing Retcode: 
  6482.  
  6483. PB_2_Click:
  6484.     call Quit
  6485. return
  6486.  
  6487. Initialize the Retcode variable in the Init routine of Window2: 
  6488.  
  6489. Init:
  6490.     Retcode = ""
  6491.     window = VRWindow()
  6492.     call VRMethod window, "CenterWindow"
  6493.     call VRSet window, "Visible", 1
  6494.     call VRMethod window, "Activate"
  6495.     drop window
  6496. return
  6497.  
  6498. And finally, change the Fini routine to return the Retcode variable: 
  6499.  
  6500. Fini:
  6501.     window = VRWindow()
  6502.     call VRSet window, "Visible", 0
  6503.     drop window
  6504. return Retcode
  6505.  
  6506.  
  6507. ΓòÉΓòÉΓòÉ 14.4. Running the program ΓòÉΓòÉΓòÉ
  6508.  
  6509. You are now ready to run the program. If the user closes the dialog by pressing 
  6510. the OK button, Window2 will return the contents of the name and password 
  6511. fields. Otherwise, it will return the null string. 
  6512.  
  6513.  
  6514. ΓòÉΓòÉΓòÉ 14.5. Multiple file considerations ΓòÉΓòÉΓòÉ
  6515.  
  6516. Because modal windows are kept in different files, you should be aware of the 
  6517. following aspects of multiple file programming: 
  6518.  
  6519. o The scope of REXX variables and labels 
  6520. o The scope of object names 
  6521.  
  6522. For programming details concerning multiple file projects, see the "Multiple 
  6523. file projects" chapter later in this manual. 
  6524.  
  6525.  
  6526. ΓòÉΓòÉΓòÉ 15. Secondary windows ΓòÉΓòÉΓòÉ
  6527.  
  6528. The previous chapter showed you how to create a custom dialog using a modal 
  6529. window in another file. Calling a modal window file is like calling a routine: 
  6530. the parent program waits and the parent window is disabled until the child 
  6531. window is closed. 
  6532.  
  6533. There are times when this type of interaction is inappropriate, when you want a 
  6534. dialog window to be visible and enabled while the main window is still enabled. 
  6535. In this case, you want a modeless window. A modeless window does not disable 
  6536. its parent window when it is open. You may have already seen modeless windows 
  6537. in the VX-REXX design environment; the tool palette, section  list, and file 
  6538. list windows are all modeless windows. 
  6539.  
  6540. There are also times when you want a modal window to be part of the same file 
  6541. as the main window so that data can be easily shared between the two windows. 
  6542.  
  6543. This chapter describes how to use windows which are part of the same file as 
  6544. the main window for both modeless and modal interactions. 
  6545.  
  6546.  
  6547. ΓòÉΓòÉΓòÉ 15.1. Primary vs. secondary ΓòÉΓòÉΓòÉ
  6548.  
  6549.  The first window you create in a file is the primary window. Normally the main 
  6550. user interaction takes place in this window. It presents information that is 
  6551. used independently from information in all other windows. Other windows that 
  6552. you create as part of the same file are secondary windows. 
  6553.  
  6554. Secondary windows are used to supplement the interaction in the primary window. 
  6555. They are associated with the primary window in the following ways: Secondary 
  6556. windows are closed, minimized, or restored when the primary window is closed, 
  6557. minimized, or restored. You can also specify that a secondary window moves when 
  6558. the primary window is moved (see the MoveWithParent property). 
  6559.  
  6560. When a window file is called, all of the code is loaded and the primary window 
  6561. is displayed. The secondary windows are loaded by the program when required. 
  6562. Because all of the code is always loaded, the REXX labels, variables and object 
  6563. names are known to all of the windows in the file. Moreover, when a secondary 
  6564. window is opened, the events associated with the primary window can also be 
  6565. used. The action in the primary window is not suspended. 
  6566.  
  6567. The following sections show you how to create and use modeless and modal 
  6568. secondary windows. 
  6569.  
  6570.  
  6571. ΓòÉΓòÉΓòÉ 15.2. Window list window ΓòÉΓòÉΓòÉ
  6572.  
  6573. To create a secondary window, use the window list window. The window list 
  6574. provides commands to create, open, close and delete secondary windows. To 
  6575. display the window list, choose Window list from the Windows menu. It will be 
  6576. as shown in Figure 76. 
  6577.  
  6578. Figure 76  Window list window
  6579.  
  6580. The window list displays the names of the primary and secondary windows in the 
  6581. current file. In this example there are two windows: the primary window, 
  6582. Window1, and a secondary window, SW_1. To see the list of windows in a 
  6583. different file, double click on the file name in the file list window. 
  6584.  
  6585. The Window menu contains commands to help you maintain multiple windows in a 
  6586. file. These commands are described by task in the following sections. 
  6587.  
  6588.  
  6589. ΓòÉΓòÉΓòÉ 15.3. Creating and editing a secondary window ΓòÉΓòÉΓòÉ
  6590.  
  6591. To create a secondary window, choose New window from the Window menu in the 
  6592. window list and enter a name for the window. Doing this creates a new empty 
  6593. window. The current window does not close so you can align and resize your 
  6594. windows as necessary. If you want to close a window, click on its system menu, 
  6595. or select the window from the window list and choose Close from the Window 
  6596. menu. The Open command will open a window for editing. 
  6597.  
  6598. When a secondary window is created, a unique window name is generated for it. 
  6599. By default the name is SW_x, where x is some number. For example, the name 
  6600. might be SW_1 if this were the first secondary window. You can specify a new 
  6601. name when the window is created or change the window name by changing the Name 
  6602. field in the window's property notebook. If you are creating several windows, 
  6603. you may want to change the default names to make it easier to remember their 
  6604. function. 
  6605.  
  6606. If the file list window is open, you will notice that adding secondary windows 
  6607. does not change it. You are not creating a new file. However, you will see new 
  6608. sections called SW_1_Close, SW_1_Create, SW_1_Init and SW_1_Fini in the section 
  6609. list. When you add event code for an object in the new window, the section name 
  6610. for the event will also be added to the section list. You can use the Section 
  6611. menu in the section list window to manage the code for any of the windows in 
  6612. the file. 
  6613.  
  6614. Once the new window is created, you can add objects and change properties as 
  6615. you would for any other window. There are several window-specific properties 
  6616. you might like to set: BorderType, TitleBar, HideButton, MaximizeButton, 
  6617. MinimizeButton, MoveWithParent and SystemMenu. 
  6618.  
  6619. MaximizeButton, HideButton and MinimizeButton are probably not needed on a 
  6620. secondary window. If the primary window contains these buttons, a secondary 
  6621. window will be minimized or restored along with the primary window. 
  6622.  
  6623. MoveWithParent should usually be set so that if you move the primary window the 
  6624. other window moves with it. 
  6625.  
  6626. The BorderType property on a secondary window that is not meant to be sizeable 
  6627. should be set to either Thin or Dialog. 
  6628.  
  6629. Many applications include a system menu as a standard way to close a window. If 
  6630. you want to be able to close a secondary window in this way, select the 
  6631. SystemMenu property on the Frame page of the window's property notebook. 
  6632.  
  6633.  
  6634. ΓòÉΓòÉΓòÉ 15.4. Opening a secondary window at run time ΓòÉΓòÉΓòÉ
  6635.  
  6636. When a file contains multiple windows, you must explicitly load the secondary 
  6637. windows in order to open them. You load a window with the VX-REXX function 
  6638. VRLoadSecondary. How you call VRLoadSecondary determines whether the secondary 
  6639. window is loaded as a modal window or as a modeless window. For example, the 
  6640. following statement loads a modeless secondary window named SW_1: 
  6641.  
  6642. window = VRLoadSecondary( "SW_1" )
  6643.  
  6644. VRLoadSecondary returns the internal name of the loaded window. If it cannot 
  6645. load the modeless window it returns an empty string. Execution immediately 
  6646. continues with the next REXX statement in the section. 
  6647.  
  6648. In contrast, the following statement loads SW_1 as a modal secondary window: 
  6649.  
  6650. call VRLoadSecondary "SW_1", "Wait"
  6651.  
  6652. Unlike the modeless case, the call to VRLoadSecondary does not return 
  6653. immediately, but rather disables the parent window and processes events for the 
  6654. secondary window. The call to VRLoadSecondary returns only when the secondary 
  6655. window is destroyed. It is similar to calling a modal window in another file, 
  6656. except that the primary window and secondary window are actually in the same 
  6657. file. Unlike modal window files, no arguments can be passed to the secondary 
  6658. window and no value is returned, so communication between the primary and 
  6659. secondary window is done using global variables. 
  6660.  
  6661. You should use the REXX procedure statement on all the event routines of modal 
  6662. secondary windows. If you do not, variables in the routine which loaded the 
  6663. window may have their values changed. This is because the loading routine will 
  6664. indirectly call the event routine via VRLoadSecondary. As a result, variables 
  6665. in the loading routine will be exposed to the event routine unless the 
  6666. procedure keyword is used. 
  6667.  
  6668. Loading a modal secondary window also sets the value returned by VRWindow to be 
  6669. the internal name of the secondary window and resets it when the window is 
  6670. destroyed. The value of VRWindow is not changed when a modeless secondary 
  6671. window is loaded. 
  6672.  
  6673. When a secondary window is loaded, a Create event occurs. By default, the 
  6674. Create event calls the window's Init routine (for example, SW_1_Init) to center 
  6675. the secondary window over its parent and make it visible and active. You can 
  6676. modify this behaviour by changing the window's Init routine. Modal secondary 
  6677. windows should always be made visible, however, because the parent window will 
  6678. have been disabled. 
  6679.  
  6680. Because they are in the same file, primary and secondary windows can easily 
  6681. share information through variables. Variables in a file can be used in any 
  6682. section or window in that file. 
  6683.  
  6684. If you want a secondary window to be opened with the primary window, you may 
  6685. want to load it in the Init section so that it is opened when your application 
  6686. is started. 
  6687.  
  6688.  
  6689. ΓòÉΓòÉΓòÉ 15.5. Closing a secondary window at run time ΓòÉΓòÉΓòÉ
  6690.  
  6691. Secondary windows remain open until you close them. If the secondary window has 
  6692. a system menu, you do not have to add any code to handle the Close event; 
  6693. VX-REXX automatically generates REXX instructions to close the window. However, 
  6694. if you provide a push button or menu item to close the window, you must add 
  6695. code to that object's click event to close the window. To close a secondary 
  6696. window, call the Fini routine for the window. For example, suppose you want to 
  6697. close a window called SW_1 when push button PB_1 is clicked. The Click event 
  6698. for the push button would look similar to: 
  6699.  
  6700. PB_1_Click:
  6701.     call SW_1_Fini
  6702. return
  6703.  
  6704. If you destroy a modeless window you must use VRLoadSecondary again to reopen 
  6705. it. 
  6706.  
  6707. If you wanted to hide a modeless window rather than destroying it, you could 
  6708. replace the code in the Fini routine with the following: 
  6709.  
  6710. call VRSet "SW_1", "Visible", 0
  6711.  
  6712.  If you make the window invisible, you can open it again by setting the 
  6713. window's visible property to 1. Note that it is faster to change a window's 
  6714. visibility than to destroy and load it again. Do not make a modal secondary 
  6715. window invisible, however, as the parent window will still be disabled. 
  6716.  
  6717.  
  6718. ΓòÉΓòÉΓòÉ 15.6. Saving a multiple window file ΓòÉΓòÉΓòÉ
  6719.  
  6720. All of the windows in a file are saved when you save the window file using Save 
  6721. or Save as from the file list window, or when you save the project using the 
  6722. Project menu. 
  6723.  
  6724.  
  6725. ΓòÉΓòÉΓòÉ 15.7. Deleting a window ΓòÉΓòÉΓòÉ
  6726.  
  6727. Use Delete from the window list Window menu to remove a window from a file. 
  6728. When you choose Delete, you are asked to confirm the deletion. If you proceed, 
  6729. the window and any event sections associated with that window object are 
  6730. removed from the file. Once you delete a window, you cannot add it back. You 
  6731. have to recreate it. 
  6732.  
  6733.  
  6734. ΓòÉΓòÉΓòÉ 16. Multiple file projects ΓòÉΓòÉΓòÉ
  6735.  
  6736. This chapter describes the tools that help you create and maintain multiple 
  6737. file projects. As you develop more complex applications you may require more 
  6738. than one file. Additional files may be simply code (for example, to provide 
  6739. general routines to share between windows or projects) or may be additional 
  6740. windows such as dialogs to display messages or request information. 
  6741.  
  6742.  
  6743. ΓòÉΓòÉΓòÉ 16.1. Overview ΓòÉΓòÉΓòÉ
  6744.  
  6745. A VX-REXX project consists of a project file and one or more window and/or code 
  6746. files. A window file consists of REXX code that describes the actions to 
  6747. perform and data that describes one or more windows. A code file is simply REXX 
  6748. code; it does not have a window associated with it. A VX-REXX project can 
  6749. consist of code files only. 
  6750.  
  6751. A window file or code file is a REXX program file. Each file has a separate 
  6752. name space. This means that labels, variables and object names are local to 
  6753. that file. To exchange data between files, values must be passed as parameters 
  6754. when calling a file, or returned as a single return value. VX-REXX also 
  6755. provides a global variable facility that can be accessed using the PutVar and 
  6756. GetVar methods. 
  6757.  
  6758. The project file lists all of the window and code files associated with the 
  6759. project. All of the files are often located in the same directory, although 
  6760. this is not necessary. When you create multiple file projects you can include 
  6761. files from other projects or general code files that are shared among projects. 
  6762. These files might be located on a network. However, when you make an executable 
  6763. file for a completed project, all of the code is assembled into one executable 
  6764. file. 
  6765.  
  6766. VX-REXX provides an integrated project management facility that simplifies the 
  6767. task of creating and organizing multiple files in a project. When your project 
  6768. requires more than one file, use the Files window to create, edit and save 
  6769. additional files. The following sections describe the Files window and how to 
  6770. use it to maintain a multiple file project. 
  6771.  
  6772.  
  6773. ΓòÉΓòÉΓòÉ 16.2. File list window ΓòÉΓòÉΓòÉ
  6774.  
  6775. The file list window provides commands to manage multiple file projects. You 
  6776. can create new window files, add or remove files from within a project, and 
  6777. save existing files. To display the file list window, choose File list from the 
  6778. Windows menu. It will be similar to the window shown in Figure 77. 
  6779.  
  6780. Figure 77  File list window
  6781.  
  6782. The list box displays the names of all files in the project. In this example, 
  6783. there are two window files called Window1 and Window2. The File menu contains 
  6784. commands to help you maintain a multiple file project. Each of these commands 
  6785. is described in the following sections. 
  6786.  
  6787.  
  6788. ΓòÉΓòÉΓòÉ 16.3. Creating and editing a new file ΓòÉΓòÉΓòÉ
  6789.  
  6790. Both the New code file and New window file items in the File menu add a new 
  6791. file to a project. A new code file lets you create REXX routines that are not 
  6792. associated with a particular window but that could be called by any window in 
  6793. any project. This allows you to develop general routines that can be shared 
  6794. across projects. A new window file creates a new window with its associated 
  6795. code. This window can be called by another window in this project and can also 
  6796. be added to another project. 
  6797.  
  6798. When you choose New code file the current file is closed and a new empty file 
  6799. is created. A unique file name is generated as File followed by a number; for 
  6800. example, File1. The name is added to the file list. Two new sections, Main and 
  6801. Halt, are generated when the file is created. The section editor is opened and 
  6802. the Main section is loaded. It only contains the section header, routine name 
  6803. and a return statement as in the following: 
  6804.  
  6805. /*:VRX */
  6806. Main:
  6807.     signal on halt
  6808.  
  6809. return
  6810.  
  6811. You can add all your code to this section or you can create new sections using 
  6812. the New menu item from the Section menu in the section list window. 
  6813.  
  6814. When you choose New window file, the current file is closed, a new window file 
  6815. is created and an empty window is displayed. Choosing this menu item is 
  6816. identical to choosing the New window file item in the VX-REXX Project menu. A 
  6817. unique file name is generated as Window followed by a number; for example, 
  6818. Window2. The new name is added to the file list. If the section list window is 
  6819. open, you will see that sections have been generated for the window as they 
  6820. were for the first window (Fini, Init, Main, Quit and Window2_Close). 
  6821.  
  6822. Note that if you select New code file or New window file when a new project has 
  6823. just been created (i.e. Window1 is still empty) Window1 will be removed before 
  6824. the new window or code file is created. This feature can be used to create a 
  6825. project that contains only code files. 
  6826.  
  6827. Edit your new window in the same way as other windows by adding objects, 
  6828. modifying properties and adding event code to the objects or adding general 
  6829. code. 
  6830.  
  6831. Only one code or window file can be open for section editing at one time. When 
  6832. you create a new code file or window file the current file is closed. You can 
  6833. open an existing code file or window file by double-clicking on its name in the 
  6834. file list or by clicking on the name to select it and then choosing Open from 
  6835. the File menu. When you do, the current file is closed and the selected file is 
  6836. opened. 
  6837.  
  6838. As you work with larger projects, you may find it useful to edit all of the 
  6839. sections in a file at once. This allows you to easily make global changes and 
  6840. to view or print all of the code at once. When you select a file and then 
  6841. choose Edit from the File menu in the file list window, the external editor 
  6842. will load all the code for the selected file; all sections of the file will be 
  6843. displayed. If the selected file is the file currently open for section editing, 
  6844. it will be closed before starting the external editor to help prevent you from 
  6845. editing the same code in two different windows. 
  6846.  
  6847. You can use the external editor to edit as many files at once as you like. This 
  6848. makes it easy to compare and copy code between files. However, VX-REXX does not 
  6849. keep track of your external editor sessions. You must remember to save the 
  6850. edited file before saving or running a project or the old version of the code 
  6851. will be used. You should also be careful to avoid editing the same file more 
  6852. than once at the same time, and to avoid opening a file for section editing 
  6853. when you already have it in an external editor. 
  6854.  
  6855.  
  6856. ΓòÉΓòÉΓòÉ 16.4. Calling a file ΓòÉΓòÉΓòÉ
  6857.  
  6858. One of the files is specified as the main file; it is the file that is executed 
  6859. when the application is started. The main file can be a window file or a code 
  6860. file. Initially the main file is the first window that is created when the 
  6861. project is created (Window1). You can change the default main file by changing 
  6862. the file name specified for Main file in the Run options dialog accessed from 
  6863. the Options menu. 
  6864.  
  6865. Other files are called from this file and those files could call additional 
  6866. files, and so on. Files are called as routines: they can be called as 
  6867. procedures or as functions, and they can be passed arguments and return values 
  6868. as shown in the following sections. When a file is called, any action in the 
  6869. calling file is suspended until the called file returns. This means that when a 
  6870. window in a second file is started, you cannot process any events in the first 
  6871. window until the second window is closed. 
  6872.  
  6873.  
  6874. ΓòÉΓòÉΓòÉ 16.4.1. Calling a code file ΓòÉΓòÉΓòÉ
  6875.  
  6876. Activating a code file from another file is the same as calling an external 
  6877. subroutine in REXX. You call it by the file name as in: 
  6878.  
  6879. call File1
  6880.  
  6881. where File1 is the name of the code file. 
  6882.  
  6883. If the code file requires information from the calling file, it can be passed 
  6884. as arguments. For example: 
  6885.  
  6886. call File1 parm1, "hello"
  6887.  
  6888. passes the value of the variable parm1 and the string "hello" to the code file 
  6889. File1. The values of the arguments are retrieved in File1 as they would be in 
  6890. any REXX program file. It is up to you to assign the arguments to variables 
  6891. with the arg or parse arg instructions. For example, you may assign the 
  6892. arguments from the previous example to variables by adding the following 
  6893. statements to the Main section of File1. 
  6894.  
  6895. parse arg parm, string
  6896.  
  6897. The value of parm1 would be assigned to the variable parm and "hello" would be 
  6898. assigned to the variable string. 
  6899.  
  6900.  
  6901. ΓòÉΓòÉΓòÉ 16.4.2. Calling a window file ΓòÉΓòÉΓòÉ
  6902.  
  6903. When windows are saved in separate files, one window is activated from another 
  6904. window by calling it with the file name as in: 
  6905.  
  6906. call Window2 VRWindow()
  6907.  
  6908. where Window2 is the file name of the second window. 
  6909.  
  6910. The VX-REXX function VRWindow returns the internal name of the current primary 
  6911. window, which must be included as the first argument. This reference is passed 
  6912. to the called window file to identify the calling window. If this parameter is 
  6913. not passed, the calling window will appear to be enabled. If you try to execute 
  6914. an event in the calling window while the called window is displayed, the events 
  6915. are queued and later executed when the called window is closed. This is 
  6916. generally not desirable. 
  6917.  
  6918. Because these windows do not share code, any information that is shared by the 
  6919. windows must be passed between the windows. Data can be passed to a window by 
  6920. including arguments in the call to the window as in the statement: 
  6921.  
  6922. call Window2 VRWindow(), parm1, "Hello"
  6923.  
  6924. In this example, the value of the variable parm1 and the string "Hello" are 
  6925. passed to Window2. When the second window is started the arguments can be 
  6926. retrieved. The arguments are stored in the compound variable InitArgs. 
  6927. InitArgs.0 contains the number of arguments. The values of the arguments are 
  6928. saved in InitArgs.1, InitArgs.2, and so on. In this example, InitArgs.1 is set 
  6929. to the value of parm1 and InitArgs.2 is set to the string "Hello". The argument 
  6930. values can be used in any section of code in Window2. The value of the argument 
  6931. VRWindow() is not included in the compound variable. 
  6932.  
  6933.  
  6934. ΓòÉΓòÉΓòÉ 16.5. Returning a value ΓòÉΓòÉΓòÉ
  6935.  
  6936. A called file may need to return a value to the calling file. For example, a 
  6937. second window may present a dialog which requests information that is needed by 
  6938. the calling window. A single value can be returned to the calling window by 
  6939. modifying the return value of the return statement in the Fini section of the 
  6940. called window. The Fini section is automatically generated when you create a 
  6941. new window. It returns 0 by default. For example, you could return a value as 
  6942. in the following: 
  6943.  
  6944. returnValue = "goodbye"
  6945. return returnValue
  6946.  
  6947.  The code in the calling window would be similar to the following: 
  6948.  
  6949. returnValue = Window2( VRWindow(), parm1, "Hello" )
  6950.  
  6951. The variable returnValue contains the string "goodbye". If you had several 
  6952. values to return you could join them together in one string and then parse the 
  6953. return value. However, VX-REXX provides an alternative to make it easier to 
  6954. return multiple values. 
  6955.  
  6956.  
  6957. ΓòÉΓòÉΓòÉ 16.5.1. Returning multiple values ΓòÉΓòÉΓòÉ
  6958.  
  6959. All VX-REXX projects have an invisible application object that you can use to 
  6960. pass results between files. The object has two methods, PutVar and GetVar, that 
  6961. store and retrieve the value of a variable for the application object. This 
  6962. provides a global variable facility for VX-REXX applications. 
  6963.  
  6964. For example, suppose code in Window1 calls a routine in Window2. The routine 
  6965. must pass back two values to Window1. The calling code in Window1 looks like 
  6966. this: 
  6967.  
  6968. call Window2
  6969. call VRMethod "Application", "GetVar", "parm."
  6970. say "Window2 returned" parm.1 "and" parm.2
  6971.  
  6972. and the called routine in Window2 looks like this: 
  6973.  
  6974. main:
  6975.     parm.0 = 2
  6976.     parm.1 = parm1
  6977.     parm.2 = "Hello"
  6978.     call VRMethod "Application", "PutVar", "parm."
  6979.     return
  6980.  
  6981. The arguments parm1 and "hello" are stored in the compound variable parm. This 
  6982. variable is stored in the application object when Window2 executes the PutVar 
  6983. method. The variable becomes available to Window1 as soon as the GetVar method 
  6984. is called. 
  6985.  
  6986. You can use PutVar in the Fini section to store the values of a stem array 
  6987. before the file exits.  The calling file then uses GetVar to retrieve the 
  6988. values. 
  6989.  
  6990.  
  6991. ΓòÉΓòÉΓòÉ 16.6. Saving files ΓòÉΓòÉΓòÉ
  6992.  
  6993. You may be familiar with saving projects with only one window -- you entered a 
  6994. name for the window file and a name for the project file. When you save a 
  6995. project with multiple windows you are asked for a file name for each window and 
  6996. code file. By default they are set to Window1, Window2... and File1, File2 and 
  6997. so on. The project file contains all of the window and code file names 
  6998. associated with the project. 
  6999.  
  7000. If you have many windows or files, you may want to change the default file 
  7001. names so that it is easier to remember their function. Note that if you change 
  7002. the file name and you have code that refers to the file, you must also change 
  7003. the name in any call statement that refers to it. 
  7004.  
  7005.  
  7006. ΓòÉΓòÉΓòÉ 16.6.1. Saving one file ΓòÉΓòÉΓòÉ
  7007.  
  7008. When you are working with multiple file applications, you may need to edit only 
  7009. one window or code file, or you may want to checkpoint your changes before 
  7010. editing another window. To save changes for one file you do not need to save 
  7011. all of the project files. You can save the window or code file with the Save or 
  7012. Save as menu items from the File menu in the file list window. 
  7013.  
  7014. If you choose Save and it is the first time you are saving the file, you will 
  7015. be prompted for a file name and location. Otherwise, you will not be  prompted 
  7016. to enter a name. The file will be saved with its current name and the previous 
  7017. contents of the file will be overwritten. 
  7018.  
  7019. If you want to save the file with a new name, choose Save as from the Project 
  7020. menu. When you enter a new file name, a file is created with that name and the 
  7021. file list is changed. The file with the old name (e.g. Window1) still exists 
  7022. but the file remains unchanged and is no longer part of the project. 
  7023.  
  7024.  
  7025. ΓòÉΓòÉΓòÉ 16.7. Removing or adding a file ΓòÉΓòÉΓòÉ
  7026.  
  7027. Remove in the File menu lets you remove a file from a project. When you choose 
  7028. Remove, the window file or code file is removed from the project file but is 
  7029. not deleted from the disk. 
  7030.  
  7031. The Add menu item in the File menu lets you add an existing window file or code 
  7032. file to your file list. You may want to use this feature to include a window 
  7033. from another project, to share code on a network, or to add a file that has 
  7034. been removed. 
  7035.  
  7036. When you add a file, only a reference to that file is added to the current 
  7037. project. If the file is shared between projects, changing it in one project 
  7038. changes it in both. However, when you make an executable for the current 
  7039. project, the code for the referenced file is included in the executable file. 
  7040.  
  7041.  
  7042. ΓòÉΓòÉΓòÉ 16.8. Saving a file as text ΓòÉΓòÉΓòÉ
  7043.  
  7044. Since window descriptions are saved in a binary format you cannot change them 
  7045. directly. However, Save as text in the File menu lets you save a window file or 
  7046. code file as a text file. It has the same name as the file but has the 
  7047. extension VRT. A window file  saved as text contains the code that defines the 
  7048. window as well as the REXX code. You can edit and print this file with any text 
  7049. editor. 
  7050.  
  7051.  
  7052. ΓòÉΓòÉΓòÉ 16.9. Loading a file ΓòÉΓòÉΓòÉ
  7053.  
  7054. The Load menu item in the File menu lets you load several different types of 
  7055. files into a VX-REXX project. You can load a file that was saved with the Save 
  7056. as text command. This lets you edit a project outside of VX-REXX and then load 
  7057. it back, converting it to VX-REXX internal format. 
  7058.  
  7059. You can use Load to copy a file from another project. Whereas Add only adds a 
  7060. reference to a file, Load copies the file into a new file in the project. You 
  7061. can change the name when you save the file or project. 
  7062.  
  7063. Load can also be used to load a REXX file. If you load a file with an extension 
  7064. other than VRX or VRT it is assumed to be a REXX file. 
  7065.  
  7066.  
  7067. ΓòÉΓòÉΓòÉ 17. Adding help to a program ΓòÉΓòÉΓòÉ
  7068.  
  7069. This chapter shows you how to add online help to an application. It is good 
  7070. programming practice to include online help in all applications. Three types of 
  7071. online help are supported by VX-REXX: 
  7072.  
  7073. o Information Presentation Facility (IPF) help files. An IPF help file (.HLP) 
  7074.   is a binary file generated by a help compiler from a set of tagged text 
  7075.   files. The IPF help compiler is part of the Client/Server Edition of VX-REXX 
  7076.   and the OS/2 Toolkit, but is not included with the Standard Edition of 
  7077.   VX-REXX. 
  7078.  
  7079. o Simple text files. If you do not have access to an IPF help compiler, you may 
  7080.   use the built-in text file facility instead. The text will be displayed in 
  7081.   windows similar to those used by the IPF help system. 
  7082.  
  7083. o Custom help files. Help requests may be intercepted and handled directly by 
  7084.   your project using the Help event. 
  7085.  
  7086. The user invokes help by pressing the F1 key at any time or by selecting an 
  7087. item from the help menu. 
  7088.  
  7089. VX-REXX also supports an optional status area on windows where hints -- 
  7090. single-line messages -- are displayed. Hints are updated automatically whenever 
  7091. the user moves the pointer over an object. For more information on hints, see 
  7092. the section on using the Window object in "Using objects". 
  7093.  
  7094.  
  7095. ΓòÉΓòÉΓòÉ 17.1. Using IPF help files ΓòÉΓòÉΓòÉ
  7096.  
  7097.  
  7098. ΓòÉΓòÉΓòÉ 17.1.1. Setting the file and title ΓòÉΓòÉΓòÉ
  7099.  
  7100. To associate an IPF help file with a window, set the window's HelpFile 
  7101. property: 
  7102.  
  7103. call VRSet "myWindow", "HelpFile", "myhelp.hlp"
  7104.  
  7105. If you do not give an absolute path and the file is not found in the current 
  7106. directory, the paths in the HELP environment variable will be searched. 
  7107.  
  7108. The title for the IPF help is set using the window's HelpTitle property: 
  7109.  
  7110. call VRSet "myWindow", "HelpTitle", "Help for my application"
  7111.  
  7112.  
  7113. ΓòÉΓòÉΓòÉ 17.1.2. Help tags ΓòÉΓòÉΓòÉ
  7114.  
  7115. Once the IPF file is associated with the window, set the HelpTag properties of 
  7116. the window and the objects on the window to the appropriate IPF tag values. The 
  7117. tag value is a number that was defined when the help file was created. It 
  7118. specifies which section of the help file to display when the F1 key is pressed. 
  7119.  
  7120. The following instructions set the help tag of the window to 1000, and sets the 
  7121. tags for two push buttons to 1001 and 1002: 
  7122.  
  7123. call VRSet "mywindow", "HelpTag", 1000
  7124. call VRSet "PB_1", "HelpTag", 1001
  7125. call VRSet "PB_2", "HelpTag", 1002
  7126.  
  7127. If the F1 key is pressed but no HelpTag property is defined, the parent 
  7128. object's help is invoked. 
  7129.  
  7130. See the section for the HelpTag property for information on how the special 
  7131. tags help index, help contents, extended help, general help and using help. 
  7132.  
  7133.  
  7134. ΓòÉΓòÉΓòÉ 17.1.3. Notes on IPF tags ΓòÉΓòÉΓòÉ
  7135.  
  7136. Help tags correspond to the res, name or id attributes of a heading in an IPF 
  7137. file. The res attribute must be a whole number in the range 1 to 64000, but id 
  7138. and name may be any series of alphanumeric characters. For example: 
  7139.  
  7140. :H1 res=1000.This is a heading
  7141.  
  7142. Links may be established from one help file to another help file (.HLP) or 
  7143. online book (.INF), or from one online book to another online book (but not to 
  7144. a help file), but the headings to be linked must be made global and only the 
  7145. res attribute can be used: 
  7146.  
  7147. :H1 global res=1000.A chapter
  7148.  
  7149. To link to this heading in the "test.hlp" help file, use: 
  7150.  
  7151. :LINK reftype=hd database='test.hlp' refid=1000.A chapter
  7152.  
  7153. If you wish to use symbolic tags (id or name) instead of or in addition to 
  7154. numeric tags (ref), the global attribute cannot be specified and hence no 
  7155. external links may be made to that heading. 
  7156.  
  7157. For more information, please consult the documentation for the OS/2 help 
  7158. compiler. 
  7159.  
  7160.  
  7161. ΓòÉΓòÉΓòÉ 17.2. Using text files for help ΓòÉΓòÉΓòÉ
  7162.  
  7163. The HelpText property may be used as an alternative to the IPF help facility. 
  7164. You may set the help text for an object directly as follows: 
  7165.  
  7166. text = "This is my sample help text."
  7167. call VRSet object, "HelpText", text
  7168.  
  7169. Long text will be word wrapped. You can force new lines by embedding carriage 
  7170. return-line feed pairs ("0d0a"x). 
  7171.  
  7172. The HelpText property can also display text defined in a file: 
  7173.  
  7174. call VRSet object, "HelpText", "(myhelp.txt)"
  7175.  
  7176. The name of the help file is enclosed in parentheses. If an absolute path is 
  7177. not specified, the file must exist in the current directory. 
  7178.  
  7179. The title of the help window is defined by setting the HelpTitle property on 
  7180. the window object. All objects on a window use the same help title. 
  7181.  
  7182. As with IPF help, if the F1 key is pressed but no HelpText property is defined, 
  7183. the parent object's help is invoked. 
  7184.  
  7185.  
  7186. ΓòÉΓòÉΓòÉ 17.3. Invoking help directly ΓòÉΓòÉΓòÉ
  7187.  
  7188. Help can be invoked under program control by using the InvokeHelp method on any 
  7189. object: 
  7190.  
  7191. call VRMethod object, "InvokeHelp"
  7192.  
  7193. The help will be displayed as if the user had pressed the F1 key. 
  7194.  
  7195. The InvokeHelp method can be used in the implementation of a help menu. After 
  7196. defining the appropriate menu items with the menu editor, define the Click 
  7197. event for each menu item as follows: 
  7198.  
  7199. Menu_Click:
  7200.     obj = VRInfo( "object" )
  7201.     call VRMethod obj, "InvokeHelp"
  7202. return
  7203.  
  7204. Now simply set the appropriate help properties on the menu items in the Init 
  7205. section. 
  7206.  
  7207.  
  7208. ΓòÉΓòÉΓòÉ 17.4. Custom help ΓòÉΓòÉΓòÉ
  7209.  
  7210. If your help requirements are more complex, a Help event is available on each 
  7211. window. If the Help event is defined, pressing the F1 key on any object on the 
  7212. window invokes the Help event instead of displaying help or text files as 
  7213. described above. In the event routine, VRInfo can be used to obtain the 
  7214. internal name of the object for which help was requested: 
  7215.  
  7216. Window_Help:
  7217.     help_for = VRInfo( "Source" )
  7218.  
  7219. For example, the InvokeHelp routine may be invoked: 
  7220.  
  7221. Window_Help:
  7222.     help_for = VRInfo( "Source" )
  7223.     call VRMethod help_for, "InvokeHelp"
  7224. return
  7225.  
  7226. A useful way to use the Help event is to display information from online books. 
  7227. An online book (.INF) is similar to a help file (.HLP) -- in fact, both are 
  7228. prepared using tagged text files and the same help compiler -- but is viewed 
  7229. using the OS/2 view command. To invoke view from your project, use the 
  7230. following syntax: 
  7231.  
  7232. address cmd 'view' books topic
  7233.  
  7234. The books variable should hold the name of the book or books to be viewed and 
  7235. topic is the topic (as listed in the table of contents) to view. Several books 
  7236. can be combined into a single volume by using '+' signs, as in: 
  7237.  
  7238. books = 'a2z+progguid+rexx'
  7239.  
  7240. If the topic is omitted, the contents page of the book is displayed instead. 
  7241.  
  7242. For example, to display the online help for the VX-REXX Window object, use: 
  7243.  
  7244. books = 'a2z'
  7245. topic = 'Window object'
  7246. address cmd 'view' books topic
  7247.  
  7248. By storing the book topic in an objects's HelpText property, pages from online 
  7249. books may be easily displayed when F1 is pressed: 
  7250.  
  7251. Window_Help:
  7252.     help_for = VRInfo( "Source" )
  7253.     books    = 'rexx'
  7254.     topic    = VRGet( help_for, "HelpText" )
  7255.     address cmd 'view' books topic
  7256. return
  7257.  
  7258.  
  7259. ΓòÉΓòÉΓòÉ 18. Debugging a project ΓòÉΓòÉΓòÉ
  7260.  
  7261. VX-REXX provides integrated debugging tools within its development environment. 
  7262. The first level of debugging support provides handling and notification of run 
  7263. time exceptions. The second level provides a fully interactive program 
  7264. debugging environment. A traditional method of debugging REXX programs through 
  7265. the use of the say and trace instructions is also supported. 
  7266.  
  7267.  
  7268. ΓòÉΓòÉΓòÉ 18.1. Run time program exceptions ΓòÉΓòÉΓòÉ
  7269.  
  7270. In the VX-REXX system, when a REXX program detects a run time error, the 
  7271. program is terminated and control is returned to VX-REXX. VX-REXX displays a 
  7272. window which notifies you of the error and where the error occurred within the 
  7273. program. Figure 78 shows a sample program exception window. 
  7274.  
  7275. Figure 78  Run time exception error handling
  7276.  
  7277. The error field displays the error which caused the program exception. Below 
  7278. that, the section field shows the section name of the selected line in the 
  7279. traceback list. 
  7280.  
  7281. The traceback list shows the sequence of instructions that led up to the error. 
  7282. The top line shows the file, section, and line number of where the error 
  7283. occurred. The second line shows the erroneous REXX line itself. The next pair 
  7284. of lines identify the code that called the section with the error. Subsequent 
  7285. pairs of lines show which section called that section, and so on. 
  7286.  
  7287. You can edit the section for any of the lines in the traceback list. There are 
  7288. two ways of doing this. Either double click on the line in the traceback list, 
  7289. or select the line, then press Open or External Editor. 
  7290.  
  7291. You cannot continue a program which has terminated due to a run time exception; 
  7292. you must run it again from the beginning. 
  7293.  
  7294.  
  7295. ΓòÉΓòÉΓòÉ 18.2. The interactive debugger ΓòÉΓòÉΓòÉ
  7296.  
  7297. A program is executed in VX-REXX using the Run project command. In this 
  7298. environment, program errors are handled as described previously. A program also 
  7299. can be run in a debugging environment which lets you trace program execution, 
  7300. set breakpoints, and display and modify variables. To use these features, use 
  7301. the Debug project command in the Run menu. No special preparation needs to be 
  7302. done to use the debugger. 
  7303.  
  7304.  
  7305. ΓòÉΓòÉΓòÉ 18.2.1. Debugger windows ΓòÉΓòÉΓòÉ
  7306.  
  7307. There are four types of debugger windows: the section list window, source 
  7308. windows, the variable display window, and the results window. The debugger 
  7309. windows are all sizeable so that you can adjust them to your viewing 
  7310. preference. Each window type is described in the following sections. 
  7311.  
  7312. The section list window 
  7313.  
  7314. The section list shows all of the files in the project, and the section names 
  7315. for the currently selected file. The section list is used to open additional 
  7316. windows to view the source for sections of REXX routines. A debugging session 
  7317. has only one section list. 
  7318.  
  7319. If your project is made up of more than one file, the section list window will 
  7320. present a list of files, and a list of the sections in the files. 
  7321.  
  7322. Figure 79  The section list window
  7323.  
  7324.  
  7325. Source windows 
  7326.  
  7327. A source window displays a section of the project. You can open multiple source 
  7328. windows, each viewing a different section. From a source window, you can set 
  7329. breakpoints and trace statement execution. You can also select variable names 
  7330. to be displayed in the variable window. 
  7331.  
  7332. Figure 80  A debugger source window
  7333.  
  7334.  
  7335. The variable window 
  7336.  
  7337. The variable window displays the values of selected variables. The window is 
  7338. updated each time control is returned to the debugger from the executing 
  7339. program. You add variables to the window by double-clicking on the variable 
  7340. name in any source window. The value of a variable can be changed by modifying 
  7341. the value displayed for that variable in the window. 
  7342.  
  7343. In a multiple file application, the variable window only shows variables 
  7344. associated with the currently active file. 
  7345.  
  7346. Figure 81  The debugger variable window
  7347.  
  7348.  
  7349. The result window 
  7350.  
  7351. The result window displays the information that is output from the REXX 
  7352. interpreter. Three types of information are displayed: the REXX source 
  7353. statement that was run, the result of the statement that was run, and trace 
  7354. messages. The results window has an extra menu: the Options menu. The options 
  7355. menu is used to select the type of information to be displayed. The result 
  7356. window also allows you to enter and run simple REXX statements. 
  7357.  
  7358. Figure 82  The debugger result window
  7359.  
  7360.  
  7361. ΓòÉΓòÉΓòÉ 18.2.2. Starting the debugger ΓòÉΓòÉΓòÉ
  7362.  
  7363. The following steps would be used to start the debugger. 
  7364.  
  7365.  1. Open the project file to be run. 
  7366.  
  7367.  2. Choose Debug project from the Run menu. 
  7368.  
  7369. When the debugger starts up, it displays the section list. The program has not 
  7370. started running at this point. You can examine your program, set breakpoints, 
  7371. and view variables before the program is run. A sample section list window is 
  7372. shown in Figure 79. 
  7373.  
  7374.  
  7375. ΓòÉΓòÉΓòÉ 18.2.3. Viewing REXX instructions ΓòÉΓòÉΓòÉ
  7376.  
  7377. You can view any section from the list of names shown in the section window. To 
  7378. view a particular section, double-click on its name in the section list. In a 
  7379. multiple file application, you need to click on the file name before selecting 
  7380. the section name. This opens a new debugger source window to view the routine. 
  7381. An example source window is shown in Figure 80. The window title contains the 
  7382. name of the section. You can open multiple debugger source windows at the same 
  7383. time. 
  7384.  
  7385. In addition to viewing the REXX statements in a section, a source window is 
  7386. used to set breakpoints, select variables to display, and control tracing of a 
  7387. program. 
  7388.  
  7389.  
  7390. ΓòÉΓòÉΓòÉ 18.2.4. Using breakpoints ΓòÉΓòÉΓòÉ
  7391.  
  7392. In VX-REXX, you use breakpoints to interrupt your program after specified 
  7393. statements. One or more breakpoints can be set in a program. There are two ways 
  7394. to set breakpoints in a program: 
  7395.  
  7396.  1. Open a debugger source window for the section containing the statement. 
  7397.  
  7398.  2. Double-click on the line number for the statement. 
  7399.  
  7400. or 
  7401.  
  7402.  1. Select Set from the Breakpoints menu in any debugger source window. 
  7403.  
  7404.  2. Select the file name and section name. 
  7405.  
  7406.  3. Type in the line number of the statement. 
  7407.  
  7408.  4. Click the OK button. 
  7409.  
  7410. The line number of a statement with a breakpoint has a red background. Figure 
  7411. 83 shows a routine with two breakpoints set. 
  7412.  
  7413. Figure 83  Source window with breakpoints
  7414.  
  7415. Once the breakpoints have been set, you can run the program by selecting Run 
  7416. from the Run menu. The program runs normally until an instruction with a 
  7417. breakpoint is executed. At this point, the debugger suspends the program and 
  7418. opens a source window displaying the section which contains the breakpoint. In 
  7419. it, the instruction that was just executed is highlighted. The source window 
  7420. will appear similar to Figure 84. 
  7421.  
  7422. Figure 84  Program halted at a breakpoint
  7423.  
  7424. While the program is suspended at a breakpoint, you can add new breakpoints, 
  7425. clear existing breakpoints, view contents of variables, modify contents of 
  7426. variables, and resume running. 
  7427.  
  7428. To clear a breakpoint from a statement, use either of the following procedures: 
  7429.  
  7430.  1. Open a debugger source window for the section containing the statement. 
  7431.  
  7432.  2. Double-click on the line number for the statement. This action clears the 
  7433.     breakpoint. 
  7434.  
  7435. or 
  7436.  
  7437.  1. Select Clear from the Breakpoints menu. 
  7438.  
  7439.  2. Select one or more breakpoints in the list. You can select all breakpoints 
  7440.     by clicking the Select All button. 
  7441.  
  7442.  3. Click the OK button. The breakpoint will be cleared. 
  7443.  
  7444.  
  7445. ΓòÉΓòÉΓòÉ 18.2.5. Tracing a program ΓòÉΓòÉΓòÉ
  7446.  
  7447. The debugger lets you interactively step through your program statement by 
  7448. statement. Tracing through your program is controlled by commands in the Run 
  7449. menu. 
  7450.  
  7451. To run the next instruction in your program, select Step from the Run menu. 
  7452. After the instruction completes, control is returned to the debugger. Every 
  7453. time you execute a step, the variable list is updated, and the instruction you 
  7454. just executed is highlighted. 
  7455.  
  7456. The Step command always steps into called routines. If you do not want to trace 
  7457. into a called routine, use the Step Over command. This command executes the 
  7458. called routine, then stops after the routine returns. This capability is useful 
  7459. to avoid tracing routines that you know work correctly. You can use Step Over 
  7460. at any time; if the next instruction is not a call instruction, Step Over just 
  7461. does a Step. 
  7462.  
  7463. If you want to execute the same instruction again, use the Redo command from 
  7464. the Run menu. For instance, you might modify the contents of a variable which 
  7465. is used in the statement that was just run. Re-running the statement would use 
  7466. the new value. 
  7467.  
  7468. To resume normal execution of your program, select Run from the Run menu. Your 
  7469. program will resume execution until another breakpoint is encountered, you 
  7470. interrupt the program, or your program completes normally. If your program 
  7471. completes or if an error occurs, the debugging session ends and you return to 
  7472. program editing. Interrupting a running program is discussed in a later 
  7473. section. 
  7474.  
  7475.  
  7476. ΓòÉΓòÉΓòÉ 18.2.6. Displaying and modifying variables ΓòÉΓòÉΓòÉ
  7477.  
  7478. You can examine and modify the contents of variables while the program is being 
  7479. debugged. The debugger variable window displays a list of selected variable 
  7480. names with associated values. The values for these variables are updated each 
  7481. time that the debugger resumes control of the executing program. A variable 
  7482. window is shown in Figure 81. 
  7483.  
  7484. To add a variable to the debugger variable window: 
  7485.  
  7486.  1. Open a debugger source window with a section that references the variable. 
  7487.  
  7488.  2. Double-click on the variable name. 
  7489.  
  7490. The selected variable is inserted into the variables window. Its value is 
  7491. displayed in an entry field to the right of the variable name. If no value has 
  7492. been assigned to the variable, "(uninitialized)" appears beside the name. 
  7493.  
  7494. Selection of a variable name is not context sensitive. Any word which is 
  7495. selected in a REXX statement will be used as a variable name, whether or not 
  7496. the word represents an actual variable name. 
  7497.  
  7498. You can change the value of a variable before execution of the program resumes. 
  7499. To change the current value of a variable: 
  7500.  
  7501.  1. Add the variable name to the variable window. 
  7502.  
  7503.  2. Click on the entry field which contains the variable's value. A cursor will 
  7504.     appear in the entry field. 
  7505.  
  7506.  3. Change the value. This new value will be used when the program continues 
  7507.     running. 
  7508.  
  7509. You can remove variables from the variable window once you are through with 
  7510. them. To remove a variable: 
  7511.  
  7512.  1. Click on the variable name in the variables window. 
  7513.  
  7514.  2. Select Delete from the Edit menu in the variables window. This action 
  7515.     removes the variable from the window. 
  7516.  
  7517.  
  7518. ΓòÉΓòÉΓòÉ 18.2.7. Interrupting a program ΓòÉΓòÉΓòÉ
  7519.  
  7520. Sometimes you may want to interrupt your program before it reaches a breakpoint 
  7521. or the end of the program. You can do this by selecting Break from the Run 
  7522. menu. You can pick this menu item whenever your program is running. After you 
  7523. interrupt the program, the debugger updates the trace and variable windows, 
  7524. giving you control again. 
  7525.  
  7526. If you want to quit the debugger before your program terminates, close the 
  7527. section list window. You can do this at any time. After leaving the debugger, 
  7528. you will return to the VX-REXX design environment. 
  7529.  
  7530.  
  7531. ΓòÉΓòÉΓòÉ 18.2.8. Executing a REXX instruction ΓòÉΓòÉΓòÉ
  7532.  
  7533. The project source cannot be modified while the program is being executed by 
  7534. the debugger. However, simple REXX statements can be entered and executed 
  7535. immediately in the debugger results window. 
  7536.  
  7537. Suppose you wanted to print the value of some expression while debugging a 
  7538. program. If the expression was 
  7539.  
  7540. interest * capital
  7541.  
  7542. You would do the following: 
  7543.  
  7544.  1. Select Results from the Windows menu, or type Ctrl+R to open the result 
  7545.     window. 
  7546.  
  7547.  2. In the entry field at the bottom of the window, type the REXX instruction 
  7548.  
  7549.         say interest * capital
  7550.  
  7551.  3. Press Enter to run the statement. 
  7552.  
  7553. The output from the say instruction is displayed in the body of the results 
  7554. window. 
  7555.  
  7556.  
  7557. ΓòÉΓòÉΓòÉ 18.2.9. Run time exception handling in the debugger ΓòÉΓòÉΓòÉ
  7558.  
  7559. A run time exception can occur while the program is executed under control of 
  7560. the debugger. When a run time exception is encountered, the debugger terminates 
  7561. and you return to the VX-REXX editing environment. You will see the Errors 
  7562. window that is described at the beginning of this chapter. 
  7563.  
  7564.  
  7565. ΓòÉΓòÉΓòÉ 18.2.10. Quitting the debugger ΓòÉΓòÉΓòÉ
  7566.  
  7567. When your program terminates, the debugger shuts down automatically, and you 
  7568. return to the design environment. If you want to quit your application before 
  7569. it ends, close the section list. 
  7570.  
  7571.  
  7572. ΓòÉΓòÉΓòÉ 18.3. Debugging with the say and trace instructions ΓòÉΓòÉΓòÉ
  7573.  
  7574. The REXX say instruction can be an effective way to trace your program and to 
  7575. display the value of variables. When the first say instruction is executed, the 
  7576. standard input/output (STDIO) console window is opened for your application. 
  7577. Results from the say and trace instructions are displayed in this window. If 
  7578. your program uses the parse pull instruction, it gets input from the STDIO 
  7579. window. The window remains open until your program terminates. 
  7580.  
  7581. Adding conditional statements around say instructions allows the debugging 
  7582. statements to be executed only when it is desired. For instance, in the 
  7583. following example the say instruction would only be executed if the value of 
  7584. the variable Debug is true. 
  7585.  
  7586. if Debug then do
  7587.      Say "Insert appropriate information to say"
  7588. end
  7589.  
  7590. The value of Debug can be set under program control or interactively using the 
  7591. debugger variable window. 
  7592.  
  7593. Similarly, the REXX trace instruction can also be used to trace the execution 
  7594. of your program. The results of the trace instruction are displayed in the 
  7595. STDIO window. In this way, you can debug your programs as if you were using a 
  7596. generic REXX environment. 
  7597.  
  7598. You can use the trace instruction along with the Run project command, but not 
  7599. with the Debug project command. 
  7600.  
  7601.  
  7602. ΓòÉΓòÉΓòÉ 19. Extending VX-REXX ΓòÉΓòÉΓòÉ
  7603.  
  7604. This chapter discusses how to extend your VX-REXX projects using VX-REXX object 
  7605. libraries and REXX external function libraries. 
  7606.  
  7607.  
  7608. ΓòÉΓòÉΓòÉ 19.1. Object libraries ΓòÉΓòÉΓòÉ
  7609.  
  7610. New objects can be developed for VX-REXX by third party developers and packaged 
  7611. as object libraries. After installing an object library using the instructions 
  7612. provided by the library developer, the objects in the library can be loaded 
  7613. into the VX-REXX design environment and used in your projects. Object libraries 
  7614. have extensions of .VXO or .DLL. 
  7615.  
  7616. To load an object library, select the Object libraries item of the Options menu 
  7617. and add the name of the object library to the list of libraries to load. You 
  7618. may also set an option to automatically search for and load all installed 
  7619. object libraries. 
  7620.  
  7621. After the object library is loaded, the tool palette is enlarged to accommodate 
  7622. the new objects. You may use the object as if it were one of the standard 
  7623. VX-REXX objects. 
  7624.  
  7625. Projects that use an object from an object library will automatically search 
  7626. for and load the object library when they are run. 
  7627.  
  7628. For more information on how to develop objects for use with VX-REXX, contact 
  7629. Watcom International. 
  7630.  
  7631.  
  7632. ΓòÉΓòÉΓòÉ 19.2. Function libraries ΓòÉΓòÉΓòÉ
  7633.  
  7634. An external function library is an OS/2 dynamic link library (.DLL) that 
  7635. defines a set of functions callable from REXX programs. To use these functions, 
  7636. they must first be registered with the REXX interpreter using the RXFUNCADD 
  7637. function. 
  7638.  
  7639. For example, when the OS/2 REXX interpreter is installed, an external function 
  7640. library called REXXUTIL is also installed. To ensure that the library is 
  7641. available to your program, add the following lines to the Init section of your 
  7642. project: 
  7643.  
  7644. call RXFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs"
  7645. call SysLoadFuncs
  7646.  
  7647. Any of the REXXUTIL functions may then be used by your project. 
  7648.  
  7649. Documentation for the REXXUTIL functions is available online as part of the 
  7650. REXX Information book installed in the VX-REXX folder. Help may also be 
  7651. obtained from the OS/2 command line by typing: 
  7652.  
  7653. help rexx rexxutil
  7654.  
  7655. Other function libraries are also available from third party developers on a 
  7656. variety of electronic media. 
  7657.  
  7658.  
  7659. ΓòÉΓòÉΓòÉ 20. Using databases with VX-REXX ΓòÉΓòÉΓòÉ
  7660.  
  7661. This chapter shows you how to use VX-REXX to create applications that use the 
  7662. REXX interface to IBM's Database 2 OS/2 (DB2/2) or Watcom SQL for OS/2. You 
  7663. should read this chapter if you have the Standard Edition of VX-REXX. If you 
  7664. have the Client/Server Edition, read the Watcom VX-REXX for OS/2 Client/Server 
  7665. Edition book instead. That manual describes the database objects, bound 
  7666. objects, and query editor tool that come with the Client/Server Edition. 
  7667. Contact Watcom for information about the Client/Server Edition. 
  7668.  
  7669. Both DB2/2 and Watcom SQL have Application Programming Interfaces (APIs) for a 
  7670. number of languages including REXX. An application that has a REXX API provides 
  7671. routines that a REXX program can call to interact with that application. Any 
  7672. OS/2 software package that supports a REXX API can be used with VX-REXX. 
  7673.  
  7674. Because VX-REXX projects are written in REXX, you can use VX-REXX to create 
  7675. database applications using the REXX API. The following sections show you how 
  7676. to build a sample application with which you can display and update information 
  7677. in an employee database. The complete program, Employee database, is included 
  7678. in the Samples folder contained in the VX-REXX folder. 
  7679.  
  7680. This chapter assumes that you are familiar with database terminology and that 
  7681. you have DB2/2 or Watcom SQL installed. If you are using DB2/2, you need the 
  7682. sample database that comes with DB2/2. If you are using Watcom SQL, the 
  7683. application uses an equivalent database that comes with VX-REXX. 
  7684.  
  7685. See IBM's Database 2 OS/2 Guide for information about installing the sample 
  7686. database for DB2/2. (To use the sample database you must first install it: 
  7687. enter sqlsampl at an OS/2 command prompt. When first installed, the sample 
  7688. database uses the userid userid and the password password). 
  7689.  
  7690.  
  7691. ΓòÉΓòÉΓòÉ 20.1. Overview ΓòÉΓòÉΓòÉ
  7692.  
  7693. Using the REXX database API requires several steps, all of which are shown in 
  7694. this chapter: 
  7695.  
  7696. o Registering the API routines 
  7697. o Starting the database manager (DB2/2 or Watcom SQL) 
  7698. o Opening the database 
  7699. o Preparing an SQL statement 
  7700. o Declaring a cursor 
  7701. o Retrieving the data 
  7702. o Closing the cursor 
  7703. o Closing the database 
  7704. o Stopping the database manager 
  7705.  
  7706. Some of these steps may be performed outside of your VX-REXX application if the 
  7707. application is just one of several that will use DB2/2 in an OS/2 session. 
  7708. These include registering the routines and starting and stopping DB2/2. 
  7709.  
  7710. The program uses an employee database which has two tables: STAFF and ORG. The 
  7711. application retrieves several fields for all staff members and displays them in 
  7712. a window. Figure 85 shows the project's window. 
  7713.  
  7714. Figure 85  Sample database application
  7715.  
  7716. The buttons on the window initiate some database action: 
  7717.  
  7718. Button              Description 
  7719.  
  7720. First               Display information for the first employee in the database. 
  7721.  
  7722. Next                Display the next employee. 
  7723.  
  7724. Previous            Display the previous employee. This button is enabled only 
  7725.                     if you are using Watcom SQL. 
  7726.  
  7727. Delete              Remove the current employee from the database. 
  7728.  
  7729. Update              Replace the information for the current employee with the 
  7730.                     values in the entry fields. 
  7731.  
  7732. New                 Add a new employee to the database using values shown in 
  7733.                     the window. 
  7734.  
  7735. Quit                Close the database and terminate the application. Pressing 
  7736.                     this button is equivalent to double-clicking on the 
  7737.                     window's system menu. 
  7738.  
  7739.  
  7740. ΓòÉΓòÉΓòÉ 20.2. Registering routines ΓòÉΓòÉΓòÉ
  7741.  
  7742. There are two REXX API routines that are used in this sample application: 
  7743.  
  7744. SQLEXEC             Used to process all SQL requests. 
  7745.  
  7746. SQLDBS              Used to call DB2/2 environment routines and utility 
  7747.                     routines. 
  7748.  
  7749. There are other routines which provide access to the Query Manager but they are 
  7750. not used in this program. For a complete description of the REXX API refer to 
  7751. the IBM manuals Database 2 OS/2 Programming Guide and Database 2 OS/2 
  7752. Programming Reference, or the Watcom SQL User's Guide. 
  7753.  
  7754. Before using these routines, you must register them using the RxFuncAdd 
  7755. routine. Once registered they remain in effect until they are dropped (with 
  7756. RxFuncDrop) or you shutdown OS/2. 
  7757.  
  7758. The following code registers the functions. Note that the REXX code to register 
  7759. these routines is different for DB2/2 and Watcom SQL. The code assumes the 
  7760. variable Globals.!DBtype contains WSQL if you are using Watcom SQL. 
  7761.  
  7762. call RxFuncDrop "SQLDBS"
  7763. call RxFuncDrop "SQLEXEC"
  7764.  
  7765. if( Globals.!DBtype = "WSQL" ) then do
  7766.     call RxFuncAdd "SQLDBS", "WSQLCAL2", "WSQLDBSREXX"
  7767.     call RxFuncAdd "SQLEXEC", "WSQLCAL2", "WSQLEXECREXX"
  7768. end
  7769. else do
  7770.     call RxFuncAdd "SQLDBS", "SQLAR", "SQLDBS"
  7771.     call RxFuncAdd "SQLEXEC", "SQLAR", "SQLEXEC"
  7772. end
  7773.  
  7774. These statements are in the Init section of the Employee database sample 
  7775. program. 
  7776.  
  7777.  
  7778. ΓòÉΓòÉΓòÉ 20.3. Starting the database manager ΓòÉΓòÉΓòÉ
  7779.  
  7780. You must start the database manager (DB2/2 or Watcom SQL) before you can access 
  7781. the database. The database manager processes the SQL statements that you issue 
  7782. in your program. In this sample program, the database is assumed to be 
  7783. installed locally and for a single user. 
  7784.  
  7785. For both DB2/2 and Watcom SQL, the command to start the database manager is: 
  7786.  
  7787. call SQLDBS "START DATABASE MANAGER"
  7788.  
  7789.  
  7790. ΓòÉΓòÉΓòÉ 20.4. Connecting to the database ΓòÉΓòÉΓòÉ
  7791.  
  7792. Once the database manager is started you can connect to the database and access 
  7793. its tables. The REXX command to connect to the DB2/2 sample database is: 
  7794.  
  7795. call SQLDBS "START USING DATABASE sample"
  7796.  
  7797. while the command to connect to the equivalent Watcom SQL database is: 
  7798.  
  7799. call SQLDBS "START USING DATABASE db22samp USER DBA IDENTIFIED BY SQL"
  7800.  
  7801.  The parameter sample (or db22samp) is the name of the database that you are 
  7802. using. 
  7803.  
  7804. These statements appear in the Init section, after the REXX API routines are 
  7805. registered. 
  7806.  
  7807.  
  7808. ΓòÉΓòÉΓòÉ 20.5. Database API return codes ΓòÉΓòÉΓòÉ
  7809.  
  7810. SQLEXEC and SQLDBS set predefined REXX variables each time they are executed. 
  7811. One of these is a compound variable SQLCA (SQL Communication Area). The 
  7812. database returns values to an application program through the set of variables 
  7813. defined in the SQLCA variable structure. The variable SQLCA.SQLCODE contains 
  7814. the primary error code. If the command is successful, the return code is 0. A 
  7815. positive error code indicates a warning condition and a negative error code 
  7816. indicates an abnormal condition. 
  7817.  
  7818. It is good programming practice to check the error code after each database 
  7819. call to ensure that the command completed successfully. For example, if the 
  7820. database manager cannot be started, your application should inform the user 
  7821. that something is wrong rather then blindly proceeding. The following 
  7822. statements make this check: 
  7823.  
  7824. call SQLDBS "START DATABASE MANAGER"
  7825. if( SQLCA.SQLCODE \= 0 & SQLCA.SQLCODE \= -1026 ) then do
  7826.     call VRMessage VRWindow(), ,
  7827.                    "Could not start the database manager:", ,
  7828.                    "SQLCODE =" SQLCA.SQLCODE, "Error"
  7829.     return
  7830. end
  7831.  
  7832. If the database is started successfully the return code is 0. The code -1026 is 
  7833. returned if the database is already started. Note that a comma at the end of a 
  7834. line is the REXX line continuation character. 
  7835.  
  7836. The VX-REXX function VRMessage displays the error code. 
  7837.  
  7838.  
  7839. ΓòÉΓòÉΓòÉ 20.6. Preparing the SELECT statement ΓòÉΓòÉΓòÉ
  7840.  
  7841. An SQL query is readied with an SQL PREPARE statement. The sample program 
  7842. prepares and issues a SELECT statement to retrieve the name, id, job, 
  7843. department name, salary, commission, and length of employment for each staff 
  7844. member in the organization. 
  7845.  
  7846. In the following code, the first line defines the SQL query and assigns it to 
  7847. stmt. The second line readies the SQL request. 
  7848.  
  7849. stmt = "SELECT name, id, job, dept, salary, comm, years",
  7850.        "FROM staff",
  7851.        "ORDER BY name"
  7852. call SQLEXEC "PREPARE s1 FROM :stmt"
  7853.  
  7854. The colon before stmt tells the database that this is a REXX variable. 
  7855.  
  7856. If there are errors in your SQL query, the PREPARE command will not complete 
  7857. successfully so you should check the SQLCA.SQLCODE. When you are creating a 
  7858. program with a number of SQL queries you may want to test them using DB2/2's 
  7859. Query Manager or Watcom SQL's ISQL before coding them in your program. 
  7860.  
  7861.  
  7862. ΓòÉΓòÉΓòÉ 20.7. Declaring a cursor ΓòÉΓòÉΓòÉ
  7863.  
  7864. You must declare a cursor before you can access the database tables. Declaring 
  7865. a cursor involves reserving a predefined cursor-name statement-name pair for 
  7866. the SELECT statement. A cursor is used to retrieve rows one at a time from the 
  7867. results of a query. The cursor names and statement names are always the letters 
  7868. C and S followed by an integer from 1 to 100. The integer for the cursor and 
  7869. statement should correspond. The pair are reserved with the SQL DECLARE 
  7870. statement: 
  7871.  
  7872. call SQLEXEC "DECLARE c1 cursor for s1"
  7873.  
  7874. You can use up to 100 cursor-statement pairs so that you can have up to 100 SQL 
  7875. queries active at any one time. 
  7876.  
  7877. In the sample program the cursor is declared in the StartQuery section. 
  7878.  
  7879.  
  7880. ΓòÉΓòÉΓòÉ 20.8. Retrieving the data ΓòÉΓòÉΓòÉ
  7881.  
  7882. After the SELECT statement has been prepared and the cursor has been declared, 
  7883. you can retrieve the results of the query one row at a time. The SQL OPEN 
  7884. command positions the cursor at the first row of the result table. You can then 
  7885. retrieve the values and assign them to REXX variables using the SQL FETCH 
  7886. command. 
  7887.  
  7888. The following code opens cursor C1 and reads data for the first employee into a 
  7889. number of REXX variables. 
  7890.  
  7891. call SQLEXEC "OPEN c1"
  7892. call SQLEXEC "FETCH c1 INTO",
  7893.              ":Globals.!Emp.!name :ind.1,",
  7894.              ":Globals.!Emp.!id :ind.2,",
  7895.              ":Globals.!Emp.!job :ind.3,",
  7896.              ":Globals.!Emp.!dept :ind.4,",
  7897.              ":Globals.!Emp.!salary :ind.5,",
  7898.              ":Globals.!Emp.!comm :ind.6,",
  7899.              ":Globals.!Emp.!years :ind.7"
  7900.  
  7901. This code appears in the Fetch routine in the sample program. 
  7902.  
  7903. In the Employee database, the values assigned to the REXX variables by the 
  7904. FETCH command are then displayed in the fields on the window. 
  7905.  
  7906.  
  7907. ΓòÉΓòÉΓòÉ 20.9. Displaying results ΓòÉΓòÉΓòÉ
  7908.  
  7909. In the sample program the Next click event displays the results of the FETCH 
  7910. instruction in the entry fields. The VRSet function assigns the values from the 
  7911. REXX variables to the entry field values. 
  7912.  
  7913. call VRSet "EF_Name", "Value", Globals.!Emp.!name
  7914. call VRSet "EF_Id", "Value", Globals.!Emp.!id
  7915. call VRSet "EF_Job", "Value", Globals.!Emp.!job
  7916. call VRSet "EF_Dept", "Value", Globals.!Emp.!dept
  7917. call VRSet "EF_Salary", "Value", Globals.!Emp.!salary
  7918. call VRSet "EF_Comm", "Value", Globals.!Emp.!comm
  7919. call VRSet "EF_Years", "Value", Globals.!Emp.!years
  7920.  
  7921.  
  7922. ΓòÉΓòÉΓòÉ 20.10. Closing the cursor ΓòÉΓòÉΓòÉ
  7923.  
  7924. When you are done making changes to a cursor, you must close it. The following 
  7925. statement closes cursor c1: 
  7926.  
  7927. call SQLEXEC "CLOSE c1"
  7928.  
  7929. If you want to make the changes to the database permanent, you must commit 
  7930. them. Alternatively, you can throw them away. The following code asks the user 
  7931. whether the changes should be saved, then executes a COMMIT or ROLLBACK 
  7932. command, depending on the user's choice. 
  7933.  
  7934. button.0 = 2
  7935. button.1 = "~Save"
  7936. button.2 = "~Discard"
  7937. rc = VRMessage( VRWindow(),,
  7938.          "Changes have been made to the database." ||,
  7939.          "Do you want to save or discard them?",,
  7940.          "Employee database",,
  7941.          "Q", "button.", 1, 2 )
  7942. if( rc = 1 ) then do
  7943.     call SQLEXEC "COMMIT"
  7944. end
  7945. else do
  7946.     call SQLEXEC "ROLLBACK"
  7947. end
  7948.  
  7949. Code similar to that shown here appears in the Quit routine of the Employee 
  7950. database sample. 
  7951.  
  7952.  
  7953. ΓòÉΓòÉΓòÉ 20.11. Stopping the database manager ΓòÉΓòÉΓòÉ
  7954.  
  7955. Before you close the application you should disconnect from the database and 
  7956. then stop the database manager. The following code does this. 
  7957.  
  7958. call SQLDBS "STOP USING DATABASE"
  7959. call SQLDBS "STOP DATABASE MANAGER"
  7960.  
  7961. Code similar to that shown here appears in the Quit routine of the Employee 
  7962. database sample. 
  7963.  
  7964.  
  7965. ΓòÉΓòÉΓòÉ 20.12. Where to go from here ΓòÉΓòÉΓòÉ
  7966.  
  7967. Combining the power and versatility of VX-REXX and SQL, you can create complex 
  7968. database programs using the basic steps outlined in this chapter. 
  7969.  
  7970. You can also create database applications using the database objects in the 
  7971. Client/Server Edition of VX-REXX. With the Client/Server Edition, you can bind 
  7972. VX-REXX objects directly to database queries so that their values are set 
  7973. automatically from the database. The Client/Server Edition also comes with a 
  7974. design tool for constructing your SELECT statements using a visual 
  7975. point-and-click interface. Contact Watcom for more information about the 
  7976. Client/Server Edition of VX-REXX. 
  7977.  
  7978.  
  7979. ΓòÉΓòÉΓòÉ 21. Writing multithreaded applications ΓòÉΓòÉΓòÉ
  7980.  
  7981. REXX programs are made up of one or more files. In the programs presented 
  7982. earlier in this book, only one file ran at a time. While one file may call 
  7983. another, the first file waits while the second one runs, so that only one 
  7984. routine is being run at a time. These types of programs are called single 
  7985. threaded. 
  7986.  
  7987. Your REXX program can take advantage of VX-REXX multithreading capabilities by 
  7988. executing a number of files at once on different threads. These programs are 
  7989. said to be multithreaded. 
  7990.  
  7991. All programs have at least one thread, called the main thread. The program can 
  7992. create more threads if required, although it is not a requirement to have more 
  7993. than one. Some guidelines on using threads are given later in this chapter. 
  7994.  
  7995. Threads are not processes. A process is a programming unit that has its own 
  7996. memory and resources. A process may use threads to do its work in the same way 
  7997. that a company uses employees. 
  7998.  
  7999. The rest of this chapter deals with specific topics related to programming with 
  8000. threads. 
  8001.  
  8002.  
  8003. ΓòÉΓòÉΓòÉ 21.1. Planning your application ΓòÉΓòÉΓòÉ
  8004.  
  8005. If you want your application to perform some task in the background, you should 
  8006. use threads. If you want to make more than one window active at a time, you can 
  8007. also use threads, but it may be more convenient to use modeless windows 
  8008. instead. 
  8009.  
  8010. Note that using threads does not necessarily make your program faster. Even 
  8011. though two REXX files may be executing at once, they still have to share the 
  8012. computer's CPU and hard drives. 
  8013.  
  8014. When planning your program, you should design it with threads in mind, but you 
  8015. should not use threads right away. Debugging a single threaded program is much 
  8016. easier than debugging a multithreaded one because only one thing is happening 
  8017. at a time. Once you have debugged a single threaded version of your 
  8018. application, then make use of threads. 
  8019.  
  8020. In most programs, a master-worker model for threads works well. In it, a master 
  8021. thread starts a number of worker threads which do some processing, then post a 
  8022. result back to the master thread. While it is possible to start threads from 
  8023. other threads, sticking to the master-worker model usually leads to code that 
  8024. is easier to develop and debug. 
  8025.  
  8026.  
  8027. ΓòÉΓòÉΓòÉ 21.2. Starting a code file thread ΓòÉΓòÉΓòÉ
  8028.  
  8029. To start a code file as a thread, use the StartThread method on the Application 
  8030. object. Starting a thread is similar to calling a file: you give the name of 
  8031. the file and a list of parameters. The following code starts executing the file 
  8032. File1 on a separate thread. 
  8033.  
  8034. tid = VRMethod( "Application", "StartThread", "File1" )
  8035. if tid = -1 then do
  8036.     say "Could not start thread."
  8037. end
  8038.  
  8039. The method returns a thread identifier. The main thread of the application 
  8040. always has the identifier 0. 
  8041.  
  8042. The maximum number of threads that can be active at any one time is 200. In 
  8043. addition, there are system limits defined in your OS/2 CONFIG.SYS file that 
  8044. provide an upper bound on the total number of threads that can be running 
  8045. across all processes. 
  8046.  
  8047.  
  8048. ΓòÉΓòÉΓòÉ 21.3. Starting a window file as a thread ΓòÉΓòÉΓòÉ
  8049.  
  8050. To start a window file as a thread, you also use the StartThread method, but 
  8051. prefix the word subroutine to name of the window file and pass the value of 
  8052. VRWindow or a null string as the first parameter: 
  8053.  
  8054. tid = VRMethod( "Application", "StartThread", ,
  8055.                 "subroutine Window2", VRWindow() )
  8056.  
  8057. The thread is started as a REXX subroutine, as opposed to a REXX command. The 
  8058. Main section of the window file uses this information and the value of the 
  8059. first parameter to assign the window's parent. If a null string is passed, the 
  8060. window's parent is the desktop. Otherwise the window is similar to a modeless 
  8061. secondary window, except that it is running on its on thread and as a separate 
  8062. file. 
  8063.  
  8064.  
  8065. ΓòÉΓòÉΓòÉ 21.4. Communicating with a thread ΓòÉΓòÉΓòÉ
  8066.  
  8067. You can pass data to a thread in the following ways: 
  8068.  
  8069. o Parameters to the StartThread method 
  8070.  
  8071.   The optional parameters to the StartThread method are passed to the thread in 
  8072.   the same way that they would if the file was simply called. For example, 
  8073.  
  8074.     call Worker "Hello"
  8075.  
  8076.   and 
  8077.  
  8078.     call VRMethod "Application", "StartThread", "Worker", "Hello"
  8079.  
  8080.   and 
  8081.  
  8082.     call VRMethod "Application", "StartThread", "subroutine Worker", ,
  8083.                   VRWindow(), "Hello"
  8084.  
  8085.   pass the string "Hello" to Worker. In the first case, Worker is called 
  8086.   synchronously. In the second, Worker is run as a code file on a new thread. 
  8087.   In the third case, Worker is run as a window file on a new thread. 
  8088.  
  8089. o Posting events to the master thread 
  8090.  
  8091.   A worker thread can post an event back to its master thread to report when it 
  8092.   is finished. The thread can use the PostQueue method to do this. 
  8093.  
  8094.   For example, suppose Worker is a code-only file that counts the words in a 
  8095.   text file whose name is passed as a parameter. The code for Worker is: 
  8096.  
  8097.     main:
  8098.         parse arg filename
  8099.  
  8100.         /* Count the words in a text file
  8101.         */
  8102.         count = 0
  8103.         do forever
  8104.             text = Linein( filename )
  8105.             if text == "" then leave
  8106.             count = count + Words( text )
  8107.         end
  8108.         call Stream filename, "C", "Close"
  8109.  
  8110.         /* Post the result back to the main thread
  8111.         */
  8112.         call VRMethod "Application", "PostQueue", 0, 1,,
  8113.             "call WorkerDone", "WordCount", count
  8114.  
  8115.     return
  8116.  
  8117.   When Worker has counted all the words in the file, it posts the event "call 
  8118.   WorkerDone" to the main queue of the main thread. This event is executed in 
  8119.   the main event loop, thus calling the routine named WorkerDone. 
  8120.  
  8121.   The WorkerDone routine uses VRInfo to retrieve the word count that was posted 
  8122.   by the Worker thread: 
  8123.  
  8124.     WorkerDone:
  8125.         count = VRInfo( "WordCount" )
  8126.         say "There are" count "words in the file."
  8127.     return
  8128.  
  8129. o Global data 
  8130.  
  8131.   Threads can use the PutVar and GetVar methods of the Application object to 
  8132.   share information between threads. Since there is only one application 
  8133.   object, access to global data is serialized. 
  8134.  
  8135.  
  8136. ΓòÉΓòÉΓòÉ 21.5. Getting information about running threads ΓòÉΓòÉΓòÉ
  8137.  
  8138. Your program can get a list of running threads using the ListThreads 
  8139. application method. A thread can get its own identifier by invoking the 
  8140. GetThreadID method. 
  8141.  
  8142.  
  8143. ΓòÉΓòÉΓòÉ 21.6. Halting a thread ΓòÉΓòÉΓòÉ
  8144.  
  8145. Use the HaltThread method to halt a thread. For example, the following 
  8146. instruction halts the thread whose thread identifier is in the variable tid: 
  8147.  
  8148. call VRMethod "Application", "HaltThread", tid
  8149.  
  8150. Halting does not destroy the thread, but instead causes a REXX HALT condition 
  8151. to occur. Halt conditions are automatically trapped by the Halt section of a 
  8152. file. If the thread is blocked doing a lengthy operation (such as a database 
  8153. access), the halt condition is only raised when the threads resumes execution. 
  8154.  
  8155. You cannot halt the main thread of your application. 
  8156.  
  8157.  
  8158. ΓòÉΓòÉΓòÉ 22. Controlling other programs ΓòÉΓòÉΓòÉ
  8159.  
  8160. VX-REXX includes a number of facilities to enable your projects to control 
  8161. other programs. The following topics are covered in this chapter: 
  8162.  
  8163. o Running programs and executing OS/2 commands 
  8164.  
  8165. o Manipulating other programs' windows 
  8166.  
  8167. o Sending key strokes to programs 
  8168.  
  8169. o Communicating with programs via DDE 
  8170.  
  8171. o Writing VX-REXX macros for other programs 
  8172.  
  8173.  
  8174. ΓòÉΓòÉΓòÉ 22.1. Running programs and executing OS/2 commands ΓòÉΓòÉΓòÉ
  8175.  
  8176. Your project can run other OS/2 programs and commands using several methods. 
  8177.  
  8178.  
  8179. ΓòÉΓòÉΓòÉ 22.1.1. The address instruction ΓòÉΓòÉΓòÉ
  8180.  
  8181. OS/2 programs and commands are executed from within a project using the address 
  8182. instruction: 
  8183.  
  8184. address cmd "dir"
  8185.  
  8186. Your project waits for the program or command to finish executing before 
  8187. continuing. The special variable RC holds the return value of the program or 
  8188. command. 
  8189.  
  8190. To start a program or command without waiting for it to finish, use the OS/2 
  8191. start command, as in: 
  8192.  
  8193. address cmd "start epm readme.txt"
  8194.  
  8195. The start command can also be used to start DOS and Microsoft Windows programs. 
  8196. For help on the OS/2 start command, type help start from an OS/2 command 
  8197. window. 
  8198.  
  8199.  
  8200. ΓòÉΓòÉΓòÉ 22.1.2. SysCreateObject and SysSetObjectData ΓòÉΓòÉΓòÉ
  8201.  
  8202. Another way to start programs is to use the SysCreateObject and 
  8203. SysSetObjectData functions from the REXXUTIL external function library. To use 
  8204. these functions you must first load the library as described in the "Extending 
  8205. VXΓêÖREXX" chapter. 
  8206.  
  8207. The following code opens a Workplace Shell object with id <SOME_PROGRAM>: 
  8208.  
  8209. object = "<SOME_PROGRAM>"
  8210. setup = "OPEN=DEFAULT"
  8211. call SysSetObjectData object, setup
  8212.  
  8213. See the online REXX Information for details on using the SysCreateObject and 
  8214. SysSetObjectData functions. 
  8215.  
  8216.  
  8217. ΓòÉΓòÉΓòÉ 22.1.3. Running commands that require OS/2 session VIO support ΓòÉΓòÉΓòÉ
  8218.  
  8219. Since VX-REXX projects are Presentation Manager (PM) programs, you cannot 
  8220. directly execute OS/2 commands or programs which require VIO support. These are 
  8221. programs that expect to be running in an OS/2 windowed or full screen session. 
  8222. For example, the OS/2 PSTAT command uses VIO support. If you try to run it from 
  8223. REXX, you will get a "SYS0436: An invalid VIO handle was found" error. 
  8224.  
  8225. Use the OS/2 start command to run these programs. The following instructions 
  8226. will run PSTAT in its own OS/2 window: 
  8227.  
  8228. address cmd "start /win pstat <con >con"
  8229.  
  8230. The use of the redirection symbols < and > is explained below. 
  8231.  
  8232.  
  8233. ΓòÉΓòÉΓòÉ 22.1.4. Redirecting standard input, output and error ΓòÉΓòÉΓòÉ
  8234.  
  8235. By default, VX-REXX redirects the standard input, output, and error streams to 
  8236. its console window. If you launch a program or execute an OS/2 command, the 
  8237. output is sent to the console and input is taken from the console. 
  8238.  
  8239. For example, the following instruction sends a directory listing to the 
  8240. console: 
  8241.  
  8242. address cmd "dir"
  8243.  
  8244. When you run non-PM programs, the output is sent to the console unless you 
  8245. explicitly redirect it. The following instruction will run PSTAT in its own 
  8246. OS/2 window, and the results will be displayed in the window. 
  8247.  
  8248. address cmd "start /win pstat <con >con"
  8249.  
  8250. If the program you are running writes to standard error, you should add 2>con 
  8251. to redirect standard error, as follows: 
  8252.  
  8253. address cmd "start /win pstat <con >con 2>con"
  8254.  
  8255. For more information on redirection, see the Master Help Index which is 
  8256. originally installed in the Information folder on your desktop. Read the 
  8257. "Redirecting" and "Input and output" sections. 
  8258.  
  8259.  
  8260. ΓòÉΓòÉΓòÉ 22.2. Manipulating windows ΓòÉΓòÉΓòÉ
  8261.  
  8262. Presentation Manager (PM) windows (not to be confused with VX-REXX Window 
  8263. objects) can be used as arguments to VRGet, VRSet and VRMethod. 
  8264.  
  8265. To identify a window, you must know its window handle. The window handle is a 
  8266. 4-byte hexadecimal value assigned to a window by PM. The window handle must be 
  8267. combined with the prefix ?HWND before passing it to VX-REXX functions:  for 
  8268. example, ?HWND08ef34. 
  8269.  
  8270. The console window is one exception to this rule: the name Console may be used 
  8271. to identify it. 
  8272.  
  8273.  
  8274. ΓòÉΓòÉΓòÉ 22.2.1. Finding a window ΓòÉΓòÉΓòÉ
  8275.  
  8276. Window handles are obtained using several methods: 
  8277.  
  8278. o Use the FindWindow method to find a window whose caption matches certain 
  8279.   criteria. 
  8280.  
  8281. o Use the ListWindows method to list all the top-level windows. 
  8282.  
  8283. o Use the GetActiveWindow method to obtain the current active window. 
  8284.  
  8285. o Use the GetFocusWindow method to obtain the current focus window. 
  8286.  
  8287. o Use the HWnd property to obtain an object's window. 
  8288.  
  8289. o Use the ServerHWnd property to obtain the handle to a DDE server. 
  8290.  
  8291. o Use ?HWND1 for the root desktop window and ?HWND2 for the root object window. 
  8292.  
  8293. Once a window handle has been obtained, the Parent, Sibling and FirstChild 
  8294. properties can be used to find the parent, sibling or child of a window. (If a 
  8295. null string is returned, no such window exists.) 
  8296.  
  8297. All window handles are returned in the correct format for use with VRGet, VRSet 
  8298. and VRMethod. 
  8299.  
  8300.  
  8301. ΓòÉΓòÉΓòÉ 22.2.2. Setting window properties ΓòÉΓòÉΓòÉ
  8302.  
  8303. Once you have a window's handle, you can use VRSet to set any of the following 
  8304. properties of that window: 
  8305.  
  8306. Left                The position of the window's left edge. 
  8307.  
  8308. Top                 The position of the window's top edge. 
  8309.  
  8310. Width               The width of the window. 
  8311.  
  8312. Height              The height of the window. 
  8313.  
  8314. Caption             The contents of the window's title bar. 
  8315.  
  8316. Visible             Whether or not the window is visible. 
  8317.  
  8318. Enabled             Whether or not the window is enabled. 
  8319.  
  8320. Parent              The window's parent. 
  8321.  
  8322. SiblingOrder        (frame windows only) The next window in the z-order, if 
  8323.                     any. 
  8324.  
  8325. WindowState         (frame windows only) Whether the window is minimized or 
  8326.                     maximized. 
  8327.  
  8328. WindowListTitle     (frame windows only) The text that appears in the OS/2 
  8329.                     Window List for this window. 
  8330.  
  8331. Set these properties as you would for VX-REXX objects. For example, the 
  8332. following code looks for a window with the caption OS/2 Window and makes it 
  8333. visible: 
  8334.  
  8335. hwnd = VRMethod( "Screen", "FindWindow", "OS/2 Window", "Desktop" )
  8336. if( hwnd \= "" )then do
  8337.     call VRSet hwnd, "Visible", 1
  8338. end
  8339.  
  8340.  
  8341. ΓòÉΓòÉΓòÉ 22.2.3. Getting window properties ΓòÉΓòÉΓòÉ
  8342.  
  8343. You can also use VRGet with a window handle to obtain information about a 
  8344. window. In addition to those properties listed above, you can also get the 
  8345. following properties VRGet: 
  8346.  
  8347. ClassName           The name of the window's PM window class. 
  8348.  
  8349. ProcessID           The ID of the process that created the window. 
  8350.  
  8351. ThreadID            The ID of the thread that created the window. 
  8352.  
  8353. ID                  The window ID (a number from 0 to 65535). 
  8354.  
  8355. Parent              The parent window, if any. 
  8356.  
  8357. Sibling             The next window in the z-order, if any. 
  8358.  
  8359. FirstChild          The first child window, if any. 
  8360.  
  8361. Owner               The owner window, if any. 
  8362.  
  8363. Self, HWnd          The window handle. 
  8364.  
  8365. Object              The internal name of the VX-REXX object corresponding to 
  8366.                     the window handle, if any. 
  8367.  
  8368. The following code uses GetFocusWindow to determine which object (if any) in 
  8369. your project has the input focus: 
  8370.  
  8371. focus = VRMethod( "Screen", "GetFocusWindow" )
  8372. if( focus \= "" )then do
  8373.     focus = VRGet( focus, "Object" )
  8374. end
  8375.  
  8376.  
  8377. ΓòÉΓòÉΓòÉ 22.2.4. Window methods ΓòÉΓòÉΓòÉ
  8378.  
  8379. VRMethod may be used to invoke certain methods on windows: 
  8380.  
  8381. o SetFocus 
  8382.  
  8383. o Maximize (frame windows only) 
  8384.  
  8385. o Minimize (frame windows only) 
  8386.  
  8387. o Restore (frame windows only) 
  8388.  
  8389. o Clear (VX-REXX Console window only) 
  8390.  
  8391. To set the focus to an arbitrary window, for example: 
  8392.  
  8393. call VRMethod hwnd, "SetFocus"
  8394.  
  8395.  
  8396. ΓòÉΓòÉΓòÉ 22.2.5. Example programs ΓòÉΓòÉΓòÉ
  8397.  
  8398. The Window Controller and Hocus Focus example programs in the Samples folder 
  8399. demonstrate the use of window handles. 
  8400.  
  8401.  
  8402. ΓòÉΓòÉΓòÉ 22.3. Sending keystrokes ΓòÉΓòÉΓòÉ
  8403.  
  8404. Keystrokes may be sent to other Presentation Manager applications, and in some 
  8405. cases to windowed DOS and OS/2 applications, using the SendKeyString and 
  8406. PostKeyString methods of the Application object. 
  8407.  
  8408. The syntax for SendKeyString is as follows: 
  8409.  
  8410. call VRMethod "Application", "SendKeyString", object, keystring
  8411.  
  8412. The syntax for PostKeyString is similar: 
  8413.  
  8414. call VRMethod "Application", "PostKeyString", object, keystring
  8415.  
  8416. For both methods object identifies the target object or window to which the 
  8417. keys are to be sent and keystring is the sequences of keystrokes to send. If a 
  8418. null string is specified as the target object for SendKeyString, the keystrokes 
  8419. will be sent to the window with the input focus. 
  8420.  
  8421. Two things differentiate the SendKeyString and PostKeyString methods: 
  8422.  
  8423.  1. PostKeyString sends keystrokes to an object without waiting for them to be 
  8424.     processed. These posted (queued) keystrokes are not translated into 
  8425.     accelerator sequences. (Accelerator sequences are sequences of keystrokes 
  8426.     that an application intercepts and handles before they can be passed to a 
  8427.     window. Accelerators are usually used as shortcuts to activate menu items.) 
  8428.  
  8429.  2. SendKeyString sends keystrokes to an object one at a time, waiting until 
  8430.     each is processed before sending the next. Each keystroke will also be 
  8431.     checked for accelerator sequences. 
  8432.  
  8433. If you send a keystring, a special sequence such as {Alt}{F4} may be handled as 
  8434. an accelerator, but not if it is posted. 
  8435.  
  8436.  
  8437. ΓòÉΓòÉΓòÉ 22.3.1. Keystroke syntax ΓòÉΓòÉΓòÉ
  8438.  
  8439. Keystrokes are described using the same syntax that the KeyString property 
  8440. uses. To send the characters A, B and C in sequence, use the string ABC. To 
  8441. send a control character, prefix the character with the string {Ctrl}, as in 
  8442. {Ctrl}Z. The strings {Alt} and {Shift} are used to specify the Alt and Shift 
  8443. keys, as in {Alt}H or {Shift}{F3}. Function keys are specified as {F1}, {F2}, 
  8444. and so on. 
  8445.  
  8446. You can combine modifiers: 
  8447.  
  8448. {Ctrl}{Shift}J
  8449. {Alt}{Ctrl}{F10}
  8450.  
  8451. Modifiers only apply to a single keystroke. The following string is used to 
  8452. send the two keystrokes Alt+F and O: 
  8453.  
  8454. {Alt}FO
  8455.  
  8456. A similar example sends Alt+Z followed by Ctrl+X: 
  8457.  
  8458. {Alt}Z{Ctrl}X
  8459.  
  8460. There is no fixed limit on the number of keystrokes allowed in a single string, 
  8461. but you should keep the sequences fairly short. 
  8462.  
  8463.  
  8464. ΓòÉΓòÉΓòÉ 22.3.2. Controlling other applications ΓòÉΓòÉΓòÉ
  8465.  
  8466. Keystrokes can be sent to objects within your own project or to windows in 
  8467. other applications. You need to know two things: 
  8468.  
  8469.  1. Decide which keystrokes are needed and whether they involve accelerators. 
  8470.     If accelerators are needed, you must use SendKeyString. 
  8471.  
  8472.  2. Decide which object or window is to be sent the keystrokes. If you want to 
  8473.     send keys to whichever window has the focus, use SendKeyString. 
  8474.  
  8475. The first step requires that you run the application you wish to control and 
  8476. write down the series of keystrokes used to accomplish your task. 
  8477.  
  8478. The second step requires some programming if you cannot simply assume that the 
  8479. destination window will be the window with the input focus. Use the methods 
  8480. outlined in the section above on finding window handles. 
  8481.  
  8482.  
  8483. ΓòÉΓòÉΓòÉ 22.3.3. Controlling a MultiLineEntryField ΓòÉΓòÉΓòÉ
  8484.  
  8485. The MultiLineEntryField object can be controlled quite extensively by sending 
  8486. it keystrokes. The MLE understands the following keystrokes: 
  8487.  
  8488. Key string          Effect 
  8489.  
  8490. {Del}               Deletes the selected region or the character to the right 
  8491.                     of the cursor. 
  8492.  
  8493. {Shift}{Del}        Cuts the contents of the selected region to the clipboard. 
  8494.  
  8495. {Ins}               Toggles between insert and overstrike mode. 
  8496.  
  8497. {Shift}{Ins}        Paste the clipboard contents into the currently selected 
  8498.                     region. 
  8499.  
  8500. {Backspace}         Deletes the selected region or the character to the left of 
  8501.                     the cursor. 
  8502.  
  8503. {Down}, {Up}, {Left}, {Right} These all move the cursor. Add a {Shift} 
  8504.                     character to select text as well. 
  8505.  
  8506. {Ctrl}{Left}, {Ctrl}{Right} Move to the previous or next word. 
  8507.  
  8508. {Ctrl}{Shift}{Left}, {Ctrl}{Shift}{Right} Select until the previous or next 
  8509.                     word. 
  8510.  
  8511. {PageUp}, {PageDown} Move up or down a page. 
  8512.  
  8513. {Ctrl}{PageUp}, {Ctrl}{PageDown} Scroll to the left or right. 
  8514.  
  8515. {Home}              Move to the beginning of the line. 
  8516.  
  8517. {End}               Move to the end of the line. 
  8518.  
  8519. {Shift}{Home}       Select from the current point to the beginning of the line. 
  8520.  
  8521. {Shift}{End}        Select from the current point to the end of the line. 
  8522.  
  8523. {Ctrl}{Home}        Move to the beginning of the data. 
  8524.  
  8525. {Ctrl}{End}         Move to the end of the data. 
  8526.  
  8527. {Ctrl}{Shift}{Home} Select from the current point to the beginning of the data. 
  8528.  
  8529. {Ctrl}{Shift}{End}  Select from the current point to the end of the data. 
  8530.  
  8531. A simple way to control an MLE in your own application is to define a routine 
  8532. such as this: 
  8533.  
  8534. SendToMLE: procedure
  8535.     call VRMethod "Application", "PostKeyString", arg(1), arg(2)
  8536. return
  8537.  
  8538. Call it as follows: 
  8539.  
  8540. call SendToMLE "MLE_1", "{Ctrl}{Home}"
  8541.  
  8542. Note that PostKeyString is used in case the control sequences the MLE 
  8543. understands conflict with accelerators in your project. 
  8544.  
  8545.  
  8546. ΓòÉΓòÉΓòÉ 22.3.4. DOS and OS/2 Windows ΓòÉΓòÉΓòÉ
  8547.  
  8548. Because of a limitation in OS/2 itself, only other Presentation Manager 
  8549. applications can be controlled by sending them keystrokes directly. Windowed 
  8550. DOS and OS/2 sessions can be sent some keystrokes, however, using the following 
  8551. method: 
  8552.  
  8553.  1. Copy the string of keys you wish to send into the clipboard using the 
  8554.     PutClipboard method. Note that the special sequences {Alt}, {Ctrl}, and so 
  8555.     on will not be translated. If you wish to send a special character, you 
  8556.     must do the translation yourself, by finding the appropriate hexadecimal 
  8557.     value for the character. For example, to add a Ctrl+M (carriage return) to 
  8558.     the end of text (which is what pressing Enter typically does) you would do 
  8559.     the following: 
  8560.  
  8561.         str = str || "0d"x
  8562.  
  8563.     because Ctrl+M maps to 0D hexadecimal. 
  8564.  
  8565.  2. Find the frame window of the DOS or OS/2 session. Use any of the methods 
  8566.     previously discussed. 
  8567.  
  8568.  3. Send a message to the frame to update its menu in case the Paste option was 
  8569.     previously disabled. 
  8570.  
  8571.  4. Send the string p to the frame window's system menu. The characters from 
  8572.     the clipboard are now pasted into the session. 
  8573.  
  8574. Here is a simple example of how to send the dir command to a DOS or OS/2 
  8575. window, using the call: 
  8576.  
  8577. call TypeInWindow win, "dir" || "0d"x
  8578.  
  8579. Where TypeInWindow is defined as: 
  8580.  
  8581. /* This function sends keystrokes to a DOS or OS/2 window
  8582. */
  8583. TypeInWindow: procedure
  8584.     parse arg frame, keys
  8585.     if( VRGet( frame, "ClassName" ) = "WC_FRAME" )then do
  8586.         call VRMethod "Application", "PutClipboard", keys
  8587.         call PasteToWindow frame
  8588.     end
  8589. return
  8590.  
  8591.  
  8592. /* Find the system menu and send it a 'p' to invoke the
  8593.    paste menu item
  8594. */
  8595. PasteToWindow: procedure
  8596.     parse arg frame
  8597.  
  8598.     child = VRGet( frame, "FirstChild" )
  8599.     do while( child \= "" )
  8600.         if( VRGet( child, "ClassName" ) = "WC_MENU" & ,
  8601.             VRGet( child, "Id" ) = 32770 )then do
  8602.             call VRMethod "Screen", "WinSendMsg", frame, 0x0033, ,
  8603.                           32770, child
  8604.             call VRMethod "Application", "SendKeyString", ,
  8605.                           child, "p"
  8606.             leave
  8607.         end
  8608.         child = VRGet( child, sibling )
  8609.     end
  8610. return
  8611.  
  8612.  
  8613. ΓòÉΓòÉΓòÉ 22.4. Dynamic Data Exchange (DDE) client ΓòÉΓòÉΓòÉ
  8614.  
  8615. DDE (Dynamic Data Exchange) is an OS/2 facility that allows applications to 
  8616. exchange data. Two applications engage in a DDE conversation, with one 
  8617. application being the DDE client (the one requesting the data), and the other a 
  8618. DDE server (the one responding to requests). 
  8619.  
  8620. VX-REXX provides a DDE client, which allows your programs to talk to other 
  8621. applications, such as spreadsheets and word processors. It is possible, for 
  8622. example, to write a VX-REXX program that extracts data from a spreadsheet, then 
  8623. inserts that data into a word processing document. 
  8624.  
  8625. DDE conversations always have a topic, which is defined when the client first 
  8626. connects to the server. The topic defines the context for the conversation. For 
  8627. example, when conversing with a word processor, the topic might be the file 
  8628. name of an open document. All DDE servers have a topic called System which can 
  8629. be used to obtain information about the server itself. 
  8630.  
  8631.  
  8632. ΓòÉΓòÉΓòÉ 22.4.1. Creating a DDE client ΓòÉΓòÉΓòÉ
  8633.  
  8634. You create a DDE client the same way you create other VX-REXX objects: select 
  8635. its icon from the tool bar, then click on the window you are editing. The 
  8636. DDEClient looks similar to a DescriptiveText object. When your application 
  8637. runs, the DDE client updates its caption to describe its current state, a 
  8638. feature which is useful in debugging. When you are satisfied that your 
  8639. application is running correctly, you can make the DDE client invisible by 
  8640. setting its Visible property to 0. 
  8641.  
  8642.  
  8643. ΓòÉΓòÉΓòÉ 22.4.2. Initiating a conversation ΓòÉΓòÉΓòÉ
  8644.  
  8645. A DDE client can participate in only one conversation at a time. You establish 
  8646. a conversation to a DDE server using the Initiate and Accept methods. Initiate 
  8647. fills a stem variable with the list of servers and topics. Each compound 
  8648. variable contains a string of the form "server,topic". 
  8649.  
  8650. call VRMethod "DDEC_1", "Initiate", "conv."
  8651. do i = 1 to conv.0
  8652.     parse var conv.i server "," topic
  8653.     say "Conversation with" server "on topic" topic
  8654. end
  8655.  
  8656. You can also initiate a conversation with a particular server and topic. The 
  8657. following code connects to server Lotus, topic System. 
  8658.  
  8659. call VRMethod "DDEC_1", "Initiate", "conv.", "Lotus", "System"
  8660. if conv.0 = 0 then do
  8661.     call VRMessage VRWindow(), "Could not connect"
  8662. end
  8663.  
  8664. At this point, no conversation has been established. The Accept method must be 
  8665. invoked to select a topic and server. 
  8666.  
  8667. call VRMethod "DDEC_1", "Accept", 3
  8668.  
  8669. The optional parameter indicates the conversation to accept (as returned by 
  8670. Initiate). If omitted, the first conversation is accepted. 
  8671.  
  8672.  
  8673. ΓòÉΓòÉΓòÉ 22.4.3. Executing server commands ΓòÉΓòÉΓòÉ
  8674.  
  8675. To send strings to the DDE server for execution, use the Execute method. The 
  8676. syntax of the command string depends on the DDE server. Refer to the server 
  8677. application's documentation for a list of commands it will accept. 
  8678.  
  8679. The Execute method returns BUSY if the server could not process the command. 
  8680. The following code fragment sends a command and resends it if the server is 
  8681. busy. 
  8682.  
  8683. cmd = "[Type("Some text")]"
  8684. do forever
  8685.     status = VRMethod( "DDEC_1", "Execute", cmd )
  8686.     if( status \= "BUSY" ) then leave
  8687. end
  8688.  
  8689. A NoWait option is available to send a command to the server without waiting 
  8690. for the reply. When the reply arrives, it will generate an Acknowledge event. 
  8691.  
  8692.  
  8693. ΓòÉΓòÉΓòÉ 22.4.4. Requesting data ΓòÉΓòÉΓòÉ
  8694.  
  8695. Your application can request information from a DDE server using the Request 
  8696. and RequestList methods. Request sends a single request, while RequestList 
  8697. sends a number of requests using tab characters as delimiters. 
  8698.  
  8699. All servers support the following requests: 
  8700.  
  8701. Topics              A list of topics for the server 
  8702.  
  8703. SysItems            A list of items available from the Server topic 
  8704.  
  8705. Refer to the server documentation for details on valid item names. 
  8706.  
  8707. The Request method is also used to create warm links and hot links between the 
  8708. client and the server. Hot and warm links notify the client using the Notify 
  8709. event when a requested data item in the server has changed value. In a hot link 
  8710. (automatic notification), the new value is automatically sent to the client. In 
  8711. a warm link, the client fetches the new value from the server. 
  8712.  
  8713.  
  8714. ΓòÉΓòÉΓòÉ 22.4.5. Sending data ΓòÉΓòÉΓòÉ
  8715.  
  8716. Data can be sent to a server using the Poke method. The server sets an item to 
  8717. a given value. 
  8718.  
  8719. For example, the following instruction sets the value of cell B15 to 23.7 in a 
  8720. Lotus 1-2-3 spreadsheet: 
  8721.  
  8722. call VRMethod client, "Poke", "B15", "23.7"
  8723.  
  8724. Refer to the server documentation for details on valid item names. 
  8725.  
  8726.  
  8727. ΓòÉΓòÉΓòÉ 22.4.6. Getting the status of a conversation ΓòÉΓòÉΓòÉ
  8728.  
  8729. The DDE client stores information about the conversation in the following 
  8730. properties: 
  8731.  
  8732. Status              Indicates whether the conversation is still active 
  8733.  
  8734. Server              The name of the DDE server 
  8735.  
  8736. Topic               The conversation topic 
  8737.  
  8738. Use VRGet to retrieve these properties at run time. 
  8739.  
  8740.  
  8741. ΓòÉΓòÉΓòÉ 22.4.7. Terminating a conversation ΓòÉΓòÉΓòÉ
  8742.  
  8743. Use the Terminate method to end a conversation. A DDE client automatically 
  8744. terminates an existing conversation when it is destroyed or when a new 
  8745. conversation is initiated. 
  8746.  
  8747.  
  8748. ΓòÉΓòÉΓòÉ 22.5. Application macros ΓòÉΓòÉΓòÉ
  8749.  
  8750. Some OS/2 applications such as the OS/2 Enhanced Editor use REXX as a macro 
  8751. language to extend the capability of the application. 
  8752.  
  8753. The following example is a macro for the Enhanced Editor which displays the 
  8754. number of lines in a file. 
  8755.  
  8756. /* A simple macro using the Enhanced Editor */
  8757. "extract /last"
  8758. lineCount = last.1
  8759. "sayerror File contains" lineCount "lines"
  8760.  
  8761. The statements in quotation marks are commands which are sent to the default 
  8762. command host -- in this case, the Enhanced Editor. The line containing the word 
  8763. sayerror is an Enhanced Editor command which displays the phrase "File contains 
  8764. n lines" on the status line of the editor window. 
  8765.  
  8766. Macros for the Enhanced Editor must be saved in a file with the extension ERX. 
  8767. For instance, the above example might be saved in the file named COUNT.ERX. To 
  8768. invoke the macro: 
  8769.  
  8770.  1. Start EPM. 
  8771.  
  8772.  2. Pick Command dialog under the (EPM) Command menu, or type Ctrl+I to open 
  8773.     the command dialog. 
  8774.  
  8775.  3. Type COUNT.ERX to start the macro. 
  8776.  
  8777.  
  8778. ΓòÉΓòÉΓòÉ 22.5.1. Creating application macros with VX-REXX ΓòÉΓòÉΓòÉ
  8779.  
  8780. You can use VX-REXX to create application macro files. These files are invoked 
  8781. by the target application. After the macro has been created within VX-REXX, you 
  8782. can make the application macro file which is invoked from within the host 
  8783. application. 
  8784.  
  8785. You can create macro files from a VX-REXX project which contain only generic 
  8786. REXX instructions and commands. You can also create macro files which include 
  8787. the visual user interface capabilities of VX-REXX. 
  8788.  
  8789. You cannot debug an application macro within VX-REXX since you must invoke the 
  8790. macro from within the host application. However, you can still use standard 
  8791. REXX debugging techniques which typically use the REXX trace statement and 
  8792. standard input and output. To simplify debugging a macro in a Presentation 
  8793. Manager session, include the VRRedirectStdIO function in your macro to redirect 
  8794. standard input and output to the VX-REXX console window. 
  8795.  
  8796. To create a new application macro project: 
  8797.  
  8798.  1. Create a new project folder by dragging and dropping the VX-REXX Project 
  8799.     template. 
  8800.  
  8801.  2. Open the project file within the new folder. 
  8802.  
  8803.  3. If no window is required, create a code-only project by selecting New code 
  8804.     file from the Project menu. 
  8805.  
  8806.  4. Build the macro user interface if required, and enter the REXX 
  8807.     instructions. 
  8808.  
  8809.  5. Create the application macro file by selecting Make macro from the Project 
  8810.     menu. 
  8811.  
  8812. You can now invoke the macro file from an application. 
  8813.  
  8814.  
  8815. ΓòÉΓòÉΓòÉ 22.5.2. Using application macro examples ΓòÉΓòÉΓòÉ
  8816.  
  8817. The following examples are simple macros which you can create and run with the 
  8818. OS/2 Enhanced Editor. The procedures described here may differ for other 
  8819. application programs which use REXX as a macro language. For example, the 
  8820. Enhanced Editor requires that the REXX instructions be saved in a file with an 
  8821. extension of ERX, such as TEST.ERX, instead of the standard CMD extension. 
  8822.  
  8823. Writing a macro with no window 
  8824.  
  8825. The following sample REXX instructions display the number of lines in a file 
  8826. using the Enhanced Editor sayerror command. To try this example, place these 
  8827. REXX instructions in the predefined routine Main of a code file only project. 
  8828.  
  8829. /*   */
  8830. "extract /last"
  8831. lineCount = last.1
  8832. "sayerror File contains" lineCount "lines"
  8833.  
  8834. Assuming you make an application macro file named DISPLAY.ERX, you would type 
  8835. the following line in the Enhanced Editor's command dialog: 
  8836.  
  8837. rx display
  8838.  
  8839. In this example, the macro would cause the phrase "File contains n lines" to 
  8840. appear in the status area of the Enhanced Editor. 
  8841.  
  8842. Writing a macro with a window 
  8843.  
  8844. The following sample REXX instructions request the number of lines in a file 
  8845. and display this number in a VX-REXX window. To try this example, start a new 
  8846. project, then modify your Init routine to be the following: 
  8847.  
  8848. Init:
  8849.     window = VRWindow()
  8850.  
  8851.     /* Set the window caption to the number of lines
  8852.     */
  8853.     "extract /last"
  8854.     information = "file contains" last.1 "lines"
  8855.     call VRSet window, "Caption", information
  8856.  
  8857.     /* Show the window
  8858.     */
  8859.     call VRMethod window, "CenterWindow"
  8860.     call VRSet window, "Visible", 1
  8861.     call VRMethod window, "Activate"
  8862.     drop window
  8863. return
  8864.  
  8865. Assuming you make an application macro file named DISPLAY.ERX, the following 
  8866. line would be used to invoke the macro from the Enhanced Editor: 
  8867.  
  8868. rx display
  8869.  
  8870. In this example, the macro would cause the phrase "File contains n lines" to 
  8871. appear as the title of the window. 
  8872.  
  8873. When you try this macro, you may notice that clicking on the EPM window brings 
  8874. it to the front, covering the macro window. If you want to make the macro 
  8875. window modal to the application, you must disable the application window and 
  8876. set the owner of the macro window to be the application window. The following 
  8877. Init routine shows how to do this. 
  8878.  
  8879. Init:
  8880.     window = VRWindow()
  8881.  
  8882.     /* Set the window owner to the EPM window
  8883.     */
  8884.     epmWindow = VRMethod( "Screen", "GetActiveWindow" )
  8885.     call VRSet window, "FrameOwner", epmWindow
  8886.  
  8887.     /* Disable the EPM window
  8888.     */
  8889.     call VRSet epmWindow, "Enabled", 0
  8890.  
  8891.     /* Set the window caption to the number of lines
  8892.     */
  8893.     "extract /last"
  8894.     information = "file contains" last.1 "lines"
  8895.     call VRSet window, "Caption", information
  8896.  
  8897.     /* Show the window
  8898.     */
  8899.     call VRMethod window, "CenterWindow"
  8900.     call VRSet window, "Visible", 1
  8901.     call VRMethod window, "Activate"
  8902.     drop window
  8903. return
  8904.  
  8905. When the user closes the macro window, the EPM window must be enabled. The 
  8906. following Fini routine shows how to do this. 
  8907.  
  8908. Fini:
  8909.     window = VRWindow()
  8910.     call VRSet window, "FrameOwner", ""
  8911.     call VRSet epmWindow, "Enabled", 1
  8912.     drop window
  8913. return 0
  8914.  
  8915.  
  8916. ΓòÉΓòÉΓòÉ 23. Creating objects at run time ΓòÉΓòÉΓòÉ
  8917.  
  8918. This chapter explains how to create objects at run time and how to associate 
  8919. events to them. 
  8920.  
  8921.  
  8922. ΓòÉΓòÉΓòÉ 23.1. Using VRCreate and VRCreateStem ΓòÉΓòÉΓòÉ
  8923.  
  8924. Any object may be created at run time by your project using the VRCreate and 
  8925. VRCreateStem functions. Objects created at run time are no different than 
  8926. objects created at design time. 
  8927.  
  8928. The first argument to VRCreate and VRCreateStem identifies the parent object, 
  8929. either by its name (as returned by the Name property) or by its internal name 
  8930. (as returned by the Self property). For most objects this argument will be the 
  8931. name of the window or group box the object is to be a child of. A null string 
  8932. can only be used when creating primary windows. 
  8933.  
  8934. The second argument to VRCreate and VRCreateStem identifies the type of object 
  8935. to create. For example, PushButton or Window. 
  8936.  
  8937. The remaining arguments, if any, set initial property values. The following 
  8938. example uses VRCreate to create a ListBox: 
  8939.  
  8940. listbox = VRCreate( VRWindow(), "ListBox", ,
  8941.                     "Name", "UserListbox", ,
  8942.                     "Visible", 1, ,
  8943.                     "Left", 200, ,
  8944.                     "Top", 200, ,
  8945.                     "Width", 600, ,
  8946.                     "Height", 1000 )
  8947.  
  8948. The same list box can be created using VRCreateStem as follows: 
  8949.  
  8950. props.0 = 12
  8951. props.1 = "Name"
  8952. props.2 = "UserListbox"
  8953. props.3 = "Visible"
  8954. props.4 = 1
  8955. props.5 = "Left"
  8956. props.6 = 200
  8957. props.7 = "Top"
  8958. props.8 = 200
  8959. props.9 = "Width"
  8960. props.10 = 600
  8961. props.11 = "Height"
  8962. props.12 = 1000
  8963.  
  8964. listbox = VRCreateStem( VRWindow(), "ListBox", "props." )
  8965.  
  8966. Because external REXX functions can accept at most 20 arguments, VRCreateStem 
  8967. must be used in place of VRCreate when a large number of properties are to be 
  8968. set. 
  8969.  
  8970. VRCreate and VRCreateStem both return the internal name of the new object or a 
  8971. null string if the object could not be created.  The internal name can be used 
  8972. to refer to the object if the object's Name property was not set. 
  8973.  
  8974.  
  8975. ΓòÉΓòÉΓòÉ 23.2. Setting properties at creation time ΓòÉΓòÉΓòÉ
  8976.  
  8977. All properties that can be set at run time using VRSet may be set when the 
  8978. object is being created. Certain properties can only be set when the object is 
  8979. being created and are "read-only" after the call to VRCreate or VRCreateStem. 
  8980. The only way to change such a property after the object has been created is to 
  8981. destroy the old object and create a new one in its place. 
  8982.  
  8983. The ListProperties method may be used to list which of an object's properties 
  8984. must be set at creation time only and which can be set at any time. 
  8985.  
  8986.  
  8987. ΓòÉΓòÉΓòÉ 23.3. Attaching events to an object ΓòÉΓòÉΓòÉ
  8988.  
  8989. Event routines can be defined for an object created at run time by setting 
  8990. properties when the object is created or at any time after. For each event an 
  8991. object supports, a corresponding property exists and it is simply a matter of 
  8992. assigning the name of a REXX procedure to that property. 
  8993.  
  8994. For example, to assign a Click event to a push button: 
  8995.  
  8996. call VRSet pb, "Click", "call PushButton_Click"
  8997.  
  8998. The value of the property is a REXX call statement. When the push button is 
  8999. clicked, VX-REXX will call the PushButton_Click routine in the file. Note that 
  9000. REXX does not allow procedures to be defined at run time; you must define the 
  9001. procedures you wish to call in the design environment by creating new sections. 
  9002. Your procedures should use the VRInfo function to obtain the object name. 
  9003.  
  9004. This technique may be used at run time to assign new event routines to any 
  9005. object. 
  9006.  
  9007.  
  9008. ΓòÉΓòÉΓòÉ 23.4. Events and event queues ΓòÉΓòÉΓòÉ
  9009.  
  9010. Events are processed on a first-come, first-serve basis by calling the VREvent 
  9011. function and interpreting the string it returns. Events are kept in a queue, 
  9012. and VREvent removes the first event from the queue. The VRInit function creates 
  9013. a new event queue and makes it the current queue, while VRFini destroys the 
  9014. current event queue and makes the previous queue the current one. VREvent 
  9015. always searches the current event queue. VRInit and VRFini are called 
  9016. automatically in the Main section of each window file. 
  9017.  
  9018. Events are processed in the order in which they occur by repeated calls to 
  9019. VREvent in the Main section of the window file. An event that is being 
  9020. processed will not be interrupted by another event. 
  9021.  
  9022. Each object is associated with an event queue. For Window objects, it is the 
  9023. event queue that was current when the object was created. For all other 
  9024. objects, it is the parent object's event queue. The objects associated with an 
  9025. event queue are destroyed when the queue is destroyed. 
  9026.  
  9027. Events can be posted to a queue using the PostEvent and PostQueue methods. 
  9028.  
  9029.  
  9030. ΓòÉΓòÉΓòÉ 23.5. Destroying objects ΓòÉΓòÉΓòÉ
  9031.  
  9032. Objects may be destroyed at any time using the VRDestroy function. Destroying 
  9033. an object destroys its child objects. After an object has been destroyed, it is 
  9034. no longer valid to refer to it. 
  9035.  
  9036.  
  9037. ΓòÉΓòÉΓòÉ 24. VX-REXX design time macros ΓòÉΓòÉΓòÉ
  9038.  
  9039. You can extend the VX-REXX design environment by writing macros that are 
  9040. invoked from the object pop-up menu. You should familiarize yourself with the 
  9041. sections on creating application macros in "Controlling other programs" before 
  9042. reading this section. 
  9043.  
  9044.  
  9045. ΓòÉΓòÉΓòÉ 24.1. The PROFILE.VRM file ΓòÉΓòÉΓòÉ
  9046.  
  9047. The PROFILE.VRM file, located in the Macros folder, is executed as a macro by 
  9048. the VX-REXX design environment when it starts, before any project is loaded. 
  9049. You modify this file, using any text editor, to register the macros that are to 
  9050. be added to the object pop-up menu. VX-REXX includes a number of sample macros 
  9051. in the Macros folder -- simply uncomment the appropriate lines in the default 
  9052. PROFILE.VRM file and start VX-REXX to try them out. 
  9053.  
  9054.  
  9055. ΓòÉΓòÉΓòÉ 24.2. Search order ΓòÉΓòÉΓòÉ
  9056.  
  9057. Except for the PROFILE.VRM file, which must be located in the Macros folder, 
  9058. the following search order is used to find macro files: 
  9059.  
  9060.  1. The directory where VX-REXX is installed, as returned by the VREPath 
  9061.     function. 
  9062.  
  9063.  2. The SYSTEM subdirectories. 
  9064.  
  9065.  3. The MACROS subdirectory (which corresponds to the Macros folder). 
  9066.  
  9067.  4. The directories listed in the PATH environment variable. 
  9068.  
  9069. Searching is only done for relative paths. If no extension is given, the 
  9070. extension .VRM is assumed. 
  9071.  
  9072. When creating macros, it is recommended that you place them in the Macros 
  9073. folder. 
  9074.  
  9075.  
  9076. ΓòÉΓòÉΓòÉ 24.3. Installing macros ΓòÉΓòÉΓòÉ
  9077.  
  9078. Macros are added to the object pop-up menu using the VREMacroAdd function: 
  9079.  
  9080. call VREMacroAdd title, path, [list], [menu], [default]
  9081.  
  9082. The arguments are defined as follows: 
  9083.  
  9084. title               The title to use on the object pop-up menu. 
  9085.  
  9086. path                The name of the macro file to invoke. If a relative path is 
  9087.                     used, the search order above is used to find the file. 
  9088.  
  9089. list                An optional list of object types, separated by semicolons. 
  9090.                     If specified, the macro will only appear on the pop-up menu 
  9091.                     if mouse button 2 is clicked on an object whose type 
  9092.                     matches one of the types in the list. If omitted, the macro 
  9093.                     always appears on the pop-up menu. 
  9094.  
  9095. menu                If Open, the macro appears in the Open conditional cascade 
  9096.                     menu on the pop-up menu. If omitted, the macro appears at 
  9097.                     the bottom of the pop-up menu. 
  9098.  
  9099. default             Set it to Default if the macro should be the default item 
  9100.                     in the conditional cascade menu, NotDefault if not. Only 
  9101.                     applies if menu is not null. 
  9102.  
  9103. For example, the following example adds an item to the bottom of the pop-up 
  9104. menu: 
  9105.  
  9106. call VREMacroAdd "Match sizes", "Resize"
  9107.  
  9108. The following example restricts the macro to certain object types: 
  9109.  
  9110. types = ';PushButton;RadioButton;CheckBox'
  9111. call VREMacroAdd "Button defaults", "bdefault.vrm", types
  9112.  
  9113. The next example adds two items to the Open... conditional cascade menu: 
  9114.  
  9115. call VREMacroAdd "Tab editor...", "settabs", "Window",,
  9116.                  "Open", "NotDefault"
  9117. call VREMacroAdd "My settings...", "myset", , "Open", "Default"
  9118.  
  9119.  
  9120. ΓòÉΓòÉΓòÉ 24.4. Macro arguments ΓòÉΓòÉΓòÉ
  9121.  
  9122. When a macro is invoked by VX-REXX, it is passed two internal object names as 
  9123. arguments. The first argument is the internal name of the object on which the 
  9124. pop-up menu was invoked (the object you clicked on with mouse button 2). The 
  9125. second argument is the internal name of the window on which the object resides. 
  9126. The VRWindow function works as usual within the macro. The VX-REXX design 
  9127. environment is disabled while the macro runs. 
  9128.  
  9129.  
  9130. ΓòÉΓòÉΓòÉ 24.5. Functions and methods ΓòÉΓòÉΓòÉ
  9131.  
  9132. As a VX-REXX project, a macro has access to all the normal VX-REXX functions 
  9133. such as VRGet, VRSet, and so on. Several new methods and functions unique to 
  9134. the VX-REXX design environment are also available to the macro. See the 
  9135. MACROS.TXT file in the Macros folder for a list. 
  9136.  
  9137.  
  9138. ΓòÉΓòÉΓòÉ 25. Distributing your projects ΓòÉΓòÉΓòÉ
  9139.  
  9140.  
  9141. ΓòÉΓòÉΓòÉ 25.1. Run time library ΓòÉΓòÉΓòÉ
  9142.  
  9143. The executable (EXE) and macro files built with VX-REXX require the run time 
  9144. library VROBJ.DLL to run. The OS/2 LIBPATH must include the directory that 
  9145. contains VROBJ.DLL. 
  9146.  
  9147. Projects using one or more objects from an object library require the object 
  9148. library to run. 
  9149.  
  9150. Note:  The LIBPATH is defined in the OS/2 CONFIG.SYS file. You cannot change it 
  9151. from an OS/2 window. You must reboot OS/2 before any changes to the LIBPATH 
  9152. will take effect. 
  9153.  
  9154.  
  9155. ΓòÉΓòÉΓòÉ 25.2. Additional redistribution rights ΓòÉΓòÉΓòÉ
  9156.  
  9157. Subject to the terms and conditions of the Watcom Software License Agreement, 
  9158. in addition to any Redistribution Rights granted therein, you are hereby 
  9159. granted a non-exclusive, royalty-free right to reproduce and distribute the 
  9160. VROBJ.DLL file located in the VX-REXX directory provided that  (a) you not 
  9161. suppress, alter or remove proprietary rights notices contained therein; and (b) 
  9162. you indemnify, hold harmless and defend Watcom and its suppliers from and 
  9163. against any claims or lawsuits, including attorney's fees, that arise or result 
  9164. from the use or distribution of your software product. 
  9165.  
  9166. Object libraries may or may not include additional redistribution rights -- 
  9167. consult their documentation for information. 
  9168.  
  9169.  
  9170. ΓòÉΓòÉΓòÉ 26. Samples ΓòÉΓòÉΓòÉ
  9171.  
  9172. The following sections describe the sample programs included with VX-REXX. The 
  9173. files for these programs are located in subdirectories of the VXREXX\SAMPLES 
  9174. directory. You can run any of these programs by opening the Samples folder and 
  9175. double-clicking on the sample's icon. 
  9176.  
  9177.  
  9178. ΓòÉΓòÉΓòÉ 26.1. Bounce ΓòÉΓòÉΓòÉ
  9179.  
  9180. The Bounce program displays a picture of the Earth which bounces in a window. 
  9181. It illustrates a simple use of the Timer object. The position of the Earth is 
  9182. updated based on the timer's Trigger event. 
  9183.  
  9184. To run the program, double click on the Bounce icon. To edit the project, 
  9185. double click on the Bounce.VRP icon in the BOUNCE folder. 
  9186.  
  9187.  
  9188. ΓòÉΓòÉΓòÉ 26.2. Button ΓòÉΓòÉΓòÉ
  9189.  
  9190. The Button program displays four push buttons with the  caption "Push Me!". 
  9191. When you click on any of the buttons, the button's color and caption changes to 
  9192. Red. When it is clicked again, the color and caption changes to Yellow. If you 
  9193. continue to click on a button, it will alternate between red and yellow. 
  9194.  
  9195. The program demonstrates VRGet and VRSet, the two VX-REXX functions used to 
  9196. access object properties at run time. 
  9197.  
  9198. To run the program, double click on the Button icon. To edit the project, 
  9199. double click on the Button.VRP icon in the BUTTON folder. 
  9200.  
  9201.  
  9202. ΓòÉΓòÉΓòÉ 26.3. Calculator ΓòÉΓòÉΓòÉ
  9203.  
  9204. Calculator is a simple calculator program. It does addition, subtraction, 
  9205. multiplication, division, and percentages. The buttons CE and C clear the 
  9206. current entry and the current calculation, respectively. Memory buttons are 
  9207. provided to save (M+ and M-), recall (MR) and clear (MC) calculations. 
  9208.  
  9209. The program illustrates using general routines for code that is used by many 
  9210. objects and shows how to pass arguments to a REXX routine. 
  9211.  
  9212. The calculator sample also demonstrates the use of the KeyPress event and 
  9213. KeyString property. Instead of using the mouse to click on the calculator 
  9214. buttons you can just type the calculator operations on the keyboard. The C 
  9215. button is accessed using the letter C on the keyboard, the CE button through 
  9216. the letter E on the keyboard, and the memory functions by pressing F5-F8 on the 
  9217. keyboard for M+, M-, MR, and MC  respectively. 
  9218.  
  9219. To run this program, double click on the Calculator icon. To edit the project, 
  9220. double click on the CALC.VRP icon in the CALC folder. 
  9221.  
  9222.  
  9223. ΓòÉΓòÉΓòÉ 26.4. DDE Explorer ΓòÉΓòÉΓòÉ
  9224.  
  9225. The DDE Explorer program lets you explore the applications on your system that 
  9226. support the DDE interface. You can list the DDE servers and topics on the 
  9227. servers. After connecting to one of the servers, you can then request 
  9228. information, execute commands, and send data to the server. 
  9229.  
  9230. To run this program, double click on the DDE Explorer icon. To edit the 
  9231. project, double click on the DDE.VRP icon in the DDE folder. 
  9232.  
  9233.  
  9234. ΓòÉΓòÉΓòÉ 26.5. DragDrop ΓòÉΓòÉΓòÉ
  9235.  
  9236. The DragDrop demo illustrates the way you can add drag and drop to your 
  9237. programs. The program displays two containers, each with a number of records. 
  9238. You can drag records from one container to another. Information about the 
  9239. source and target records and containers is shown in the VX-REXX console 
  9240. window. 
  9241.  
  9242. To run this program, double click on the DragDrop icon. To edit the project, 
  9243. double click on the DRAGDROP.VRP icon in the DRAGDROP folder. 
  9244.  
  9245.  
  9246. ΓòÉΓòÉΓòÉ 26.6. Employee database ΓòÉΓòÉΓòÉ
  9247.  
  9248. The Employee database program uses the REXX API to DB2/2 and Watcom SQL to view 
  9249. and update an employee database. See the application was designed. 
  9250.  
  9251. To run this program, double click on the Employee database icon. To edit the 
  9252. project, double click on the Employee.VRP icon in the EMPLOYEE folder. 
  9253.  
  9254.  
  9255. ΓòÉΓòÉΓòÉ 26.7. File browser ΓòÉΓòÉΓòÉ
  9256.  
  9257. The File browser example is a simple file browser. It displays files and lets 
  9258. you navigate the directory tree much like the OS/2 Drive object does. 
  9259.  
  9260. The program displays the contents of the current directory in a container. You 
  9261. can display the directory as icons or as text. You change directories by double 
  9262. clicking on a folder icon in the container. 
  9263.  
  9264. To run this program, double click on the File Browser icon. To edit the 
  9265. project, double click on the FILEBRO.VRP icon in the FILEBRO folder. 
  9266.  
  9267.  
  9268. ΓòÉΓòÉΓòÉ 26.8. Hint and Help ΓòÉΓòÉΓòÉ
  9269.  
  9270. The Hint and Help sample program demonstrates the use of hints and context 
  9271. sensitive help in VX-REXX projects. When the program is running, move the 
  9272. pointer over each of the objects in the window to view the hints for each. The 
  9273. hints appear in the status area in the bottom of the window. Press the F1 key 
  9274. to open a help window. 
  9275.  
  9276. To run this program, double click on the Hint and Help icon. To edit the 
  9277. project, double click on the HINTHELP.VRP icon in the HINTHELP folder. 
  9278.  
  9279.  
  9280. ΓòÉΓòÉΓòÉ 26.9. Mind Game ΓòÉΓòÉΓòÉ
  9281.  
  9282. Mind Game is a game in which you must guess the colors of four buttons in ten 
  9283. guesses or less. When it is run, the buttons for the first guess are located 
  9284. above the horizontal bar at the bottom left hand corner of the window. To 
  9285. begin, choose a color from the color palette at the top right hand corner of 
  9286. the window. The currently selected color is shown in the large colored button 
  9287. to the right the color palette. When you have chosen a color, click on the 
  9288. button to which you want to assign the color. When you have chosen colors for 
  9289. all four  buttons, click on Guess. An X is displayed for each button for which 
  9290. the color is correct. An O indicates that a correct color is chosen but it is 
  9291. not assigned to the correct button. You continue guessing until you guess 
  9292. correctly or complete ten tries. The New item in the Game menu starts a new 
  9293. game. The Peek item lets you see the correct solution. The About item in the 
  9294. Help menu shows copyright information. 
  9295.  
  9296. This program shows how to add a dialog to a program (the About dialog) and how 
  9297. to use VX-REXX predefined functions (VRMessage). It also illustrates using 
  9298. general routines for code that is used by many objects and shows how to pass 
  9299. arguments to a REXX routine. It shows some of the features of the REXX language 
  9300. such as program control statements (do and if) and how to use REXX stem 
  9301. variables as arrays to simplify programming. MindGame also demonstrates the use 
  9302. of menus. 
  9303.  
  9304. To run this program, double click on the Mind Game icon. To edit the project, 
  9305. double click on the MINDGAME.VRP icon in the MINDGAME folder. 
  9306.  
  9307.  
  9308. ΓòÉΓòÉΓòÉ 26.10. MMW ΓòÉΓòÉΓòÉ
  9309.  
  9310. The MMW sample program demonstrates the difference between modal and modeless 
  9311. windows. It allows you to open both modeless and modal windows, and explains at 
  9312. each step how you should proceed. 
  9313.  
  9314. To run this program, double click on the MMW icon. To edit the project, double 
  9315. click on the MMW.VRP icon in the MMW folder. 
  9316.  
  9317.  
  9318. ΓòÉΓòÉΓòÉ 26.11. Movies ΓòÉΓòÉΓòÉ
  9319.  
  9320. The Movies sample program demonstrates the use of VX-REXX with the multimedia 
  9321. extensions to OS/2. You will require the IBM Multimedia Presentation Manager/2 
  9322. software to run this sample. This software is included in OS/2 2.1 but is 
  9323. installed separately. 
  9324.  
  9325. This sample allows you to play movies, either in the main thread, or as part of 
  9326. a separate thread, allowing you to continue working in  the current thread. 
  9327.  
  9328. To run this program, double click on the Movies icon. To edit the project, 
  9329. double click on the Movies.VRP icon in the MOVIES folder. 
  9330.  
  9331.  
  9332. ΓòÉΓòÉΓòÉ 26.12. Notebook ΓòÉΓòÉΓòÉ
  9333.  
  9334. The Notebook program lets the user change the color and size of a push button 
  9335. at run time. It does this by displaying a notebook with the BackColor, 
  9336. ForeColor, Height, and Width properties. The user can alter the values and see 
  9337. the changes to the button. 
  9338.  
  9339. This sample shows how to use the Notebook object in a simple application. 
  9340.  
  9341. To run this program, double click on the Notebook icon. To edit the project, 
  9342. double click on the Notebook.VRP icon in the NOTEBOOK folder. 
  9343.  
  9344.  
  9345. ΓòÉΓòÉΓòÉ 26.13. Popup ΓòÉΓòÉΓòÉ
  9346.  
  9347. The Popup program lets the user change the color and caption of a number of 
  9348. push buttons at run time. When the user clicks mouse button 2 on any of the 
  9349. buttons, a pop-up menu is displayed, listing the button properties that can be 
  9350. changed. 
  9351.  
  9352. This sample shows how to use the Popup method to display a pop-up menu. 
  9353.  
  9354. To run this program, double click on the Popup icon. To edit the project, 
  9355. double click on the Popup.VRP icon in the POPUP folder. 
  9356.  
  9357.  
  9358. ΓòÉΓòÉΓòÉ 26.14. Printing ΓòÉΓòÉΓòÉ
  9359.  
  9360. The Printing sample program lets the user send a file to a given printer. It 
  9361. illustrates the use of the ListPrinters method and the VRPrintFile function. 
  9362.  
  9363. To run this program, double click on the Printing icon. To edit the project, 
  9364. double click on the Printing.VRP icon in the PRINTING folder. 
  9365.  
  9366.  
  9367. ΓòÉΓòÉΓòÉ 26.15. RGB ΓòÉΓòÉΓòÉ
  9368.  
  9369. The RGB project illustrates the use of the Slider and ValueSet set objects. The 
  9370. sliders control the color of each item in the value set. 
  9371.  
  9372. To run this program, double click on the RGB icon. To edit the project, double 
  9373. click on the RGB.VRP icon in the RGB folder. 
  9374.  
  9375.  
  9376. ΓòÉΓòÉΓòÉ 26.16. Scan ΓòÉΓòÉΓòÉ
  9377.  
  9378. In this sample, VX-REXX was used to create a REXX macro that can be run with 
  9379. the OS/2 Enhanced Editor (EPM). When run from EPM, the Scan macro searches the 
  9380. current file for all REXX labels (with format labelname) and displays the 
  9381. labels in a list box. If you double click on a label in the list box, that 
  9382. label becomes the current line in the editor. 
  9383.  
  9384. The sample program was created with VX-REXX. The macro was created using Make 
  9385. macro from the VX-REXX Project menu. 
  9386.  
  9387. To start the macro, open the EPM with Scan object in the Scan folder. 
  9388. Alternatively, you can run the macro from within EPM by doing the following: 
  9389.  
  9390.  1. Press Ctrl+I or choose Command dialog from the Command menu. 
  9391.  
  9392.  2. Type the following in the entry field: 
  9393.  
  9394.    rx c:\vxrexx\samples\scan\scan 
  9395.  
  9396. The Scan folder also includes a Profile.ERX file that will add a menu to EPM 
  9397. which can be used to run the macro. To use the profile: 
  9398.  
  9399.  1. Open EPM. 
  9400.  
  9401.  2. Select Command dialog from the Command menu. 
  9402.  
  9403.  3. Enter Profile on and select OK in the Command dialog. 
  9404.  
  9405.  4. Select Save options from the Options menu. 
  9406.  
  9407.  5. Close EPM. 
  9408.  
  9409. Now when you double click on the EPM with Scan icon and select a label, EPM 
  9410. should include a Labels menu. Selecting Find from this menu will run the sample 
  9411. macro. 
  9412.  
  9413. To edit the project, double click on the Scan.VRP icon in the SCAN folder. 
  9414.  
  9415. For more information on writing macros for other programs, see the "Controlling 
  9416. other programs" chapter in this manual. 
  9417.  
  9418.  
  9419. ΓòÉΓòÉΓòÉ 26.17. Threads ΓòÉΓòÉΓòÉ
  9420.  
  9421. The Threads sample program demonstrates VX-REXX's ability to create 
  9422. multithreaded applications. This feature allows you to write applications which 
  9423. perform lengthy operations in the background. For example, an application could 
  9424. allow the user to continue to work in the main window while saving files in the 
  9425. background. The main window would be one thread, and the part of the program 
  9426. saving the files would be another thread. 
  9427.  
  9428. This sample allows you to create threads by clicking on the Spawn New Thread 
  9429. button. A new window is opened into which you can enter text. Clicking on the 
  9430. Send to parent button then sends the text to the main window, where it is 
  9431. displayed in a list box. 
  9432.  
  9433. You can also stop the new threads that you create by selecting a thread number, 
  9434. then clicking on the Halt Selected Thread button. 
  9435.  
  9436. To run this program, double click on the Threads icon. To edit the project, 
  9437. double click on the Threads.VRP icon in the THREADS folder. 
  9438.  
  9439.  
  9440. ΓòÉΓòÉΓòÉ 26.18. Window Controller ΓòÉΓòÉΓòÉ
  9441.  
  9442. The Window Controller demo illustrates the use of the ListWindows method and PM 
  9443. window handles. The program lists all of the top level frame windows that are 
  9444. currently visible on the desktop. 
  9445.  
  9446. Some of these windows may have a "+" next to their name. By clicking on a plus 
  9447. sign, you expand the display to show the child windows of the selected window. 
  9448. Some of these child windows may have child windows of their own, and you can 
  9449. expand the display to show them as well. When a window's children are 
  9450. displayed, the plus sign changes to a minus sign. Clicking on this minus sign 
  9451. hides the child windows of the selected window. 
  9452.  
  9453. After selecting a window in the program's container, you can press buttons to 
  9454. minimize, maximize, restore, or shake the selected window. There is also an 
  9455. update button, which updates the list of windows displayed in the container. 
  9456.  
  9457. To run this program, double click on the Window Controller icon. To edit the 
  9458. project, double click on the WinCtrl.VRP icon in the WINCTRL folder.