home *** CD-ROM | disk | FTP | other *** search
-
- ΓòÉΓòÉΓòÉ 1. Oct 1994 Title Page ΓòÉΓòÉΓòÉ
-
- EDM/2
-
- The Electronic Developer's Magazine for OS/2
-
- Portions copyright (c) by Larry Salomon Jr.
- Volume 2, issue 9
-
- Copyright Notice and Other Stuff
-
- The Editor-in-Chief of this electronic magazine is Larry Salomon, Jr.
-
- Portions of EDM/2 are copyrighted by the editors. This publication may be
- freely distributed in electronic form provided that all parts are present in
- their original unmodified form. A reasonable fee may be charged for the
- physical act of distribution; no fee may be charged for the publication itself.
-
- All articles are copyrighted by their authors. No part of any article may be
- reproduced without permission from the original author.
-
- Neither this publication nor the editors are affiliated with International
- Business Machines Corporation.
-
- OS/2 is a registered trademark of International Business Machines Corporation.
- Other trademarks are property of their respective owners. Any mention of a
- product in this publication does not constitute an endorsement or affiliation
- unless specifically stated in the text.
-
- Administrivia
-
- Welcome to this month's issue. Time really seems to be flying as we anticipate
- the release of OS/2 version 3.0, which up to now has gone by the moniker
- "Warp". At work, we have the second beta installed and I know others with the
- gamma version, and if it delivers on the excitement that I hear in their voices
- when I talk to the people that use it, we have something to look forward to.
-
- But first, we have a party to attend! That's right; many of you received
- invitations in the mail from IBM to attend the rollout celebration. I was lucky
- enough to be in Las Vegas for the 2.0 rollout and knowing IBM and their desire
- to put OS/2 on the desktops of America, this party should be lots bigger.
- Considering that IBM wanted fireworks at the last one (but got nixed by the
- Fire Marshall)...well, you figure out how good it can be. I plan to be there
- and I urge anyone who has the means and the time to attend also.
-
- Richard Rogers Theatre
- Manhattan, New York City
- 10:00 am-11:00 am
-
- There will be a one hour reception immediately following at the Marriott Hotel.
-
- What's On Your Mind?
-
- Lately, my mailbox has seen little activity and that has me worried. You see,
- even though I used to get mail which only summarized the reader's feelings, it
- was better than nothing. Here at EDM/2, we struggle to improve the magazine
- more and more, but we can't do it without your help, since it is the job of the
- reader to define what is "better" and what isn't.
-
- Is there something that you'd like to see? Some feature, perhaps?
-
- Are there areas in which you would like to see articles written on?
-
- Could the layout be better organized?
-
- We would like to hear what you have to say about the magazine. Keep those
- cards and letters coming!
-
- On That Note
-
- One very industrious reader, Hilton Goldstein, put together an index of the
- past issues of the magazine. From what I understand (I have neglected to this
- point to download the index and check it out myself), it has hypertext links to
- the articles within each issue so you can avoid the tiresome browsing of each
- issue just to find what you are looking for. Carsten and I have known that
- this is a need for quite some time, but lack the time ourselves to properly act
- upon this popular request. However, it is still foremost in our minds and we
- will hopefully have a solution soon to better facilitate something like a
- "master index".
-
- Layout Change
-
- It has been decided to phase out the Scratch Patch as a column due to lack of
- activity; since the only useful things of late in that column are the Gotcha
- and Documentation Chop Shop sections, a recurring article entitled Scratch
- Patch will appear containing new discoveries.
-
- Reader's Choice Awards
-
- Yes, it is quickly coming up to the end of the year again. Not meaning to put
- a carrot on a stick, but only articles that were published in the year 1994
- will be eligible for voting upon. So, start writing!
-
- Title Page - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 2. Visual REXX Faceoff - Part 3 ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 2.1. Introduction ΓòÉΓòÉΓòÉ
-
- Visual REXX Faceoff - Part 3
-
- Written by Gordon Zeglinski
-
- Introduction
-
- This issue sees the third part of the Visual REXX Faceoff. We start by looking
- at VisPro REXX GOLD edition Version 2.03 by Hockware and then see how it
- compares to VP BRONZE and VX REXX.
-
- VisPro ships on a single floppy disk and comes with a 400+ page manual. In
- addition to the base package, the Data Entry Object Pack and the VP SOM toolkit
- were shipped on two additional floppies. An additional 90 page manual is
- included for the data entry objects.
-
- Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 2.2. Installation ΓòÉΓòÉΓòÉ
-
- Installation
-
- Like the BRONZE edition, the GOLD edition is easy to install. Just run
- SETUP.EXE on each floppy and then reboot, and you are ready to go. One of my
- biggest gripes about the BRONZE edition was the lack of advanced sample
- applications; this version has plenty of good samples.
-
- The install folder for VP GOLD is slightly different than that for the BRONZE
- edition. When done, you will see the following folder on the desktop (assuming
- you install everything).
-
- Figure 1. Installation Folder
-
- The sample projects cover topics like multi-threading, multi-windows, the DB2/2
- database designer, and the new data entry objects. Below is the sample project
- for the data entry objects.
-
- Figure 2. Sample Project
-
- Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 2.3. Look and Feel ΓòÉΓòÉΓòÉ
-
- Look and Feel
-
- VP BRONZE and GOLD are nearly identical. All of what applied to the BRONZE
- edition looked at two issues ago also apply to this issue. The layout view has
- changed slightly as shown in figure 3.
-
- Figure 3. User Interface
-
- Also shown in Figure 3 are three controls types from the Data entry pack. The
- calendar, split bar (the blue vertical line), and clock controls are shown.
- One thing Figure 3 doesn't show about the clock control is that the hands move
- while you are editing the layout; this is a nice touch in my opinion.
-
- The SOM development kit is fairly easy to use. It worked well until I
- installed the SOM developers kit, however; I still haven't figured out how to
- get it working with the SOM 2 compiler or even at whom I should point my finger
- (if anyone). The problem here arises because the SOM 2 compiler seems to be
- generating an incorrect reference to a SOM 1 function or something like that;
- getting the SOM 1 toolkit to work with the SOM 2 compiler would probably be
- quite challenging for a new SOM programmer. As the workaround, one can edit
- the makefile so that it uses only SOM 1 compiler components.
-
- Figure 4 shows the SOM Object Builder.
-
- Figure 4. The VP SOM Object Builder
-
- The SOM Builder is pretty easy to use. You just fill in the notebook and hit
- the generate button. It creates all the necessary files to define the "SOM
- code". The SOM code includes the .CSC, .C and .H files that define the SOM
- object and implement its methods, after which you edit the C files and then
- make the object using the supplied makefile. (Of course you have to read the
- toolkit documentation before trying this.) If this sounds too good to be true,
- there is a cloud for this silver lining - the sample projects assume you are
- using C-Set/2 not C-Set++, so some manual tweaking of the samples is needed.
- Also, The SOM Builder only generates C code, so one can't use the C++ bindings
- found in OS/2 2.1 Programmers Toolkit.
-
- Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 2.4. Feature Comparison ΓòÉΓòÉΓòÉ
-
- Feature Comparison
-
- The following table compares the features in VX-REXX to those in VP BRONZE.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéFeature ΓöéVX-REXX ΓöéVisPro REXX (BRONZE)ΓöéVisPro REXX (GOLD) Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéControl Windows Γöé Γöé Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéStatic Text ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéGroup Box ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéButton ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéRadio Button ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéCheck Box ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPicture Button ΓöéYes ΓöéNo ΓöéNo Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPicture Radio Button ΓöéYes ΓöéNo ΓöéNo Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPicture Box ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéList Box ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéCombination Box ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéDrop Down List ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéEntry Field ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMulti Line Entry Field ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéValue Set ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéSlider ΓöéYes ΓöéNo ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéSpin Button ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéNotebook ΓöéYes ΓöéNo ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéContainer ΓöéYes ΓöéNo ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéFree Form ΓöéNo ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMenus ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéHelp Support ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéDDE ΓöéYes ΓöéNo ΓöéNo Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéTimer ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéThreads ΓöéYes ΓöéNo (1) ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéDrag and Drop ΓöéYes (2) ΓöéNo ΓöéYes(3) Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéQ+E support ΓöéYes ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéISV extendible ΓöéIn Beta ΓöéYes ΓöéYes Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéVisual DB2/2 database ΓöéNo. ΓöéNo ΓöéYes Γöé
- Γöédesigner Γöé Γöé Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéBusiness Graphs ΓöéNo ΓöéNo ΓöéYes(4) Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- (1) Threads in REXX are not the same as threads in C. Global data is not
- automatically shared in REXX. There are several freeware and shareware REXX
- libraries that will allow you to have multi-threaded REXX programs (assuming
- your package doesn't already support this).
-
- (2) In container controls only
-
- (3) In container controls and on the main window
-
- (4) Supports Pie, Bar, Line, Area and Stacked bar graphs.
-
- Additional object kits will be available that provide additional multi-media
- support and other features. If you develop objects for VP REXX, HockWare has a
- marketing assistance program.
-
- The DB2/2 support allows one to reverse engineer an existing database, or
- visually create a new one. Once done, all the code necessary for setting up
- the REXX to DB2/2 interface can be automatically generated. This can
- substantially lower the development time.
-
- Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 2.5. Wrapping Things Up ΓòÉΓòÉΓòÉ
-
- Wrapping Things Up
-
- The VP REXX GOLD package is very impressive. It mimics the look and feel of
- the WPS closely allowing one to start developing quickly. The part that amazes
- me the most, is that it's runtime DLLs are small when compared to other visual
- REXX offerings. I must balance this by adding that it is not the perfect
- choice for creating scripts. Both VP products currently suffer from the
- limitation of being limited to 1 active VP program per process. In an
- environment that allows multiple scripts to be run simultaneously, this can be
- a hindrance. This limitation has no affect on the REXX programs wrapped in
- their own executable file.
-
- The DB2/2 tools are easy to use. I only used them briefly because DB2/2 was
- removed due to a lack of hard drive space. From what I did see of them, they
- are a must have item for programmers that are doing a lot of DB/2 work and need
- to rapidly prototype DB/2 interfaces.
-
- Visual REXX Faceoff (Part 3) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3. WPS Programming the Easy Way - Part 2 ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 3.1. Introduction ΓòÉΓòÉΓòÉ
-
- WPS Programming the Easy Way - Part 2
-
- Written by Frank Matthijs
-
- Introduction
-
- This is the second and last article of WPS Programming the Easy Way. This mini
- series is intended to be an introduction to WPS programming. Still more than
- the previous article, you are encouraged to follow the article with your
- compiler ready. This way, you can see for yourself how to make and extend a
- typical WPS class.
-
- I'll presume you already know a little about WPS programming. If this is not
- the case, I suggest you read my previous article. I explained things like
- classes, metaclasses, inheritance, overriding, SOM (briefly) and the essence of
- WPS programming. You should at least know these terms and what they mean in
- order to be able to follow this article.
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.2. Overview ΓòÉΓòÉΓòÉ
-
- Overview
-
- At the end of the previous article, I already showed how to make a primitive,
- but fully functional WPS class. The instances of that class have a distinct
- type, which makes it very easy to recognize them, e.g. when they are dropped
- over your application program. This article will further expand the class,
- adding an icon and a settings page, and improving the WPS integration by
- allowing folders to show details of our objects (apart from the normal details
- like file creation time, etc.). These features will be added step by step,
- allowing you to study each improvement separately.
-
- The examples are chosen to show some methods you'll override very often (as in
- the previous article), and as an addition to the Car sample from the IBM
- toolkit. The latter does a lot of things right, but there are some things it
- does not do properly (like showing details data). These things will be
- explained here.
-
- As in the previous article, you'll encounter useful tips from time to time.
- These tips give more information or show problem areas of WPS programming. A
- tip looks like this:
-
- Tip
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.3. First Things First ΓòÉΓòÉΓòÉ
-
- First Things First
-
- Before I start the article proper, I have some additions to my previous
- article.
-
- The locked .DLL problem
-
- OK, you know the problem: when you deregister a class DLL, it is still locked,
- so you cannot simply copy your new DLL over it and register the class again.
- The DLL gets unlocked when you delete the template, as I told you in the
- previous article. Since deleting the template can be tedious, there is a
- simpler method, which was pointed out to me by Martin Thierer (thanks,
- Martin!): instead of always having to delete the template, why not prevent a
- template from being generated in the first place? You can do this by
- overriding the wpclsQueryStyle method and setting the CLSSTYLE_NEVERTEMPLATE
- flag. See the PM Reference for more information. You can do this during
- development, and add the template for your final class release.
-
- Unfortunately, both methods don't always work. When you are working with
- classes that affect other classes (such as the details display I'll cover later
- on), the WPS seems to become unstable when you replace a DLL as outlined above.
- The way I solve this problem is by killing the PMSHELL.EXE process. The WPS has
- a built-in recovery process, so the shell will restart automatically. This
- achieves the same effect as completely rebooting, but takes considerably less
- time. Moreover, all your windows (and the command history) stay intact. Only
- make sure the shell doesn't try to restart all your processes. As always, if
- you have a better way of solving this problem, please let me know.
-
- Tip
-
- Metaclasses
-
- Some of you have asked me to explain the concept of metaclasses in more detail.
- Since this is something not all OO-ish languages support, I'll do that right
- away. Note however, that this can actually make things less clear (it may get
- confusing if you're not familiar with this).
-
- In SOM (and thus in WPS), you not only have objects as instances of a class,
- but the classes themselves are also instances of some class. This class is
- called their metaclass. This means that a class is itself an object, called a
- class object to distinguish it from normal objects. This class object has
- methods of its own, defined by the metaclass (just as a normal object responds
- to methods defined by the class). To make the distinction clear, the methods
- performed by class objects (and defined by their metaclass) are called class
- methods, while the methods performed by normal objects (and defined by their
- class) are called instance methods.
-
- It is important to make the distinction between parent classes and metaclasses.
- A parent of a class is a class from which instance methods and instance
- variables are inherited: instances of the subclass (the child class) can also
- perform instance methods defined by the parent class. The class Animal might
- define methods for eating, so all classes derived from Animal inherit the
- methods for eating. Instances of such derived classes can thus perform these
- methods.
-
- A metaclass is a class that defines the class methods (the methods that the
- class objects can perform). So the metaclass of Animal might be AnimalMClass,
- which defines the methods that can be invoked on class Animal (such as methods
- for creating objects of the class Animal). Note that there are methods that
- the class object can perform, and there are method the class defines for its
- instances.
-
- To summarize: the parent of a class provides inherited methods that the
- class's instances can perform, whereas the metaclass of a class provides class
- methods that the class itself can perform.
-
- So what's the relevance with regard to WPS programming? Well, the only thing
- you should always keep in mind is that there are such things as metaclasses, so
- in WPS programming you really work with two classes: the normal class where
- you define the functionality of the instances of your class (instance methods),
- and its metaclass, where you define the functionality of the class itself
- (class methods).
-
- Since these are completely different classes, class variables are not available
- in the implementation of instance methods and vice versa. That's why for
- example I use a file scope variable to store the module handle of the class DLL
- file, instead of a class variable: I'll need this handle later on in an
- instance method.
-
- Class methods are really used quite often in WPS. They all contain cls as part
- of their name, and define the behaviour and properties of the class itself,
- like the name of the class (wpclsQueryTitle), its icon (wpclsQueryIconData) and
- so on. The other sort of methods are instance methods, and they define the
- behaviour and properties of each individual instance of the class (like the
- contents of a folder (wpQueryContent), the real name of a file system object
- (wpQueryRealName) and so on.
-
- I'll explain some class and instance methods in what follows. And what follows
- will start right away.
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.4. Step 1: Adding an Icon ΓòÉΓòÉΓòÉ
-
- Step 1: Adding an Icon
-
- Until now, our data file has been rather dull looking. The remedy is to give
- our class its own icon. This can be done by overriding the wpclsQueryIconData
- method. So we add the following line to our class definition file
- (datadel.csc):
-
- override wpclsQueryIconData, class;
-
- The way we will implement this is by adding an icon to our DLL file and reading
- this icon when necessary.
-
- Adding the icon to the DLL file is simple. Since we already have a resource
- file, we only need to add one line to it:
-
- POINTER ID_ICON "datadel.ico"
-
- We already have the necessary tools for the implementation of
- wpclsQueryIconData: we can use clsQueryModuleHandle to get the handle of our
- DLL where the icon is stored. Listing 1 shows what else we need to do to add
- an icon.
-
- SOM_Scope ULONG SOMLINK dfdM_wpclsQueryIconData(M_MyDataFile *somSelf, PICONINFO pIconInfo)
- {
- M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsQueryIconData");
-
- if(pIconInfo) {
- pIconInfo->fFormat = ICON_RESOURCE;
- pIconInfo->hmod = _clsQueryModuleHandle(somSelf);
- pIconInfo->resid = ID_ICON;
- }
- return (sizeof(ICONINFO));
- }
-
- Listing 1
-
- The ICONINFO structure can be used to identify the icon in several different
- ways. We use the module handle and resource ID here. The use of this method
- is explained properly in the PM Reference, except for the field names of the
- ICONINFO structure.
-
- If you compile the source files, you'll notice the template for our class has
- indeed a new icon, and if you create a few instances of our class, you'll see
- the new icon there too. (This icon does not look very exciting either, but you
- can always substitute your own flashy icon.)
-
- Tip
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.5. Step 2: Filling the File ΓòÉΓòÉΓòÉ
-
- Step 2: Filling the File
-
- Remember: when you create an instance of our MyDataFile class, you create a
- real file at the same time. This file had zero size in all previous examples.
- There are situations, however, where a file of zero size is not really a valid
- file of the intended type. For example, an empty bitmap is not a bitmap of
- zero size. Instead, it has a header identifying it as a bitmap, even if it
- doesn't contain picture data. Many data files will in fact use a header, so it
- is inconvenient and even incorrect if we only generate zero size instances
- (after all, this doesn't generate valid data files, because they lack the
- necessary header).
-
- Fortunately, it is not very difficult to write a header (or whatever data is
- needed) to the file at creation (instantiation) time. As always, the trick is
- to find a proper method we can override. In this case, wpSetup is a good
- candidate. It is called when an object is created, and allows the object to
- initialize itself. Since writing a header is part of the initialization, this
- is the place to do it. This is the first instance method we override in the
- examples. It is not a class method, because every object can be set up
- differently, so the method acts on instances of the class, not on the class
- itself.
-
- Listing 2 shows how to do it. This is a nice example of delegating some work
- to the parent: wpSetup is also used to pass a setup string to an object, such
- as "OPEN=DEFAULT". You can define your own setup strings and interpret them
- here, but in our case, we simply use the existing setup strings. We don't do
- anything with the setup strings in our code. Instead, we let the parent
- process them.
-
- SOM_Scope BOOL SOMLINK dfd_wpSetup(MyDataFile *somSelf,PSZ pszSetupString){
- VALUES val;
- /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
- MyDataFileMethodDebug("MyDataFile","dfd_wpSetup");
-
- DosBeep(2000,20);
- val.ulField1 = DEFAULT_FIELD1;
- val.ulField2 = DEFAULT_FIELD2;
- return (WriteToDisk(somSelf, &val)
- && parent_wpSetup(somSelf,pszSetupString));
- }
-
- Listing 2
-
- The code requires some explanation. VALUES is a structure with two fields.
- This will be the data that is written to file. The code fills the fields with
- default values, and then writes the structure to file. Everything related to
- this data is contained in the files values.c and values.h. For example, the
- code to write the data to file is contained in values.c and can be found in
- listing 3.
-
- BOOL WriteToDisk(MyDataFile* somSelf, VALUES* val) {
- CHAR szObjectFileName[CCHMAXPATH];
- ULONG cb = sizeof(szObjectFileName);
- HFILE hf;
- ULONG ulAction;
- ULONG cbBytesWritten;
-
- if (!_wpQueryRealName(somSelf, szObjectFileName, &cb, TRUE)) return FALSE;
- if (DosOpen(szObjectFileName, &hf, &ulAction,
- 0, FILE_NORMAL, FILE_OPEN | FILE_CREATE,
- OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
- NULL)) return FALSE;
- DosWrite(hf, val, sizeof(VALUES), &cbBytesWritten);
- DosClose(hf);
- return (cbBytesWritten == sizeof(VALUES));
- }
-
- Listing 3
-
- The interesting functions are indicated in red. First of all, we need a way to
- determine the name of the data file. After all, we have been working with
- object pointers (MyDataFile *), not with file names. The method
- wpQueryRealName will give us a fully qualified file name, just what we need.
- After that, we can use the normal Dos API functions to manipulate the file.
-
- If anything should go wrong, we return FALSE. When wpSetup returns FALSE, the
- creation of the object is terminated.
-
- Of course, the call to DosBeep in listing 2 is not really required. I've
- added it here, so that you can hear when this method gets called. You'll find
- it is called at class registration time. At that time, the template is
- generated. Since the template is a data file just like any other instance of
- our class, wpSetup is called for the template when it is created.
-
- I've included a REXX script to create an instance of class MyDataFile (it is
- called INSTANCE.CMD). When you run it, it will create a new data file on the
- desktop, and you'll hear a beep to tell you wpSetup has been called. Now try
- to drag the template to create another instance. You won't hear any beeps
- here, because when you drag a template of a data file, the WPS will simply copy
- the contents of the file, without calling wpSetup (the method has been called
- already, at the time the template was created). But the final result is the
- same: all instances of MyDataFile have the right contents (you can check the
- file size in the settings notebook).
-
- Tip
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.6. Step 3: Using Details Data ΓòÉΓòÉΓòÉ
-
- Step 3: Using Details Data
-
- The previous steps (in this and the previous article) were quite
- straightforward and showed some standard methods you will override very often.
- This step is a little bit more involved. We will inform the WPS that objects
- of class MyDataFile have some extra information that can be displayed in every
- WPS folder's details view. This extra information can also be used in other
- parts of the WPS, as we'll see later. We'll use the contents of the file
- header for this extra data.
-
- There are two things we should do to make this work:
-
- 1. Inform the WPS that our class really has this data. This is done by
- overriding the class method wpclsQueryDetailsInfo. In this method, we
- provide all the details the WPS needs, like for example the kind of data
- (ULONG in our example), the length of each data item (4 bytes here), etc.
-
- 2. Allow each instance to provide the actual values of the data. Since these
- values can differ from instance to instance, we do this by overriding an
- instance method, namely wpQueryDetailsData.
-
- The wpclsQueryDetailsInfo method is called quite often. Therefore, we will
- precalculate the necessary data in the wpclsInitData method. Listing 4 shows
- what we need to do (the new items are in red).
-
- SOM_Scope void SOMLINK dfdM_wpclsInitData(M_MyDataFile *somSelf){
- ULONG i;
- PCLASSFIELDINFO pCFI;
- M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsInitData");
-
- if (!WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), _clsQueryModuleHandle(somSelf),
- ID_TITLE, sizeof(_szTitle), _szTitle))
- strcpy(_szTitle, parent_wpclsQueryTitle(somSelf));
-
- parent_wpclsInitData(somSelf);
-
- for (i = 0, pCFI = fieldinfo; i < DETAILS_COLUMNS; i++, pCFI++) {
- memset((PCH) pCFI, 0, sizeof(CLASSFIELDINFO));
- pCFI->cb = sizeof(CLASSFIELDINFO);
- pCFI->flData = CFA_RIGHT | CFA_SEPARATOR | CFA_FIREADONLY;
- pCFI->flTitle = CFA_CENTER | CFA_SEPARATOR | CFA_HORZSEPARATOR |
- CFA_STRING | CFA_FITITLEREADONLY;
- pCFI->pNextFieldInfo = pCFI + 1;
- pCFI->pTitleData = pszTitles[i];
- pCFI->flCompare = COMPARE_SUPPORTED | SORTBY_SUPPORTED;
- pCFI->ulLenCompareValue = sizeof(ULONG);
-
- switch (i) {
- case INDEX_FIELD1:
- pCFI->flData |= CFA_ULONG;
- pCFI->offFieldData = (ULONG)(FIELDOFFSET(VALUES, ulField1));
- pCFI->ulLenFieldData = sizeof(ULONG);
- pCFI->pMaxCompareValue = &ulMaxField1;
- break;
- case INDEX_FIELD2:
- pCFI->flData |= CFA_ULONG;
- pCFI->offFieldData = (ULONG)(FIELDOFFSET(VALUES, ulField2));
- pCFI->ulLenFieldData = sizeof(ULONG);
- pCFI->pMaxCompareValue = &ulMaxField2;
- break;
- }
- }
- fieldinfo[DETAILS_COLUMNS - 1].pNextFieldInfo = NULL;
- }
-
- Listing 4
-
- For each data item, we must fill in a CLASSFIELDINFO structure. This is an
- extension of the FIELDINFO structure (used by container classes), and is
- defined in the file wpobject.h. All structures should form a linked list. We
- start by filling the complete structure with zeroes. This way, we don't need
- to fill in everything explicitly (the structure has many fields). The switch
- statement is used to fill in the data that can differ for each data item.
-
- The following are the most important fields of CLASSFIELDINFO:
-
- flData
- This defines some properties of the data item. The most important
- property is the type of the data. In our case, we will display ULONG
- values, so we add CFA_ULONG to the flags. See the PM Reference under
- FIELDINFO for more information on these flags.
-
- ulLenFieldData
- This is the length of the data in bytes.
-
- pNextFieldInfo
- This is a pointer to the next CLASSFIELDINFO structure. The
- structures form a linked list.
-
- pTitleData
- Here we define the column heading data. In our example, we use
- strings to describe the data.
-
- Now that we have the necessary information, we can provide it when the WPS
- calls wpclsQueryDetailsInfo. This method gets called to query the size of all
- the details data, as well as to get the details data itself. We first call the
- parent, and add our own data to the parent's data. Listing 5 shows how it is
- done.
-
- SOM_Scope ULONG SOMLINK dfdM_wpclsQueryDetailsInfo(M_MyDataFile *somSelf, PCLASSFIELDINFO *ppClassFieldInfo, PULONG pSize)
- {
- ULONG cParentColumns;
- PCLASSFIELDINFO pCFI;
-
- M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsQueryDetailsInfo");
-
- cParentColumns = parent_wpclsQueryDetailsInfo(somSelf,ppClassFieldInfo,pSize);
-
- if (pSize) *pSize += sizeof(VALUES);
- if (ppClassFieldInfo) {
- pCFI = *ppClassFieldInfo;
- if (pCFI) {
- while (pCFI->pNextFieldInfo) pCFI = pCFI->pNextFieldInfo;
- pCFI->pNextFieldInfo = fieldinfo;
- }
- else *ppClassFieldInfo = fieldinfo;
- }
- return (ULONG)cParentColumns + (ULONG)DETAILS_COLUMNS;
- }
-
- Listing 5
-
- All this code does is add the size of our data to the size of our ancestors'
- data, and add the list of CLASSFIELDINFO structures to the ancestors' list.
- This completes the first part of our job.
-
- Now we need to provide the actual data in the wpQueryDetailsData method.
- Listing 6 shows the implementation of the method.
-
- SOM_Scope ULONG SOMLINK dfd_wpQueryDetailsData(MyDataFile *somSelf, PVOID *ppDetailsData, PULONG pcp)
- {
- /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
- MyDataFileMethodDebug("MyDataFile","dfd_wpQueryDetailsData");
-
- parent_wpQueryDetailsData(somSelf,ppDetailsData, pcp);
-
- if (ppDetailsData) {
- PVALUES pdd = (PVALUES) *ppDetailsData;
- ReadFromDisk(somSelf, pdd);
- *ppDetailsData= pdd + 1;
- }
- else *pcp += sizeof(VALUES);
- return TRUE;
- }
-
- Listing 6
-
- The code reads the complete VALUES structure from the file directly into the
- details data. ReadFromDisk is responsible for this, and is very similar to
- WriteToDisk (it is also contained in the values.c file).
-
- After the code is compiled and the class registered, you won't notice anything
- different about the objects. In fact, our code affects WPFolder objects and
- objects of derived classes. You can see this by opening the settings notebook
- of a folder. When you select the last page under the "View" tab, you can see
- something similar to figure 1 (select the correct object class under "Object
- type"). Under "Details to display", you can see the two fields we have added.
-
- Figure 1
-
- When you open that folder in details view, it will show the contents of the
- header of every instance of MyDataFile it contains.
-
- The "Include" tab also shows something new. There now is a completely new
- settings page for every folder on your desktop (see figure 2). Here you can add
- criteria the WPS uses to decide which objects to display. When you select the
- "Add" button, you get a dialog box similar to the one in figure 3.
-
- Figure 2
-
- Figure 3 shows how you would make the WPS only show Datafile Deluxe objects
- with a Field1 values less that 40.
-
- Figure 3
-
- These features are available for each data item of which the flCompare field of
- the CLASSFIELDINFO structure contains the flag COMPARE_SUPPORTED. If this
- field contains the flag SORTBY_SUPPORTED, the contents of the folder can also
- be sorted based on that item (see the "Sort" tab).
-
- The pMaxCompareValue field contains a pointer to the maximum value of the data
- item. You can use this to constrain the possible values, and the entry field
- for adding criteria ("Comparison value" in figure 3) will not allow larger
- values.
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.7. Step 4: Adding a Settings Page ΓòÉΓòÉΓòÉ
-
- Step 4: Adding a Settings Page
-
- The last thing we'll add to our class is a page in the settings notebook. This
- is in fact not very difficult. We define an instance method (AddAboutPage) for
- adding our page and override wpAddSettingsPages so we can really add the page
- to the settings notebook.
-
- Since a notebook page is in fact a dialog, we also need to provide the
- functionality of the dialog. I have put the relevant code in the files
- dialog.c and dialog.h.
-
- Listing 7 shows how we add a page. We only need to fill in a PAGEINFO
- structure. The interesting fields are in red.
-
- SOM_Scope ULONG SOMLINK dfd_AddAboutPage(MyDataFile *somSelf,HWND hwndNotebook)
- {
- PAGEINFO pageinfo;
-
- /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
- MyDataFileMethodDebug("MyDataFile","dfd_AddAboutPage");
-
- memset((PCH)&pageinfo, 0, sizeof(PAGEINFO));
- pageinfo.cb = sizeof(PAGEINFO);
- pageinfo.hwndPage = NULLHANDLE;
- pageinfo.usPageStyleFlags = BKA_MAJOR;
- pageinfo.usPageInsertFlags = BKA_FIRST;
- pageinfo.pfnwp = AboutDlgProc;
- pageinfo.resid = hmod;
- pageinfo.dlgid = ID_ABOUT;
- pageinfo.pszName = "~About";
- pageinfo.pCreateParams = somSelf;
- return _wpInsertSettingsPage(somSelf, hwndNotebook, &pageinfo);
- }
-
- Listing 7
-
- The most relevant items are discussed below:
-
- pfnwp
- This is the dialog procedure to be used with the dialog.
-
- resid
- This identifies where the resources are to be found. We use the
- module handle of our class DLL here. Note that we use the file scope
- variable hmod without a call to clsQueryModuleHandle. This is
- because we can't access class methods here (they are methods of a
- completely different class). The method has been called at the point
- hmod is needed here, so it indeed contains the correct value.
-
- dlgid
- This is the ID of our dialog template.
-
- pszName
- This is the text for the page tab.
-
- pCreateParams
- This should always be somSelf.
-
- The implementation of wpAddSettingsPages is also very simple, as shown in
- listing 8.
-
- SOM_Scope BOOL SOMLINK dfd_wpAddSettingsPages(MyDataFile *somSelf,HWND hwndNotebook)
- {
- /* MyDataFileData *somThis = MyDataFileGetData(somSelf); */
- MyDataFileMethodDebug("MyDataFile","dfd_wpAddSettingsPages");
-
- return (parent_wpAddSettingsPages(somSelf,hwndNotebook)
- && _AddAboutPage(somSelf, hwndNotebook));
- }
-
- Listing 8
-
- We let the parent add its pages, and then we add our own. The pages are filled
- from bottom to top, so if we want to add our page to the bottom, we should do
- so before calling the parent's method. Here we add our page after calling the
- parent. This adds our page on top of the others.
-
- Listing 9 shows the dialog procedure. In this example, it is kept very simple
- (and not even completely functional).
-
- MRESULT EXPENTRY AboutDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {
- switch(msg) {
- case WM_INITDLG :
- WinSetWindowText(WinWindowFromID(hwnd, DID_ENTRY), "This is a test");
- WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwnd, DID_ENTRY));
- return (MRESULT) TRUE;
- case WM_COMMAND :
- switch (SHORT1FROMMP(mp1)) {
- /* Process commands here */
- }
- return (MRESULT) TRUE;
- break;
- }
- return WinDefDlgProc(hwnd, msg, mp1, mp2);
- }
-
- Listing 9
-
- It is important that one of the entry fields have the input focus initially,
- because otherwise, the settings notebook will lose the input focus in some
- cases and will even allow another window to get on top of it when the extra
- page is selected (try this with the Car example). In our example, we
- explicitly call WinSetFocus to set the focus to one of the fields.
-
- When handling WM_COMMAND, don't pass control to WinDefDlgProc, because if you
- do, your dialog box will disappear from the notebook when a button is pressed.
-
- Tip
-
- Compile and register the class, and you will see the settings page added as the
- first page in the settings notebook of every instance of our MyDataFile class.
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 3.8. Conclusion ΓòÉΓòÉΓòÉ
-
- Conclusion
-
- I think you now have a fairly good idea of what WPS programming is and how you
- can make WPS classes. There are some important things I haven't explained here
- (such as modifying the popup menu of an object, and opening a view of an
- object), but I think you can determine how to do these things by examining
- sample WPS source code with the knowledge you now have (the Car class in the
- Toolkit, for example, but there are also a few samples available on various
- electronic systems, such as the one you obtained this EDM from).
-
- I hope these two articles will inspire you to start making your own WPS
- classes. WPS programming is a bit different from "normal" programming, but it
- can be very rewarding (and fun). And if you don't want to spend too much time
- on this, you can always use the source code from the articles as a starting
- point for your own data files.
-
- One last remark: The current versions of OS/2 come with SOM 1.0, whereas
- future versions will have SOM 2.0 built-in. SOM 2.0 uses a different syntax to
- describe classes (Interface Definition Language) but is backwards compatible
- with previous versions of SOM. I'm only telling you so that you know you'll
- see some changes in the near future, but you can continue using the syntax used
- in this and the previous article.
-
- If you have any comments or questions about this or the previous article, feel
- free to contact me. See elsewhere in this issue for information on how to
- reach me.
-
- WPS Programming the Easy Way (Part 2) - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 4. The Design and Implementation of VIOWIN - Part 2 ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 4.1. Introduction ΓòÉΓòÉΓòÉ
-
- The Design and Implementation of VIOWIN - Part 2
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- For my job, I once had to write an application that ran only when OS/2 booted
- from the floppy diskettes. Because I had no access to the functionality PM
- provides, I resorted to a line-oriented interface, where messages were
- displayed on the screen and scrolled up when necessary. It was a good
- interface, I thought; it was fully NLS enabled and had intelligent defaults so
- the user basically only had to type in the name of the application.
- Unfortunately, the Quality Assurance team didn't concur with my opinion. "We
- want a nice interface!" one exclaimed. "Yeah, one with different windows and
- such!" another shouted.
-
- I was backed into a corner that I could only get out of one way.
-
- This series describes the design and implementation of VIOWIN, a library that
- implements a subset of the Win APIs provided by PM for fullscreen sessions.
- The reasoning behind writing this series is that it provided me and will
- hopefully provide you with some unique insights into how a windowing system is
- developed; and since it is based on PM, your familiarity with the already
- defined interface will increase your capability to fully understand what is
- being described.
-
- Obviously, this series assumes you have PM application development experience,
- but it isn't required.
-
- Last Month
-
- Last month we looked at some of the capabilities of the system as well as four
- of the data structures used in the library. You will notice that while some of
- the design considerations were discussed, the design itself was casually
- avoided since there is no overall design that was followed; instead, the design
- of the individual components will be discussed.
-
- The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2,
- Issue 9
-
-
- ΓòÉΓòÉΓòÉ 4.2. Day One (and Already Problems) ΓòÉΓòÉΓòÉ
-
- Day One (and Already Problems)
-
- My first problem occurred with the issue of input to the application (output,
- too, was a problem already, but I already knew what to do about that). We all
- know from writing PM applications that input is not "pulled" by the application
- from the system but is instead "pushed" by the system to the application via
- the WM_CHAR message and the various mouse messages. In haste, I decided to
- discard the use of the mouse from the system and concentrate on the keyboard,
- since that would be enough to use the system fully. Obviously, asynchronous
- sending of WM_CHAR messages implies a second thread. From here, I had one of
- two options:
-
- 1. I could use the KbdCharIn() function to retrieve keystrokes, or
- 2. I could use a device monitor to monitor the keyboard activity.
-
- ...and then from there, I would have to convert the data returned from the
- system into the appropriate form for the WM_CHAR message.
-
- Again, the urgency of the situation asserted itself and since I knew a bit
- about how device monitors worked and knew nothing about the Kbd subsystem, I
- took the second option.
-
- Note!
-
- Let this be an example of how "haste makes waste", since - as you will see -
- this was the wrong choice to make.
-
- Device Monitors
-
- Device monitors are interesting beasts - they can only be used to monitor
- devices that are serial (i.e. not block devices such as disk drives). Worse
- yet, as with the Kbd, Mou, and Vio subsystems, they are no longer supported
- under OS/2 2.x .
-
- The way a device monitor works is quite similar to a system wide hook in PM
- applications; you read data from the device which you either write back out to
- the data stream to be fed to the next monitor or the application, or you don't
- and the data is "eaten". After consulting several older manuals and after a
- lot of trial-n-error, I was able to correctly implement the keyboard device
- monitor. For all monitors, the following rules apply:
-
- 1. Call DosMonOpen() with the name of the device you wish to monitor, e.g.
- "KBD$" in our case.
- 2. Call DosMonReg() to register your application with the system and to pass
- the data buffers to be used internally by OS/2. There are a few caveats to
- be aware of with this step; see below for more information.
- 3. Loop, calling DosMonRead() and then calling DosMonWrite() to pass the data
- along (assuming this is what you want to do). There are some interesting
- caveats here, too. See below for more information.
- 4. Call DosMonClose() to close the device monitor.
-
- DosMonReg() is an interesting function; it requires the session number, first,
- which cannot be obtained using any documented 32-bit API; however, this
- function itself is 16-bit, so we might as well call the 16-bit API
- DosGetInfoSeg() to get the session number. It needs to be noted that you
- cannot install a keyboard monitor in the PM session (session 1). Pay close
- attention here: because of this, debugging is now impossible. Yes, you read
- that correctly.
-
- Note!
-
- There seems to be a problem, and since I have not tried this on other
- development environments (e.g. Borland or Watcom), I do not know if this is a
- problem with the debugger (IPMD) or OS/2. When debugging, DosGetInfoSeg()
- always returns session 1, which causes the call to DosMonReg() to fail.
-
- The workaround was to write another application - called SESS - which also
- calls DosGetInfoSeg() and prints the foreground session number. Then, in my
- keyboard monitor, I assign the current session number to a local variable;
- setting a breakpoint just following this allows you to change the value of the
- local variable to the value printed by SESS. Sneaky it is, and a pain in the
- butt, too.
-
- Another interesting "property" of DosMonReg() is that the documentation does
- not give the correct figure for the size of the buffers to be passed as
- arguments; fortunately, DosMonReg() will return the size of the buffers if what
- was passed is not big enough. A call to DosAllocMem() follows and we now have
- buffers that are large enough.
-
- DosMonRead() and DosMonWrite() are not without their peculiarities either.
- Instead of passing in the buffers to DosMonOpen() and returning a handle to be
- used when reading and writing, you have to register the buffers separately and
- pass the buffer pointers to DosMonRead() and DosMonWrite()! So, don't throw
- them away just yet!
-
- Specific to Keyboard Monitors
-
- The data returned by DosMonRead() is a structure, which (since it isn't present
- in the Toolkit header files) I called a MONKEYPACKET:
-
- struct _MONKEYPACKET {
- UCHAR uchFlags;
- UCHAR uchOrigScanCode;
- KBDKEYINFO kkiKey;
- USHORT usKbdDDFlags;
- };
-
- uchFlags General flags about the device monitor data stream. These,
- as opposed to usKbdDDFlags are set by OS/2 and not the
- device driver.
- uchOrigScanCode The original scancode of the key pressed.
- kkiKey A structure describing the keystroke. The definition is in
- the header files and will be included if you #define
- INCL_KBD.
- usKbdDDFlags Flags being passed along the data stream by the device
- driver.
-
- If the second bit (counting from zero) in uchFlags is set, the system is
- indicating that you need to flush any internal buffers you are using and that
- you are requires to write this packet back to the device monitor data stream.
-
- Parlez Vous?
-
- Finally, if the "flush" bit isn't set, we need to convert the data into that
- which is documented for the WM_CHAR message. This is a fairly trivial
- procedure which involves checking the scan code and building the parameters
- from that and the associated flags (which describe the state of the shift keys,
- etc.).
-
- Note!
-
- There is an NLS exposure here, since scan codes could differ based on the
- keyboard type. I know of no way to alleviate this, but suspect that the
- interpretation of the KEYBOARD.DCP file (see your CONFIG.SYS) could help. If
- anyone has any information on the format of this file, I'd be very interested
- in speaking with you.
-
- The Code
-
- The code for the keyboard monitor - included in the file VIOWIN2.ZIP - is shown
- below. It is run, as we said, as a separate thread.
-
- VOID _Optlink keyMonitor(PVOID pvDummy)
- //-------------------------------------------------------------------------
- // This function is the keyboard monitor installed by vwInitialize(). It
- // attempts to install itself and sets a flag in habAnchor->ulStatus
- // indicating success or failure. If it succeeds, it loops reading
- // characters from the keyboard and calling postKeyMsg() to convert to
- // WM_CHAR message and post it.
- //-------------------------------------------------------------------------
- {
- USHORT usMonitor;
- USHORT usGlobalSel;
- USHORT usLocalSel;
- struct _GINFOSEG *pgisInfo;
- USHORT usSession;
- USHORT abMonIn[2];
- USHORT abMonOut[2];
- PBYTE pbMonData;
- struct _MONBUFF *pmbMonIn;
- struct _MONBUFF *pmbMonOut;
- USHORT usSzData;
- struct _MONKEYPACKET mkpChar;
- APIRET16 arRc;
-
- if (DosMonOpen("KBD$",&usMonitor)!=0) {
- habAnchor->ulStatus|=VW_HABST_MONINITBAD;
- return;
- } /* endif */
-
- //----------------------------------------------------------------------
- // DosMonReg() requires the session number. Note the following
- // problem when using IPMD to debug: PM (session 1) does not allow
- // monitors to be installed in its session. When running from IPMD,
- // pgisInfo->sgCurrent always reports the current session as 1, instead
- // of the session of the program being debugged. The result is that
- // the monitor fails to install, causing vmInitialize() to return FALSE.
- //
- // The way to get around this is to use the following procedure:
- //
- // 1) Open a new full screen session
- // 2) Run the program SESS.EXE, which prints the session number
- // 3) Set a breakpoint on the line following the assignment to
- // usSession.
- // 4) Open a variable monitor and type in the session number of the
- // full screen session opened in step 1
- // 5) Continue running
- //
- // This forces you to input your keystrokes in the session opened in
- // step 1, but the results are still displayed in the debug full-screen
- // session. I realize this is a pain, but it is the only way.
- //----------------------------------------------------------------------
- DosGetInfoSeg(&usGlobalSel,&usLocalSel);
- pgisInfo=(struct _GINFOSEG *)MAKEP(usGlobalSel,0);
- usSession=pgisInfo->sgCurrent;
-
- //----------------------------------------------------------------------
- // Query the size of the needed monitor buffers
- //----------------------------------------------------------------------
- abMonIn[0]=sizeof(abMonIn);
- abMonOut[0]=sizeof(abMonOut);
-
- if (DosMonReg(usMonitor,
- (struct _MONBUFF *)abMonIn,
- (struct _MONBUFF *)abMonOut,
- MONITOR_BEGIN,
- usSession)!=ERROR_MON_BUFFER_TOO_SMALL) {
- DosMonClose(usMonitor);
- habAnchor->ulStatus|=VW_HABST_MONINITBAD;
- return;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Allocate memory for the total size and specify the OBJ_TILE
- // attribute to force this to be 64K segment aligned. This results
- // in both pmbMonIn and pmbMonOut to be in the same 16-bit segment
- // which is a requirement of DosMonReg().
- //----------------------------------------------------------------------
- if (DosAllocMem((PPVOID)&pbMonData,
- abMonIn[1]+abMonOut[1],
- PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE)!=0) {
- DosMonClose(usMonitor);
- habAnchor->ulStatus|=VW_HABST_MONINITBAD;
- return;
- } /* endif */
-
- pmbMonIn=(struct _MONBUFF *)pbMonData;
- pmbMonOut=(struct _MONBUFF *)(((PBYTE)pbMonData)+abMonIn[1]);
-
- pmbMonIn->cb=abMonIn[1];
- pmbMonOut->cb=abMonOut[1];
-
- if (DosMonReg(usMonitor,pmbMonIn,pmbMonOut,MONITOR_BEGIN,usSession)!=0) {
- DosMonClose(usMonitor);
- DosFreeMem(pbMonData);
- habAnchor->ulStatus|=VW_HABST_MONINITBAD;
- return;
- } /* endif */
-
- habAnchor->ulStatus|=VW_HABST_MONINITGOOD;
-
- //----------------------------------------------------------------------
- // Loop - read from the monitor and if not a "flush buffer" packet,
- // call postKeyMsg(), else pass the packet along the monitor chain.
- //----------------------------------------------------------------------
- while ((habAnchor->ulStatus & VW_HABST_MONSHOULDTERM)==0) {
- usSzData=sizeof(mkpChar);
-
- arRc=DosMonRead(pmbMonIn,DCWW_WAIT,&mkpChar,&usSzData);
- if (arRc==0) {
- if (mkpChar.uchFlags & 0x04) {
- DosMonWrite(pmbMonOut,&mkpChar,usSzData);
- } else {
- postKeyMsg(&mkpChar);
- } /* endif */
- } /* endif */
- } /* endwhile */
-
- DosMonClose(usMonitor);
- DosFreeMem(pbMonData);
- habAnchor->ulStatus|=VW_HABST_MONTERM;
- }
-
- The function postKeyMsg() which converts the MONKEYPACKET structure to a
- WM_CHAR message is also shown below.
-
- BOOL postKeyMsg(struct _MONKEYPACKET *pmkpChar)
- //-------------------------------------------------------------------------
- // This function is called by the keyboard monitor. It converts the
- // MONKEYPACKET structure to the WM_CHAR parameter format, and then
- // posts the message to the window with the focus.
- //
- // Input: pmkpChar - points to the _MONKEYPACKET structure containing
- // the keyboard information as received by the keyboard
- // monitor
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- BOOL bInit;
- USHORT usFlags;
- BYTE bRepeat;
- CHAR chScan;
- CHAR chChar1;
- CHAR chChar2;
- USHORT usVkey;
- USHORT usMods;
- BOOL bNeedPost;
- HVWWND hwndFocus;
-
- bInit=TRUE;
- usFlags=0;
- bRepeat=0;
- chScan=pmkpChar->kkiKey.chScan;
- chChar1=0;
- chChar2=0;
- usVkey=0;
-
- //----------------------------------------------------------------------
- // Set the WM_CHAR flags first
- //----------------------------------------------------------------------
- if ((pmkpChar->usKbdDDFlags & 0x0040)!=0) {
- usFlags|=KC_KEYUP;
- } /* endif */
-
- if ((pmkpChar->kkiKey.fsState & (KBDSTF_LEFTSHIFT | KBDSTF_RIGHTSHIFT))!=0) {
- usFlags|=KC_SHIFT;
- } /* endif */
-
- if ((pmkpChar->kkiKey.fsState & KBDSTF_CONTROL)!=0) {
- usFlags|=KC_CTRL;
- } /* endif */
-
- if ((pmkpChar->kkiKey.fsState & KBDSTF_ALT)!=0) {
- usFlags|=KC_ALT;
- } /* endif */
-
- //----------------------------------------------------------------------
- // If chChar==0 or chChar==0xE0, then we have an extended key code, i.e.
- // KC_VIRTUALKEY. Check the scan code to determine what key was pressed.
- // THIS WILL CREATE PROBLEMS ON OTHER KEYBOARD LAYOUTS!!! We need to
- // figure out a way around this (\OS2\KEYBOARD.DCP interpretation maybe?).
- //----------------------------------------------------------------------
- if (pmkpChar->kkiKey.chChar==0) {
- usFlags|=KC_VIRTUALKEY;
-
- switch (chScan) {
- case 0x0F:
- if ((usFlags & (KC_SHIFT | KC_CTRL | KC_ALT))==KC_SHIFT) {
- usVkey=VK_BACKTAB;
- } else {
- usVkey=VK_TAB;
- } /* endif */
- break;
- //-------------------------------------------------------------------
- // Since there are function keys F1-F12 and F13-F24, assign F1-F12 with
- // shift key to F13-F24, and all other F1-F12 to F1-F12.
- //-------------------------------------------------------------------
- case 0x3B: // Normal
- case 0x5E: // Control
- case 0x68: // Alt
- usVkey=VK_F1;
- break;
- case 0x3C:
- case 0x5F:
- case 0x69:
- usVkey=VK_F2;
- break;
- case 0x3D:
- case 0x60:
- case 0x6A:
- usVkey=VK_F3;
- break;
- case 0x3E:
- case 0x61:
- case 0x6B:
- usVkey=VK_F4;
- break;
- case 0x3F:
- case 0x62:
- case 0x6C:
- usVkey=VK_F5;
- break;
- case 0x40:
- case 0x63:
- case 0x6D:
- usVkey=VK_F6;
- break;
- case 0x41:
- case 0x64:
- case 0x6E:
- usVkey=VK_F7;
- break;
- case 0x42:
- case 0x65:
- case 0x6F:
- usVkey=VK_F8;
- break;
- case 0x43:
- case 0x66:
- case 0x70:
- usVkey=VK_F9;
- break;
- case 0x44:
- case 0x67:
- case 0x71:
- usVkey=VK_F10;
- break;
- case 0x45:
- case 0x89:
- case 0x8B:
- usVkey=VK_F11;
- break;
- case 0x46:
- case 0x8A:
- case 0x8C:
- usVkey=VK_F12;
- break;
- case 0x54:
- usVkey=VK_F13;
- break;
- case 0x55:
- usVkey=VK_F14;
- break;
- case 0x56:
- usVkey=VK_F15;
- break;
- case 0x57:
- usVkey=VK_F16;
- break;
- case 0x58:
- usVkey=VK_F17;
- break;
- case 0x59:
- usVkey=VK_F18;
- break;
- case 0x5A:
- usVkey=VK_F19;
- break;
- case 0x5B:
- usVkey=VK_F20;
- break;
- case 0x5C:
- usVkey=VK_F21;
- break;
- case 0x5D:
- usVkey=VK_F22;
- break;
- case 0x87:
- usVkey=VK_F23;
- break;
- case 0x88:
- usVkey=VK_F24;
- break;
- case 0x52:
- usVkey=VK_INSERT;
- break;
- case 0x47:
- usVkey=VK_HOME;
- break;
- case 0x49:
- usVkey=VK_PAGEUP;
- break;
- case 0x53:
- usVkey=VK_DELETE;
- break;
- case 0x4F:
- usVkey=VK_END;
- break;
- case 0x51:
- usVkey=VK_PAGEDOWN;
- break;
- case 0x4B:
- usVkey=VK_LEFT;
- break;
- case 0x48:
- usVkey=VK_UP;
- break;
- case 0x4D:
- usVkey=VK_RIGHT;
- break;
- case 0x50:
- usVkey=VK_DOWN;
- break;
- default:
- bInit=FALSE;
- break;
- } /* endswitch */
- } else
- if (pmkpChar->kkiKey.chChar==0xE0) {
- usFlags|=KC_VIRTUALKEY;
-
- switch (chScan) {
- case 0x52:
- usVkey=VK_INSERT;
- break;
- case 0x47:
- usVkey=VK_HOME;
- break;
- case 0x49:
- usVkey=VK_PAGEUP;
- break;
- case 0x53:
- usVkey=VK_DELETE;
- break;
- case 0x4F:
- usVkey=VK_END;
- break;
- case 0x51:
- usVkey=VK_PAGEDOWN;
- break;
- case 0x4B:
- usVkey=VK_LEFT;
- break;
- case 0x48:
- usVkey=VK_UP;
- break;
- case 0x4D:
- usVkey=VK_RIGHT;
- break;
- case 0x50:
- usVkey=VK_DOWN;
- break;
- default:
- bInit=FALSE;
- break;
- } /* endswitch */
- } else {
- //-------------------------------------------------------------------
- // Certain "non-extended" characters are still translated to
- // KC_VIRTUALKEY WM_CHAR messages. Check for these cases and
- // act accordingly.
- //-------------------------------------------------------------------
- switch (pmkpChar->kkiKey.chChar) {
- case 0x08:
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_BACKSPACE;
- break;
- case 0x09:
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_TAB;
- break;
- case 0x0D:
- if (chScan==0x1C) {
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_NEWLINE;
- } else {
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_ENTER;
- } /* endif */
- break;
- case 0x1B:
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_ESC;
- break;
- case 0x20:
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_SPACE;
- break;
- case 0x37:
- usFlags|=KC_VIRTUALKEY;
- usVkey=VK_PRINTSCRN;
- break;
- default:
- usFlags|=KC_CHAR;
- chChar1=pmkpChar->kkiKey.chChar;
- } /* endswitch */
- } /* endif */
-
- if ((bInit) && (habAnchor->hwndFocus!=NULL)) {
- usMods=KC_CTRL | KC_ALT | KC_SHIFT;
-
- if ((usFlags & KC_VIRTUALKEY)!=KC_VIRTUALKEY) {
- if (vwIsWindowEnabled(habAnchor->hwndFocus)) {
- if (!vwPostMsg(habAnchor->hwndFocus,
- WM_CHAR,
- MPFROM2SHORT(usFlags,MAKEUSHORT(bRepeat,chScan)),
- MPFROM2SHORT(MAKEUSHORT(chChar1,chChar2),usVkey))) {
- vwAlarm(WA_ERROR);
- } /* endif */
- } else {
- vwAlarm(WA_ERROR);
- } /* endif */
-
- return TRUE;
- } else
- if ((usFlags & KC_KEYUP)!=0) {
- if (vwIsWindowEnabled(habAnchor->hwndFocus)) {
- if (!vwPostMsg(habAnchor->hwndFocus,
- WM_CHAR,
- MPFROM2SHORT(usFlags,MAKEUSHORT(bRepeat,chScan)),
- MPFROM2SHORT(MAKEUSHORT(chChar1,chChar2),usVkey))) {
- vwAlarm(WA_ERROR);
- } /* endif */
- } else {
- vwAlarm(WA_ERROR);
- } /* endif */
-
- return TRUE;
- } /* endif */
-
- bNeedPost=TRUE;
-
- switch (usFlags & usMods) {
- case 0:
- {
- ULONG ulDlgCode;
-
- if (usVkey==VK_TAB) {
- hwndFocus=habAnchor->hwndFocus;
-
- do {
- hwndFocus=vwQueryWindow(hwndFocus,QW_NEXT);
-
- if (hwndFocus==NULLHANDLE) {
- hwndFocus=vwQueryWindow(habAnchor->hwndFocus,QW_TOP);
- } /* endif */
-
- ulDlgCode=LONGFROMMR(vwSendMsg(hwndFocus,
- WM_QUERYDLGCODE,
- 0,
- 0));
- } while ((((ulDlgCode & DLGC_TABONCLICK)!=0) ||
- (!vwIsWindowEnabled(hwndFocus))) &&
- (hwndFocus!=habAnchor->hwndFocus)); /* enddo */
-
- if (hwndFocus!=habAnchor->hwndFocus) {
- vwSetFocus(hwndFocus);
- } /* endif */
-
- bNeedPost=FALSE;
- } /* endif */
- }
- break;
- case KC_SHIFT:
- {
- ULONG ulDlgCode;
-
- if (usVkey==VK_BACKTAB) {
- hwndFocus=habAnchor->hwndFocus;
-
- do {
- hwndFocus=vwQueryWindow(hwndFocus,QW_PREV);
-
- if (hwndFocus==NULLHANDLE) {
- hwndFocus=vwQueryWindow(habAnchor->hwndFocus,QW_BOTTOM);
- } /* endif */
-
- ulDlgCode=LONGFROMMR(vwSendMsg(hwndFocus,
- WM_QUERYDLGCODE,
- 0,
- 0));
- } while ((((ulDlgCode & DLGC_TABONCLICK)!=0) ||
- (!vwIsWindowEnabled(hwndFocus))) &&
- (hwndFocus!=habAnchor->hwndFocus)); /* enddo */
-
- if (hwndFocus!=habAnchor->hwndFocus) {
- vwSetFocus(hwndFocus);
- } /* endif */
-
- bNeedPost=FALSE;
- } /* endif */
- }
- break;
- default:
- break;
- } /* endswitch */
-
- if (bNeedPost) {
- if (vwIsWindowEnabled(habAnchor->hwndFocus)) {
- if (!vwPostMsg(habAnchor->hwndFocus,
- WM_CHAR,
- MPFROM2SHORT(usFlags,MAKEUSHORT(bRepeat,chScan)),
- MPFROM2SHORT(MAKEUSHORT(chChar1,chChar2),usVkey))) {
- vwAlarm(WA_ERROR);
- } /* endif */
- } else {
- vwAlarm(WA_ERROR);
- } /* endif */
- } /* endif */
- } /* endif */
-
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2,
- Issue 9
-
-
- ΓòÉΓòÉΓòÉ 4.3. Initialization, Termination, and Other Miscellany ΓòÉΓòÉΓòÉ
-
- Initialization, Termination, and Other Miscellany
-
- Presented here is the code to initialize the library. It should be fairly
- straightforward given the function prologue and the brief comments throughout
- the function.
-
- BOOL EXPENTRY vwInitialize(VOID)
- //-------------------------------------------------------------------------
- // This function initializes the library.
- //
- // 1) Initializes the memory manager
- // 2) Creates the anchor block and message queue
- // 3) Creates the linked lists for housekeeping
- // 4) Initializes the system values array
- // 5) Starts the keyboard monitor
- // 6) Calls ordinal 1 in the class library so that the public classes
- // may be registered.
- //
- // Returns: TRUE if successful, FALSE otherwise.
- //-------------------------------------------------------------------------
- {
- HCMMEM hcmWork;
- struct _VIOCURSORINFO vciCursor;
- PFNDLLINIT pfnInit;
-
- if (habAnchor!=NULL) {
- return FALSE;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Initialize the memory manager
- //----------------------------------------------------------------------
- if (CmnMemInitialize(NULL,&hcmWork)!=MEM_ERR_NOERROR) {
- return FALSE;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Create the anchor block and message queue and initialize them
- //----------------------------------------------------------------------
- CmnMemAllocate(hcmWork,sizeof(VWAB),(PPVOID)&habAnchor);
- if (habAnchor==NULL) {
- CmnMemTerminate(&hcmWork);
- return FALSE;
- } /* endif */
-
- habAnchor->ulSzStruct=sizeof(VWAB);
- habAnchor->ulStatus=0;
- habAnchor->hcmWork=hcmWork;
-
- //----------------------------------------------------------------------
- // Create the housekeeping lists
- //----------------------------------------------------------------------
- if (!CmnLstCreateList(sizeof(VWCLASSINFO),&habAnchor->hclClasses)) {
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- return FALSE;
- } /* endif */
-
- if (!CmnLstCreateList(sizeof(VWWND),&habAnchor->hclWindows)) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- return FALSE;
- } /* endif */
-
- if (!CmnLstCreateList(sizeof(VWTIMERINFO),&habAnchor->hclTimers)) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- return FALSE;
- } /* endif */
-
- habAnchor->bIsSendMsg=FALSE;
- habAnchor->hwndFocus=NULL;
-
- CmnMemAllocate(habAnchor->hcmWork,
- sizeof(VWCURSORINFO),
- (PPVOID)&habAnchor->pciCursor);
- if (habAnchor->pciCursor==NULL) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- return FALSE;
- } /* endif */
-
- CmnMemAllocate(habAnchor->hcmWork,sizeof(VWMQ),(PPVOID)&hmqQueue);
- if (hmqQueue==NULL) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- return FALSE;
- } /* endif */
-
- hmqQueue->ulSzStruct=sizeof(VWMQ);
- hmqQueue->ulHead=0;
- hmqQueue->ulTail=0;
-
- habAnchor->pciCursor->hwndWnd=NULL;
- habAnchor->pciCursor->sX=0;
- habAnchor->pciCursor->sY=0;
- habAnchor->pciCursor->usFlags=0;
-
- habAnchor->usCursorState=0;
-
- //----------------------------------------------------------------------
- // Initialize the system values array
- //----------------------------------------------------------------------
- habAnchor->alSysValues[VWSV_ERRORFREQ]=200;
- habAnchor->alSysValues[VWSV_NOTEFREQ]=800;
- habAnchor->alSysValues[VWSV_WARNINGFREQ]=400;
- habAnchor->alSysValues[VWSV_ERRORDURATION]=75;
- habAnchor->alSysValues[VWSV_NOTEDURATION]=75;
- habAnchor->alSysValues[VWSV_WARNINGDURATION]=75;
- habAnchor->alSysValues[VWSV_CXSCREEN]=80;
- habAnchor->alSysValues[VWSV_CYSCREEN]=25;
- habAnchor->alSysValues[VWSV_INSERTMODE]=TRUE;
- habAnchor->alSysValues[VWSV_CTIMERS]=16;
-
- //----------------------------------------------------------------------
- // Start the keyboard monitor
- //----------------------------------------------------------------------
- if (_beginthread(keyMonitor,NULL,0x2000,NULL)==-1) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- hmqQueue=NULL;
- return FALSE;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Loop until we get a status back
- //----------------------------------------------------------------------
- while ((habAnchor->ulStatus &
- (VW_HABST_MONINITGOOD | VW_HABST_MONINITBAD))==0) {
- DosSleep(0);
- } /* endwhile */
-
- //----------------------------------------------------------------------
- // If bad, cleanup and return an error
- //----------------------------------------------------------------------
- if ((habAnchor->ulStatus & VW_HABST_MONINITBAD)!=0) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- hmqQueue=NULL;
- return FALSE;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Hide the real cursor
- //----------------------------------------------------------------------
- VioGetCurType(&vciCursor,NULLHANDLE);
- vciCursor.attr=-1;
- VioSetCurType(&vciCursor,NULLHANDLE);
-
- //----------------------------------------------------------------------
- // Load the classes DLL and call ordinal 1
- //----------------------------------------------------------------------
- if (DosLoadModule(NULL,0,DLL_CLASS,&habAnchor->hmClasses)!=0) {
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- hmqQueue=NULL;
- return FALSE;
- } /* endif */
-
- if (DosQueryProcAddr(habAnchor->hmClasses,1,NULL,(PFN *)&pfnInit)!=0) {
- DosFreeModule(habAnchor->hmClasses);
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- hmqQueue=NULL;
- return FALSE;
- } /* endif */
-
- if (!(*pfnInit)()) {
- DosFreeModule(habAnchor->hmClasses);
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclTimers);
- CmnMemTerminate(&hcmWork);
- habAnchor=NULL;
- hmqQueue=NULL;
- return FALSE;
- } /* endif */
-
- return TRUE;
- }
-
- Note!
-
- You should note two things from the code above:
-
- o The use of the ordinal number instead of a function name in the interface to
- the class DLL instead of a function name. This allows the class DLL
- developer (who just happened to be me) to name the function anything, which
- ultimately results in not having to document a name as the developer of the
- main library. (I know; it sounds cheesy.)
- o The lack of creation of a desktop window. I took a particularly interesting
- approach to the desktop; since I didn't plan to support dialogs, I had to
- ease the development of dialog-based applications. Thus, I chose to
- implement the desktop in this manner - if vwCreateWindow() is called and no
- windows currently exist, that window becomes the desktop. So, if the desktop
- destroys itself and another window is created, it becomes the new desktop;
- this can easily lend itself to dialogs with the user.
-
- Termination of the library is really simple: destroy the windows, destroy the
- timers, destroy the lists, then return any other memory used back to the
- system.
-
- BOOL EXPENTRY vwTerminate(VOID)
- //-------------------------------------------------------------------------
- // This function terminates the library.
- //
- // Returns: TRUE if successful, FALSE otherwise.
- //-------------------------------------------------------------------------
- {
- ULONG ulNumItems;
- ULONG ulIndex;
- HVWWND hwndList;
- PVWTIMERINFO ptiTimer;
- HCMMEM hcmWork;
- struct _VIOCURSORINFO vciCursor;
- BYTE abAttr[2];
-
- //----------------------------------------------------------------------
- // Make sure we were initialized
- //----------------------------------------------------------------------
- if (hmqQueue==NULL) {
- return FALSE;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Destroy the windows
- //----------------------------------------------------------------------
- ulNumItems=CmnLstQueryRecordCount(habAnchor->hclWindows);
-
- for (ulIndex=0; ulIndex<ulNumItems; ulIndex++) {
- if (ulIndex==0) {
- hwndList=(HVWWND)CmnLstQueryRecord(habAnchor->hclWindows,0);
- } else {
- hwndList=(HVWWND)CmnLstQueryRelative(hwndList,LQR_NEXT);
- } /* endif */
-
- vwDestroyWindow(hwndList);
- } /* endfor */
-
- //----------------------------------------------------------------------
- // Destroy the timers
- //----------------------------------------------------------------------
- ulNumItems=CmnLstQueryRecordCount(habAnchor->hclTimers);
-
- for (ulIndex=0; ulIndex<ulNumItems; ulIndex++) {
- if (ulIndex==0) {
- ptiTimer=(PVWTIMERINFO)CmnLstQueryRecord(habAnchor->hclTimers,0);
- } else {
- ptiTimer=(PVWTIMERINFO)CmnLstQueryRelative(ptiTimer,LQR_NEXT);
- } /* endif */
-
- vwStopTimer(ptiTimer->hwndWnd,ptiTimer->ulId);
- } /* endfor */
-
- //----------------------------------------------------------------------
- // Tell the keyboard monitor to disengage itself
- //----------------------------------------------------------------------
- habAnchor->ulStatus|=VW_HABST_MONSHOULDTERM;
-
- while ((habAnchor->ulStatus & VW_HABST_MONTERM)!=0) {
- DosSleep(0);
- } /* endwhile */
-
- //----------------------------------------------------------------------
- // Cleanup the rest
- //----------------------------------------------------------------------
- DosFreeModule(habAnchor->hmClasses);
- CmnLstDestroyList(&habAnchor->hclWindows);
- CmnLstDestroyList(&habAnchor->hclClasses);
- CmnLstDestroyList(&habAnchor->hclTimers);
-
- hcmWork=habAnchor->hcmWork;
- CmnMemTerminate(&hcmWork);
-
- habAnchor=NULL;
- hmqQueue=NULL;
-
- //----------------------------------------------------------------------
- // Restore the cursor
- //----------------------------------------------------------------------
- VioGetCurType(&vciCursor,NULLHANDLE);
- vciCursor.attr=0;
- VioSetCurType(&vciCursor,NULLHANDLE);
-
- //----------------------------------------------------------------------
- // Clear the screen
- //----------------------------------------------------------------------
- abAttr[0]=' ';
- abAttr[1]=((((BYTE)VWCLR_BLACK) & 0x07)<<4)|(((BYTE)VWCLR_WHITE) & 0x07);
-
- VioScrollDn(0,0,25,80,999,abAttr,NULLHANDLE);
-
- return TRUE;
- }
-
- Note!
-
- Note the assumption that the screen is 80x25. When the final library code is
- presented at the end of this series (see below), switch to 43 lines and run a
- test application to see the lower half of your screen be unused.
-
- I have not presented a set of DLLs and header files in this series because even
- as I write the series and present the code, I am finding oversights in the code
- that I am correcting. While I know that this makes things quite annoying, I
- have to be quality conscious about this. Finally, the code will be presented
- in connected and unconnected chunks; eventually, I will distribute the entire
- source tree.
-
- In the rest of VIOWIN.C, there is the set/query focus functions, the set/query
- system value functions, and the alarm function. The code for these can be
- found in VIOWIN2.ZIP .
-
- The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2,
- Issue 9
-
-
- ΓòÉΓòÉΓòÉ 4.4. Next Month ΓòÉΓòÉΓòÉ
-
- Next Month
-
- That's it for this month. Next month, we will look at the window module since
- it is central to the operation of the library. As always, comments on this
- series will be entertained at my email address.
-
- The Design and Implementation of VIOWIN (Part 2) - EDM/2 - Oct 1994 - Volume 2,
- Issue 9
-
-
- ΓòÉΓòÉΓòÉ 5. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 5.1. Introduction ΓòÉΓòÉΓòÉ
-
- /dev/EDM2/BookReview
-
- Written by Carsten Whimster
-
- Introduction
-
- /dev/EDM2/BookReview is a monthly column which focuses on development oriented
- books and materials. The column is from a beginning PM programmer's eyes,
- because that's what I am. Pick up whichever book strikes your fancy, and join
- the growing group of people following our PM programming columns. I will
- review books aimed at beginners for a while, and then move on from there.
-
- Please send me your comments and thoughts so that I can make this column as
- good as possible. All mail to me gets read and responded to.
-
- The REXX Reference Summary Handbook is a REXX reference book in the truest
- sense of the word. It does little or no hand-holding, and its aim is to inform
- the initiated. It won an OS/2 Magazine Editor's Award, and may well win more
- awards as the popularity of OS/2 and REXX increases.
-
- (Note: The book is really white. Unfortunately, I don't have access to a
- really good scanner, so the above is the result.)
-
- /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 5.2. Errata ΓòÉΓòÉΓòÉ
-
- Errata
-
- Not much to say this month; it was quiet on the EDM/2 front.
-
- It was very busy at home though. I upgraded my computer to an S3 805 card, and
- spent a lot of time figuring out how to set it up, locating drivers, and so on.
- Eventually, it all worked, but man, what a hazzle. Hopefully OS/2 3.0 will do
- away with much of this. I now run 800x600x65k, and I may rearrange my column
- slightly to accomodate this format better, just in case I had missed something
- when I was running 1024x768x256. Hopefully I can afford the extra meg of RAM
- soon, so I can run 1024x768x65k :) Then again, I may not want the slowdown, so
- I might stick with 800x600x65k.
-
- I also ditched the 486sx25 in favour of a 486dx2-50 (which was hard to find, by
- the way). This means I should be spending more time ray-tracing and
- programming soon, and I'll probably update POV-Panel/2 soon. I will likely
- write an article on programming in VX-REXX and use POV-Panel/2 as an example.
- Hopefully I can afford to upgrade to VX-REXX 2.1 before then.
-
- I have been tinkering with the Warp-II beta, and absolutely love it. It
- addresses about 80% of my complaints with OS/2! Now for the last 20%... It
- did cause some problems, however, one of which I finally traced to
- incompatibilities between Warp-II and the 2.1 toolkit. Now I can finally
- compile with IPFC again (important when you work on EDM/2).
-
- Anyhow, on to more programming oriented things...
-
- /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 5.3. REXX Reference Summary Handbook ΓòÉΓòÉΓòÉ
-
- REXX Reference Summary Handbook
-
- The REXX Reference Summary Handbook is a small, but dense handbook of REXX
- commands and their syntax. It is ring-bound, and lies flat on the table
- without changing pages on you. It covers both standard REXX and also some
- extension libraries. It even has a small pseudo-tutorial for those who have
- forgotten how REXX handles expressions and so on. The chapters are as follows
- (I have included the sub-chapter headings to give a better idea of what it
- covers):
-
- 1. Language Summary
-
- a. Basic Fundamentals and Structure
- b. Keyword Instructions
- c. System Commands & Subcommand Environments
- d. Built-in Functions
-
- 2. SAA REXX External Function Modules
-
- a. REXXUTIL Functions
-
- 3. Other Rexx (sic) External Function Modules
-
- a. REXXLIB Functions
- b. RXWINDOW Functions
-
- 4. Work Place Shell
-
- a. WPS Objects
- b. WPS Classes
- c. WPS Object Key-Pairs
- d. DOS / WIN-OS/2 Settings
-
- 5. Appendix A: ASCII and IBM Character Set
- 6. Appendix B: Codes Returned by SysGetKey
- 7. Appendix C: REXXLIB Video Attributes
- 8. Appendix D: REXX Error Codes
-
- Chapter one covers standard REXX as implemented in OS/2. It describes the
- instruction layout and semantics briefly before launching into a summary of
- OS/2 SAA REXX keywords (referred to as REXX from here on in). The descriptions
- are very terse, but informational, as can be seen in this small
- excerpt/example:
-
- QUEUE [expression]
- Places the value of expression at the bottom (/FIFO) of the
- currently active REXX data queue. If expression is
- omitted, a null string is stacked.
-
- Only the needed information, but it is all there. In the third sub-section of
- chapter one, the RXQUEUE and RXSUBCOM functions are described. Lastly, in
- section four, a complete list of all standard REXX functions is presented,
- including all the most common ones, and also such pearls as complete
- descriptions of what effect using CHARIN, CHAROUT, and CHARS have on opening
- and closing files, all very neatly and clearly described in just a few lines.
- IBM take notice. Both system calls such as DIRECTORY(), text tools such as
- RXMESSAGEBOX and standard library functions such as RANDOM() are explained.
-
- Chapter two covers the functions available in the REXXUTIL library, and shows
- how to set REXXUTIL up. The REXXUTIL library is a colletion of mostly system
- functions, such as SysGetEA(), SysPutEA(), SysCreateObject(), and so on. Many
- of these are quite powerful, and enable you to manipulate WPS objects, files,
- cursor postition, et cetera. There may or may not be enough information in
- this little chapter to get you going with REXXUTIL, but if you have a fair idea
- of what is available, then there is more than enough information here to
- refresh your memory, or point out syntactic details. Some of the text funtions
- described do not work in PMREXX, or other PM environments.
-
- The third chapter describes the use of the REXXLIB and RXWINDOW libraries from
- Quercus. REXXLIB contains the following: mathematical functions, stem and
- array functions for sorting and so on, extended attribute support, file
- control, various system functions, hardware information and access functions,
- and a collection of semaphore functions. Many of these functions go a long way
- towards making REXX a viable option to C when programming small applications.
- REXXLIB is available from Quercus as part of Personal REXX, and is also
- available on many ftp sites. The RXWINDOW library contains functions to
- manipulate windows in the PM environment, and include functions to mirror most
- mouse actions, examine window styles, and so on.
-
- Chapter four starts with a list of Object IDs for various programs and objects.
- This list enables you to access most, if not all of the OS/2 desktop. The WPS
- classes are then listed, and although it is not quite complete, it should be
- adequate for most uses. Only some of the more esoteric pieces of the hierarchy
- have not been placed into the tree. The third section lists the WPS Object
- Key-Pairs. These consist of keynames, values, and descriptions, and are needed
- for the SysCreateObject() and SysSetObjectData() functions. Finally, key-pairs
- are listed for setting DOS and Windows session settings.
-
- Appendix A is a complete ASCII and IBM character set table, with ASCII values
- up to 255.
-
- Appendix B lists all the various codes that are returned by SysGetKey(), and
- includes all shifted, alt'ed, and control'ed characters, and all the
- combinations of the above.
-
- Appendix C lists the REXXLIB video attributes, i.e. the foreground and
- background colour codes, and explains how to combine the two numbers to get the
- combined code.
-
- The last Appendix in the book, Appendix D, lists REXX error codes with
- explanations for the non-obvious codes.
-
- Finally, and all authors and publishers should pay attention here, the index is
- a masterpiece of cross-referencing, and although all books should have this
- good an index, very few do. This is a sign of excellent attention to detail
- and a high quality publication.
-
- /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 5.4. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- This diminutive, but packed reference book is very high quality, and includes
- all kinds of un-called for details that you simply cannot find anywhere else in
- one place. A lot of work has gone into every aspect of this book, and it
- shows. It won an OS/2 Magazine Editor's Award, and if I was in the business of
- giving out awards, I would give it one as well. The REXX Reference Summary
- Handbook has a very clear goal, and fulfils it well. It doesn't try to be
- everything to everyone; it merely covers standard REXX, and some of the most
- popular add-on libraries completely. All REXX programmers should own a copy.
- This book has no right to be reasonably priced, considering what it contains,
- but it is.
-
- /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 5.5. Books Reviewed ΓòÉΓòÉΓòÉ
-
- Books Reviewed
-
- This table contains all books I have reviewed, so that you can find what you
- are looking for at a glance. I will be careful to rate books fairly. If I
- feel a need to adjust ratings, I will adjust all of them at the same time, and
- write a note explaining why I felt this necessary. Please note that books
- aimed at different audiences should only be compared with great care, if at
- all. I intend to concentrate on the strong points of the books I review, but I
- will point out any weaknesses in a constructive manner.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéBOOK ΓöéAUDIENCE ΓöéMARKΓöéCOMMENTS Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéReal-World Programming for OS/2 ΓöéIntermediateΓöéB+ ΓöéLots of good code examples, but Γöé
- Γöé2.1, Blain, Delimon, and English, Γöéto Advanced Γöé Γöésometimes it is too complex for Γöé
- ΓöéSAMS Publishing. ISBN ΓöéPM C Γöé Γöénovices. Accurate. Well organized. Γöé
- Γöé0-672-30300-0. US$40, CAN$50. Γöéprogrammers Γöé ΓöéThe index needs a little beefing up. Γöé
- Γöé Γöé Γöé ΓöéGood, but not entirely complete how-to Γöé
- Γöé Γöé Γöé Γöéreference. Good purchase. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéLearning to Program OS/2 2.0 ΓöéBeginning PMΓöéB- ΓöéThis book can be both frustrating and Γöé
- ΓöéPresentation Manager by Example, ΓöéC Γöé Γöévery rewarding. It is not very large, Γöé
- ΓöéKnight, Van Nostrand Reinhold. ΓöéProgrammers Γöé Γöéand a bit pricey, but has some Γöé
- ΓöéISBN 0-442-01292-6. US$40, Γöé Γöé Γöéexcellent chapters on certain beginningΓöé
- ΓöéCAN$50. Γöé Γöé Γöétopics, such as messages, resources, Γöé
- Γöé Γöé Γöé ΓöéIPF, and dialog boxes. Strictly for Γöé
- Γöé Γöé Γöé Γöébeginners. This book has only one Γöé
- Γöé Γöé Γöé Γöé(large) sample program! Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéWriting OS/2 2.1 Device Drivers inΓöéAdvanced C ΓöéA- ΓöéThe only thing a device driver Γöé
- ΓöéC, 2nd Edition, Mastrianni, Van ΓöéProgrammers,Γöé Γöéprogrammer would not find in here is Γöé
- ΓöéNostrand Reinhold. ISBN Γöéfamiliar Γöé Γöéhow to write SCSI, ADD, and IFS Γöé
- Γöé0-442-01729-4. US$35, CAN$45. Γöéwith Γöé Γöédrivers. Most everything else is in Γöé
- Γöé Γöéhardware Γöé Γöéhere, along with skeleton examples. AnΓöé
- Γöé Γöéprogramming Γöé Γöéoptional DevHlp library of C-callable Γöé
- Γöé Γöé Γöé Γöéfunctions can be purchased by those whoΓöé
- Γöé Γöé Γöé Γöédon't have time to write their own. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéOS/2 Presentation Manager GPI, ΓöéIntermediateΓöéC+ ΓöéThis book needs updating for OS/2 2.x. Γöé
- ΓöéWinn, Van Nostrand Reinhold. ISBN Γöéto advanced Γöé ΓöéIt is a well-written in-depth coverage Γöé
- Γöé0-442-00739-6. US$35, CAN$45. ΓöéPM C Γöé Γöéof the OS/2 way of programming for Γöé
- Γöé Γöéprogrammers Γöé Γöégraphics. It is not an introductory PMΓöé
- Γöé Γöé Γöé Γöéor graphics programming book. You Γöé
- Γöé Γöé Γöé Γöéshould know the basics of PM Γöé
- Γöé Γöé Γöé Γöéprogramming already. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéThe Art of OS/2 2.1 C Programming,ΓöéBeginning ΓöéB+ ΓöéThis is a great introductory PM Γöé
- ΓöéPanov, Salomon, and Panov, ΓöéOS/2 and PM Γöé Γöéprogramming book. It covers basic OS/2Γöé
- ΓöéWiley-QED. ISBN 0-471-58802-4. Γöéprogrammers Γöé Γöéissues like threads before it jumps Γöé
- ΓöéUS$40, CAN$50. Γöé Γöé Γöéinto PM programming. The coverage is Γöé
- Γöé Γöé Γöé Γöéquite thourough, with just enough Γöé
- Γöé Γöé Γöé Γöéreference material to make it useful Γöé
- Γöé Γöé Γöé Γöéafter you read it through the first Γöé
- Γöé Γöé Γöé Γöétime. The upcoming revised edition Γöé
- Γöé Γöé Γöé Γöéshould be a killer. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMastering OS/2 REXX, Gargiulo, ΓöéIntermediateΓöéB ΓöéThis book is very easy to understand. Γöé
- ΓöéWiley-QED. ISBN 0-471-51901-4. ΓöéOS/2 users Γöé ΓöéIf you program with any regularity, Γöé
- ΓöéUS$40, CAN$50. Γöéand novice Γöé Γöélook elsewhere, but if you need an Γöé
- Γöé Γöéprogrammers Γöé Γöéeasily read, well-explained beginner's Γöé
- Γöé Γöé Γöé Γöébook, look no further. Some more Γöé
- Γöé Γöé Γöé Γöédetailed, and complex real-world Γöé
- Γöé Γöé Γöé Γöéexamples might be useful as you learn Γöé
- Γöé Γöé Γöé Γöéthe material. Good coverage of REXX's Γöé
- Γöé Γöé Γöé Γöécapabilities. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéREXX Reference Summary Handbook, Γöébeginning toΓöéA ΓöéThis little handbook is packed full of Γöé
- ΓöéGoran, C F S Nevada. ISBN Γöéexpert REXX Γöé Γöéuseful information. Includes chapters Γöé
- Γöé0-9639854-1-8. US$20, CAN$25 Γöéprogrammers Γöé Γöéon both built-in and some popular Γöé
- Γöé Γöé Γöé Γöécommercial libraries. Well-written andΓöé
- Γöé Γöé Γöé Γöécomprehensively indexed. A must for Γöé
- Γöé Γöé Γöé ΓöéREXX programmers. Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- LEGEND:
-
- BOOK: The name of the book, author(s), publishing company, ISBN, and
- approximate price.
-
- AUDIENCE: This is a description of the audience I think the book targets best.
- This is not intended as gospel, just a guideline for people not familiar with
- the book.
-
- MARK: My opinion of the success of the book's presentation, and how well it
- targets its audience. Technical content, accuracy, organization, readability,
- and quality of index all weigh heavily here, but the single most important item
- is how well the book covers what it says it covers. Many books try to cover
- too much, and get a lower mark as a result.
-
- ΓöîΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéA+ ΓöéGround-breaking, all-around outstanding book. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéA ΓöéExcellent book. This is what I want to see happen a lot. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéA- ΓöéExcellent book with minor flaws. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéB+ ΓöéVery good book with minor flaws or omissions. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéB ΓöéGood book with some flaws and omissions. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéB- ΓöéGood book, but in need of improvement. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéC+ ΓöéMediocre book with some potential, but in need of some updating. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéC ΓöéMediocre book with some good sections, but badly in need of fixing. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéC- ΓöéMediocre book, little good material, desperately in need of an overhaul. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéD ΓöéDon't buy this book unless you need it, and nothing else exists. Γöé
- Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéF ΓöéDon't buy this book. Period. Γöé
- ΓööΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- COMMENTS: This is a very brief summary of the review proper.
-
- /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 5.6. Coming Up ΓòÉΓòÉΓòÉ
-
- Coming Up
-
- Next month I will be looking at either Application Development Using OS/2 REXX,
- Rudd or OS/2 Presentation Manager Programming, Petzold. I have been treating
- REXX fairly heavily recently, and would like a change of pace, but we'll see.
- The books I intend to review are (not necessarily in this order):
-
- o OS/2 Presentation Manager Programming, Petzold
- o Application Development Using OS/2 REXX, Rudd
- o The Design of OS/2, 2nd Edititon, Kogan and Deitel - 1994 - not published yet
- (or is it?)
-
- I am considering reviewing the IBM OS/2 Redbooks, since they are readily and
- cheaply available, and look like good reference.
-
- I am also considering reviewing Designing OS/2 Applications, Reich, mostly
- because it promises to present a different angle on OS/2 programming, namely
- that of how to design OS/2 applications, rather than how to program OS/2
- applications.
-
- Finally, I am considering reviewing OS/2 Unleashed, but it is not strictly
- speaking a development book, so I'm going to wait until the list of real
- development books has diminished a bit. I hear that there is a CD-ROM version
- of it out now, and I will try to get a copy of this.
-
- If anyone has a book they want to see reviewed, I will be happy to oblige, as
- long as I can afford it. Of course, requests can be satisfied quicker when
- accompanied by a book :) Publishers can send me books at the address on my
- personal page at the end of the magazine, and I will review all OS/2
- development-related and advanced user books I receive.
-
- /dev/EDM2/BookReview - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 6. C++ Corner ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 6.1. Introduction ΓòÉΓòÉΓòÉ
-
- C++ Corner
-
- Written by Gordon Zeglinski
-
- Introduction
-
- A few issue back, we looked at encapsulating the profile file API in C++. In
- this issue, we will use SOM to mirror the C++ object.
-
- Recall the C++ call definition:
-
- class ProfileFile{
- APIRET Error;
- HINI hini;
- HAB hab;
- PSZ FileName;
- char Close;
-
- public:
- ProfileFile(PSZ name,HAB hb);
- ProfileFile(HINI H);
- ~ProfileFile();
-
- APIRET GetError(){return Error;}
- HINI GetHandle(){return hini;}
-
- void WriteString(PSZ App,PSZ Key, PSZ String);
- void WriteData(PSZ App, PSZ Key, void * Buff, ULONG BLen);
- ULONG GetDataSize(PSZ App,PSZ Key);
- void GetData(PSZ App,PSZ Key,void * Buff, ULONG & BufMax);
- ULONG GetString(PSZ App,PSZ Key,PSZ Buff,ULONG BufMax,PSZ DefArg=NULL);
- LONG GetInt(PSZ App,PSZ Key,LONG DefArg=0);
- void WriteInt(PSZ App,PSZ Key,LONG Num);
- PRFPROFILE Querry();
- };
-
- The above definition will be mirrored using SOM.
-
- C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 6.2. The SOM Profile Class Definition ΓòÉΓòÉΓòÉ
-
- The SOM Profile Class Definition
-
- Following is the SOM IDL definition for the profile class and its metaclass.
- This listing is from the file INIObjs.idl. We'll look at this in detail later.
-
- #ifndef __INIObj_h__
- #define __INIObj_h__
-
- #include <somcls.idl>
-
- interface M_INIObj;
- interface INIObj : SOMObject
- {
- typedef unsigned long ULONG;
- typedef sequence<char> buffType;
-
- attribute long Error; // Stores the Error Data
- attribute long DidCreate; // Flag used to indicate wether we should close the ini file
-
- unsigned long GetHandle();
- void SetHandle(in unsigned long H);
-
- void WriteString(in string App,in string Key, in string String);
- // write a string
-
- void WriteData(in string App, in string Key,in buffType Buff,in ULONG BLen);
- // write the Buffer
-
- void WriteInt(in string App,in string Key,in long Num);
- // write an "int"
-
-
-
- ULONG GetDataSize(in string App,in string Key);
- // return the lenght of the data
-
- void GetData(in string App,in string Key,in buffType Buff, inout ULONG BufMax);
- // return the data in Buff
-
- ULONG GetString(in string App,in string Key,in buffType Buff,in ULONG BufMax, \
- in string DefArg);
- // return the String in Buff, defaults to DefArg if App/Key not present
-
- ULONG GetStringNoDef(in string App,in string Key,in buffType Buff,in ULONG BufMax);
- // return the String in Buff
-
- long GetInt(in string App,in string Key,in long DefArg);
- // return the "int" in App/Key or the DefArg if App/Key not present
-
- long GetIntNoDef(in string App,in string Key);
- // return the "int" in App/Key
-
- #ifdef __SOMIDL__
- implementation
- {
- //we use an unsigned long because that's what OS/2 uses for a HIHI
- unsigned long INIHandle;
-
-
-
- releaseorder: GetHandle,SetHandle,_get_Error,_set_Error,_set_DidCreate, _get_DidCreate, \
- WriteString,WriteData,WriteInt,GetDataSize,GetData,GetString,GetStringNoDef, \
- GetInt,GetIntNoDef;
-
-
- callstyle=oidl;
- filestem = iniobjs;
- metaclass = M_INIObj;
- somInit: override; // initialize instance variables to 0
- somUninit:override; // close INI file if we opened it
-
- passthru C_xh_after= "#define INCL_WINSHELLDATA" \
- "#include <os2.h>";
- };
- #endif /* __SOMIDL__ */
- };
-
- interface M_INIObj : SOMClass
- {
-
- INIObj INICreate(in unsigned long hab,in string FileName); // create an INI file with the given Name
- INIObj CreateFromOpen(in unsigned long HINI);
-
- INIObj GetUserINI();
- INIObj GetSystemINI();
-
- #ifdef __SOMIDL__
- implementation
- {
- INIObj UserINI; //the user INI file
- INIObj SystemINI; //the System INI file
-
- releaseorder: INICreate,CreateFromOpen,GetUserINI,GetSystemINI;
- callstyle=oidl;
- filestem = iniobjs;
- functionprefix=M_;
- somInitMIClass: override;
- somInit: override; // just a test for parent call macros
- somUninit:override; // clean up any instances we make
- };
- #endif /* __SOMIDL__ */
- };
-
- #endif /* __INIObj_h__ */
-
- Pretty impressive stuff huh? :)
-
- The M_INIObj Metaclass
-
- As mentioned in the last issue, the metaclass provides the constructor and
- class methods. We provide 2 constructors, CreateFromOpen and INICreate.
- INICreate takes the HAB and the name of the profile file; its implementation
- follows.
-
- SOM_Scope INIObj* SOMLINK M_INICreate(M_INIObj *somSelf, unsigned long hab,
- string FileName)
- {
- /* M_INIObjData *somThis = M_INIObjGetData(somSelf); */
- M_INIObjMethodDebug("M_INIObj","M_INICreate");
-
- /* Return statement to be customized: */
- // { INIObj* retVal; return (retVal); }
-
- // call the OS/2 API function to open the profile function
- HINI hini=PrfOpenProfile(hab,FileName);
-
-
- //create the INIObj instance
- INIObj* INI=somSelf->somNew();
-
- // if hini is non zero, then we opened the file successfully
- if(hini){
- INI->_set_Error(0); //clear the instance variable Error
- INI->SetHandle(hini); //set the profile handle
- INI->_set_DidCreate(1); //set the flag indicating that the file should
- } //be closed when the instace is destroyed
- // otherwise an error occured
- else{
- INI->_set_Error(1);
- INI->SetHandle(hini);
- INI->_set_DidCreate(0);
- }
-
- //return the instance
- return INI;
- }
-
- In the above snippet, the bold text is the code added to the stubs created by
- the som compiler. The constructor CreateFromOpen is provided to create an
- instance of a INIObj give a handle of an already open profile file.
-
- The implementation section of the M_INIObj metaclass contains the declaration
- of two class variables, UserINI and SystemINI. These variables will be used to
- store an instance of INIObj for the System and User INI files. They are
- accessed by the class methods GetUserINI and GetUserINI respectively. Below is
- the implementation for the GetUserINI method.
-
- SOM_Scope INIObj* SOMLINK M_GetUserINI(M_INIObj *somSelf)
- {
- M_INIObjData *somThis = M_INIObjGetData(somSelf);
- M_INIObjMethodDebug("M_INIObj","M_GetUserINI");
-
- /* Return statement to be customized: */
- // { INIObj* retVal; return (retVal); }
- //check to see if the UserINI variable is NULL
- if(!somThis->UserINI){
- //if it is, then create an instance of the INIObj class
- somThis->UserINI=somSelf->somNew();
- //and set it handle to that of the user profile file
- somThis->UserINI->SetHandle(HINI_USERPROFILE);
- //we didn't create the file so we won't close it
- somThis->UserINI->_set_DidCreate(0);
- }
-
- //return instance of the user ini file.
- return somThis->UserINI;
- }
-
- The above snippet illustrates how to access class data using somThis. Now to
- take care of a few details. Notice that we tested UserINI against 0 to see if
- we created an instance before. How do we know it will be zero if we previously
- didn't create an instance of INIObj for it? Also note that we create a new
- instance of INIObj. Where does it get deleted? For the answer to these two
- questions, we look at the implementation section of the metaclass again. We
- see:
-
- somInit: override; // just a test for parent call macros
- somUninit:override; // clean up any instances we make
-
- These methods take care of the initialization and destruction of the metaclass
- data members. Their implementation follows.
-
- SOM_Scope void SOMLINK M_somInit(M_INIObj *somSelf)
- {
- M_INIObjData *somThis = M_INIObjGetData(somSelf);
- M_INIObjMethodDebug("M_INIObj","M_somInit");
-
- M_INIObj_parent_SOMClass_somInit(somSelf);
-
- // initialize the variables to 0
- somThis->UserINI=0;
- somThis->SystemINI=0;
- }
-
- SOM_Scope void SOMLINK M_somUninit(M_INIObj *somSelf)
- {
- M_INIObjData *somThis = M_INIObjGetData(somSelf);
- M_INIObjMethodDebug("M_INIObj","M_somUninit");
-
- M_INIObj_parent_SOMClass_somUninit(somSelf);
- if(!somThis->UserINI) //if we created it delete it
- delete somThis->UserINI;
-
- if(!somThis->SystemINI) //if we created it delete it
- delete somThis->SystemINI;
- }
-
- That's it for the metaclass. As an exercise for the reader, modify the
- constructor CreateFromOpen so that it fails to create an instance of INIObj if
- it is passed a handle to either the system or user INI.
-
- The INIObj Class
-
- Now that we've seen the metaclass, we can start looking at the INIObj class.
- Going back to the SOM interface definition listing at the start of this section
- and comparing it to the C++ code, we see that there is nearly a 1 to 1
- correlation between the functions. We won't cover what each function does, but
- merely explore the "highlights". The SOM version includes two additional
- functions GetStringNoDef and GetIntNoDef. These methods are necessary because
- in SOM there's no way to set default arguments and each function must be
- uniquely named. It's not CORBA compliant to use pointers as parameters. Thus,
- we define the type buffType, typedef sequence<char> buffType;. A sequence is
- similar to an "array/pointer" in C except it can have a maximum bound. Again,
- we override the somInit and somUninit to zero the instance variables and to
- provide clean up. Following is the code for somUninit.
-
- SOM_Scope void SOMLINK somUninit(INIObj *somSelf)
- {
- INIObjData *somThis = INIObjGetData(somSelf);
- INIObjMethodDebug("INIObj","somUninit");
-
- INIObj_parent_SOMObject_somUninit(somSelf);
- if(somThis->DidCreate)
- PrfCloseProfile(somThis->INIHandle);
- }
-
- The above routine calls the parent somUninit methods and then performs it's
- clean up. If DidCreate variable is non-zero, then the instance opened the
- profile file and should close it when destroyed.
-
- C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 6.3. Testing The Code ΓòÉΓòÉΓòÉ
-
- Testing The Code
-
- Now that we've seen how to implement the SOM object, let's see how to use it.
- The following code is the main routine taken from the file MAIN.CPP.
-
- int main(int argc, char *argv[]){
- // create an the INIObj class by creating an instance of M_INIObj
- M_INIObj *INIObjclass=INIObjNewClass(INIObj_MajorVersion ,INIObj_MinorVersion);
-
- //now create an instance of INIObj
- INIObj *INIFile=INIObjclass->INICreate(0,"test.ini");
-
- //Write some strings to the ini file
- // application "TestApp", key "TestKey1"
- INIFile->WriteString("TestApp","TestKey1","This is the First Test");
- // application "TestApp", key "TestKey2"
- INIFile->WriteString("TestApp","TestKey2","This is the Second Test");
-
-
- char Junk[300]; // some space to the results from the GetString calls
-
- // read in and display the two app/key pairs
- INIFile->GetStringNoDef("TestApp","TestKey1",(INIObj_buffType*)Junk,300);
- cout<<Junk<<endl;
-
- INIFile->GetStringNoDef("TestApp","TestKey2",(INIObj_buffType*)Junk,300);
- cout<<Junk<<endl;
-
- // read in a app/key pair that doesn't exist ... do we get the default value ?
- INIFile->GetString("TestApp","TestKey3",(INIObj_buffType*)Junk,300,"No Such Key");
- cout<<Junk<<endl;
-
- delete INIFile; // delete the instance of INIObj
- delete INIObjclass; // delete the instance of M_INIObj
- return 0;
- }
-
- Using our C++ based wrapper previously defined, the code would look like:
-
- int main(int argc, char *argv[]){
-
- //now create an instance of Profile File
- INIObj *INIFile=new ProfileFile("test.ini",0);
-
- //Write some strings to the ini file
- // application "TestApp", key "TestKey1"
- INIFile->WriteString("TestApp","TestKey1","This is the First Test");
- // application "TestApp", key "TestKey2"
- INIFile->WriteString("TestApp","TestKey2","This is the Second Test");
-
- char Junk[300]; // some space to the results from the GetString calls
-
- // read in and display the two app/key pairs
- INIFile->GetString("TestApp","TestKey1",(INIObj_buffType*)Junk,300);
- cout<<Junk<<endl;
-
- INIFile->GetString("TestApp","TestKey2",(INIObj_buffType*)Junk,300);
- cout<<Junk<<endl;
-
- // read in a app/key pair that doesn't exist ... do we get the default value ?
- INIFile->GetString("TestApp","TestKey3",(INIObj_buffType*)Junk,300,"No Such Key");
- cout<<Junk<<endl;
-
- delete INIFile; // delete the instance of ProfileFile
-
- return 0;
- }
-
- There are only two major differences between the C++ and SOM version (at this
- level). First, the SOM version uses a metaclass. Therefore, the SOM version
- needs code to create and delete the metaclass. Second, C++ allows default
- parameters so the GetString() function can be used in several locations.
-
- C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 6.4. Wrapping Things Up ΓòÉΓòÉΓòÉ
-
- Wrapping Things Up
-
- This concludes another thrilling episode of SOM exploration. The reader is
- encouraged to see how the implementation of the C++ members and SOM members
- differ. In particular, see how the inout parameters in SOM differ from the
- reference parameters in C++.
-
- C++ Corner - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 7. Introduction to PM Programming ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 7.1. Introduction ΓòÉΓòÉΓòÉ
-
- Introduction to PM Programming
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- The purpose of this column is to provide the readers out there who are not
- familiar with PM application development the information necessary to satisfy
- their curiousity, educate themselves, and give them an advantage over the
- documentation supplied by IBM. Of course, much of this stuff could probably be
- found in one of the many books out there, but the problem with books in general
- is that they don't answer the questions you have after you read the book the
- first time through.
-
- I will gladly entertain feedback from the readers about what was "glossed over"
- or what was detailed well, what tangential topics need to be covered and what
- superfluous crap should have been removed. This feedback is essential in
- guaranteeing that you get what you pay for. :)
-
- It should be said that you must not depend solely on this column to teach you
- how to develop PM applications; instead, this should be viewed as a supplement
- to your other information storehouses (books, the network conferences, etc.).
- Because this column must take a general approach, there will be some topics
- that you would like to see discussed that really do not belong here. Specific
- questions can be directed to the Scratch Patch, where an attempt to answer them
- will be made.
-
- Last Month
-
- Last month, we finished up the WC_LISTBOX class and we shall begin looking at
- the WC_BUTTON class.
-
- Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 7.2. The Button Control ΓòÉΓòÉΓòÉ
-
- The Button Control
-
- The button control is an interesting one. While there is one constant
- (WC_BUTTON) for the class, there are in reality five different classes. Listed
- below are the five types of buttons.
-
- 1. Push button class (BS_PUSHBUTTON) - this type of button is used to send a
- command to the application, e.g. "Ok" (continue), "Cancel", etc. It is
- used by clicking on it with the mouse or by pressing the spacebar while it
- has the input focus.
-
- 2. Radio button class (BS_RADIOBUTTON, BS_AUTORADIOBUTTON) - this type of
- button is used to allow the user to select a single item in a set of
- choices. It is used by clicking on it with the mouse or by using the arrow
- keys when any item in the set has the input focus.
-
- 3. Check box class (BS_CHECKBOX, BS_AUTOCHECKBOX) - this type of button is
- used to allow the user to select one or more items in a set of choices. It
- is used by clicking on it with the mouse or by pressing the spacebar while
- it has the input focus.
-
- 4. Tri-state button class (BS_3STATE, BS_AUTO3STATE) - this type of button is
- similar to the check box class except that it has a third state which is
- "undefined". It is used in the same manner as the check box class.
-
- 5. Ownerdraw button class (BS_USERBUTTON) - this type of button is really a
- push button except that the application controls its appearance. It is
- used in the same manner as the pushbutton class.
-
- Listed below is some terminology that applies to button controls.
-
- Control group
-
- A control group is a group of buttons, the first of which has the style
- WS_GROUP. The end of the group is marked by the beginning of the next group or
- by the end of the z-order for the siblings under a parent (usually a dialog).
- The first control in the z-order has an implied WS_GROUP style.
-
- Control groups are used for button controls only and specifically for radio
- buttons only. Since radio buttons are used to allow the user to select a
- single item in a group, a way was provided to find out which item was selected
- instead of having to send a BM_QUERYCHECK message to each button in the group.
-
- Auto buttons
-
- For radio buttons, check boxes, and tri-state controls, the application is
- notified whenever the user clicks on it using the mouse or keyboard. If the
- default action to be taken by the application is to check or uncheck the
- button, you should create the button as an auto button; this tells the button
- control to check or uncheck itself automatically instead of relying upon the
- application to send the appropriate messages to do this.
-
- Ownerdraw controls
-
- As we have mentioned previously, an ownerdraw control is a special type of a
- control which allowed the application to paint it. There are a few classes
- that support this feature, some more than others.
-
- Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 7.3. Button Messages ΓòÉΓòÉΓòÉ
-
- Button Messages
-
- Below are the five messages that are specific to button controls.
-
- BM_CLICK
-
- Purpose
-
- This message simulates a mouse click on the button, causing any WM_CONTROL
- messages to be sent.
-
- Applies to
-
- This message can be sent to all button types.
-
- Parameters
-
- This message takes no parameters.
-
- Returns
-
- This message returns no value.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- BM_QUERYCHECK
-
- Purpose
-
- This message returns the check state of the button
-
- Applies to
-
- This message can be sent to radio buttons, check boxes, and tri-state buttons.
-
- Parameters
-
- This message takes no parameters.
-
- Returns
-
- LONGFROMMR(mrResult):
-
- 0 Unchecked
- 1 Checked
- 2 For tri-state buttons only, the "undetermined" state.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- BM_QUERYCHECKINDEX
-
- Purpose
-
- This message returns the index of the checked button in a button group.
-
- Applies to
-
- This message can be sent to radio buttons only.
-
- Parameters
-
- This message takes no parameters.
-
- Returns
-
- LONGFROMMR(mrResult) - zero-based index from the first button in the group that
- is checked, or -1 if no button is checked or an error occurred.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- BM_SETCHECK - Set the check state
-
- Purpose
-
- This message sets the checked state of a button.
-
- Applies to
-
- This message can be sent to radio buttons, check boxes, and tri-state buttons.
-
- Parameters
-
- LONGFROMMP(mpParm1) - the new check state. See the return values from
- BM_QUERYCHECK for the interpretation of the values.
-
- Returns
-
- LONGFROMMR(mrResult) - the previous check state.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- BM_SETDEFAULT
-
- Purpose
-
- This message sets a button as the default button.
-
- Applies to
-
- This message can be sent to pushbuttons and ownerdraw buttons.
-
- Parameters
-
- LONGFROMMP(mpParm1) - a BOOL which specifies the new default state.
-
- Returns
-
- LONGFROMMR(mrResult) - a BOOL which specifies if the state changed from its
- previous state.
-
- Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 7.4. Control Notifications ΓòÉΓòÉΓòÉ
-
- Control Notifications
-
- The button control can send three different notifications to its owner via the
- WM_CONTROL message.
-
- BN_CLICKED
-
- Purpose
-
- This notification is sent whenever the button was clicked on with the mouse or
- via the keyboard.
-
- Parameters
-
- No parameters are sent in mpParm2.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- BN_DBLCLICKED
-
- Purpose
-
- This notification is sent whenever the button was double clicked on with the
- mouse.
-
- Parameters
-
- No parameters are sent in mpParm2.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- BN_PAINT
-
- Purpose
-
- This notification is sent whenever the button control needs to be repainted.
-
- Parameters
-
- mpParm2 points to an USERBUTTON structure. Ownerdraw buttons will be looked at
- in more detail next issue.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 7.5. Next Month ΓòÉΓòÉΓòÉ
-
- Next Month
-
- This month we took a good look at the button control from a purely referential
- standpoint. Next month, we will look at the code for a dialog box that
- contains each of these button types and will also look extensively at ownerdraw
- buttons.
-
- Introduction to PM Programming - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 8. Contributors to this Issue ΓòÉΓòÉΓòÉ
-
- Are You a Potential Author?
-
- We are always looking for (new) authors. If you have a topic about which you
- would like to write, send a brief description of the topic electronically to
- any of the editors, whose addresses are listed below, by the 15th of the month
- before the month in which your article will appear. This alerts us that you
- will be sending an article so that we can plan the issue layout accordingly.
- After you have done this, get the latest copy of the Article Submission
- Guidelines from ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory.
- (The file is artsub.zip.) The completed text of your article should be sent to
- us no later than five days prior to the last day of the month; any articles
- received after that time may be pushed to the next issue.
-
- The editors can be reached at the following email addresses:
-
- o Larry Salomon - os2man@panix.com (Internet).
- o Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet).
-
- The following people contributed to this issue in one form or another (in
- alphabetical order):
-
- o Frank Matthijs
- o Larry Salomon, Jr.
- o Carsten Whimster
- o Gordon Zeglinski
- o Network distributors
-
- Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 8.1. Frank Matthijs ΓòÉΓòÉΓòÉ
-
- Frank Matthijs
-
- Frank Matthijs received his Master's degree in Civil Engineering, Computer
- Science at the Katholieke Universiteit Leuven (Catholic University of Louvain,
- Belgium). He is currently a PhD student at the same university, researching
- Input/Output frameworks for parallel/distributed systems. He started
- programming in DOS using Pascal and Assembler, started using and programming
- OS/2 since version 2.0 and now uses C and C++ almost exclusively.
-
- He can be reached electronically on the Internet as
-
- Frank.Matthijs@cs.kuleuven.ac.be or
-
- frankm@cs.kuleuven.ac.be.
-
- You may contact him for any reason. He can also be reached at the following
- address:
-
- Frank Matthijs
- Windekindstraat 6
- 1850 Grimbergen
- Belgium
-
-
- ΓòÉΓòÉΓòÉ 8.2. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
-
- Larry Salomon, Jr.
-
- Larry Salomon, Jr. wrote his first Presentation Manager application for OS/2
- version 1.1 in 1989. Since that time, he has written numerous VIO and PM
- applications, including the Scramble applet included with OS/2 and the
- I-Brow/Magnify/Screen Capture trio being distributed by IBM with the
- Professional Developers Kit CD-ROM. Currently, he works for Cheyenne Software
- in Roslyn, New York and resides in Bellerose, New York with his wife Lisa.
-
- Larry can be reached electronically via the Internet at os2man@panix.com.
-
- Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 8.3. Carsten Whimster ΓòÉΓòÉΓòÉ
-
- Carsten Whimster
-
- Carsten is an undergraduate Computer Science student at the University of
- Waterloo. He is currently in his third year, taking operating system,
- language, compiler, and graphics courses and enjoying it. This fall he is
- working at the University of Waterloo as a tutor (course assistant) for CS241,
- an introductory course to compilers.
-
- Carsten is a huge OS/2 enthusiast as of OS/2 2.0. Currently, he is using Warp
- II as his only OS/2! He is a beginning OS/2 PM programmer with a few projects
- on the go. He uses Watcom C/C++ 10.0 and Watcom VX-REXX 2.0b. He is also a
- TEAM-OS/2 member.
-
- Carsten is the author of POV-Panel/2, a popular shareware dashboard-like
- front-end for the POV-Ray 2.x compilers. It can be found on ftp-os2.cdrom.com
- in pub/os2/2_x/graphics and some of the other major OS/2 ftp sites.
-
- You may reach Carsten...
-
- ...via email:
-
- bcrwhims@undergrad.math.uwaterloo.ca - Internet
-
- ...via snail mail (notice the changed address):
-
- Carsten Whimster
- 318A Spruce Street
- Waterloo, Ontario
- Canada
- N2L 3M7
-
- Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 8.4. Gordon Zeglinski ΓòÉΓòÉΓòÉ
-
- Gordon Zeglinski
-
- Gordon Zeglinski is a freelance programmer/consultant who received his Master's
- degree in Mechanical Engineering with a thesis on C++ sparse matrix objects.
- He has been programming in C++ for 6 years and also has a strong background in
- FORTRAN. He started developing OS/2 applications with version 2.0 .
-
- His current projects include a client/server communications program that
- utilitizes OS/2's features which has entered beta testing. Additionally, he is
- involved in the development of a "real-time" automated vehicle based on OS/2
- and using C++ in which he does device driver development and designs the
- applications that comprise the control logic and user interface.
-
- He can be reached via the Internet at zeglins@cc.umanitoba.ca.
-
- Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 8.5. Network distributors ΓòÉΓòÉΓòÉ
-
- Network Distributors
-
- These people are part of our distribution system to provide EDM/2 on networks
- other than the Internet. Their help to provide access to this magazine for
- others is voluntary and we appreciate them a lot!
-
- o Paul Hethmon (hethmon@apac.ag.utk.edu) - Compuserve
- o Gess Shankar (gess@knex.mind.org) - Internet
- o David Singer (singer@almaden.ibm.com) - IBM Internal
- o Andre Asselin (ASSELIN AT RALVM12) - IBM Internal
-
- If you would like to become a "network distributor", be sure to contact the
- editors so that we can give you the credit you deserve!
-
- Contributors - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ 9. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
-
- How Do I Get EDM/2?
-
- EDM/2 can be obtained in any of the following ways:
-
- On the Internet
-
- o All back issues are available via anonymous FTP from the following sites:
-
- - ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory.
- - ftp.luth.se in the /pub/os2/programming/newsletter directory.
- - generalhq.pc.cc.cmu.edu
-
- o The EDM/2 mailing list. Send an empty message to edm2-info@knex.mind.org to
- receive a file containing (among other things) instructions for subscribing
- to EDM/2. This is a UUCP connection, so be patient please.
- o IBM's external gopher/WWW server in Almaden. The address is
- index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of the
- "OS/2 Information" menu; the URL is
- "gopher://index.almaden.ibm.com/1nonibm/os2nonib.70".
-
- On Compuserve
-
- All back issues are available in the OS/2 Developers Forum 2.
-
- IBM Internal
-
- o IBM's internal gopher/WWW server in Almaden. The address is
- n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu; the
- URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70".
- o IBM's REQUEST command on all internal VM systems. Enter the VM command
- REQUEST LIST FROM ASSELIN AT RALVM12 and a list of the requestable packages
- will be sent to you; in this list are the names of the packages containing
- the EDM/2 issues.
-
- How do I Get EDM/2? - EDM/2 - Oct 1994 - Volume 2, Issue 9
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- This is a tip.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- I have included a REXX script (RESTART.CMD) that restarts the WPS as outlined
- above. It kills the second instance of PMSHELL.EXE and uses KILL.EXE for that
- purpose (this program can kill any process of which the process ID is known).
- Make sure you have this KILL program and PSTAT somewhere in your path for this
- to work.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- This is actually more a reminder than a tip. When you want to compile the
- source files discussed in this article, you should first install the sample
- programs. To do this, unzip the files for this article and type the following
- at any OS/2 prompt (in the directory where you unzipped the files):
-
- WPS INSTALL
-
- When the program is running, you can specify a directory to install the samples
- in. This will be your working directory for compiling the sample classes. I
- suggest you assign a separate directory for this purpose. You can also use the
- same directory you used for the samples of the previous article. In that case,
- be sure to rename the old WPS.CMD program to something different (e.g.
- WPS1.CMD) if you still need it, because otherwise it gets overwritten (no other
- files are overwritten during the installation).
-
- After successfully installing the files, you can use the WPS program in your
- working directory to ready the correct files for each step: simply invoke the
- WPS program with the number of the step as a parameter, for example
-
- WPS 1
-
- This will ready the source files for this step (step 1). Note that the WPS
- program will only install the files that are different from the previous step,
- so don't skip any steps.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- There is something you should know about the way WPS handles templates. When
- you register a class, the system will check if there already is a template for
- it. When there is, the template will not be updated. This is important if you
- change something in your source code that affects the setup of the instances
- (for example, if you define a different header). If you don't delete the old
- template (from a previous compile, for example), you won't get the new one.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- You should define the dialog page without titlebar, system menu and border.