home *** CD-ROM | disk | FTP | other *** search
/ Arawak OS/2 Shareware / PAKLED.ISO / docs / edm / edmi2-9.inf (.txt) < prev    next >
Encoding:
OS/2 Help File  |  1994-10-14  |  273.8 KB  |  3,266 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Oct 1994 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.                                       EDM/2
  5.  
  6.                   The Electronic Developer's Magazine for OS/2
  7.  
  8.                    Portions copyright (c) by Larry Salomon Jr.
  9.                                 Volume 2, issue 9
  10.  
  11. Copyright Notice and Other Stuff 
  12.  
  13. The Editor-in-Chief of this electronic magazine is Larry Salomon, Jr. 
  14.  
  15. Portions of EDM/2 are copyrighted by the editors.  This publication may be 
  16. freely distributed in electronic form provided that all parts are present in 
  17. their original unmodified form.  A reasonable fee may be charged for the 
  18. physical act of distribution; no fee may be charged for the publication itself. 
  19.  
  20. All articles are copyrighted by their authors. No part of any article may be 
  21. reproduced without permission from the original author. 
  22.  
  23. Neither this publication nor the editors are affiliated with International 
  24. Business Machines Corporation. 
  25.  
  26. OS/2 is a registered trademark of International Business Machines Corporation. 
  27. Other trademarks are property of their respective owners.  Any mention of a 
  28. product in this publication does not constitute an endorsement or affiliation 
  29. unless specifically stated in the text. 
  30.  
  31. Administrivia 
  32.  
  33. Welcome to this month's issue.  Time really seems to be flying as we anticipate 
  34. the release of OS/2 version 3.0, which up to now has gone by the moniker 
  35. "Warp".  At work, we have the second beta installed and I know others with the 
  36. gamma version, and if it delivers on the excitement that I hear in their voices 
  37. when I talk to the people that use it, we have something to look forward to. 
  38.  
  39. But first, we have a party to attend!  That's right; many of you received 
  40. invitations in the mail from IBM to attend the rollout celebration. I was lucky 
  41. enough to be in Las Vegas for the 2.0 rollout and knowing IBM and their desire 
  42. to put OS/2 on the desktops of America, this party should be lots bigger. 
  43. Considering that IBM wanted fireworks at the last one (but got nixed by the 
  44. Fire Marshall)...well, you figure out how good it can be.  I plan to be there 
  45. and I urge anyone who has the means and the time to attend also. 
  46.  
  47. Richard Rogers Theatre
  48. Manhattan, New York City
  49. 10:00 am-11:00 am
  50.  
  51. There will be a one hour reception immediately following at the Marriott Hotel. 
  52.  
  53. What's On Your Mind? 
  54.  
  55. Lately, my mailbox has seen little activity and that has me worried.  You see, 
  56. even though I used to get mail which only summarized the reader's feelings, it 
  57. was better than nothing.  Here at EDM/2, we struggle to improve the magazine 
  58. more and more, but we can't do it without your help, since it is the job of the 
  59. reader to define what is "better" and what isn't. 
  60.  
  61. Is there something that you'd like to see?  Some feature, perhaps? 
  62.  
  63. Are there areas in which you would like to see articles written on? 
  64.  
  65. Could the layout be better organized? 
  66.  
  67. We would like to hear what you have to say about the magazine.  Keep those 
  68. cards and letters coming! 
  69.  
  70. On That Note 
  71.  
  72. One very industrious reader, Hilton Goldstein, put together an index of the 
  73. past issues of the magazine.  From what I understand (I have neglected to this 
  74. point to download the index and check it out myself), it has hypertext links to 
  75. the articles within each issue so you can avoid the tiresome browsing of each 
  76. issue just to find what you are looking for.  Carsten and I have known that 
  77. this is a need for quite some time, but lack the time ourselves to properly act 
  78. upon this popular request.  However, it is still foremost in our minds and we 
  79. will hopefully have a solution soon to better facilitate something like a 
  80. "master index". 
  81.  
  82. Layout Change 
  83.  
  84. It has been decided to phase out the Scratch Patch as a column due to lack of 
  85. activity; since the only useful things of late in that column are the Gotcha 
  86. and Documentation Chop Shop sections, a recurring article entitled Scratch 
  87. Patch will appear containing new discoveries. 
  88.  
  89. Reader's Choice Awards 
  90.  
  91. Yes, it is quickly coming up to the end of the year again.  Not meaning to put 
  92. a carrot on a stick, but only articles that were published in the year 1994 
  93. will be eligible for voting upon.  So, start writing! 
  94.  
  95. Title Page - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  96.  
  97.  
  98. ΓòÉΓòÉΓòÉ 2. Visual REXX Faceoff - Part 3 ΓòÉΓòÉΓòÉ
  99.  
  100.  
  101. ΓòÉΓòÉΓòÉ 2.1. Introduction ΓòÉΓòÉΓòÉ
  102.  
  103. Visual REXX Faceoff - Part 3 
  104.  
  105. Written by Gordon Zeglinski 
  106.  
  107. Introduction 
  108.  
  109. This issue sees the third part of the Visual REXX Faceoff.  We start by looking 
  110. at VisPro REXX GOLD edition Version 2.03 by Hockware and then see how it 
  111. compares to VP BRONZE and VX REXX. 
  112.  
  113. VisPro ships on a single floppy disk and comes with a 400+ page manual.  In 
  114. addition to the base package, the Data Entry Object Pack and the VP SOM toolkit 
  115. were shipped on two additional floppies.  An additional 90 page manual is 
  116. included for the data entry objects. 
  117.  
  118. Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  119.  
  120.  
  121. ΓòÉΓòÉΓòÉ 2.2. Installation ΓòÉΓòÉΓòÉ
  122.  
  123. Installation 
  124.  
  125. Like the BRONZE edition, the GOLD edition is easy to install.  Just run 
  126. SETUP.EXE on each floppy and then reboot, and you are ready to go. One of my 
  127. biggest gripes about the BRONZE edition was the lack of advanced sample 
  128. applications; this version has plenty of good samples. 
  129.  
  130. The install folder for VP GOLD is slightly different than that for the BRONZE 
  131. edition.  When done, you will see the following folder on the desktop (assuming 
  132. you install everything). 
  133.  
  134. Figure 1. Installation Folder 
  135.  
  136. The sample projects cover topics like multi-threading, multi-windows, the DB2/2 
  137. database designer, and the new data entry objects.  Below is the sample project 
  138. for the data entry objects. 
  139.  
  140. Figure 2. Sample Project 
  141.  
  142. Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  143.  
  144.  
  145. ΓòÉΓòÉΓòÉ 2.3. Look and Feel ΓòÉΓòÉΓòÉ
  146.  
  147. Look and Feel 
  148.  
  149. VP BRONZE and GOLD are nearly identical.  All of what applied to the BRONZE 
  150. edition looked at two issues ago also apply to this issue.  The layout view has 
  151. changed slightly as shown in figure 3. 
  152.  
  153. Figure 3. User Interface 
  154.  
  155. Also shown in Figure 3 are three controls types from the Data entry pack. The 
  156. calendar, split bar (the blue vertical line), and clock controls are shown. 
  157. One thing Figure 3 doesn't show about the clock control is that the hands move 
  158. while you are editing the layout; this is a nice touch in my opinion. 
  159.  
  160. The SOM development kit is fairly easy to use.  It worked well until I 
  161. installed the SOM developers kit, however; I still haven't figured out how to 
  162. get it working with the SOM 2 compiler or even at whom I should point my finger 
  163. (if anyone).  The problem here arises because the SOM 2 compiler seems to be 
  164. generating an incorrect reference to a SOM 1 function or something like that; 
  165. getting the SOM 1 toolkit to work with the SOM 2 compiler would probably be 
  166. quite challenging for a new SOM programmer.  As the workaround, one can edit 
  167. the makefile so that it uses only SOM 1 compiler components. 
  168.  
  169. Figure 4 shows the SOM Object Builder. 
  170.  
  171. Figure 4. The VP SOM Object Builder 
  172.  
  173. The SOM Builder is pretty easy to use.  You just fill in the notebook and hit 
  174. the generate button.  It creates all the necessary files to define the "SOM 
  175. code".  The SOM code includes the .CSC, .C and .H files that define the SOM 
  176. object and implement its methods, after which you edit the C files and then 
  177. make the object using the supplied makefile.  (Of course you have to read the 
  178. toolkit documentation before trying this.)  If this sounds too good to be true, 
  179. there is a cloud for this silver lining - the sample projects assume you are 
  180. using C-Set/2 not C-Set++, so some manual tweaking of the samples is needed. 
  181. Also, The SOM Builder only generates C code, so one can't use the C++ bindings 
  182. found in OS/2 2.1 Programmers Toolkit. 
  183.  
  184. Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  185.  
  186.  
  187. ΓòÉΓòÉΓòÉ 2.4. Feature Comparison ΓòÉΓòÉΓòÉ
  188.  
  189. Feature Comparison 
  190.  
  191. The following table compares the features in VX-REXX to those in VP BRONZE. 
  192.  
  193. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  194. ΓöéFeature                  ΓöéVX-REXX   ΓöéVisPro REXX (BRONZE)ΓöéVisPro REXX (GOLD)  Γöé
  195. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  196. ΓöéControl Windows          Γöé          Γöé                    Γöé                    Γöé
  197. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  198. ΓöéStatic Text              ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  199. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  200. ΓöéGroup Box                ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  201. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  202. ΓöéButton                   ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  203. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  204. ΓöéRadio Button             ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  205. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  206. ΓöéCheck Box                ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  207. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  208. ΓöéPicture Button           ΓöéYes       ΓöéNo                  ΓöéNo                  Γöé
  209. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  210. ΓöéPicture Radio Button     ΓöéYes       ΓöéNo                  ΓöéNo                  Γöé
  211. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  212. ΓöéPicture Box              ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  213. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  214. ΓöéList Box                 ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  215. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  216. ΓöéCombination Box          ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  217. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  218. ΓöéDrop Down List           ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  219. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  220. ΓöéEntry Field              ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  221. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  222. ΓöéMulti Line Entry Field   ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  223. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  224. ΓöéValue Set                ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  225. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  226. ΓöéSlider                   ΓöéYes       ΓöéNo                  ΓöéYes                 Γöé
  227. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  228. ΓöéSpin Button              ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  229. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  230. ΓöéNotebook                 ΓöéYes       ΓöéNo                  ΓöéYes                 Γöé
  231. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  232. ΓöéContainer                ΓöéYes       ΓöéNo                  ΓöéYes                 Γöé
  233. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  234. ΓöéFree Form                ΓöéNo        ΓöéYes                 ΓöéYes                 Γöé
  235. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  236. ΓöéMenus                    ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  237. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  238. ΓöéHelp Support             ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  239. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  240. ΓöéDDE                      ΓöéYes       ΓöéNo                  ΓöéNo                  Γöé
  241. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  242. ΓöéTimer                    ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  243. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  244. ΓöéThreads                  ΓöéYes       ΓöéNo (1)              ΓöéYes                 Γöé
  245. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  246. ΓöéDrag and Drop            ΓöéYes (2)   ΓöéNo                  ΓöéYes(3)              Γöé
  247. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  248. ΓöéQ+E support              ΓöéYes       ΓöéYes                 ΓöéYes                 Γöé
  249. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  250. ΓöéISV extendible           ΓöéIn Beta   ΓöéYes                 ΓöéYes                 Γöé
  251. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  252. ΓöéVisual DB2/2 database    ΓöéNo.       ΓöéNo                  ΓöéYes                 Γöé
  253. Γöédesigner                 Γöé          Γöé                    Γöé                    Γöé
  254. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  255. ΓöéBusiness Graphs          ΓöéNo        ΓöéNo                  ΓöéYes(4)              Γöé
  256. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  257.  
  258. (1) Threads in REXX are not the same as threads in C.  Global data is not 
  259. automatically shared in REXX.  There are several freeware and shareware REXX 
  260. libraries that will allow you to have multi-threaded REXX programs (assuming 
  261. your package doesn't already support this). 
  262.  
  263. (2) In container controls only 
  264.  
  265. (3) In container controls and on the main window 
  266.  
  267. (4) Supports Pie, Bar, Line, Area and Stacked bar graphs. 
  268.  
  269. Additional object kits will be available that provide additional multi-media 
  270. support and other features.  If you develop objects for VP REXX, HockWare has a 
  271. marketing assistance program. 
  272.  
  273. The DB2/2 support allows one to reverse engineer an existing database, or 
  274. visually create a new one.  Once done, all the code necessary for setting up 
  275. the REXX to DB2/2 interface can be automatically generated.  This can 
  276. substantially lower the development time. 
  277.  
  278. Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  279.  
  280.  
  281. ΓòÉΓòÉΓòÉ 2.5. Wrapping Things Up ΓòÉΓòÉΓòÉ
  282.  
  283. Wrapping Things Up 
  284.  
  285. The VP REXX GOLD package is very impressive.  It mimics the look and feel of 
  286. the WPS closely allowing one to start developing quickly.  The part that amazes 
  287. me the most, is that it's runtime DLLs are small when compared to other visual 
  288. REXX offerings.  I must balance this by adding that it is not the perfect 
  289. choice for creating scripts.  Both VP products currently suffer from the 
  290. limitation of being limited to 1 active VP program per process.  In an 
  291. environment that allows multiple scripts to be run simultaneously, this can be 
  292. a hindrance.  This limitation has no affect on the REXX programs wrapped in 
  293. their own executable file. 
  294.  
  295. The DB2/2 tools are easy to use.  I only used them briefly because DB2/2 was 
  296. removed due to a lack of hard drive space.  From what I did see of them, they 
  297. are a must have item for programmers that are doing a lot of DB/2 work and need 
  298. to rapidly prototype DB/2 interfaces. 
  299.  
  300. Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  301.  
  302.  
  303. ΓòÉΓòÉΓòÉ 3. WPS Programming the Easy Way - Part 2 ΓòÉΓòÉΓòÉ
  304.  
  305.  
  306. ΓòÉΓòÉΓòÉ 3.1. Introduction ΓòÉΓòÉΓòÉ
  307.  
  308. WPS Programming the Easy Way - Part 2 
  309.  
  310. Written by Frank Matthijs 
  311.  
  312. Introduction 
  313.  
  314. This is the second and last article of WPS Programming the Easy Way.  This mini 
  315. series is intended to be an introduction to WPS programming.  Still more than 
  316. the previous article, you are encouraged to follow the article with your 
  317. compiler ready.  This way, you can see for yourself how to make and extend a 
  318. typical WPS class. 
  319.  
  320. I'll presume you already know a little about WPS programming.  If this is not 
  321. the case, I suggest you read my previous article.  I explained things like 
  322. classes, metaclasses, inheritance, overriding, SOM (briefly) and the essence of 
  323. WPS programming.  You should at least know these terms and what they mean in 
  324. order to be able to follow this article. 
  325.  
  326. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  327.  
  328.  
  329. ΓòÉΓòÉΓòÉ 3.2. Overview ΓòÉΓòÉΓòÉ
  330.  
  331. Overview 
  332.  
  333. At the end of the previous article, I already showed how to make a primitive, 
  334. but fully functional WPS class.  The instances of that class have a distinct 
  335. type, which makes it very easy to recognize them, e.g.  when they are dropped 
  336. over your application program.  This article will further expand the class, 
  337. adding an icon and a settings page, and improving the WPS integration by 
  338. allowing folders to show details of our objects (apart from the normal details 
  339. like file creation time, etc.).  These features will be added step by step, 
  340. allowing you to study each improvement separately. 
  341.  
  342. The examples are chosen to show some methods you'll override very often (as in 
  343. the previous article), and as an addition to the Car sample from the IBM 
  344. toolkit.  The latter does a lot of things right, but there are some things it 
  345. does not do properly (like showing details data).  These things will be 
  346. explained here. 
  347.  
  348. As in the previous article, you'll encounter useful tips from time to time. 
  349. These tips give more information or show problem areas of WPS programming.  A 
  350. tip looks like this: 
  351.  
  352. Tip 
  353.  
  354. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  355.  
  356.  
  357. ΓòÉΓòÉΓòÉ 3.3. First Things First ΓòÉΓòÉΓòÉ
  358.  
  359. First Things First 
  360.  
  361. Before I start the article proper, I have some additions to my previous 
  362. article. 
  363.  
  364. The locked .DLL problem 
  365.  
  366. OK, you know the problem:  when you deregister a class DLL, it is still locked, 
  367. so you cannot simply copy your new DLL over it and register the class again. 
  368. The DLL gets unlocked when you delete the template, as I told you in the 
  369. previous article.  Since deleting the template can be tedious, there is a 
  370. simpler method, which was pointed out to me by Martin Thierer (thanks, 
  371. Martin!):  instead of always having to delete the template, why not prevent a 
  372. template from being generated in the first place?  You can do this by 
  373. overriding the wpclsQueryStyle method and setting the CLSSTYLE_NEVERTEMPLATE 
  374. flag.  See the PM Reference for more information.  You can do this during 
  375. development, and add the template for your final class release. 
  376.  
  377. Unfortunately, both methods don't always work.  When you are working with 
  378. classes that affect other classes (such as the details display I'll cover later 
  379. on), the WPS seems to become unstable when you replace a DLL as outlined above. 
  380. The way I solve this problem is by killing the PMSHELL.EXE process. The WPS has 
  381. a built-in recovery process, so the shell will restart automatically.  This 
  382. achieves the same effect as completely rebooting, but takes considerably less 
  383. time.  Moreover, all your windows (and the command history) stay intact.  Only 
  384. make sure the shell doesn't try to restart all your processes.  As always, if 
  385. you have a better way of solving this problem, please let me know. 
  386.  
  387. Tip 
  388.  
  389. Metaclasses 
  390.  
  391. Some of you have asked me to explain the concept of metaclasses in more detail. 
  392. Since this is something not all OO-ish languages support, I'll do that right 
  393. away.  Note however, that this can actually make things less clear (it may get 
  394. confusing if you're not familiar with this). 
  395.  
  396. In SOM (and thus in WPS), you not only have objects as instances of a class, 
  397. but the classes themselves are also instances of some class.  This class is 
  398. called their metaclass.  This means that a class is itself an object, called a 
  399. class object to distinguish it from normal objects.  This class object has 
  400. methods of its own, defined by the metaclass (just as a normal object responds 
  401. to methods defined by the class).  To make the distinction clear, the methods 
  402. performed by class objects (and defined by their metaclass) are called class 
  403. methods, while the methods performed by normal objects (and defined by their 
  404. class) are called instance methods. 
  405.  
  406. It is important to make the distinction between parent classes and metaclasses. 
  407. A parent of a class is a class from which instance methods and instance 
  408. variables are inherited: instances of the subclass (the child class) can also 
  409. perform instance methods defined by the parent class.  The class Animal might 
  410. define methods for eating, so all classes derived from Animal inherit the 
  411. methods for eating. Instances of such derived classes can thus perform these 
  412. methods. 
  413.  
  414. A metaclass is a class that defines the class methods (the methods that the 
  415. class objects can perform).  So the metaclass of Animal might be AnimalMClass, 
  416. which defines the methods that can be invoked on class Animal (such as methods 
  417. for creating objects of the class Animal).  Note that there are methods that 
  418. the class object can perform, and there are method the class defines for its 
  419. instances. 
  420.  
  421. To summarize:  the parent of a class provides inherited methods that the 
  422. class's instances can perform, whereas the metaclass of a class provides class 
  423. methods that the class itself can perform. 
  424.  
  425. So what's the relevance with regard to WPS programming?  Well, the only thing 
  426. you should always keep in mind is that there are such things as metaclasses, so 
  427. in WPS programming you really work with two classes:  the normal class where 
  428. you define the functionality of the instances of your class (instance methods), 
  429. and its metaclass, where you define the functionality of the class itself 
  430. (class methods). 
  431.  
  432. Since these are completely different classes, class variables are not available 
  433. in the implementation of instance methods and vice versa.  That's why for 
  434. example I use a file scope variable to store the module handle of the class DLL 
  435. file, instead of a class variable:  I'll need this handle later on in an 
  436. instance method. 
  437.  
  438. Class methods are really used quite often in WPS.  They all contain cls as part 
  439. of their name, and define the behaviour and properties of the class itself, 
  440. like the name of the class (wpclsQueryTitle), its icon (wpclsQueryIconData) and 
  441. so on.  The other sort of methods are instance methods, and they define the 
  442. behaviour and properties of each individual instance of the class (like the 
  443. contents of a folder (wpQueryContent), the real name of a file system object 
  444. (wpQueryRealName) and so on. 
  445.  
  446. I'll explain some class and instance methods in what follows.  And what follows 
  447. will start right away. 
  448.  
  449. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  450.  
  451.  
  452. ΓòÉΓòÉΓòÉ 3.4. Step 1: Adding an Icon ΓòÉΓòÉΓòÉ
  453.  
  454. Step 1:  Adding an Icon 
  455.  
  456. Until now, our data file has been rather dull looking.  The remedy is to give 
  457. our class its own icon.  This can be done by overriding the wpclsQueryIconData 
  458. method.  So we add the following line to our class definition file 
  459. (datadel.csc): 
  460.  
  461. override wpclsQueryIconData, class;
  462.  
  463. The way we will implement this is by adding an icon to our DLL file and reading 
  464. this icon when necessary. 
  465.  
  466. Adding the icon to the DLL file is simple.  Since we already have a resource 
  467. file, we only need to add one line to it: 
  468.  
  469. POINTER ID_ICON "datadel.ico"
  470.  
  471. We already have the necessary tools for the implementation of 
  472. wpclsQueryIconData:  we can use clsQueryModuleHandle to get the handle of our 
  473. DLL where the icon is stored.  Listing 1 shows what else we need to do to add 
  474. an icon. 
  475.  
  476. SOM_Scope ULONG   SOMLINK dfdM_wpclsQueryIconData(M_MyDataFile *somSelf, PICONINFO pIconInfo)
  477. {
  478.     M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
  479.     M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsQueryIconData");
  480.  
  481.     if(pIconInfo) {
  482.        pIconInfo->fFormat = ICON_RESOURCE;
  483.        pIconInfo->hmod = _clsQueryModuleHandle(somSelf);
  484.        pIconInfo->resid = ID_ICON;
  485.        }
  486.     return (sizeof(ICONINFO));
  487. }
  488.  
  489. Listing 1 
  490.  
  491. The ICONINFO structure can be used to identify the icon in several different 
  492. ways.  We use the module handle and resource ID here.  The use of this method 
  493. is explained properly in the PM Reference, except for the field names of the 
  494. ICONINFO structure. 
  495.  
  496. If you compile the source files, you'll notice the template for our class has 
  497. indeed a new icon, and if you create a few instances of our class, you'll see 
  498. the new icon there too.  (This icon does not look very exciting either, but you 
  499. can always substitute your own flashy icon.) 
  500.  
  501. Tip 
  502.  
  503. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  504.  
  505.  
  506. ΓòÉΓòÉΓòÉ 3.5. Step 2: Filling the File ΓòÉΓòÉΓòÉ
  507.  
  508. Step 2:  Filling the File 
  509.  
  510. Remember:  when you create an instance of our MyDataFile class, you create a 
  511. real file at the same time.  This file had zero size in all previous examples. 
  512. There are situations, however, where a file of zero size is not really a valid 
  513. file of the intended type.  For example, an empty bitmap is not a bitmap of 
  514. zero size.  Instead, it has a header identifying it as a bitmap, even if it 
  515. doesn't contain picture data.  Many data files will in fact use a header, so it 
  516. is inconvenient and even incorrect if we only generate zero size instances 
  517. (after all, this doesn't generate valid data files, because they lack the 
  518. necessary header). 
  519.  
  520. Fortunately, it is not very difficult to write a header (or whatever data is 
  521. needed) to the file at creation (instantiation) time.  As always, the trick is 
  522. to find a proper method we can override.  In this case, wpSetup is a good 
  523. candidate.  It is called when an object is created, and allows the object to 
  524. initialize itself.  Since writing a header is part of the initialization, this 
  525. is the place to do it.  This is the first instance method we override in the 
  526. examples.  It is not a class method, because every object can be set up 
  527. differently, so the method acts on instances of the class, not on the class 
  528. itself. 
  529.  
  530. Listing 2 shows how to do it.  This is a nice example of delegating some work 
  531. to the parent:  wpSetup is also used to pass a setup string to an object, such 
  532. as "OPEN=DEFAULT".  You can define your own setup strings and interpret them 
  533. here, but in our case, we simply use the existing setup strings.  We don't do 
  534. anything with the setup strings in our code.  Instead, we let the parent 
  535. process them. 
  536.  
  537. SOM_Scope BOOL   SOMLINK dfd_wpSetup(MyDataFile *somSelf,PSZ pszSetupString){
  538.     VALUES val;
  539.     /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
  540.     MyDataFileMethodDebug("MyDataFile","dfd_wpSetup");
  541.  
  542.     DosBeep(2000,20);
  543.     val.ulField1 = DEFAULT_FIELD1;
  544.     val.ulField2 = DEFAULT_FIELD2;
  545.     return (WriteToDisk(somSelf, &val)
  546.               && parent_wpSetup(somSelf,pszSetupString));
  547. }
  548.  
  549. Listing 2 
  550.  
  551. The code requires some explanation.  VALUES is a structure with two fields. 
  552. This will be the data that is written to file.  The code fills the fields with 
  553. default values, and then writes the structure to file.  Everything related to 
  554. this data is contained in the files values.c and values.h.  For example, the 
  555. code to write the data to file is contained in values.c  and can be found in 
  556. listing 3. 
  557.  
  558. BOOL WriteToDisk(MyDataFile* somSelf, VALUES* val) {
  559.     CHAR szObjectFileName[CCHMAXPATH];
  560.     ULONG cb = sizeof(szObjectFileName);
  561.     HFILE hf;
  562.     ULONG ulAction;
  563.     ULONG cbBytesWritten;
  564.  
  565.     if (!_wpQueryRealName(somSelf, szObjectFileName, &cb, TRUE)) return FALSE;
  566.     if (DosOpen(szObjectFileName, &hf, &ulAction,
  567.                 0, FILE_NORMAL, FILE_OPEN | FILE_CREATE,
  568.                 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
  569.                 NULL)) return FALSE;
  570.     DosWrite(hf, val, sizeof(VALUES), &cbBytesWritten);
  571.     DosClose(hf);
  572.     return (cbBytesWritten == sizeof(VALUES));
  573. }
  574.  
  575. Listing 3 
  576.  
  577. The interesting functions are indicated in red.  First of all, we need a way to 
  578. determine the name of the data file.  After all, we have been working with 
  579. object pointers (MyDataFile *), not with file names.  The method 
  580. wpQueryRealName will give us a fully qualified file name, just what we need. 
  581. After that, we can use the normal Dos API functions to manipulate the file. 
  582.  
  583. If anything should go wrong, we return FALSE.  When wpSetup returns FALSE, the 
  584. creation of the object is terminated. 
  585.  
  586. Of course, the call to DosBeep  in listing 2 is not really required.  I've 
  587. added it here, so that you can hear when this method gets called.  You'll find 
  588. it is called at class registration time.  At that time, the template is 
  589. generated.  Since the template is a data file just like any other instance of 
  590. our class, wpSetup is called for the template when it is created. 
  591.  
  592. I've included a REXX script to create an instance of class MyDataFile (it is 
  593. called INSTANCE.CMD).  When you run it, it will create a new data file on the 
  594. desktop, and you'll hear a beep to tell you wpSetup has been called.  Now try 
  595. to drag the template to create another instance.  You won't hear any beeps 
  596. here, because when you drag a template of a data file, the WPS will simply copy 
  597. the contents of the file, without calling wpSetup (the method has been called 
  598. already, at the time the template was created).  But the final result is the 
  599. same: all instances of MyDataFile have the right contents (you can check the 
  600. file size in the settings notebook). 
  601.  
  602. Tip 
  603.  
  604. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  605.  
  606.  
  607. ΓòÉΓòÉΓòÉ 3.6. Step 3: Using Details Data ΓòÉΓòÉΓòÉ
  608.  
  609. Step 3:  Using Details Data 
  610.  
  611. The previous steps (in this and the previous article) were quite 
  612. straightforward and showed some standard methods you will override very often. 
  613. This step is a little bit more involved.  We will inform the WPS that objects 
  614. of class MyDataFile have some extra information that can be displayed in every 
  615. WPS folder's details view.  This extra information can also be used in other 
  616. parts of the WPS, as we'll see later.  We'll use the contents of the file 
  617. header for this extra data. 
  618.  
  619. There are two things we should do to make this work: 
  620.  
  621.  1. Inform the WPS that our class really has this data.  This is done by 
  622.     overriding the class method wpclsQueryDetailsInfo.  In this method, we 
  623.     provide all the details the WPS needs, like for example the kind of data 
  624.     (ULONG in our example), the length of each data item (4 bytes here), etc. 
  625.  
  626.  2. Allow each instance to provide the actual values of the data.  Since these 
  627.     values can differ from instance to instance, we do this by overriding an 
  628.     instance method, namely wpQueryDetailsData. 
  629.  
  630. The wpclsQueryDetailsInfo method is called quite often. Therefore, we will 
  631. precalculate the necessary data in the wpclsInitData method.  Listing 4 shows 
  632. what we need to do (the new items are in red). 
  633.  
  634. SOM_Scope void   SOMLINK dfdM_wpclsInitData(M_MyDataFile *somSelf){
  635.     ULONG i;
  636.     PCLASSFIELDINFO pCFI;
  637.     M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
  638.     M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsInitData");
  639.  
  640.     if (!WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), _clsQueryModuleHandle(somSelf),
  641.           ID_TITLE, sizeof(_szTitle), _szTitle))
  642.       strcpy(_szTitle, parent_wpclsQueryTitle(somSelf));
  643.  
  644.     parent_wpclsInitData(somSelf);
  645.  
  646.     for (i = 0, pCFI = fieldinfo; i < DETAILS_COLUMNS; i++, pCFI++) {
  647.         memset((PCH) pCFI, 0, sizeof(CLASSFIELDINFO));
  648.         pCFI->cb                = sizeof(CLASSFIELDINFO);
  649.         pCFI->flData            = CFA_RIGHT | CFA_SEPARATOR | CFA_FIREADONLY;
  650.         pCFI->flTitle           = CFA_CENTER | CFA_SEPARATOR | CFA_HORZSEPARATOR |
  651.                                   CFA_STRING | CFA_FITITLEREADONLY;
  652.         pCFI->pNextFieldInfo    = pCFI + 1;
  653.         pCFI->pTitleData        = pszTitles[i];
  654.         pCFI->flCompare         = COMPARE_SUPPORTED | SORTBY_SUPPORTED;
  655.         pCFI->ulLenCompareValue = sizeof(ULONG);
  656.  
  657.         switch (i) {
  658.             case INDEX_FIELD1:
  659.                 pCFI->flData          |= CFA_ULONG;
  660.                 pCFI->offFieldData     = (ULONG)(FIELDOFFSET(VALUES, ulField1));
  661.                 pCFI->ulLenFieldData   = sizeof(ULONG);
  662.                 pCFI->pMaxCompareValue = &ulMaxField1;
  663.                 break;
  664.             case INDEX_FIELD2:
  665.                 pCFI->flData          |= CFA_ULONG;
  666.                 pCFI->offFieldData     = (ULONG)(FIELDOFFSET(VALUES, ulField2));
  667.                 pCFI->ulLenFieldData   = sizeof(ULONG);
  668.                 pCFI->pMaxCompareValue = &ulMaxField2;
  669.                 break;
  670.             }
  671.         }
  672.     fieldinfo[DETAILS_COLUMNS - 1].pNextFieldInfo = NULL;
  673. }
  674.  
  675. Listing 4 
  676.  
  677. For each data item, we must fill in a CLASSFIELDINFO structure. This is an 
  678. extension of the FIELDINFO structure (used by container classes), and is 
  679. defined in the file wpobject.h.  All structures should form a linked list.  We 
  680. start by filling the complete structure with zeroes.  This way, we don't need 
  681. to fill in everything explicitly (the structure has many fields).  The switch 
  682. statement is used to fill in the data that can differ for each data item. 
  683.  
  684. The following are the most important fields of CLASSFIELDINFO: 
  685.  
  686. flData 
  687.           This defines some properties of the data item.  The most important 
  688.           property is the type of the data.  In our case, we will display ULONG 
  689.           values, so we add CFA_ULONG to the flags.  See the PM Reference under 
  690.           FIELDINFO for more information on these flags. 
  691.  
  692. ulLenFieldData 
  693.           This is the length of the data in bytes. 
  694.  
  695. pNextFieldInfo 
  696.           This is a pointer to the next CLASSFIELDINFO structure.  The 
  697.           structures form a linked list. 
  698.  
  699. pTitleData 
  700.           Here we define the column heading data.  In our example, we use 
  701.           strings to describe the data. 
  702.  
  703. Now that we have the necessary information, we can provide it when the WPS 
  704. calls wpclsQueryDetailsInfo.  This method gets called to query the size of all 
  705. the details data, as well as to get the details data itself.  We first call the 
  706. parent, and add our own data to the parent's data.  Listing 5 shows how it is 
  707. done. 
  708.  
  709. SOM_Scope ULONG   SOMLINK dfdM_wpclsQueryDetailsInfo(M_MyDataFile *somSelf, PCLASSFIELDINFO *ppClassFieldInfo, PULONG pSize)
  710. {
  711.     ULONG cParentColumns;
  712.     PCLASSFIELDINFO pCFI;
  713.  
  714.     M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
  715.     M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsQueryDetailsInfo");
  716.  
  717.     cParentColumns = parent_wpclsQueryDetailsInfo(somSelf,ppClassFieldInfo,pSize);
  718.  
  719.     if (pSize) *pSize += sizeof(VALUES);
  720.     if (ppClassFieldInfo) {
  721.         pCFI = *ppClassFieldInfo;
  722.         if (pCFI) {
  723.             while (pCFI->pNextFieldInfo) pCFI = pCFI->pNextFieldInfo;
  724.             pCFI->pNextFieldInfo = fieldinfo;
  725.             }
  726.         else *ppClassFieldInfo = fieldinfo;
  727.         }
  728.     return (ULONG)cParentColumns + (ULONG)DETAILS_COLUMNS;
  729. }
  730.  
  731. Listing 5 
  732.  
  733. All this code does is add the size of our data to the size of our ancestors' 
  734. data, and add the list of CLASSFIELDINFO structures to the ancestors' list. 
  735. This completes the first part of our job. 
  736.  
  737. Now we need to provide the actual data in the wpQueryDetailsData method. 
  738. Listing 6 shows the implementation of the method. 
  739.  
  740. SOM_Scope ULONG   SOMLINK dfd_wpQueryDetailsData(MyDataFile *somSelf, PVOID *ppDetailsData, PULONG pcp)
  741. {
  742.     /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
  743.     MyDataFileMethodDebug("MyDataFile","dfd_wpQueryDetailsData");
  744.  
  745.     parent_wpQueryDetailsData(somSelf,ppDetailsData, pcp);
  746.  
  747.     if (ppDetailsData) {
  748.         PVALUES pdd = (PVALUES) *ppDetailsData;
  749.         ReadFromDisk(somSelf, pdd);
  750.         *ppDetailsData= pdd + 1;
  751.     }
  752.     else  *pcp += sizeof(VALUES);
  753.     return TRUE;
  754. }
  755.  
  756. Listing 6 
  757.  
  758. The code reads the complete VALUES structure from the file directly into the 
  759. details data.  ReadFromDisk is responsible for this, and is very similar to 
  760. WriteToDisk (it is also contained in the values.c file). 
  761.  
  762. After the code is compiled and the class registered, you won't notice anything 
  763. different about the objects.  In fact, our code affects WPFolder objects and 
  764. objects of derived classes.  You can see this by opening the settings notebook 
  765. of a folder.  When you select the last page under the "View"  tab, you can see 
  766. something similar to figure 1 (select the correct object class under "Object 
  767. type").  Under "Details to display", you can see the two fields we have added. 
  768.  
  769. Figure 1 
  770.  
  771. When you open that folder in details view, it will show the contents of the 
  772. header of every instance of MyDataFile  it contains. 
  773.  
  774. The "Include" tab also shows something new.  There now is a completely new 
  775. settings page for every folder on your desktop (see figure 2). Here you can add 
  776. criteria the WPS uses to decide which objects to display. When you select the 
  777. "Add" button, you get a dialog box similar to the one in figure 3. 
  778.  
  779. Figure 2 
  780.  
  781. Figure 3 shows how you would make the WPS only show Datafile Deluxe objects 
  782. with a Field1 values less that 40. 
  783.  
  784. Figure 3 
  785.  
  786. These features are available for each data item of which the flCompare field of 
  787. the CLASSFIELDINFO structure contains the flag COMPARE_SUPPORTED.  If this 
  788. field contains the flag SORTBY_SUPPORTED, the contents of the folder can also 
  789. be sorted based on that item (see the "Sort" tab). 
  790.  
  791. The pMaxCompareValue field contains a pointer to the maximum value of the data 
  792. item.  You can use this to constrain the possible values, and the entry field 
  793. for adding criteria ("Comparison value"  in figure 3) will not allow larger 
  794. values. 
  795.  
  796. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  797.  
  798.  
  799. ΓòÉΓòÉΓòÉ 3.7. Step 4: Adding a Settings Page ΓòÉΓòÉΓòÉ
  800.  
  801. Step 4:  Adding a Settings Page 
  802.  
  803. The last thing we'll add to our class is a page in the settings notebook. This 
  804. is in fact not very difficult.  We define an instance method (AddAboutPage) for 
  805. adding our page and override wpAddSettingsPages so we can really add the page 
  806. to the settings notebook. 
  807.  
  808. Since a notebook page is in fact a dialog, we also need to provide the 
  809. functionality of the dialog.  I have put the relevant code in the files 
  810. dialog.c and dialog.h. 
  811.  
  812. Listing 7 shows how we add a page.  We only need to fill in a PAGEINFO 
  813. structure.  The interesting fields are in red. 
  814.  
  815. SOM_Scope ULONG   SOMLINK dfd_AddAboutPage(MyDataFile *somSelf,HWND hwndNotebook)
  816. {
  817.     PAGEINFO pageinfo;
  818.  
  819.     /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
  820.     MyDataFileMethodDebug("MyDataFile","dfd_AddAboutPage");
  821.  
  822.     memset((PCH)&pageinfo, 0, sizeof(PAGEINFO));
  823.     pageinfo.cb = sizeof(PAGEINFO);
  824.     pageinfo.hwndPage = NULLHANDLE;
  825.     pageinfo.usPageStyleFlags = BKA_MAJOR;
  826.     pageinfo.usPageInsertFlags = BKA_FIRST;
  827.     pageinfo.pfnwp = AboutDlgProc;
  828.     pageinfo.resid = hmod;
  829.     pageinfo.dlgid = ID_ABOUT;
  830.     pageinfo.pszName = "~About";
  831.     pageinfo.pCreateParams = somSelf;
  832.     return _wpInsertSettingsPage(somSelf, hwndNotebook, &pageinfo);
  833. }
  834.  
  835. Listing 7 
  836.  
  837. The most relevant items are discussed below: 
  838.  
  839. pfnwp 
  840.           This is the dialog procedure to be used with the dialog. 
  841.  
  842. resid 
  843.           This identifies where the resources are to be found.  We use the 
  844.           module handle of our class DLL here.  Note that we use the file scope 
  845.           variable hmod without a call to clsQueryModuleHandle.  This is 
  846.           because we can't access class methods here (they are methods of a 
  847.           completely different class).  The method has been called at the point 
  848.           hmod  is needed here, so it indeed contains the correct value. 
  849.  
  850. dlgid 
  851.           This is the ID of our dialog template. 
  852.  
  853. pszName 
  854.           This is the text for the page tab. 
  855.  
  856. pCreateParams 
  857.           This should always be somSelf. 
  858.  
  859. The implementation of wpAddSettingsPages is also very simple, as shown in 
  860. listing 8. 
  861.  
  862. SOM_Scope BOOL   SOMLINK dfd_wpAddSettingsPages(MyDataFile *somSelf,HWND hwndNotebook)
  863. {
  864.     /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
  865.     MyDataFileMethodDebug("MyDataFile","dfd_wpAddSettingsPages");
  866.  
  867.     return (parent_wpAddSettingsPages(somSelf,hwndNotebook)
  868.               && _AddAboutPage(somSelf, hwndNotebook));
  869. }
  870.  
  871. Listing 8 
  872.  
  873. We let the parent add its pages, and then we add our own.  The pages are filled 
  874. from bottom to top, so if we want to add our page to the bottom, we should do 
  875. so before calling the parent's method.  Here we add our page after calling the 
  876. parent.  This adds our page on top of the others. 
  877.  
  878. Listing 9 shows the dialog procedure.  In this example, it is kept very simple 
  879. (and not even completely functional). 
  880.  
  881. MRESULT EXPENTRY AboutDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {
  882. switch(msg) {
  883.         case WM_INITDLG :
  884.             WinSetWindowText(WinWindowFromID(hwnd, DID_ENTRY), "This is a test");
  885.             WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwnd, DID_ENTRY));
  886.             return (MRESULT) TRUE;
  887.         case WM_COMMAND :
  888.             switch (SHORT1FROMMP(mp1)) {
  889.               /* Process commands here */
  890.               }
  891.             return (MRESULT) TRUE;
  892.             break;
  893.     }
  894.     return WinDefDlgProc(hwnd, msg, mp1, mp2);
  895. }
  896.  
  897. Listing 9 
  898.  
  899. It is important that one of the entry fields have the input focus initially, 
  900. because otherwise, the settings notebook will lose the input focus in some 
  901. cases and will even allow another window to get on top of it when the extra 
  902. page is selected (try this with the Car example).  In our example, we 
  903. explicitly call WinSetFocus to set the focus to one of the fields. 
  904.  
  905. When handling WM_COMMAND, don't pass control to WinDefDlgProc, because if you 
  906. do, your dialog box will disappear from the notebook when a button is pressed. 
  907.  
  908. Tip 
  909.  
  910. Compile and register the class, and you will see the settings page added as the 
  911. first page in the settings notebook of every instance of our MyDataFile class. 
  912.  
  913. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  914.  
  915.  
  916. ΓòÉΓòÉΓòÉ 3.8. Conclusion ΓòÉΓòÉΓòÉ
  917.  
  918. Conclusion 
  919.  
  920. I think you now have a fairly good idea of what WPS programming is and how you 
  921. can make WPS classes.  There are some important things I haven't explained here 
  922. (such as modifying the popup menu of an object, and opening a view of an 
  923. object), but I think you can determine how to do these things by examining 
  924. sample WPS source code with the knowledge you now have (the Car class in the 
  925. Toolkit, for example, but there are also a few samples available on various 
  926. electronic systems, such as the one you obtained this EDM from). 
  927.  
  928. I hope these two articles will inspire you to start making your own WPS 
  929. classes.  WPS programming is a bit different from "normal" programming, but it 
  930. can be very rewarding (and fun).  And if you don't want to spend too much time 
  931. on this, you can always use the source code from the articles as a starting 
  932. point for your own data files. 
  933.  
  934. One last remark:  The current versions of OS/2 come with SOM 1.0, whereas 
  935. future versions will have SOM 2.0 built-in.  SOM 2.0 uses a different syntax to 
  936. describe classes (Interface Definition Language) but is backwards compatible 
  937. with previous versions of SOM.  I'm only telling you so that you know you'll 
  938. see some changes in the near future, but you can continue using the syntax used 
  939. in this and the previous article. 
  940.  
  941. If you have any comments or questions about this or the previous article, feel 
  942. free to contact me.  See elsewhere in this issue for information on how to 
  943. reach me. 
  944.  
  945. WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  946.  
  947.  
  948. ΓòÉΓòÉΓòÉ 4. The Design and Implementation of VIOWIN - Part 2 ΓòÉΓòÉΓòÉ
  949.  
  950.  
  951. ΓòÉΓòÉΓòÉ 4.1. Introduction ΓòÉΓòÉΓòÉ
  952.  
  953. The Design and Implementation of VIOWIN - Part 2 
  954.  
  955. Written by Larry Salomon, Jr. 
  956.  
  957. Introduction 
  958.  
  959. For my job, I once had to write an application that ran only when OS/2 booted 
  960. from the floppy diskettes.  Because I had no access to the functionality PM 
  961. provides, I resorted to a line-oriented interface, where messages were 
  962. displayed on the screen and scrolled up when necessary.  It was a good 
  963. interface, I thought; it was fully NLS enabled and had intelligent defaults so 
  964. the user basically only had to type in the name of the application. 
  965. Unfortunately, the Quality Assurance team didn't concur with my opinion.  "We 
  966. want a nice interface!" one exclaimed.  "Yeah, one with different windows and 
  967. such!" another shouted. 
  968.  
  969. I was backed into a corner that I could only get out of one way. 
  970.  
  971. This series describes the design and implementation of VIOWIN, a library that 
  972. implements a subset of the Win APIs provided by PM for fullscreen sessions. 
  973. The reasoning behind writing this series is that it provided me and will 
  974. hopefully provide you with some unique insights into how a windowing system is 
  975. developed; and since it is based on PM, your familiarity with the already 
  976. defined interface will increase your capability to fully understand what is 
  977. being described. 
  978.  
  979. Obviously, this series assumes you have PM application development experience, 
  980. but it isn't required. 
  981.  
  982. Last Month 
  983.  
  984. Last month we looked at some of the capabilities of the system as well as four 
  985. of the data structures used in the library.  You will notice that while some of 
  986. the design considerations were discussed, the design itself was casually 
  987. avoided since there is no overall design that was followed; instead, the design 
  988. of the individual components will be discussed. 
  989.  
  990. The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2, 
  991. Issue 9 
  992.  
  993.  
  994. ΓòÉΓòÉΓòÉ 4.2. Day One (and Already Problems) ΓòÉΓòÉΓòÉ
  995.  
  996. Day One (and Already Problems) 
  997.  
  998. My first problem occurred with the issue of input to the application (output, 
  999. too, was a problem already, but I already knew what to do about that).  We all 
  1000. know from writing PM applications that input is not "pulled" by the application 
  1001. from the system but is instead "pushed" by the system to the application via 
  1002. the WM_CHAR message and the various mouse messages.  In haste, I decided to 
  1003. discard the use of the mouse from the system and concentrate on the keyboard, 
  1004. since that would be enough to use the system fully.  Obviously, asynchronous 
  1005. sending of WM_CHAR messages implies a second thread.  From here, I had one of 
  1006. two options: 
  1007.  
  1008.  1. I could use the KbdCharIn() function to retrieve keystrokes, or 
  1009.  2. I could use a device monitor to monitor the keyboard activity. 
  1010.  
  1011. ...and then from there, I would have to convert the data returned from the 
  1012. system into the appropriate form for the WM_CHAR message. 
  1013.  
  1014. Again, the urgency of the situation asserted itself and since I knew a bit 
  1015. about how device monitors worked and knew nothing about the Kbd subsystem, I 
  1016. took the second option. 
  1017.  
  1018. Note! 
  1019.  
  1020. Let this be an example of how "haste makes waste", since - as you will see - 
  1021. this was the wrong choice to make. 
  1022.  
  1023. Device Monitors 
  1024.  
  1025. Device monitors are interesting beasts - they can only be used to monitor 
  1026. devices that are serial (i.e. not block devices such as disk drives).  Worse 
  1027. yet, as with the Kbd, Mou, and Vio subsystems, they are no longer supported 
  1028. under OS/2 2.x . 
  1029.  
  1030. The way a device monitor works is quite similar to a system wide hook in PM 
  1031. applications; you read data from the device which you either write back out to 
  1032. the data stream to be fed to the next monitor or the application, or you don't 
  1033. and the data is "eaten".  After consulting several older manuals and after a 
  1034. lot of trial-n-error, I was able to correctly implement the keyboard device 
  1035. monitor.  For all monitors, the following rules apply: 
  1036.  
  1037.  1. Call DosMonOpen() with the name of the device you wish to monitor, e.g. 
  1038.     "KBD$" in our case. 
  1039.  2. Call DosMonReg() to register your application with the system and to pass 
  1040.     the data buffers to be used internally by OS/2.  There are a few caveats to 
  1041.     be aware of with this step; see below for more information. 
  1042.  3. Loop, calling DosMonRead() and then calling DosMonWrite() to pass the data 
  1043.     along (assuming this is what you want to do).  There are some interesting 
  1044.     caveats here, too.  See below for more information. 
  1045.  4. Call DosMonClose() to close the device monitor. 
  1046.  
  1047. DosMonReg() is an interesting function; it requires the session number, first, 
  1048. which cannot be obtained using any documented 32-bit API; however, this 
  1049. function itself is 16-bit, so we might as well call the 16-bit API 
  1050. DosGetInfoSeg() to get the session number.  It needs to be noted that you 
  1051. cannot install a keyboard monitor in the PM session (session 1).  Pay close 
  1052. attention here:  because of this, debugging is now impossible. Yes, you read 
  1053. that correctly. 
  1054.  
  1055. Note! 
  1056.  
  1057. There seems to be a problem, and since I have not tried this on other 
  1058. development environments (e.g. Borland or Watcom), I do not know if this is a 
  1059. problem with the debugger (IPMD) or OS/2.  When debugging, DosGetInfoSeg() 
  1060. always returns session 1, which causes the call to DosMonReg() to fail. 
  1061.  
  1062. The workaround was to write another application - called SESS - which also 
  1063. calls DosGetInfoSeg() and prints the foreground session number.  Then, in my 
  1064. keyboard monitor, I assign the current session number to a local variable; 
  1065. setting a breakpoint just following this allows you to change the value of the 
  1066. local variable to the value printed by SESS.  Sneaky it is, and a pain in the 
  1067. butt, too. 
  1068.  
  1069. Another interesting "property" of DosMonReg() is that the documentation does 
  1070. not give the correct figure for the size of the buffers to be passed as 
  1071. arguments; fortunately, DosMonReg() will return the size of the buffers if what 
  1072. was passed is not big enough.  A call to DosAllocMem() follows and we now have 
  1073. buffers that are large enough. 
  1074.  
  1075. DosMonRead() and DosMonWrite() are not without their peculiarities either. 
  1076. Instead of passing in the buffers to DosMonOpen() and returning a handle to be 
  1077. used when reading and writing, you have to register the buffers separately and 
  1078. pass the buffer pointers to DosMonRead() and DosMonWrite()!  So, don't throw 
  1079. them away just yet! 
  1080.  
  1081. Specific to Keyboard Monitors 
  1082.  
  1083. The data returned by DosMonRead() is a structure, which (since it isn't present 
  1084. in the Toolkit header files) I called a MONKEYPACKET: 
  1085.  
  1086. struct _MONKEYPACKET {
  1087.    UCHAR uchFlags;
  1088.    UCHAR uchOrigScanCode;
  1089.    KBDKEYINFO kkiKey;
  1090.    USHORT usKbdDDFlags;
  1091. };
  1092.  
  1093. uchFlags            General flags about the device monitor data stream.  These, 
  1094.                     as opposed to usKbdDDFlags are set by OS/2 and not the 
  1095.                     device driver. 
  1096. uchOrigScanCode     The original scancode of the key pressed. 
  1097. kkiKey              A structure describing the keystroke.  The definition is in 
  1098.                     the header files and will be included if you #define 
  1099.                     INCL_KBD. 
  1100. usKbdDDFlags        Flags being passed along the data stream by the device 
  1101.                     driver. 
  1102.  
  1103. If the second bit (counting from zero) in uchFlags is set, the system is 
  1104. indicating that you need to flush any internal buffers you are using and that 
  1105. you are requires to write this packet back to the device monitor data stream. 
  1106.  
  1107. Parlez Vous? 
  1108.  
  1109. Finally, if the "flush" bit isn't set, we need to convert the data into that 
  1110. which is documented for the WM_CHAR message.  This is a fairly trivial 
  1111. procedure which involves checking the scan code and building the parameters 
  1112. from that and the associated flags (which describe the state of the shift keys, 
  1113. etc.). 
  1114.  
  1115. Note! 
  1116.  
  1117. There is an NLS exposure here, since scan codes could differ based on the 
  1118. keyboard type.  I know of no way to alleviate this, but suspect that the 
  1119. interpretation of the KEYBOARD.DCP file (see your CONFIG.SYS) could help.  If 
  1120. anyone has any information on the format of this file, I'd be very interested 
  1121. in speaking with you. 
  1122.  
  1123. The Code 
  1124.  
  1125. The code for the keyboard monitor - included in the file VIOWIN2.ZIP - is shown 
  1126. below.  It is run, as we said, as a separate thread. 
  1127.  
  1128. VOID _Optlink keyMonitor(PVOID pvDummy)
  1129. //-------------------------------------------------------------------------
  1130. // This function is the keyboard monitor installed by vwInitialize().  It
  1131. // attempts to install itself and sets a flag in habAnchor->ulStatus
  1132. // indicating success or failure.  If it succeeds, it loops reading
  1133. // characters from the keyboard and calling postKeyMsg() to convert to
  1134. // WM_CHAR message and post it.
  1135. //-------------------------------------------------------------------------
  1136. {
  1137.    USHORT usMonitor;
  1138.    USHORT usGlobalSel;
  1139.    USHORT usLocalSel;
  1140.    struct _GINFOSEG *pgisInfo;
  1141.    USHORT usSession;
  1142.    USHORT abMonIn[2];
  1143.    USHORT abMonOut[2];
  1144.    PBYTE pbMonData;
  1145.    struct _MONBUFF *pmbMonIn;
  1146.    struct _MONBUFF *pmbMonOut;
  1147.    USHORT usSzData;
  1148.    struct _MONKEYPACKET mkpChar;
  1149.    APIRET16 arRc;
  1150.  
  1151.    if (DosMonOpen("KBD$",&usMonitor)!=0) {
  1152.       habAnchor->ulStatus|=VW_HABST_MONINITBAD;
  1153.       return;
  1154.    } /* endif */
  1155.  
  1156.    //----------------------------------------------------------------------
  1157.    // DosMonReg() requires the session number.  Note the following
  1158.    // problem when using IPMD to debug:  PM (session 1) does not allow
  1159.    // monitors to be installed in its session.  When running from IPMD,
  1160.    // pgisInfo->sgCurrent always reports the current session as 1, instead
  1161.    // of the session of the program being debugged.  The result is that
  1162.    // the monitor fails to install, causing vmInitialize() to return FALSE.
  1163.    //
  1164.    // The way to get around this is to use the following procedure:
  1165.    //
  1166.    // 1)  Open a new full screen session
  1167.    // 2)  Run the program SESS.EXE, which prints the session number
  1168.    // 3)  Set a breakpoint on the line following the assignment to
  1169.    //     usSession.
  1170.    // 4)  Open a variable monitor and type in the session number of the
  1171.    //     full screen session opened in step 1
  1172.    // 5)  Continue running
  1173.    //
  1174.    // This forces you to input your keystrokes in the session opened in
  1175.    // step 1, but the results are still displayed in the debug full-screen
  1176.    // session.  I realize this is a pain, but it is the only way.
  1177.    //----------------------------------------------------------------------
  1178.    DosGetInfoSeg(&usGlobalSel,&usLocalSel);
  1179.    pgisInfo=(struct _GINFOSEG *)MAKEP(usGlobalSel,0);
  1180.    usSession=pgisInfo->sgCurrent;
  1181.  
  1182.    //----------------------------------------------------------------------
  1183.    // Query the size of the needed monitor buffers
  1184.    //----------------------------------------------------------------------
  1185.    abMonIn[0]=sizeof(abMonIn);
  1186.    abMonOut[0]=sizeof(abMonOut);
  1187.  
  1188.    if (DosMonReg(usMonitor,
  1189.                  (struct _MONBUFF *)abMonIn,
  1190.                  (struct _MONBUFF *)abMonOut,
  1191.                  MONITOR_BEGIN,
  1192.                  usSession)!=ERROR_MON_BUFFER_TOO_SMALL) {
  1193.       DosMonClose(usMonitor);
  1194.       habAnchor->ulStatus|=VW_HABST_MONINITBAD;
  1195.       return;
  1196.    } /* endif */
  1197.  
  1198.    //----------------------------------------------------------------------
  1199.    // Allocate memory for the total size and specify the OBJ_TILE
  1200.    // attribute to force this to be 64K segment aligned.  This results
  1201.    // in both pmbMonIn and pmbMonOut to be in the same 16-bit segment
  1202.    // which is a requirement of DosMonReg().
  1203.    //----------------------------------------------------------------------
  1204.    if (DosAllocMem((PPVOID)&pbMonData,
  1205.                    abMonIn[1]+abMonOut[1],
  1206.                    PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE)!=0) {
  1207.       DosMonClose(usMonitor);
  1208.       habAnchor->ulStatus|=VW_HABST_MONINITBAD;
  1209.       return;
  1210.    } /* endif */
  1211.  
  1212.    pmbMonIn=(struct _MONBUFF *)pbMonData;
  1213.    pmbMonOut=(struct _MONBUFF *)(((PBYTE)pbMonData)+abMonIn[1]);
  1214.  
  1215.    pmbMonIn->cb=abMonIn[1];
  1216.    pmbMonOut->cb=abMonOut[1];
  1217.  
  1218.    if (DosMonReg(usMonitor,pmbMonIn,pmbMonOut,MONITOR_BEGIN,usSession)!=0) {
  1219.       DosMonClose(usMonitor);
  1220.       DosFreeMem(pbMonData);
  1221.       habAnchor->ulStatus|=VW_HABST_MONINITBAD;
  1222.       return;
  1223.    } /* endif */
  1224.  
  1225.    habAnchor->ulStatus|=VW_HABST_MONINITGOOD;
  1226.  
  1227.    //----------------------------------------------------------------------
  1228.    // Loop - read from the monitor and if not a "flush buffer" packet,
  1229.    // call postKeyMsg(), else pass the packet along the monitor chain.
  1230.    //----------------------------------------------------------------------
  1231.    while ((habAnchor->ulStatus & VW_HABST_MONSHOULDTERM)==0) {
  1232.       usSzData=sizeof(mkpChar);
  1233.  
  1234.       arRc=DosMonRead(pmbMonIn,DCWW_WAIT,&mkpChar,&usSzData);
  1235.       if (arRc==0) {
  1236.          if (mkpChar.uchFlags & 0x04) {
  1237.             DosMonWrite(pmbMonOut,&mkpChar,usSzData);
  1238.          } else {
  1239.             postKeyMsg(&mkpChar);
  1240.          } /* endif */
  1241.       } /* endif */
  1242.    } /* endwhile */
  1243.  
  1244.    DosMonClose(usMonitor);
  1245.    DosFreeMem(pbMonData);
  1246.    habAnchor->ulStatus|=VW_HABST_MONTERM;
  1247. }
  1248.  
  1249. The function postKeyMsg() which converts the MONKEYPACKET structure to a 
  1250. WM_CHAR message is also shown below. 
  1251.  
  1252. BOOL postKeyMsg(struct _MONKEYPACKET *pmkpChar)
  1253. //-------------------------------------------------------------------------
  1254. // This function is called by the keyboard monitor.  It converts the
  1255. // MONKEYPACKET structure to the WM_CHAR parameter format, and then
  1256. // posts the message to the window with the focus.
  1257. //
  1258. // Input:  pmkpChar - points to the _MONKEYPACKET structure containing
  1259. //                    the keyboard information as received by the keyboard
  1260. //                    monitor
  1261. // Returns:  TRUE if successful, FALSE otherwise
  1262. //-------------------------------------------------------------------------
  1263. {
  1264.    BOOL bInit;
  1265.    USHORT usFlags;
  1266.    BYTE bRepeat;
  1267.    CHAR chScan;
  1268.    CHAR chChar1;
  1269.    CHAR chChar2;
  1270.    USHORT usVkey;
  1271.    USHORT usMods;
  1272.    BOOL bNeedPost;
  1273.    HVWWND hwndFocus;
  1274.  
  1275.    bInit=TRUE;
  1276.    usFlags=0;
  1277.    bRepeat=0;
  1278.    chScan=pmkpChar->kkiKey.chScan;
  1279.    chChar1=0;
  1280.    chChar2=0;
  1281.    usVkey=0;
  1282.  
  1283.    //----------------------------------------------------------------------
  1284.    // Set the WM_CHAR flags first
  1285.    //----------------------------------------------------------------------
  1286.    if ((pmkpChar->usKbdDDFlags & 0x0040)!=0) {
  1287.       usFlags|=KC_KEYUP;
  1288.    } /* endif */
  1289.  
  1290.    if ((pmkpChar->kkiKey.fsState & (KBDSTF_LEFTSHIFT | KBDSTF_RIGHTSHIFT))!=0) {
  1291.       usFlags|=KC_SHIFT;
  1292.    } /* endif */
  1293.  
  1294.    if ((pmkpChar->kkiKey.fsState & KBDSTF_CONTROL)!=0) {
  1295.       usFlags|=KC_CTRL;
  1296.    } /* endif */
  1297.  
  1298.    if ((pmkpChar->kkiKey.fsState & KBDSTF_ALT)!=0) {
  1299.       usFlags|=KC_ALT;
  1300.    } /* endif */
  1301.  
  1302.    //----------------------------------------------------------------------
  1303.    // If chChar==0 or chChar==0xE0, then we have an extended key code, i.e.
  1304.    // KC_VIRTUALKEY.  Check the scan code to determine what key was pressed.
  1305.    // THIS WILL CREATE PROBLEMS ON OTHER KEYBOARD LAYOUTS!!!  We need to
  1306.    // figure out a way around this (\OS2\KEYBOARD.DCP interpretation maybe?).
  1307.    //----------------------------------------------------------------------
  1308.    if (pmkpChar->kkiKey.chChar==0) {
  1309.       usFlags|=KC_VIRTUALKEY;
  1310.  
  1311.       switch (chScan) {
  1312.       case 0x0F:
  1313.          if ((usFlags & (KC_SHIFT | KC_CTRL | KC_ALT))==KC_SHIFT) {
  1314.             usVkey=VK_BACKTAB;
  1315.          } else {
  1316.             usVkey=VK_TAB;
  1317.          } /* endif */
  1318.          break;
  1319.       //-------------------------------------------------------------------
  1320.       // Since there are function keys F1-F12 and F13-F24, assign F1-F12 with
  1321.       // shift key to F13-F24, and all other F1-F12 to F1-F12.
  1322.       //-------------------------------------------------------------------
  1323.       case 0x3B:                 // Normal
  1324.       case 0x5E:                 // Control
  1325.       case 0x68:                 // Alt
  1326.          usVkey=VK_F1;
  1327.          break;
  1328.       case 0x3C:
  1329.       case 0x5F:
  1330.       case 0x69:
  1331.          usVkey=VK_F2;
  1332.          break;
  1333.       case 0x3D:
  1334.       case 0x60:
  1335.       case 0x6A:
  1336.          usVkey=VK_F3;
  1337.          break;
  1338.       case 0x3E:
  1339.       case 0x61:
  1340.       case 0x6B:
  1341.          usVkey=VK_F4;
  1342.          break;
  1343.       case 0x3F:
  1344.       case 0x62:
  1345.       case 0x6C:
  1346.          usVkey=VK_F5;
  1347.          break;
  1348.       case 0x40:
  1349.       case 0x63:
  1350.       case 0x6D:
  1351.          usVkey=VK_F6;
  1352.          break;
  1353.       case 0x41:
  1354.       case 0x64:
  1355.       case 0x6E:
  1356.          usVkey=VK_F7;
  1357.          break;
  1358.       case 0x42:
  1359.       case 0x65:
  1360.       case 0x6F:
  1361.          usVkey=VK_F8;
  1362.          break;
  1363.       case 0x43:
  1364.       case 0x66:
  1365.       case 0x70:
  1366.          usVkey=VK_F9;
  1367.          break;
  1368.       case 0x44:
  1369.       case 0x67:
  1370.       case 0x71:
  1371.          usVkey=VK_F10;
  1372.          break;
  1373.       case 0x45:
  1374.       case 0x89:
  1375.       case 0x8B:
  1376.          usVkey=VK_F11;
  1377.          break;
  1378.       case 0x46:
  1379.       case 0x8A:
  1380.       case 0x8C:
  1381.          usVkey=VK_F12;
  1382.          break;
  1383.       case 0x54:
  1384.          usVkey=VK_F13;
  1385.          break;
  1386.       case 0x55:
  1387.          usVkey=VK_F14;
  1388.          break;
  1389.       case 0x56:
  1390.          usVkey=VK_F15;
  1391.          break;
  1392.       case 0x57:
  1393.          usVkey=VK_F16;
  1394.          break;
  1395.       case 0x58:
  1396.          usVkey=VK_F17;
  1397.          break;
  1398.       case 0x59:
  1399.          usVkey=VK_F18;
  1400.          break;
  1401.       case 0x5A:
  1402.          usVkey=VK_F19;
  1403.          break;
  1404.       case 0x5B:
  1405.          usVkey=VK_F20;
  1406.          break;
  1407.       case 0x5C:
  1408.          usVkey=VK_F21;
  1409.          break;
  1410.       case 0x5D:
  1411.          usVkey=VK_F22;
  1412.          break;
  1413.       case 0x87:
  1414.          usVkey=VK_F23;
  1415.          break;
  1416.       case 0x88:
  1417.          usVkey=VK_F24;
  1418.          break;
  1419.       case 0x52:
  1420.          usVkey=VK_INSERT;
  1421.          break;
  1422.       case 0x47:
  1423.          usVkey=VK_HOME;
  1424.          break;
  1425.       case 0x49:
  1426.          usVkey=VK_PAGEUP;
  1427.          break;
  1428.       case 0x53:
  1429.          usVkey=VK_DELETE;
  1430.          break;
  1431.       case 0x4F:
  1432.          usVkey=VK_END;
  1433.          break;
  1434.       case 0x51:
  1435.          usVkey=VK_PAGEDOWN;
  1436.          break;
  1437.       case 0x4B:
  1438.          usVkey=VK_LEFT;
  1439.          break;
  1440.       case 0x48:
  1441.          usVkey=VK_UP;
  1442.          break;
  1443.       case 0x4D:
  1444.          usVkey=VK_RIGHT;
  1445.          break;
  1446.       case 0x50:
  1447.          usVkey=VK_DOWN;
  1448.          break;
  1449.       default:
  1450.          bInit=FALSE;
  1451.          break;
  1452.       } /* endswitch */
  1453.    } else
  1454.    if (pmkpChar->kkiKey.chChar==0xE0) {
  1455.       usFlags|=KC_VIRTUALKEY;
  1456.  
  1457.       switch (chScan) {
  1458.       case 0x52:
  1459.          usVkey=VK_INSERT;
  1460.          break;
  1461.       case 0x47:
  1462.          usVkey=VK_HOME;
  1463.          break;
  1464.       case 0x49:
  1465.          usVkey=VK_PAGEUP;
  1466.          break;
  1467.       case 0x53:
  1468.          usVkey=VK_DELETE;
  1469.          break;
  1470.       case 0x4F:
  1471.          usVkey=VK_END;
  1472.          break;
  1473.       case 0x51:
  1474.          usVkey=VK_PAGEDOWN;
  1475.          break;
  1476.       case 0x4B:
  1477.          usVkey=VK_LEFT;
  1478.          break;
  1479.       case 0x48:
  1480.          usVkey=VK_UP;
  1481.          break;
  1482.       case 0x4D:
  1483.          usVkey=VK_RIGHT;
  1484.          break;
  1485.       case 0x50:
  1486.          usVkey=VK_DOWN;
  1487.          break;
  1488.       default:
  1489.          bInit=FALSE;
  1490.          break;
  1491.       } /* endswitch */
  1492.    } else {
  1493.       //-------------------------------------------------------------------
  1494.       // Certain "non-extended" characters are still translated to
  1495.       // KC_VIRTUALKEY WM_CHAR messages.  Check for these cases and
  1496.       // act accordingly.
  1497.       //-------------------------------------------------------------------
  1498.       switch (pmkpChar->kkiKey.chChar) {
  1499.       case 0x08:
  1500.          usFlags|=KC_VIRTUALKEY;
  1501.          usVkey=VK_BACKSPACE;
  1502.          break;
  1503.       case 0x09:
  1504.          usFlags|=KC_VIRTUALKEY;
  1505.          usVkey=VK_TAB;
  1506.          break;
  1507.       case 0x0D:
  1508.          if (chScan==0x1C) {
  1509.             usFlags|=KC_VIRTUALKEY;
  1510.             usVkey=VK_NEWLINE;
  1511.          } else {
  1512.             usFlags|=KC_VIRTUALKEY;
  1513.             usVkey=VK_ENTER;
  1514.          } /* endif */
  1515.          break;
  1516.       case 0x1B:
  1517.          usFlags|=KC_VIRTUALKEY;
  1518.          usVkey=VK_ESC;
  1519.          break;
  1520.       case 0x20:
  1521.          usFlags|=KC_VIRTUALKEY;
  1522.          usVkey=VK_SPACE;
  1523.          break;
  1524.       case 0x37:
  1525.          usFlags|=KC_VIRTUALKEY;
  1526.          usVkey=VK_PRINTSCRN;
  1527.          break;
  1528.       default:
  1529.          usFlags|=KC_CHAR;
  1530.          chChar1=pmkpChar->kkiKey.chChar;
  1531.       } /* endswitch */
  1532.    } /* endif */
  1533.  
  1534.    if ((bInit) && (habAnchor->hwndFocus!=NULL)) {
  1535.       usMods=KC_CTRL | KC_ALT | KC_SHIFT;
  1536.  
  1537.       if ((usFlags & KC_VIRTUALKEY)!=KC_VIRTUALKEY) {
  1538.          if (vwIsWindowEnabled(habAnchor->hwndFocus)) {
  1539.             if (!vwPostMsg(habAnchor->hwndFocus,
  1540.                            WM_CHAR,
  1541.                            MPFROM2SHORT(usFlags,MAKEUSHORT(bRepeat,chScan)),
  1542.                            MPFROM2SHORT(MAKEUSHORT(chChar1,chChar2),usVkey))) {
  1543.                vwAlarm(WA_ERROR);
  1544.             } /* endif */
  1545.          } else {
  1546.             vwAlarm(WA_ERROR);
  1547.          } /* endif */
  1548.  
  1549.          return TRUE;
  1550.       } else
  1551.       if ((usFlags & KC_KEYUP)!=0) {
  1552.          if (vwIsWindowEnabled(habAnchor->hwndFocus)) {
  1553.             if (!vwPostMsg(habAnchor->hwndFocus,
  1554.                            WM_CHAR,
  1555.                            MPFROM2SHORT(usFlags,MAKEUSHORT(bRepeat,chScan)),
  1556.                            MPFROM2SHORT(MAKEUSHORT(chChar1,chChar2),usVkey))) {
  1557.                vwAlarm(WA_ERROR);
  1558.             } /* endif */
  1559.          } else {
  1560.             vwAlarm(WA_ERROR);
  1561.          } /* endif */
  1562.  
  1563.          return TRUE;
  1564.       } /* endif */
  1565.  
  1566.       bNeedPost=TRUE;
  1567.  
  1568.       switch (usFlags & usMods) {
  1569.       case 0:
  1570.          {
  1571.             ULONG ulDlgCode;
  1572.  
  1573.             if (usVkey==VK_TAB) {
  1574.                hwndFocus=habAnchor->hwndFocus;
  1575.  
  1576.                do {
  1577.                   hwndFocus=vwQueryWindow(hwndFocus,QW_NEXT);
  1578.  
  1579.                   if (hwndFocus==NULLHANDLE) {
  1580.                      hwndFocus=vwQueryWindow(habAnchor->hwndFocus,QW_TOP);
  1581.                   } /* endif */
  1582.  
  1583.                   ulDlgCode=LONGFROMMR(vwSendMsg(hwndFocus,
  1584.                                                  WM_QUERYDLGCODE,
  1585.                                                  0,
  1586.                                                  0));
  1587.                } while ((((ulDlgCode & DLGC_TABONCLICK)!=0) ||
  1588.                          (!vwIsWindowEnabled(hwndFocus))) &&
  1589.                         (hwndFocus!=habAnchor->hwndFocus)); /* enddo */
  1590.  
  1591.                if (hwndFocus!=habAnchor->hwndFocus) {
  1592.                   vwSetFocus(hwndFocus);
  1593.                } /* endif */
  1594.  
  1595.                bNeedPost=FALSE;
  1596.             } /* endif */
  1597.          }
  1598.          break;
  1599.       case KC_SHIFT:
  1600.          {
  1601.             ULONG ulDlgCode;
  1602.  
  1603.             if (usVkey==VK_BACKTAB) {
  1604.                hwndFocus=habAnchor->hwndFocus;
  1605.  
  1606.                do {
  1607.                   hwndFocus=vwQueryWindow(hwndFocus,QW_PREV);
  1608.  
  1609.                   if (hwndFocus==NULLHANDLE) {
  1610.                      hwndFocus=vwQueryWindow(habAnchor->hwndFocus,QW_BOTTOM);
  1611.                   } /* endif */
  1612.  
  1613.                   ulDlgCode=LONGFROMMR(vwSendMsg(hwndFocus,
  1614.                                                  WM_QUERYDLGCODE,
  1615.                                                  0,
  1616.                                                  0));
  1617.                } while ((((ulDlgCode & DLGC_TABONCLICK)!=0) ||
  1618.                          (!vwIsWindowEnabled(hwndFocus))) &&
  1619.                         (hwndFocus!=habAnchor->hwndFocus)); /* enddo */
  1620.  
  1621.                if (hwndFocus!=habAnchor->hwndFocus) {
  1622.                   vwSetFocus(hwndFocus);
  1623.                } /* endif */
  1624.  
  1625.                bNeedPost=FALSE;
  1626.             } /* endif */
  1627.          }
  1628.          break;
  1629.       default:
  1630.          break;
  1631.       } /* endswitch */
  1632.  
  1633.       if (bNeedPost) {
  1634.          if (vwIsWindowEnabled(habAnchor->hwndFocus)) {
  1635.             if (!vwPostMsg(habAnchor->hwndFocus,
  1636.                            WM_CHAR,
  1637.                            MPFROM2SHORT(usFlags,MAKEUSHORT(bRepeat,chScan)),
  1638.                            MPFROM2SHORT(MAKEUSHORT(chChar1,chChar2),usVkey))) {
  1639.                vwAlarm(WA_ERROR);
  1640.             } /* endif */
  1641.          } else {
  1642.             vwAlarm(WA_ERROR);
  1643.          } /* endif */
  1644.       } /* endif */
  1645.    } /* endif */
  1646.  
  1647.    return TRUE;
  1648. }
  1649.  
  1650. The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2, 
  1651. Issue 9 
  1652.  
  1653.  
  1654. ΓòÉΓòÉΓòÉ 4.3. Initialization, Termination, and Other Miscellany ΓòÉΓòÉΓòÉ
  1655.  
  1656. Initialization, Termination, and Other Miscellany 
  1657.  
  1658. Presented here is the code to initialize the library.  It should be fairly 
  1659. straightforward given the function prologue and the brief comments throughout 
  1660. the function. 
  1661.  
  1662. BOOL EXPENTRY vwInitialize(VOID)
  1663. //-------------------------------------------------------------------------
  1664. // This function initializes the library.
  1665. //
  1666. // 1) Initializes the memory manager
  1667. // 2) Creates the anchor block and message queue
  1668. // 3) Creates the linked lists for housekeeping
  1669. // 4) Initializes the system values array
  1670. // 5) Starts the keyboard monitor
  1671. // 6) Calls ordinal 1 in the class library so that the public classes
  1672. //    may be registered.
  1673. //
  1674. // Returns:  TRUE if successful, FALSE otherwise.
  1675. //-------------------------------------------------------------------------
  1676. {
  1677.    HCMMEM hcmWork;
  1678.    struct _VIOCURSORINFO vciCursor;
  1679.    PFNDLLINIT pfnInit;
  1680.  
  1681.    if (habAnchor!=NULL) {
  1682.       return FALSE;
  1683.    } /* endif */
  1684.  
  1685.    //----------------------------------------------------------------------
  1686.    // Initialize the memory manager
  1687.    //----------------------------------------------------------------------
  1688.    if (CmnMemInitialize(NULL,&hcmWork)!=MEM_ERR_NOERROR) {
  1689.       return FALSE;
  1690.    } /* endif */
  1691.  
  1692.    //----------------------------------------------------------------------
  1693.    // Create the anchor block and message queue and initialize them
  1694.    //----------------------------------------------------------------------
  1695.    CmnMemAllocate(hcmWork,sizeof(VWAB),(PPVOID)&habAnchor);
  1696.    if (habAnchor==NULL) {
  1697.       CmnMemTerminate(&hcmWork);
  1698.       return FALSE;
  1699.    } /* endif */
  1700.  
  1701.    habAnchor->ulSzStruct=sizeof(VWAB);
  1702.    habAnchor->ulStatus=0;
  1703.    habAnchor->hcmWork=hcmWork;
  1704.  
  1705.    //----------------------------------------------------------------------
  1706.    // Create the housekeeping lists
  1707.    //----------------------------------------------------------------------
  1708.    if (!CmnLstCreateList(sizeof(VWCLASSINFO),&habAnchor->hclClasses)) {
  1709.       CmnMemTerminate(&hcmWork);
  1710.       habAnchor=NULL;
  1711.       return FALSE;
  1712.    } /* endif */
  1713.  
  1714.    if (!CmnLstCreateList(sizeof(VWWND),&habAnchor->hclWindows)) {
  1715.       CmnLstDestroyList(&habAnchor->hclClasses);
  1716.       CmnMemTerminate(&hcmWork);
  1717.       habAnchor=NULL;
  1718.       return FALSE;
  1719.    } /* endif */
  1720.  
  1721.    if (!CmnLstCreateList(sizeof(VWTIMERINFO),&habAnchor->hclTimers)) {
  1722.       CmnLstDestroyList(&habAnchor->hclClasses);
  1723.       CmnLstDestroyList(&habAnchor->hclWindows);
  1724.       CmnMemTerminate(&hcmWork);
  1725.       habAnchor=NULL;
  1726.       return FALSE;
  1727.    } /* endif */
  1728.  
  1729.    habAnchor->bIsSendMsg=FALSE;
  1730.    habAnchor->hwndFocus=NULL;
  1731.  
  1732.    CmnMemAllocate(habAnchor->hcmWork,
  1733.                   sizeof(VWCURSORINFO),
  1734.                   (PPVOID)&habAnchor->pciCursor);
  1735.    if (habAnchor->pciCursor==NULL) {
  1736.       CmnLstDestroyList(&habAnchor->hclClasses);
  1737.       CmnLstDestroyList(&habAnchor->hclWindows);
  1738.       CmnLstDestroyList(&habAnchor->hclTimers);
  1739.       CmnMemTerminate(&hcmWork);
  1740.       habAnchor=NULL;
  1741.       return FALSE;
  1742.    } /* endif */
  1743.  
  1744.    CmnMemAllocate(habAnchor->hcmWork,sizeof(VWMQ),(PPVOID)&hmqQueue);
  1745.    if (hmqQueue==NULL) {
  1746.       CmnLstDestroyList(&habAnchor->hclClasses);
  1747.       CmnLstDestroyList(&habAnchor->hclWindows);
  1748.       CmnLstDestroyList(&habAnchor->hclTimers);
  1749.       CmnMemTerminate(&hcmWork);
  1750.       habAnchor=NULL;
  1751.       return FALSE;
  1752.    } /* endif */
  1753.  
  1754.    hmqQueue->ulSzStruct=sizeof(VWMQ);
  1755.    hmqQueue->ulHead=0;
  1756.    hmqQueue->ulTail=0;
  1757.  
  1758.    habAnchor->pciCursor->hwndWnd=NULL;
  1759.    habAnchor->pciCursor->sX=0;
  1760.    habAnchor->pciCursor->sY=0;
  1761.    habAnchor->pciCursor->usFlags=0;
  1762.  
  1763.    habAnchor->usCursorState=0;
  1764.  
  1765.    //----------------------------------------------------------------------
  1766.    // Initialize the system values array
  1767.    //----------------------------------------------------------------------
  1768.    habAnchor->alSysValues[VWSV_ERRORFREQ]=200;
  1769.    habAnchor->alSysValues[VWSV_NOTEFREQ]=800;
  1770.    habAnchor->alSysValues[VWSV_WARNINGFREQ]=400;
  1771.    habAnchor->alSysValues[VWSV_ERRORDURATION]=75;
  1772.    habAnchor->alSysValues[VWSV_NOTEDURATION]=75;
  1773.    habAnchor->alSysValues[VWSV_WARNINGDURATION]=75;
  1774.    habAnchor->alSysValues[VWSV_CXSCREEN]=80;
  1775.    habAnchor->alSysValues[VWSV_CYSCREEN]=25;
  1776.    habAnchor->alSysValues[VWSV_INSERTMODE]=TRUE;
  1777.    habAnchor->alSysValues[VWSV_CTIMERS]=16;
  1778.  
  1779.    //----------------------------------------------------------------------
  1780.    // Start the keyboard monitor
  1781.    //----------------------------------------------------------------------
  1782.    if (_beginthread(keyMonitor,NULL,0x2000,NULL)==-1) {
  1783.       CmnLstDestroyList(&habAnchor->hclClasses);
  1784.       CmnLstDestroyList(&habAnchor->hclWindows);
  1785.       CmnLstDestroyList(&habAnchor->hclTimers);
  1786.       CmnMemTerminate(&hcmWork);
  1787.       habAnchor=NULL;
  1788.       hmqQueue=NULL;
  1789.       return FALSE;
  1790.    } /* endif */
  1791.  
  1792.    //----------------------------------------------------------------------
  1793.    // Loop until we get a status back
  1794.    //----------------------------------------------------------------------
  1795.    while ((habAnchor->ulStatus &
  1796.           (VW_HABST_MONINITGOOD | VW_HABST_MONINITBAD))==0) {
  1797.       DosSleep(0);
  1798.    } /* endwhile */
  1799.  
  1800.    //----------------------------------------------------------------------
  1801.    // If bad, cleanup and return an error
  1802.    //----------------------------------------------------------------------
  1803.    if ((habAnchor->ulStatus & VW_HABST_MONINITBAD)!=0) {
  1804.       CmnLstDestroyList(&habAnchor->hclClasses);
  1805.       CmnLstDestroyList(&habAnchor->hclWindows);
  1806.       CmnLstDestroyList(&habAnchor->hclTimers);
  1807.       CmnMemTerminate(&hcmWork);
  1808.       habAnchor=NULL;
  1809.       hmqQueue=NULL;
  1810.       return FALSE;
  1811.    } /* endif */
  1812.  
  1813.    //----------------------------------------------------------------------
  1814.    // Hide the real cursor
  1815.    //----------------------------------------------------------------------
  1816.    VioGetCurType(&vciCursor,NULLHANDLE);
  1817.    vciCursor.attr=-1;
  1818.    VioSetCurType(&vciCursor,NULLHANDLE);
  1819.  
  1820.    //----------------------------------------------------------------------
  1821.    // Load the classes DLL and call ordinal 1
  1822.    //----------------------------------------------------------------------
  1823.    if (DosLoadModule(NULL,0,DLL_CLASS,&habAnchor->hmClasses)!=0) {
  1824.       CmnLstDestroyList(&habAnchor->hclClasses);
  1825.       CmnLstDestroyList(&habAnchor->hclWindows);
  1826.       CmnLstDestroyList(&habAnchor->hclTimers);
  1827.       CmnMemTerminate(&hcmWork);
  1828.       habAnchor=NULL;
  1829.       hmqQueue=NULL;
  1830.       return FALSE;
  1831.    } /* endif */
  1832.  
  1833.    if (DosQueryProcAddr(habAnchor->hmClasses,1,NULL,(PFN *)&pfnInit)!=0) {
  1834.       DosFreeModule(habAnchor->hmClasses);
  1835.       CmnLstDestroyList(&habAnchor->hclClasses);
  1836.       CmnLstDestroyList(&habAnchor->hclWindows);
  1837.       CmnLstDestroyList(&habAnchor->hclTimers);
  1838.       CmnMemTerminate(&hcmWork);
  1839.       habAnchor=NULL;
  1840.       hmqQueue=NULL;
  1841.       return FALSE;
  1842.    } /* endif */
  1843.  
  1844.    if (!(*pfnInit)()) {
  1845.       DosFreeModule(habAnchor->hmClasses);
  1846.       CmnLstDestroyList(&habAnchor->hclClasses);
  1847.       CmnLstDestroyList(&habAnchor->hclWindows);
  1848.       CmnLstDestroyList(&habAnchor->hclTimers);
  1849.       CmnMemTerminate(&hcmWork);
  1850.       habAnchor=NULL;
  1851.       hmqQueue=NULL;
  1852.       return FALSE;
  1853.    } /* endif */
  1854.  
  1855.    return TRUE;
  1856. }
  1857.  
  1858. Note! 
  1859.  
  1860. You should note two things from the code above: 
  1861.  
  1862. o The use of the ordinal number instead of a function name in the interface to 
  1863.   the class DLL instead of a function name.  This allows the class DLL 
  1864.   developer (who just happened to be me) to name the function anything, which 
  1865.   ultimately results in not having to document a name as the developer of the 
  1866.   main library.  (I know; it sounds cheesy.) 
  1867. o The lack of creation of a desktop window.  I took a particularly interesting 
  1868.   approach to the desktop; since I didn't plan to support dialogs, I had to 
  1869.   ease the development of dialog-based applications.  Thus, I chose to 
  1870.   implement the desktop in this manner - if vwCreateWindow() is called and no 
  1871.   windows currently exist, that window becomes the desktop. So, if the desktop 
  1872.   destroys itself and another window is created, it becomes the new desktop; 
  1873.   this can easily lend itself to dialogs with the user. 
  1874.  
  1875. Termination of the library is really simple:  destroy the windows, destroy the 
  1876. timers, destroy the lists, then return any other memory used back to the 
  1877. system. 
  1878.  
  1879. BOOL EXPENTRY vwTerminate(VOID)
  1880. //-------------------------------------------------------------------------
  1881. // This function terminates the library.
  1882. //
  1883. // Returns:  TRUE if successful, FALSE otherwise.
  1884. //-------------------------------------------------------------------------
  1885. {
  1886.    ULONG ulNumItems;
  1887.    ULONG ulIndex;
  1888.    HVWWND hwndList;
  1889.    PVWTIMERINFO ptiTimer;
  1890.    HCMMEM hcmWork;
  1891.    struct _VIOCURSORINFO vciCursor;
  1892.    BYTE abAttr[2];
  1893.  
  1894.    //----------------------------------------------------------------------
  1895.    // Make sure we were initialized
  1896.    //----------------------------------------------------------------------
  1897.    if (hmqQueue==NULL) {
  1898.       return FALSE;
  1899.    } /* endif */
  1900.  
  1901.    //----------------------------------------------------------------------
  1902.    // Destroy the windows
  1903.    //----------------------------------------------------------------------
  1904.    ulNumItems=CmnLstQueryRecordCount(habAnchor->hclWindows);
  1905.  
  1906.    for (ulIndex=0; ulIndex<ulNumItems; ulIndex++) {
  1907.       if (ulIndex==0) {
  1908.          hwndList=(HVWWND)CmnLstQueryRecord(habAnchor->hclWindows,0);
  1909.       } else {
  1910.          hwndList=(HVWWND)CmnLstQueryRelative(hwndList,LQR_NEXT);
  1911.       } /* endif */
  1912.  
  1913.       vwDestroyWindow(hwndList);
  1914.    } /* endfor */
  1915.  
  1916.    //----------------------------------------------------------------------
  1917.    // Destroy the timers
  1918.    //----------------------------------------------------------------------
  1919.    ulNumItems=CmnLstQueryRecordCount(habAnchor->hclTimers);
  1920.  
  1921.    for (ulIndex=0; ulIndex<ulNumItems; ulIndex++) {
  1922.       if (ulIndex==0) {
  1923.          ptiTimer=(PVWTIMERINFO)CmnLstQueryRecord(habAnchor->hclTimers,0);
  1924.       } else {
  1925.          ptiTimer=(PVWTIMERINFO)CmnLstQueryRelative(ptiTimer,LQR_NEXT);
  1926.       } /* endif */
  1927.  
  1928.       vwStopTimer(ptiTimer->hwndWnd,ptiTimer->ulId);
  1929.    } /* endfor */
  1930.  
  1931.    //----------------------------------------------------------------------
  1932.    // Tell the keyboard monitor to disengage itself
  1933.    //----------------------------------------------------------------------
  1934.    habAnchor->ulStatus|=VW_HABST_MONSHOULDTERM;
  1935.  
  1936.    while ((habAnchor->ulStatus & VW_HABST_MONTERM)!=0) {
  1937.       DosSleep(0);
  1938.    } /* endwhile */
  1939.  
  1940.    //----------------------------------------------------------------------
  1941.    // Cleanup the rest
  1942.    //----------------------------------------------------------------------
  1943.    DosFreeModule(habAnchor->hmClasses);
  1944.    CmnLstDestroyList(&habAnchor->hclWindows);
  1945.    CmnLstDestroyList(&habAnchor->hclClasses);
  1946.    CmnLstDestroyList(&habAnchor->hclTimers);
  1947.  
  1948.    hcmWork=habAnchor->hcmWork;
  1949.    CmnMemTerminate(&hcmWork);
  1950.  
  1951.    habAnchor=NULL;
  1952.    hmqQueue=NULL;
  1953.  
  1954.    //----------------------------------------------------------------------
  1955.    // Restore the cursor
  1956.    //----------------------------------------------------------------------
  1957.    VioGetCurType(&vciCursor,NULLHANDLE);
  1958.    vciCursor.attr=0;
  1959.    VioSetCurType(&vciCursor,NULLHANDLE);
  1960.  
  1961.    //----------------------------------------------------------------------
  1962.    // Clear the screen
  1963.    //----------------------------------------------------------------------
  1964.    abAttr[0]=' ';
  1965.    abAttr[1]=((((BYTE)VWCLR_BLACK) & 0x07)<<4)|(((BYTE)VWCLR_WHITE) & 0x07);
  1966.  
  1967.    VioScrollDn(0,0,25,80,999,abAttr,NULLHANDLE);
  1968.  
  1969.    return TRUE;
  1970. }
  1971.  
  1972. Note! 
  1973.  
  1974. Note the assumption that the screen is 80x25.  When the final library code is 
  1975. presented at the end of this series (see below), switch to 43 lines and run a 
  1976. test application to see the lower half of your screen be unused. 
  1977.  
  1978. I have not presented a set of DLLs and header files in this series because even 
  1979. as I write the series and present the code, I am finding oversights in the code 
  1980. that I am correcting.  While I know that this makes things quite annoying, I 
  1981. have to be quality conscious about this.  Finally, the code will be presented 
  1982. in connected and unconnected chunks; eventually, I will distribute the entire 
  1983. source tree. 
  1984.  
  1985. In the rest of VIOWIN.C, there is the set/query focus functions, the set/query 
  1986. system value functions, and the alarm function.  The code for these can be 
  1987. found in VIOWIN2.ZIP . 
  1988.  
  1989. The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2, 
  1990. Issue 9 
  1991.  
  1992.  
  1993. ΓòÉΓòÉΓòÉ 4.4. Next Month ΓòÉΓòÉΓòÉ
  1994.  
  1995. Next Month 
  1996.  
  1997. That's it for this month.  Next month, we will look at the window module since 
  1998. it is central to the operation of the library.  As always, comments on this 
  1999. series will be entertained at my email address. 
  2000.  
  2001. The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2, 
  2002. Issue 9 
  2003.  
  2004.  
  2005. ΓòÉΓòÉΓòÉ 5. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
  2006.  
  2007.  
  2008. ΓòÉΓòÉΓòÉ 5.1. Introduction ΓòÉΓòÉΓòÉ
  2009.  
  2010. /dev/EDM2/BookReview 
  2011.  
  2012. Written by Carsten Whimster 
  2013.  
  2014. Introduction 
  2015.  
  2016. /dev/EDM2/BookReview is a monthly column which focuses on development oriented 
  2017. books and materials.  The column is from a beginning PM programmer's eyes, 
  2018. because that's what I am.  Pick up whichever book strikes your fancy, and join 
  2019. the growing group of people following our PM programming columns.  I will 
  2020. review books aimed at beginners for a while, and then move on from there. 
  2021.  
  2022. Please send me your comments and thoughts so that I can make this column as 
  2023. good as possible.  All mail to me gets read and responded to. 
  2024.  
  2025. The REXX Reference Summary Handbook is a REXX reference book in the truest 
  2026. sense of the word.  It does little or no hand-holding, and its aim is to inform 
  2027. the initiated.  It won an OS/2 Magazine Editor's Award, and may well win more 
  2028. awards as the popularity of OS/2 and REXX increases. 
  2029.  
  2030. (Note:  The book is really white.  Unfortunately, I don't have access to a 
  2031. really good scanner, so the above is the result.) 
  2032.  
  2033. /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2034.  
  2035.  
  2036. ΓòÉΓòÉΓòÉ 5.2. Errata ΓòÉΓòÉΓòÉ
  2037.  
  2038. Errata 
  2039.  
  2040. Not much to say this month; it was quiet on the EDM/2 front. 
  2041.  
  2042. It was very busy at home though.  I upgraded my computer to an S3 805 card, and 
  2043. spent a lot of time figuring out how to set it up, locating drivers, and so on. 
  2044. Eventually, it all worked, but man, what a hazzle.  Hopefully OS/2 3.0 will do 
  2045. away with much of this.  I now run 800x600x65k, and I may rearrange my column 
  2046. slightly to accomodate this format better, just in case I had missed something 
  2047. when I was running 1024x768x256.  Hopefully I can afford the extra meg of RAM 
  2048. soon, so I can run 1024x768x65k :)  Then again, I may not want the slowdown, so 
  2049. I might stick with 800x600x65k. 
  2050.  
  2051. I also ditched the 486sx25 in favour of a 486dx2-50 (which was hard to find, by 
  2052. the way).  This means I should be spending more time ray-tracing and 
  2053. programming soon, and I'll probably update POV-Panel/2 soon.  I will likely 
  2054. write an article on programming in VX-REXX and use POV-Panel/2 as an example. 
  2055. Hopefully I can afford to upgrade to VX-REXX 2.1 before then. 
  2056.  
  2057. I have been tinkering with the Warp-II beta, and absolutely love it.  It 
  2058. addresses about 80% of my complaints with OS/2!  Now for the last 20%...  It 
  2059. did cause some problems, however, one of which I finally traced to 
  2060. incompatibilities between Warp-II and the 2.1 toolkit.  Now I can finally 
  2061. compile with IPFC again (important when you work on EDM/2). 
  2062.  
  2063. Anyhow, on to more programming oriented things... 
  2064.  
  2065. /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2066.  
  2067.  
  2068. ΓòÉΓòÉΓòÉ 5.3. REXX Reference Summary Handbook ΓòÉΓòÉΓòÉ
  2069.  
  2070. REXX Reference Summary Handbook 
  2071.  
  2072. The REXX Reference Summary Handbook is a small, but dense handbook of REXX 
  2073. commands and their syntax.  It is ring-bound, and lies flat on the table 
  2074. without changing pages on you.  It covers both standard REXX and also some 
  2075. extension libraries.  It even has a small pseudo-tutorial for those who have 
  2076. forgotten how REXX handles expressions and so on.  The chapters are as follows 
  2077. (I have included the sub-chapter headings to give a better idea of what it 
  2078. covers): 
  2079.  
  2080.  1. Language Summary 
  2081.  
  2082.     a. Basic Fundamentals and Structure 
  2083.     b. Keyword Instructions 
  2084.     c. System Commands & Subcommand Environments 
  2085.     d. Built-in Functions 
  2086.  
  2087.  2. SAA REXX External Function Modules 
  2088.  
  2089.     a. REXXUTIL Functions 
  2090.  
  2091.  3. Other Rexx (sic) External Function Modules 
  2092.  
  2093.     a. REXXLIB Functions 
  2094.     b. RXWINDOW Functions 
  2095.  
  2096.  4. Work Place Shell 
  2097.  
  2098.     a. WPS Objects 
  2099.     b. WPS Classes 
  2100.     c. WPS Object Key-Pairs 
  2101.     d. DOS / WIN-OS/2 Settings 
  2102.  
  2103.  5. Appendix A: ASCII and IBM Character Set 
  2104.  6. Appendix B: Codes Returned by SysGetKey 
  2105.  7. Appendix C: REXXLIB Video Attributes 
  2106.  8. Appendix D: REXX Error Codes 
  2107.  
  2108. Chapter one covers standard REXX as implemented in OS/2.  It describes the 
  2109. instruction layout and semantics briefly before launching into a summary of 
  2110. OS/2 SAA REXX keywords (referred to as REXX from here on in).  The descriptions 
  2111. are very terse, but informational, as can be seen in this small 
  2112. excerpt/example: 
  2113.  
  2114. QUEUE [expression]
  2115.    Places the value of expression at the bottom (/FIFO) of the
  2116.    currently active REXX data queue. If expression is
  2117.    omitted, a null string is stacked.
  2118.  
  2119. Only the needed information, but it is all there.  In the third sub-section of 
  2120. chapter one, the RXQUEUE and RXSUBCOM functions are described.  Lastly, in 
  2121. section four, a complete list of all standard REXX functions is presented, 
  2122. including all the most common ones, and also such pearls as complete 
  2123. descriptions of what effect using CHARIN, CHAROUT, and CHARS have on opening 
  2124. and closing files, all very neatly and clearly described in just a few lines. 
  2125. IBM take notice.  Both system calls such as DIRECTORY(), text tools such as 
  2126. RXMESSAGEBOX and standard library functions such as RANDOM() are explained. 
  2127.  
  2128. Chapter two covers the functions available in the REXXUTIL library, and shows 
  2129. how to set REXXUTIL up.  The REXXUTIL library is a colletion of mostly system 
  2130. functions, such as SysGetEA(), SysPutEA(), SysCreateObject(), and so on.  Many 
  2131. of these are quite powerful, and enable you to manipulate WPS objects, files, 
  2132. cursor postition, et cetera.  There may or may not be enough information in 
  2133. this little chapter to get you going with REXXUTIL, but if you have a fair idea 
  2134. of what is available, then there is more than enough information here to 
  2135. refresh your memory, or point out syntactic details.  Some of the text funtions 
  2136. described do not work in PMREXX, or other PM environments. 
  2137.  
  2138. The third chapter describes the use of the REXXLIB and RXWINDOW libraries from 
  2139. Quercus.  REXXLIB contains the following:  mathematical functions, stem and 
  2140. array functions for sorting and so on, extended attribute support, file 
  2141. control, various system functions, hardware information and access functions, 
  2142. and a collection of semaphore functions.  Many of these functions go a long way 
  2143. towards making REXX a viable option to C when programming small applications. 
  2144. REXXLIB is available from Quercus as part of Personal REXX, and is also 
  2145. available on many ftp sites.  The RXWINDOW library contains functions to 
  2146. manipulate windows in the PM environment, and include functions to mirror most 
  2147. mouse actions, examine window styles, and so on. 
  2148.  
  2149. Chapter four starts with a list of Object IDs for various programs and objects. 
  2150. This list enables you to access most, if not all of the OS/2 desktop.  The WPS 
  2151. classes are then listed, and although it is not quite complete, it should be 
  2152. adequate for most uses.  Only some of the more esoteric pieces of the hierarchy 
  2153. have not been placed into the tree.  The third section lists the WPS Object 
  2154. Key-Pairs.  These consist of keynames, values, and descriptions, and are needed 
  2155. for the SysCreateObject() and SysSetObjectData() functions.  Finally, key-pairs 
  2156. are listed for setting DOS and Windows session settings. 
  2157.  
  2158. Appendix A is a complete ASCII and IBM character set table, with ASCII values 
  2159. up to 255. 
  2160.  
  2161. Appendix B lists all the various codes that are returned by SysGetKey(), and 
  2162. includes all shifted, alt'ed, and control'ed characters, and all the 
  2163. combinations of the above. 
  2164.  
  2165. Appendix C lists the REXXLIB video attributes, i.e.  the foreground and 
  2166. background colour codes, and explains how to combine the two numbers to get the 
  2167. combined code. 
  2168.  
  2169. The last Appendix in the book, Appendix D, lists REXX error codes with 
  2170. explanations for the non-obvious codes. 
  2171.  
  2172. Finally, and all authors and publishers should pay attention here, the index is 
  2173. a masterpiece of cross-referencing, and although all books should have this 
  2174. good an index, very few do.  This is a sign of excellent attention to detail 
  2175. and a high quality publication. 
  2176.  
  2177. /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2178.  
  2179.  
  2180. ΓòÉΓòÉΓòÉ 5.4. Summary ΓòÉΓòÉΓòÉ
  2181.  
  2182. Summary 
  2183.  
  2184. This diminutive, but packed reference book is very high quality, and includes 
  2185. all kinds of un-called for details that you simply cannot find anywhere else in 
  2186. one place.  A lot of work has gone into every aspect of this book, and it 
  2187. shows.  It won an OS/2 Magazine Editor's Award, and if I was in the business of 
  2188. giving out awards, I would give it one as well.  The REXX Reference Summary 
  2189. Handbook has a very clear goal, and fulfils it well.  It doesn't try to be 
  2190. everything to everyone; it merely covers standard REXX, and some of the most 
  2191. popular add-on libraries completely.  All REXX programmers should own a copy. 
  2192. This book has no right to be reasonably priced, considering what it contains, 
  2193. but it is. 
  2194.  
  2195. /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2196.  
  2197.  
  2198. ΓòÉΓòÉΓòÉ 5.5. Books Reviewed ΓòÉΓòÉΓòÉ
  2199.  
  2200. Books Reviewed 
  2201.  
  2202. This table contains all books I have reviewed, so that you can find what you 
  2203. are looking for at a glance.  I will be careful to rate books fairly.  If I 
  2204. feel a need to adjust ratings, I will adjust all of them at the same time, and 
  2205. write a note explaining why I felt this necessary.  Please note that books 
  2206. aimed at different audiences should only be compared with great care, if at 
  2207. all.  I intend to concentrate on the strong points of the books I review, but I 
  2208. will point out any weaknesses in a constructive manner. 
  2209.  
  2210. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2211. ΓöéBOOK                              ΓöéAUDIENCE    ΓöéMARKΓöéCOMMENTS                               Γöé
  2212. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2213. ΓöéReal-World Programming for OS/2   ΓöéIntermediateΓöéB+  ΓöéLots of good code examples, but        Γöé
  2214. Γöé2.1, Blain, Delimon, and English, Γöéto Advanced Γöé    Γöésometimes it is too complex for        Γöé
  2215. ΓöéSAMS Publishing.  ISBN            ΓöéPM C        Γöé    Γöénovices. Accurate.  Well organized.    Γöé
  2216. Γöé0-672-30300-0.  US$40, CAN$50.    Γöéprogrammers Γöé    ΓöéThe index needs a little beefing up.   Γöé
  2217. Γöé                                  Γöé            Γöé    ΓöéGood, but not entirely complete how-to Γöé
  2218. Γöé                                  Γöé            Γöé    Γöéreference.  Good purchase.             Γöé
  2219. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2220. ΓöéLearning to Program OS/2 2.0      ΓöéBeginning PMΓöéB-  ΓöéThis book can be both frustrating and  Γöé
  2221. ΓöéPresentation Manager by Example,  ΓöéC           Γöé    Γöévery rewarding.  It is not very large, Γöé
  2222. ΓöéKnight, Van Nostrand Reinhold.    ΓöéProgrammers Γöé    Γöéand a bit pricey, but has some         Γöé
  2223. ΓöéISBN 0-442-01292-6.  US$40,       Γöé            Γöé    Γöéexcellent chapters on certain beginningΓöé
  2224. ΓöéCAN$50.                           Γöé            Γöé    Γöétopics, such as messages, resources,   Γöé
  2225. Γöé                                  Γöé            Γöé    ΓöéIPF, and dialog boxes.  Strictly for   Γöé
  2226. Γöé                                  Γöé            Γöé    Γöébeginners.  This book has only one     Γöé
  2227. Γöé                                  Γöé            Γöé    Γöé(large) sample program!                Γöé
  2228. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2229. ΓöéWriting OS/2 2.1 Device Drivers inΓöéAdvanced C  ΓöéA-  ΓöéThe only thing a device driver         Γöé
  2230. ΓöéC, 2nd Edition, Mastrianni, Van   ΓöéProgrammers,Γöé    Γöéprogrammer would not find in here is   Γöé
  2231. ΓöéNostrand Reinhold.  ISBN          Γöéfamiliar    Γöé    Γöéhow to write SCSI, ADD, and IFS        Γöé
  2232. Γöé0-442-01729-4.  US$35, CAN$45.    Γöéwith        Γöé    Γöédrivers.  Most everything else is in   Γöé
  2233. Γöé                                  Γöéhardware    Γöé    Γöéhere, along with skeleton examples.  AnΓöé
  2234. Γöé                                  Γöéprogramming Γöé    Γöéoptional DevHlp library of C-callable  Γöé
  2235. Γöé                                  Γöé            Γöé    Γöéfunctions can be purchased by those whoΓöé
  2236. Γöé                                  Γöé            Γöé    Γöédon't have time to write their own.    Γöé
  2237. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2238. ΓöéOS/2 Presentation Manager GPI,    ΓöéIntermediateΓöéC+  ΓöéThis book needs updating for OS/2 2.x. Γöé
  2239. ΓöéWinn, Van Nostrand Reinhold. ISBN Γöéto advanced Γöé    ΓöéIt is a well-written in-depth coverage Γöé
  2240. Γöé0-442-00739-6.  US$35, CAN$45.    ΓöéPM C        Γöé    Γöéof the OS/2 way of programming for     Γöé
  2241. Γöé                                  Γöéprogrammers Γöé    Γöégraphics.  It is not an introductory PMΓöé
  2242. Γöé                                  Γöé            Γöé    Γöéor graphics programming book.  You     Γöé
  2243. Γöé                                  Γöé            Γöé    Γöéshould know the basics of PM           Γöé
  2244. Γöé                                  Γöé            Γöé    Γöéprogramming already.                   Γöé
  2245. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2246. ΓöéThe Art of OS/2 2.1 C Programming,ΓöéBeginning   ΓöéB+  ΓöéThis is a great introductory PM        Γöé
  2247. ΓöéPanov, Salomon, and Panov,        ΓöéOS/2 and PM Γöé    Γöéprogramming book.  It covers basic OS/2Γöé
  2248. ΓöéWiley-QED.  ISBN 0-471-58802-4.   Γöéprogrammers Γöé    Γöéissues like threads before it jumps    Γöé
  2249. ΓöéUS$40, CAN$50.                    Γöé            Γöé    Γöéinto PM programming.  The coverage is  Γöé
  2250. Γöé                                  Γöé            Γöé    Γöéquite thourough, with just enough      Γöé
  2251. Γöé                                  Γöé            Γöé    Γöéreference material to make it useful   Γöé
  2252. Γöé                                  Γöé            Γöé    Γöéafter you read it through the first    Γöé
  2253. Γöé                                  Γöé            Γöé    Γöétime.  The upcoming revised edition    Γöé
  2254. Γöé                                  Γöé            Γöé    Γöéshould be a killer.                    Γöé
  2255. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2256. ΓöéMastering OS/2 REXX, Gargiulo,    ΓöéIntermediateΓöéB   ΓöéThis book is very easy to understand.  Γöé
  2257. ΓöéWiley-QED.  ISBN 0-471-51901-4.   ΓöéOS/2 users  Γöé    ΓöéIf you program with any regularity,    Γöé
  2258. ΓöéUS$40, CAN$50.                    Γöéand novice  Γöé    Γöélook elsewhere, but if you need an     Γöé
  2259. Γöé                                  Γöéprogrammers Γöé    Γöéeasily read, well-explained beginner's Γöé
  2260. Γöé                                  Γöé            Γöé    Γöébook, look no further.  Some more      Γöé
  2261. Γöé                                  Γöé            Γöé    Γöédetailed, and complex real-world       Γöé
  2262. Γöé                                  Γöé            Γöé    Γöéexamples might be useful as you learn  Γöé
  2263. Γöé                                  Γöé            Γöé    Γöéthe material.  Good coverage of REXX's Γöé
  2264. Γöé                                  Γöé            Γöé    Γöécapabilities.                          Γöé
  2265. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2266. ΓöéREXX Reference Summary Handbook,  Γöébeginning toΓöéA   ΓöéThis little handbook is packed full of Γöé
  2267. ΓöéGoran, C F S Nevada.  ISBN        Γöéexpert REXX Γöé    Γöéuseful information.  Includes chapters Γöé
  2268. Γöé0-9639854-1-8.  US$20, CAN$25     Γöéprogrammers Γöé    Γöéon both built-in and some popular      Γöé
  2269. Γöé                                  Γöé            Γöé    Γöécommercial libraries.  Well-written andΓöé
  2270. Γöé                                  Γöé            Γöé    Γöécomprehensively indexed.  A must for   Γöé
  2271. Γöé                                  Γöé            Γöé    ΓöéREXX programmers.                      Γöé
  2272. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2273.  
  2274. LEGEND: 
  2275.  
  2276. BOOK:  The name of the book, author(s), publishing company, ISBN, and 
  2277. approximate price. 
  2278.  
  2279. AUDIENCE:  This is a description of the audience I think the book targets best. 
  2280. This is not intended as gospel, just a guideline for people not familiar with 
  2281. the book. 
  2282.  
  2283. MARK:  My opinion of the success of the book's presentation, and how well it 
  2284. targets its audience.  Technical content, accuracy, organization, readability, 
  2285. and quality of index all weigh heavily here, but the single most important item 
  2286. is how well the book covers what it says it covers.  Many books try to cover 
  2287. too much, and get a lower mark as a result. 
  2288.  
  2289. ΓöîΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2290. ΓöéA+ ΓöéGround-breaking, all-around outstanding book.                                Γöé
  2291. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2292. ΓöéA  ΓöéExcellent book.  This is what I want to see happen a lot.                    Γöé
  2293. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2294. ΓöéA- ΓöéExcellent book with minor flaws.                                             Γöé
  2295. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2296. ΓöéB+ ΓöéVery good book with minor flaws or omissions.                                Γöé
  2297. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2298. ΓöéB  ΓöéGood book with some flaws and omissions.                                     Γöé
  2299. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2300. ΓöéB- ΓöéGood book, but in need of improvement.                                       Γöé
  2301. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2302. ΓöéC+ ΓöéMediocre book with some potential, but in need of some updating.             Γöé
  2303. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2304. ΓöéC  ΓöéMediocre book with some good sections, but badly in need of fixing.          Γöé
  2305. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2306. ΓöéC- ΓöéMediocre book, little good material, desperately in need of an overhaul.     Γöé
  2307. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2308. ΓöéD  ΓöéDon't buy this book unless you need it, and nothing else exists.             Γöé
  2309. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2310. ΓöéF  ΓöéDon't buy this book.  Period.                                                Γöé
  2311. ΓööΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2312.  
  2313. COMMENTS:  This is a very brief summary of the review proper. 
  2314.  
  2315. /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2316.  
  2317.  
  2318. ΓòÉΓòÉΓòÉ 5.6. Coming Up ΓòÉΓòÉΓòÉ
  2319.  
  2320. Coming Up 
  2321.  
  2322. Next month I will be looking at either Application Development Using OS/2 REXX, 
  2323. Rudd or OS/2 Presentation Manager Programming, Petzold.  I have been treating 
  2324. REXX fairly heavily recently, and would like a change of pace, but we'll see. 
  2325. The books I intend to review are (not necessarily in this order): 
  2326.  
  2327. o OS/2 Presentation Manager Programming, Petzold 
  2328. o Application Development Using OS/2 REXX, Rudd 
  2329. o The Design of OS/2, 2nd Edititon, Kogan and Deitel - 1994 - not published yet 
  2330.   (or is it?) 
  2331.  
  2332. I am considering reviewing the IBM OS/2 Redbooks, since they are readily and 
  2333. cheaply available, and look like good reference. 
  2334.  
  2335. I am also considering reviewing Designing OS/2 Applications, Reich, mostly 
  2336. because it promises to present a different angle on OS/2 programming, namely 
  2337. that of how to design OS/2 applications, rather than how to program OS/2 
  2338. applications. 
  2339.  
  2340. Finally, I am considering reviewing OS/2 Unleashed, but it is not strictly 
  2341. speaking a development book, so I'm going to wait until the list of real 
  2342. development books has diminished a bit.  I hear that there is a CD-ROM version 
  2343. of it out now, and I will try to get a copy of this. 
  2344.  
  2345. If anyone has a book they want to see reviewed, I will be happy to oblige, as 
  2346. long as I can afford it.  Of course, requests can be satisfied quicker when 
  2347. accompanied by a book :)  Publishers can send me books at the address on my 
  2348. personal page at the end of the magazine, and I will review all OS/2 
  2349. development-related and advanced user books I receive. 
  2350.  
  2351. /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2352.  
  2353.  
  2354. ΓòÉΓòÉΓòÉ 6. C++ Corner ΓòÉΓòÉΓòÉ
  2355.  
  2356.  
  2357. ΓòÉΓòÉΓòÉ 6.1. Introduction ΓòÉΓòÉΓòÉ
  2358.  
  2359. C++ Corner 
  2360.  
  2361. Written by Gordon Zeglinski 
  2362.  
  2363. Introduction 
  2364.  
  2365. A few issue back, we looked at encapsulating the profile file API in C++. In 
  2366. this issue, we will use SOM to mirror the C++ object. 
  2367.  
  2368. Recall the C++ call definition: 
  2369.  
  2370. class ProfileFile{
  2371.    APIRET  Error;
  2372.    HINI hini;
  2373.    HAB hab;
  2374.    PSZ FileName;
  2375.    char Close;
  2376.  
  2377. public:
  2378.    ProfileFile(PSZ name,HAB hb);
  2379.    ProfileFile(HINI H);
  2380.    ~ProfileFile();
  2381.  
  2382.    APIRET GetError(){return Error;}
  2383.    HINI GetHandle(){return hini;}
  2384.  
  2385.    void WriteString(PSZ App,PSZ Key, PSZ String);
  2386.    void WriteData(PSZ App, PSZ Key, void * Buff, ULONG BLen);
  2387.    ULONG GetDataSize(PSZ App,PSZ Key);
  2388.    void GetData(PSZ App,PSZ Key,void * Buff, ULONG & BufMax);
  2389.    ULONG GetString(PSZ App,PSZ Key,PSZ Buff,ULONG BufMax,PSZ DefArg=NULL);
  2390.    LONG GetInt(PSZ App,PSZ Key,LONG DefArg=0);
  2391.    void WriteInt(PSZ App,PSZ Key,LONG Num);
  2392.    PRFPROFILE Querry();
  2393. };
  2394.  
  2395. The above definition will be mirrored using SOM. 
  2396.  
  2397. C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2398.  
  2399.  
  2400. ΓòÉΓòÉΓòÉ 6.2. The SOM Profile Class Definition ΓòÉΓòÉΓòÉ
  2401.  
  2402. The SOM Profile Class Definition 
  2403.  
  2404. Following is the SOM IDL definition for the profile class and its metaclass. 
  2405. This listing is from the file INIObjs.idl.  We'll look at this in detail later. 
  2406.  
  2407. #ifndef __INIObj_h__
  2408. #define __INIObj_h__
  2409.  
  2410. #include <somcls.idl>
  2411.  
  2412. interface M_INIObj;
  2413. interface INIObj : SOMObject
  2414. {
  2415.    typedef unsigned long ULONG;
  2416.    typedef sequence<char> buffType;
  2417.  
  2418.    attribute long Error; // Stores the Error Data
  2419.    attribute long DidCreate; // Flag used to indicate wether we should close the ini file
  2420.  
  2421.    unsigned long GetHandle();
  2422.    void SetHandle(in unsigned long H);
  2423.  
  2424.    void  WriteString(in string App,in string Key, in string String);
  2425.          // write a string
  2426.  
  2427.    void  WriteData(in string App, in string Key,in buffType Buff,in ULONG BLen);
  2428.          // write the Buffer
  2429.  
  2430.    void  WriteInt(in string App,in string Key,in long Num);
  2431.          // write an "int"
  2432.  
  2433.  
  2434.  
  2435.    ULONG GetDataSize(in string App,in string Key);
  2436.          // return the lenght of the data
  2437.  
  2438.    void  GetData(in string App,in string Key,in buffType Buff, inout ULONG BufMax);
  2439.          // return the data in Buff
  2440.  
  2441.    ULONG GetString(in string App,in string Key,in buffType Buff,in ULONG BufMax, \
  2442.             in string DefArg);
  2443.          // return the String in Buff, defaults to DefArg if App/Key not present
  2444.  
  2445.    ULONG GetStringNoDef(in string App,in string Key,in buffType Buff,in ULONG BufMax);
  2446.          // return the String in Buff
  2447.  
  2448.    long  GetInt(in string App,in string Key,in long DefArg);
  2449.          // return the "int" in App/Key or the DefArg if App/Key not present
  2450.  
  2451.    long  GetIntNoDef(in string App,in string Key);
  2452.          // return the "int" in App/Key
  2453.  
  2454. #ifdef __SOMIDL__
  2455. implementation
  2456. {
  2457.     //we use an unsigned long because that's what OS/2 uses for a HIHI
  2458.    unsigned long INIHandle;
  2459.  
  2460.  
  2461.  
  2462.     releaseorder: GetHandle,SetHandle,_get_Error,_set_Error,_set_DidCreate, _get_DidCreate, \
  2463.                   WriteString,WriteData,WriteInt,GetDataSize,GetData,GetString,GetStringNoDef, \
  2464.                   GetInt,GetIntNoDef;
  2465.  
  2466.  
  2467.     callstyle=oidl;
  2468.     filestem = iniobjs;
  2469.     metaclass = M_INIObj;
  2470.     somInit: override;  // initialize instance variables to 0
  2471.     somUninit:override; // close INI file if we opened it
  2472.  
  2473.     passthru C_xh_after=   "#define INCL_WINSHELLDATA" \
  2474.                            "#include <os2.h>";
  2475. };
  2476. #endif /* __SOMIDL__ */
  2477. };
  2478.  
  2479. interface M_INIObj : SOMClass
  2480. {
  2481.  
  2482.    INIObj INICreate(in unsigned long hab,in string FileName); // create an INI file with the given Name
  2483.    INIObj CreateFromOpen(in unsigned long HINI);
  2484.  
  2485.    INIObj GetUserINI();
  2486.    INIObj GetSystemINI();
  2487.  
  2488. #ifdef __SOMIDL__
  2489. implementation
  2490. {
  2491.    INIObj UserINI;        //the user INI file
  2492.    INIObj SystemINI;      //the System INI file
  2493.  
  2494.    releaseorder: INICreate,CreateFromOpen,GetUserINI,GetSystemINI;
  2495.    callstyle=oidl;
  2496.    filestem = iniobjs;
  2497.    functionprefix=M_;
  2498.    somInitMIClass: override;
  2499.    somInit: override; // just a test for parent call macros
  2500.    somUninit:override; // clean up any instances we make
  2501. };
  2502. #endif /* __SOMIDL__ */
  2503. };
  2504.  
  2505. #endif /* __INIObj_h__ */
  2506.  
  2507. Pretty impressive stuff huh?  :) 
  2508.  
  2509. The M_INIObj Metaclass 
  2510.  
  2511. As mentioned in the last issue, the metaclass provides the constructor and 
  2512. class methods.  We provide 2 constructors, CreateFromOpen and INICreate. 
  2513. INICreate takes the HAB and the name of the profile file; its implementation 
  2514. follows. 
  2515.  
  2516. SOM_Scope INIObj*  SOMLINK M_INICreate(M_INIObj *somSelf, unsigned long hab,
  2517.                                        string FileName)
  2518. {
  2519.     /* M_INIObjData *somThis = M_INIObjGetData(somSelf); */
  2520.     M_INIObjMethodDebug("M_INIObj","M_INICreate");
  2521.  
  2522.     /* Return statement to be customized: */
  2523. //    { INIObj* retVal;  return (retVal); }
  2524.  
  2525.    // call the OS/2 API function to open the  profile function
  2526.    HINI hini=PrfOpenProfile(hab,FileName);
  2527.  
  2528.  
  2529.    //create the INIObj instance
  2530.    INIObj* INI=somSelf->somNew();
  2531.  
  2532.    // if hini is non zero, then we opened the file successfully
  2533.    if(hini){
  2534.       INI->_set_Error(0);        //clear the instance variable Error
  2535.       INI->SetHandle(hini);      //set the profile handle
  2536.       INI->_set_DidCreate(1);    //set the flag indicating that the file should
  2537.    }                             //be closed when the instace is destroyed
  2538.    // otherwise an error occured
  2539.    else{
  2540.       INI->_set_Error(1);
  2541.       INI->SetHandle(hini);
  2542.       INI->_set_DidCreate(0);
  2543.    }
  2544.  
  2545. //return the instance
  2546. return INI;
  2547. }
  2548.  
  2549. In the above snippet, the bold text is the code added to the stubs created by 
  2550. the som compiler.  The constructor CreateFromOpen is provided to create an 
  2551. instance of a INIObj give a handle of an already open profile file. 
  2552.  
  2553. The implementation section of the M_INIObj metaclass contains the declaration 
  2554. of two class variables, UserINI and SystemINI.  These variables will be used to 
  2555. store an instance of INIObj for the System and User INI files.  They are 
  2556. accessed by the class methods GetUserINI and GetUserINI respectively.  Below is 
  2557. the implementation for the GetUserINI method. 
  2558.  
  2559. SOM_Scope INIObj*  SOMLINK M_GetUserINI(M_INIObj *somSelf)
  2560. {
  2561.     M_INIObjData *somThis = M_INIObjGetData(somSelf);
  2562.     M_INIObjMethodDebug("M_INIObj","M_GetUserINI");
  2563.  
  2564.     /* Return statement to be customized: */
  2565. //    { INIObj* retVal;  return (retVal); }
  2566.     //check to see if the UserINI variable is NULL
  2567.     if(!somThis->UserINI){
  2568.       //if it is, then create an instance of the INIObj class
  2569.       somThis->UserINI=somSelf->somNew();
  2570.       //and set it handle to that of the user profile file
  2571.       somThis->UserINI->SetHandle(HINI_USERPROFILE);
  2572.       //we didn't create the file so we won't close it
  2573.       somThis->UserINI->_set_DidCreate(0);
  2574.     }
  2575.  
  2576.    //return instance of the user ini file.
  2577.    return somThis->UserINI;
  2578. }
  2579.  
  2580. The above snippet illustrates how to access class data using somThis.  Now to 
  2581. take care of a few details.  Notice that we tested UserINI against 0 to see if 
  2582. we created an instance before.  How do we know it will be zero if we previously 
  2583. didn't create an instance of INIObj for it?  Also note that we create a new 
  2584. instance of INIObj.  Where does it get deleted?  For the answer to these two 
  2585. questions, we look at the implementation section of the metaclass again.  We 
  2586. see: 
  2587.  
  2588.    somInit: override; // just a test for parent call macros
  2589.    somUninit:override; // clean up any instances we make
  2590.  
  2591. These methods take care of the initialization and destruction of the metaclass 
  2592. data members.  Their implementation follows. 
  2593.  
  2594. SOM_Scope void  SOMLINK M_somInit(M_INIObj *somSelf)
  2595. {
  2596.     M_INIObjData *somThis = M_INIObjGetData(somSelf);
  2597.     M_INIObjMethodDebug("M_INIObj","M_somInit");
  2598.  
  2599.     M_INIObj_parent_SOMClass_somInit(somSelf);
  2600.  
  2601.     // initialize the variables to 0
  2602.     somThis->UserINI=0;
  2603.     somThis->SystemINI=0;
  2604. }
  2605.  
  2606. SOM_Scope void  SOMLINK M_somUninit(M_INIObj *somSelf)
  2607. {
  2608.     M_INIObjData *somThis = M_INIObjGetData(somSelf);
  2609.     M_INIObjMethodDebug("M_INIObj","M_somUninit");
  2610.  
  2611.     M_INIObj_parent_SOMClass_somUninit(somSelf);
  2612.     if(!somThis->UserINI) //if we created it delete it
  2613.       delete somThis->UserINI;
  2614.  
  2615.     if(!somThis->SystemINI) //if we created it delete it
  2616.       delete somThis->SystemINI;
  2617. }
  2618.  
  2619. That's it for the metaclass.  As an exercise for the reader, modify the 
  2620. constructor CreateFromOpen so that it fails to create an instance of INIObj if 
  2621. it is passed a handle to either the system or user INI. 
  2622.  
  2623. The INIObj Class 
  2624.  
  2625. Now that we've seen the metaclass, we can start looking at the INIObj class. 
  2626. Going back to the SOM interface definition listing at the start of this section 
  2627. and comparing it to the C++ code, we see that there is nearly a 1 to 1 
  2628. correlation between the functions.  We won't cover what each function does, but 
  2629. merely explore the "highlights".  The SOM version includes two additional 
  2630. functions GetStringNoDef and GetIntNoDef.  These methods are necessary because 
  2631. in SOM there's no way to set default arguments and each function must be 
  2632. uniquely named.  It's not CORBA compliant to use pointers as parameters.  Thus, 
  2633. we define the type buffType, typedef sequence<char> buffType;.  A sequence is 
  2634. similar to an "array/pointer" in C except it can have a maximum bound.  Again, 
  2635. we override the somInit and somUninit to zero the instance variables and to 
  2636. provide clean up.  Following is the code for somUninit. 
  2637.  
  2638. SOM_Scope void  SOMLINK somUninit(INIObj *somSelf)
  2639. {
  2640.     INIObjData *somThis = INIObjGetData(somSelf);
  2641.     INIObjMethodDebug("INIObj","somUninit");
  2642.  
  2643.     INIObj_parent_SOMObject_somUninit(somSelf);
  2644.    if(somThis->DidCreate)
  2645.       PrfCloseProfile(somThis->INIHandle);
  2646. }
  2647.  
  2648. The above routine calls the parent somUninit methods and then performs it's 
  2649. clean up.  If DidCreate  variable is non-zero, then the instance opened the 
  2650. profile file and should close it when destroyed. 
  2651.  
  2652. C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2653.  
  2654.  
  2655. ΓòÉΓòÉΓòÉ 6.3. Testing The Code ΓòÉΓòÉΓòÉ
  2656.  
  2657. Testing The Code 
  2658.  
  2659. Now that we've seen how to implement the SOM object, let's see how to use it. 
  2660. The following code is the main routine taken from the file MAIN.CPP. 
  2661.  
  2662. int main(int argc, char *argv[]){
  2663.    // create an the INIObj class by creating an instance of M_INIObj
  2664.    M_INIObj *INIObjclass=INIObjNewClass(INIObj_MajorVersion ,INIObj_MinorVersion);
  2665.  
  2666.    //now create an instance of INIObj
  2667.    INIObj *INIFile=INIObjclass->INICreate(0,"test.ini");
  2668.  
  2669.    //Write some strings to the ini file
  2670.    // application "TestApp", key "TestKey1"
  2671.    INIFile->WriteString("TestApp","TestKey1","This is the First Test");
  2672.    // application "TestApp", key "TestKey2"
  2673.    INIFile->WriteString("TestApp","TestKey2","This is the Second Test");
  2674.  
  2675.  
  2676.    char Junk[300];  // some space to the results from the GetString calls
  2677.  
  2678.    // read in and display the two app/key pairs
  2679.    INIFile->GetStringNoDef("TestApp","TestKey1",(INIObj_buffType*)Junk,300);
  2680.    cout<<Junk<<endl;
  2681.  
  2682.    INIFile->GetStringNoDef("TestApp","TestKey2",(INIObj_buffType*)Junk,300);
  2683.    cout<<Junk<<endl;
  2684.  
  2685.    // read in a app/key pair that doesn't exist ... do we get the default value ?
  2686.    INIFile->GetString("TestApp","TestKey3",(INIObj_buffType*)Junk,300,"No Such Key");
  2687.    cout<<Junk<<endl;
  2688.  
  2689.    delete INIFile;      // delete the instance of INIObj
  2690.    delete INIObjclass;  // delete the instance of M_INIObj
  2691.    return 0;
  2692. }
  2693.  
  2694. Using our C++ based wrapper previously defined, the code would look like: 
  2695.  
  2696. int main(int argc, char *argv[]){
  2697.  
  2698.    //now create an instance of Profile File
  2699.    INIObj *INIFile=new ProfileFile("test.ini",0);
  2700.  
  2701.    //Write some strings to the ini file
  2702.    // application "TestApp", key "TestKey1"
  2703.    INIFile->WriteString("TestApp","TestKey1","This is the First Test");
  2704.    // application "TestApp", key "TestKey2"
  2705.    INIFile->WriteString("TestApp","TestKey2","This is the Second Test");
  2706.  
  2707.    char Junk[300];  // some space to the results from the GetString calls
  2708.  
  2709.    // read in and display the two app/key pairs
  2710.    INIFile->GetString("TestApp","TestKey1",(INIObj_buffType*)Junk,300);
  2711.    cout<<Junk<<endl;
  2712.  
  2713.    INIFile->GetString("TestApp","TestKey2",(INIObj_buffType*)Junk,300);
  2714.    cout<<Junk<<endl;
  2715.  
  2716.    // read in a app/key pair that doesn't exist ... do we get the default value ?
  2717.    INIFile->GetString("TestApp","TestKey3",(INIObj_buffType*)Junk,300,"No Such Key");
  2718.    cout<<Junk<<endl;
  2719.  
  2720.    delete INIFile;      // delete the instance of ProfileFile
  2721.  
  2722.    return 0;
  2723. }
  2724.  
  2725. There are only two major differences between the C++ and SOM version (at this 
  2726. level).  First, the SOM version uses a metaclass.  Therefore, the SOM version 
  2727. needs code to create and delete the metaclass.  Second, C++ allows default 
  2728. parameters so the GetString() function can be used in several locations. 
  2729.  
  2730. C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2731.  
  2732.  
  2733. ΓòÉΓòÉΓòÉ 6.4. Wrapping Things Up ΓòÉΓòÉΓòÉ
  2734.  
  2735. Wrapping Things Up 
  2736.  
  2737. This concludes another thrilling episode of SOM exploration.  The reader is 
  2738. encouraged to see how the implementation of the C++ members and SOM members 
  2739. differ.  In particular, see how the inout parameters in SOM differ from the 
  2740. reference parameters in C++. 
  2741.  
  2742. C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2743.  
  2744.  
  2745. ΓòÉΓòÉΓòÉ 7. Introduction to PM Programming ΓòÉΓòÉΓòÉ
  2746.  
  2747.  
  2748. ΓòÉΓòÉΓòÉ 7.1. Introduction ΓòÉΓòÉΓòÉ
  2749.  
  2750. Introduction to PM Programming 
  2751.  
  2752. Written by Larry Salomon, Jr. 
  2753.  
  2754. Introduction 
  2755.  
  2756. The purpose of this column is to provide the readers out there who are not 
  2757. familiar with PM application development the information necessary to satisfy 
  2758. their curiousity, educate themselves, and give them an advantage over the 
  2759. documentation supplied by IBM.  Of course, much of this stuff could probably be 
  2760. found in one of the many books out there, but the problem with books in general 
  2761. is that they don't answer the questions you have after you read the book the 
  2762. first time through. 
  2763.  
  2764. I will gladly entertain feedback from the readers about what was "glossed over" 
  2765. or what was detailed well, what tangential topics need to be covered and what 
  2766. superfluous crap should have been removed.  This feedback is essential in 
  2767. guaranteeing that you get what you pay for.  :) 
  2768.  
  2769. It should be said that you must not depend solely on this column to teach you 
  2770. how to develop PM applications; instead, this should be viewed as a supplement 
  2771. to your other information storehouses (books, the network conferences, etc.). 
  2772. Because this column must take a general approach, there will be some topics 
  2773. that you would like to see discussed that really do not belong here.  Specific 
  2774. questions can be directed to the Scratch Patch, where an attempt to answer them 
  2775. will be made. 
  2776.  
  2777. Last Month 
  2778.  
  2779. Last month, we finished up the WC_LISTBOX class and we shall begin looking at 
  2780. the WC_BUTTON class. 
  2781.  
  2782. Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2783.  
  2784.  
  2785. ΓòÉΓòÉΓòÉ 7.2. The Button Control ΓòÉΓòÉΓòÉ
  2786.  
  2787. The Button Control 
  2788.  
  2789. The button control is an interesting one.  While there is one constant 
  2790. (WC_BUTTON) for the class, there are in reality five different classes.  Listed 
  2791. below are the five types of buttons. 
  2792.  
  2793.  1. Push button class (BS_PUSHBUTTON) - this type of button is used to send a 
  2794.     command to the application, e.g. "Ok" (continue), "Cancel", etc.  It is 
  2795.     used by clicking on it with the mouse or by pressing the spacebar while it 
  2796.     has the input focus. 
  2797.  
  2798.  2. Radio button class (BS_RADIOBUTTON, BS_AUTORADIOBUTTON) - this type of 
  2799.     button is used to allow the user to select a single item in a set of 
  2800.     choices.  It is used by clicking on it with the mouse or by using the arrow 
  2801.     keys when any item in the set has the input focus. 
  2802.  
  2803.  3. Check box class (BS_CHECKBOX, BS_AUTOCHECKBOX) - this type of button is 
  2804.     used to allow the user to select one or more items in a set of choices.  It 
  2805.     is used by clicking on it with the mouse or by pressing the spacebar while 
  2806.     it has the input focus. 
  2807.  
  2808.  4. Tri-state button class (BS_3STATE, BS_AUTO3STATE) - this type of button is 
  2809.     similar to the check box class except that it has a third state which is 
  2810.     "undefined".  It is used in the same manner as the check box class. 
  2811.  
  2812.  5. Ownerdraw button class (BS_USERBUTTON) - this type of button is really a 
  2813.     push button except that the application controls its appearance.  It is 
  2814.     used in the same manner as the pushbutton class. 
  2815.  
  2816. Listed below is some terminology that applies to button controls. 
  2817.  
  2818. Control group 
  2819.  
  2820. A control group is a group of buttons, the first of which has the style 
  2821. WS_GROUP.  The end of the group is marked by the beginning of the next group or 
  2822. by the end of the z-order for the siblings under a parent (usually a dialog). 
  2823. The first control in the z-order has an implied WS_GROUP style. 
  2824.  
  2825. Control groups are used for button controls only and specifically for radio 
  2826. buttons only.  Since radio buttons are used to allow the user to select a 
  2827. single item in a group, a way was provided to find out which item was selected 
  2828. instead of having to send a BM_QUERYCHECK message to each button in the group. 
  2829.  
  2830. Auto buttons 
  2831.  
  2832. For radio buttons, check boxes, and tri-state controls, the application is 
  2833. notified whenever the user clicks on it using the mouse or keyboard.  If the 
  2834. default action to be taken by the application is to check or uncheck the 
  2835. button, you should create the button as an auto button; this tells the button 
  2836. control to check or uncheck itself automatically instead of relying upon the 
  2837. application to send the appropriate messages to do this. 
  2838.  
  2839. Ownerdraw controls 
  2840.  
  2841. As we have mentioned previously, an ownerdraw control is a special type of a 
  2842. control which allowed the application to paint it.  There are a few classes 
  2843. that support this feature, some more than others. 
  2844.  
  2845. Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2846.  
  2847.  
  2848. ΓòÉΓòÉΓòÉ 7.3. Button Messages ΓòÉΓòÉΓòÉ
  2849.  
  2850. Button Messages 
  2851.  
  2852. Below are the five messages that are specific to button controls. 
  2853.  
  2854. BM_CLICK 
  2855.  
  2856. Purpose 
  2857.  
  2858. This message simulates a mouse click on the button, causing any WM_CONTROL 
  2859. messages to be sent. 
  2860.  
  2861. Applies to 
  2862.  
  2863. This message can be sent to all button types. 
  2864.  
  2865. Parameters 
  2866.  
  2867. This message takes no parameters. 
  2868.  
  2869. Returns 
  2870.  
  2871. This message returns no value. 
  2872.  
  2873. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  2874.  
  2875. BM_QUERYCHECK 
  2876.  
  2877. Purpose 
  2878.  
  2879. This message returns the check state of the button 
  2880.  
  2881. Applies to 
  2882.  
  2883. This message can be sent to radio buttons, check boxes, and tri-state buttons. 
  2884.  
  2885. Parameters 
  2886.  
  2887. This message takes no parameters. 
  2888.  
  2889. Returns 
  2890.  
  2891. LONGFROMMR(mrResult): 
  2892.  
  2893. 0                   Unchecked 
  2894. 1                   Checked 
  2895. 2                   For tri-state buttons only, the "undetermined" state. 
  2896.  
  2897. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  2898.  
  2899. BM_QUERYCHECKINDEX 
  2900.  
  2901. Purpose 
  2902.  
  2903. This message returns the index of the checked button in a button group. 
  2904.  
  2905. Applies to 
  2906.  
  2907. This message can be sent to radio buttons only. 
  2908.  
  2909. Parameters 
  2910.  
  2911. This message takes no parameters. 
  2912.  
  2913. Returns 
  2914.  
  2915. LONGFROMMR(mrResult) - zero-based index from the first button in the group that 
  2916. is checked, or -1 if no button is checked or an error occurred. 
  2917.  
  2918. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  2919.  
  2920. BM_SETCHECK - Set the check state 
  2921.  
  2922. Purpose 
  2923.  
  2924. This message sets the checked state of a button. 
  2925.  
  2926. Applies to 
  2927.  
  2928. This message can be sent to radio buttons, check boxes, and tri-state buttons. 
  2929.  
  2930. Parameters 
  2931.  
  2932. LONGFROMMP(mpParm1) - the new check state.  See the return values from 
  2933. BM_QUERYCHECK for the interpretation of the values. 
  2934.  
  2935. Returns 
  2936.  
  2937. LONGFROMMR(mrResult) - the previous check state. 
  2938.  
  2939. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  2940.  
  2941. BM_SETDEFAULT 
  2942.  
  2943. Purpose 
  2944.  
  2945. This message sets a button as the default button. 
  2946.  
  2947. Applies to 
  2948.  
  2949. This message can be sent to pushbuttons and ownerdraw buttons. 
  2950.  
  2951. Parameters 
  2952.  
  2953. LONGFROMMP(mpParm1) - a BOOL which specifies the new default state. 
  2954.  
  2955. Returns 
  2956.  
  2957. LONGFROMMR(mrResult) - a BOOL which specifies if the state changed from its 
  2958. previous state. 
  2959.  
  2960. Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  2961.  
  2962.  
  2963. ΓòÉΓòÉΓòÉ 7.4. Control Notifications ΓòÉΓòÉΓòÉ
  2964.  
  2965. Control Notifications 
  2966.  
  2967. The button control can send three different notifications to its owner via the 
  2968. WM_CONTROL message. 
  2969.  
  2970. BN_CLICKED 
  2971.  
  2972. Purpose 
  2973.  
  2974. This notification is sent whenever the button was clicked on with the mouse or 
  2975. via the keyboard. 
  2976.  
  2977. Parameters 
  2978.  
  2979. No parameters are sent in mpParm2. 
  2980.  
  2981. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  2982.  
  2983. BN_DBLCLICKED 
  2984.  
  2985. Purpose 
  2986.  
  2987. This notification is sent whenever the button was double clicked on with the 
  2988. mouse. 
  2989.  
  2990. Parameters 
  2991.  
  2992. No parameters are sent in mpParm2. 
  2993.  
  2994. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  2995.  
  2996. BN_PAINT 
  2997.  
  2998. Purpose 
  2999.  
  3000. This notification is sent whenever the button control needs to be repainted. 
  3001.  
  3002. Parameters 
  3003.  
  3004. mpParm2 points to an USERBUTTON structure.  Ownerdraw buttons will be looked at 
  3005. in more detail next issue. 
  3006.  
  3007. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  3008.  
  3009. Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3010.  
  3011.  
  3012. ΓòÉΓòÉΓòÉ 7.5. Next Month ΓòÉΓòÉΓòÉ
  3013.  
  3014. Next Month 
  3015.  
  3016. This month we took a good look at the button control from a purely referential 
  3017. standpoint.  Next month, we will look at the code for a dialog box that 
  3018. contains each of these button types and will also look extensively at ownerdraw 
  3019. buttons. 
  3020.  
  3021. Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3022.  
  3023.  
  3024. ΓòÉΓòÉΓòÉ 8. Contributors to this Issue ΓòÉΓòÉΓòÉ
  3025.  
  3026. Are You a Potential Author? 
  3027.  
  3028. We are always looking for (new) authors.  If you have a topic about which you 
  3029. would like to write, send a brief description of the topic electronically to 
  3030. any of the editors, whose addresses are listed below, by the 15th of the month 
  3031. before the month in which your article will appear.  This alerts us that you 
  3032. will be sending an article so that we can plan the issue layout accordingly. 
  3033. After you have done this, get the latest copy of the Article Submission 
  3034. Guidelines from ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory. 
  3035. (The file is artsub.zip.)  The completed text of your article should be sent to 
  3036. us no later than five days prior to the last day of the month; any articles 
  3037. received after that time may be pushed to the next issue. 
  3038.  
  3039. The editors can be reached at the following email addresses: 
  3040.  
  3041. o Larry Salomon - os2man@panix.com (Internet). 
  3042. o Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet). 
  3043.  
  3044. The following people contributed to this issue in one form or another (in 
  3045. alphabetical order): 
  3046.  
  3047. o Frank Matthijs 
  3048. o Larry Salomon, Jr. 
  3049. o Carsten Whimster 
  3050. o Gordon Zeglinski 
  3051. o Network distributors 
  3052.  
  3053. Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3054.  
  3055.  
  3056. ΓòÉΓòÉΓòÉ 8.1. Frank Matthijs ΓòÉΓòÉΓòÉ
  3057.  
  3058. Frank Matthijs 
  3059.  
  3060. Frank Matthijs received his Master's degree in Civil Engineering, Computer 
  3061. Science at the Katholieke Universiteit Leuven (Catholic University of Louvain, 
  3062. Belgium).  He is currently a PhD student at the same university, researching 
  3063. Input/Output frameworks for parallel/distributed systems.  He started 
  3064. programming in DOS using Pascal and Assembler, started using and programming 
  3065. OS/2 since version 2.0 and now uses C and C++ almost exclusively. 
  3066.  
  3067. He can be reached electronically on the Internet as 
  3068.  
  3069. Frank.Matthijs@cs.kuleuven.ac.be or 
  3070.  
  3071. frankm@cs.kuleuven.ac.be. 
  3072.  
  3073. You may contact him for any reason.  He can also be reached at the following 
  3074. address: 
  3075.  
  3076. Frank Matthijs
  3077. Windekindstraat 6
  3078. 1850 Grimbergen
  3079. Belgium
  3080.  
  3081.  
  3082. ΓòÉΓòÉΓòÉ 8.2. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
  3083.  
  3084. Larry Salomon, Jr. 
  3085.  
  3086. Larry Salomon, Jr. wrote his first Presentation Manager application for OS/2 
  3087. version 1.1 in 1989.  Since that time, he has written numerous VIO and PM 
  3088. applications, including the Scramble applet included with OS/2 and the 
  3089. I-Brow/Magnify/Screen Capture trio being distributed by IBM with the 
  3090. Professional Developers Kit CD-ROM.  Currently, he works for Cheyenne Software 
  3091. in Roslyn, New York and resides in Bellerose, New York with his wife Lisa. 
  3092.  
  3093. Larry can be reached electronically via the Internet at os2man@panix.com. 
  3094.  
  3095. Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3096.  
  3097.  
  3098. ΓòÉΓòÉΓòÉ 8.3. Carsten Whimster ΓòÉΓòÉΓòÉ
  3099.  
  3100. Carsten Whimster 
  3101.  
  3102. Carsten is an undergraduate Computer Science student at the University of 
  3103. Waterloo.  He is currently in his third year, taking operating system, 
  3104. language, compiler, and graphics courses and enjoying it.  This fall he is 
  3105. working at the University of Waterloo as a tutor (course assistant) for CS241, 
  3106. an introductory course to compilers. 
  3107.  
  3108. Carsten is a huge OS/2 enthusiast as of OS/2 2.0.  Currently, he is using Warp 
  3109. II as his only OS/2!  He is a beginning OS/2 PM programmer with a few projects 
  3110. on the go.  He uses Watcom C/C++ 10.0 and Watcom VX-REXX 2.0b.  He is also a 
  3111. TEAM-OS/2 member. 
  3112.  
  3113. Carsten is the author of POV-Panel/2, a popular shareware dashboard-like 
  3114. front-end for the POV-Ray 2.x compilers.  It can be found on ftp-os2.cdrom.com 
  3115. in pub/os2/2_x/graphics and some of the other major OS/2 ftp sites. 
  3116.  
  3117. You may reach Carsten... 
  3118.  
  3119. ...via email: 
  3120.  
  3121. bcrwhims@undergrad.math.uwaterloo.ca  - Internet 
  3122.  
  3123. ...via snail mail (notice the changed address): 
  3124.  
  3125. Carsten Whimster
  3126. 318A Spruce Street
  3127. Waterloo, Ontario
  3128. Canada
  3129. N2L 3M7
  3130.  
  3131.  Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3132.  
  3133.  
  3134. ΓòÉΓòÉΓòÉ 8.4. Gordon Zeglinski ΓòÉΓòÉΓòÉ
  3135.  
  3136. Gordon Zeglinski 
  3137.  
  3138. Gordon Zeglinski is a freelance programmer/consultant who received his Master's 
  3139. degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. 
  3140. He has been programming in C++ for 6 years and also has a strong background in 
  3141. FORTRAN.  He started developing OS/2 applications with version 2.0 . 
  3142.  
  3143. His current projects include a client/server communications program that 
  3144. utilitizes OS/2's features which has entered beta testing.  Additionally, he is 
  3145. involved in the development of a "real-time" automated vehicle based on OS/2 
  3146. and using C++ in which he does device driver development and designs the 
  3147. applications that comprise the control logic and user interface. 
  3148.  
  3149. He can be reached via the Internet at zeglins@cc.umanitoba.ca. 
  3150.  
  3151. Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3152.  
  3153.  
  3154. ΓòÉΓòÉΓòÉ 8.5. Network distributors ΓòÉΓòÉΓòÉ
  3155.  
  3156. Network Distributors 
  3157.  
  3158. These people are part of our distribution system to provide EDM/2 on networks 
  3159. other than the Internet.  Their help to provide access to this magazine for 
  3160. others is voluntary and we appreciate them a lot! 
  3161.  
  3162. o Paul Hethmon (hethmon@apac.ag.utk.edu) - Compuserve 
  3163. o Gess Shankar (gess@knex.mind.org) - Internet 
  3164. o David Singer (singer@almaden.ibm.com) - IBM Internal 
  3165. o Andre Asselin (ASSELIN AT RALVM12) - IBM Internal 
  3166.  
  3167. If you would like to become a "network distributor", be sure to contact the 
  3168. editors so that we can give you the credit you deserve! 
  3169.  
  3170. Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3171.  
  3172.  
  3173. ΓòÉΓòÉΓòÉ 9. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  3174.  
  3175. How Do I Get EDM/2? 
  3176.  
  3177. EDM/2 can be obtained in any of the following ways: 
  3178.  
  3179. On the Internet 
  3180.  
  3181. o All back issues are available via anonymous FTP from the following sites: 
  3182.  
  3183.    - ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory. 
  3184.    - ftp.luth.se in the /pub/os2/programming/newsletter directory. 
  3185.    - generalhq.pc.cc.cmu.edu 
  3186.  
  3187. o The EDM/2 mailing list.  Send an empty message to edm2-info@knex.mind.org to 
  3188.   receive a file containing (among other things) instructions for subscribing 
  3189.   to EDM/2.  This is a UUCP connection, so be patient please. 
  3190. o IBM's external gopher/WWW server in Almaden. The address is 
  3191.   index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of the 
  3192.   "OS/2 Information" menu; the URL is 
  3193.   "gopher://index.almaden.ibm.com/1nonibm/os2nonib.70". 
  3194.  
  3195. On Compuserve 
  3196.  
  3197. All back issues are available in the OS/2 Developers Forum 2. 
  3198.  
  3199. IBM Internal 
  3200.  
  3201. o IBM's internal gopher/WWW server in Almaden. The address is 
  3202.   n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu; the 
  3203.   URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70". 
  3204. o IBM's REQUEST command on all internal VM systems.  Enter the VM command 
  3205.   REQUEST LIST FROM ASSELIN AT RALVM12 and a list of the requestable packages 
  3206.   will be sent to you; in this list are the names of the packages containing 
  3207.   the EDM/2 issues. 
  3208.  
  3209. How do I Get EDM/2? - EDM/2 - Oct 1994 - Volume 2, Issue 9 
  3210.  
  3211.  
  3212. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  3213.  
  3214. This is a tip. 
  3215.  
  3216.  
  3217. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  3218.  
  3219. I have included a REXX script (RESTART.CMD) that restarts the WPS as outlined 
  3220. above.  It kills the second instance of PMSHELL.EXE and uses KILL.EXE for that 
  3221. purpose (this program can kill any process of which the process ID is known). 
  3222. Make sure you have this KILL program and PSTAT somewhere in your path for this 
  3223. to work. 
  3224.  
  3225.  
  3226. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  3227.  
  3228. This is actually more a reminder than a tip.  When you want to compile the 
  3229. source files discussed in this article, you should first install the sample 
  3230. programs.  To do this, unzip the files for this article and type the following 
  3231. at any OS/2 prompt (in the directory where you unzipped the files): 
  3232.  
  3233. WPS INSTALL
  3234.  
  3235. When the program is running, you can specify a directory to install the samples 
  3236. in.  This will be your working directory for compiling the sample classes.  I 
  3237. suggest you assign a separate directory for this purpose.  You can also use the 
  3238. same directory you used for the samples of the previous article. In that case, 
  3239. be sure to rename the old WPS.CMD program to something different (e.g. 
  3240. WPS1.CMD) if you still need it, because otherwise it gets overwritten (no other 
  3241. files are overwritten during the installation). 
  3242.  
  3243. After successfully installing the files, you can use the WPS program in your 
  3244. working directory to ready the correct files for each step: simply invoke the 
  3245. WPS program with the number of the step as a parameter, for example 
  3246.  
  3247. WPS 1
  3248.  
  3249. This will ready the source files for this step (step 1).  Note that the WPS 
  3250. program will only install the files that are different from the previous step, 
  3251. so don't skip any steps. 
  3252.  
  3253.  
  3254. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  3255.  
  3256. There is something you should know about the way WPS handles templates. When 
  3257. you register a class, the system will check if there already is a template for 
  3258. it.  When there is, the template will not be updated. This is important if you 
  3259. change something in your source code that affects the setup of the instances 
  3260. (for example, if you define a different header).  If you don't delete the old 
  3261. template (from a previous compile, for example), you won't get the new one. 
  3262.  
  3263.  
  3264. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  3265.  
  3266. You should define the dialog page without titlebar, system menu and border.