home *** CD-ROM | disk | FTP | other *** search
-
- ΓòÉΓòÉΓòÉ 1. Dec 1994 Title Page ΓòÉΓòÉΓòÉ
-
- EDM/2
-
- The Electronic Developer's Magazine for OS/2
-
- Portions copyright (c) by Larry Salomon Jr.
- Volume 2, issue 11
-
- 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.
-
- Happy Holidays
-
- I hesitate to say "Merry Christmas", since this is an international magazine
- whose readers have international religious philosophies, but I do hope everyone
- is enjoying this time of the year. Only in December can you spend more than
- you earn on someone else, and we all know how enjoyable that is. <grin> This
- is especially true in my house because my wife is an accountant by profession
- and she wants to buy a house (sometime this decade, so she says), so I can't
- spend a penny more than I need to on anything.
-
- Okay, maybe it's not that bad.
-
- "Honey, can I have my lunch money for next week?"
-
- Game of the Year
-
- I need to make a plug. This is not a plug made out of obligation, but one made
- because I truly think every one of us needs to know about this method of
- frustration-release. The thing for which I am making this plug is Roids
- (currently at version 2.2). It is the reincarnation of the Asteroids game that
- we loved so much in the arcades of yesteryear, complete with vectorized
- graphics and flying rocks that will smash your ship to pieces if you are not
- careful. But wait(!) for there is more. This new version, produced by Hungry
- Man Productions, also has more things to get you and is fully configurable.
- Better yet, it has full support for MMPM/2, so you can not only watch yourself
- get blown to pieces, but you can hear it also.
-
- Roids 2.2 can be retrieved from hobbes.nmsu.edu; it is shareware with a $10
- (U.S.) registration fee.
-
- New Icon
-
- I finally decided to make the icon more presentable. While the first icon
- accurately depicted what I envisioned EDM/2 to be - a newsletter - it has grown
- beyond that to become more of a magazine. So, the new icon displays that. I
- hope you like it.
-
- In Search Of...
-
- We are looking to expand our content by adding new columnists. While I have a
- few people in mind, I would be more than happy to receive recommendations for
- people to write columns on the following topics:
-
- o Graphics
- o REXX Language
- o Multimedia
- o Client/Server Programming
-
- All of these are with respect to development on the OS/2 platform, of course.
- If you know of someone who knows any of these topics quite well and would
- consider writing a monthly column, please send their name and email address to
- os2man@panix.com (Internet).
-
- Before I Forget (Cause I Already Forgot Once)
-
- Gordon Zeglinski's C++ Corner will be missing from this issue as he rushes to
- finish his soon-to-be-released InterCOMM product. He will be missed and we
- wish him a speedy completion of his product.
-
- Reader's Choice Awards
-
- This month marks the end of our second calendar year in existance. And that
- means that it is time once again for the Reader's Choice Awards! While I
- haven't started my annual fishing expedition for the prizes, that doesn't mean
- that you can refrain from voting. Choose from the list below the three best
- articles, in your opinion, and send your choices to os2man@panix.com (Internet)
- by January 15. The votes will be tallied and the results, as well as the
- prizes, will be revealed in the February issue.
-
- o A Review of Personal REXX for OS/2 (Issue 2)
- o Adding Sounds to Your OS/2 Application (Issue 1)
- o /dev/EDM/BookReview (Column)
- o Coding for Dollars: Copy Protection and Prevention
- o Controlling Yourself: A Framework for Configurable Options
- o C++ Corner (Column)
- o Debugging Classes in Borland C++ (Issue 4)
- o Introduction to PM Programming (Column)
- o Making Noise with MMPM/2 - Parts 1 and 2 (Issues 1 and 3)
- o Porting STEP02 to ICLUI (Issue 3)
- o Resources and Decompiling Them (Issue 6)
- o Scratch Patch (Column)
- o Sprites and Animation - Parts 1-4 (Issues 5-8)
- o TCP/IP Socket Programming in REXX (Issue 2)
- o The Design and Implementation of VIOWIN - Parts 1-4 (Issues 8-11)
- o Using SYSLEVEL Files in Your Applications (Issue 5)
- o Utilizing Hooks for Added Capabilities (Issue 1)
- o Visual REXX Faceoff - Parts 1-3 (Issues 6, 7, and 9)
- o WPS Programming the Easy Way - Parts 1 and 2 (Issues 8 and 9)
- o Workplace Shell Development 101 (Issue 3)
-
- Title Page - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 2. Coding for Dollars: Copy Protection and Prevention ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 2.1. Introduction ΓòÉΓòÉΓòÉ
-
- Coding for Dollars: Copy Protection and Prevention
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- Have you ever written a wonderful application, decided to distribute it
- commercially, get little money for it, but find out that many people have a
- copy nonetheless? Ask Gordon Zeglinski; or ask Describe; or ask any of the
- many commercial developers in the world what it feels like to see your revenue
- lost due to piracy.
-
- I am reminded specifically the story of the brother of an ex-girlfriend of
- mine: he wrote a really good cribbage program for DOS but received only
- approximately 40 orders for the program. He lived in Raleigh, where the
- National Cribbage Tournament is held annually and everyone at the next
- tournament told him how good his program was. He was ready, though; he had
- memorized the names of all of the people that had ordered the program and
- confronted those that had not on the spot.
-
- Of course, this isn't considered the best way to handle this situation,
- especially since he didn't receive any more money from the people who he had
- "caught with their hands in the cookie jar." No, the best way is to follow the
- age-old adage, "an ounce of prevention is worth a pound of cure." This article
- will attempt to do just that - develop code that will enable an application to
- keep track of the number of licenses available and prevent unauthorized copying
- of the application.
-
- The reader should be forewarned: if a software pirate wants something bad
- enough, they will get it. I can remember the days when I bought the COPYIIPC
- hardware adapter which copied the analog representation of a diskette's data to
- another. This hardware-assisted "archival copy enabler" ("Yeah, that's the
- ticket...") could copy anything, including software that used the infamous
- weak-bit protection scheme. The point is that no protection scheme is 100%
- secure, much less this one which I conceived, designed, and coded in two hours
- one morning while suffering from ennui.
-
- Coding for Dollars: Copy Protection and Prevention - EDM/2 - Dec 1994 - Volume
- 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 2.2. Magic Cookies and Other Nonsense ΓòÉΓòÉΓòÉ
-
- Magic Cookies and Other Nonsense
-
- The idea behind any protection scheme is that of the software license, i.e. the
- developer or company allows you to use a preset number of copies of the
- software. The user should not be allowed to exceed this number in any
- situation. If software were something tangible then this might be enforcable,
- but since software is really a collection of analog signals transferred via
- magnetic media enforcing this is more than a trivial matter.
-
- What the now infamous dongle did was make a part of the software tangible
- through a hardware device which attaches to the parallel port of your PC and is
- software addressable, to insure its presence. If the dongle isn't there the
- software displays an appropriate message and stops.
-
- Illusions of Association
-
- What makes the dongle successful (and annoying and the same time) is the bond,
- the association between the dongle and the software - if the dongle isn't there
- then the software will not continue. It then becomes our challenge to discover
- some method of binding the software with something that is unchangeable (which
- implies a hardware-assisted solution) or something that is very difficult to
- change (which can be done entirely through software).
-
- So what shall we use as our magic cookie, the item which needs to be present in
- order to allow our application to run? The answer to this was nothing obvious
- and was discovered only by following a hunch I had one morning when pondering
- the CmnFilFormatDiskette() code that I had written some time ago.
-
- Try this exercise in futility:
-
- 1. Format a diskette and give it a label.
-
- 2. DISKCOPY the formatted diskette so that you now have two blank,
- just-formatted diskettes.
-
- 3. Examine both diskettes and discover the one difference between them that
- can be exploited under OS/2.
-
- [E:\]dir a:
-
- Volume in drive A is TESTDISK
- The Volume Serial Number is 25C2:5415
- Directory of A:\
-
- TEST DAT 70 11-14-94 10:09a
- 1 file(s) 70 bytes used
- 1455616 bytes free
-
- [E:\]dir a:
-
- Volume in drive A is TESTDISK
- The Volume Serial Number is 226D:EC14
- Directory of A:\
-
- TEST DAT 70 11-14-94 10:09a
- 1 file(s) 70 bytes used
- 1455616 bytes free
-
- [E:\]
-
- Sleight of Hand
-
- The answer, for those who cannot see it, is the volume serial number (VSN).
- Even if you use DISKCOPY to copy one diskette to another, the VSN is changed on
- the target diskette. As you will see, this is the key to the entire solution.
-
- Coding for Dollars: Copy Protection and Prevention - EDM/2 - Dec 1994 - Volume
- 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 2.3. The Principle of Contagion ΓòÉΓòÉΓòÉ
-
- The Principle of Contagion
-
- "Once together, always together," wrote Lyn Hardy in the series Master of the
- Five Magics and this is what we want to accomplish using the VSN as our magic
- cookie. Obviously, this means we have to tuck the VSN somewhere where the
- potential hacker cannot find it. And, while we're at it, we might as well put
- the number of available licenses remaining and the volume label of the diskette
- in our holding place also. But where do we put this information? An ASCII file
- wouldn't work because it is too easily cracked; a binary file would be better,
- but an inquisitive hacker could decypher the meaning of the data, once the
- purpose of the data was discovered. What we need is a way to store this
- important information in such a way that the data is never noticed, invoking
- the "Axiom of Forgetfulness" - "out of sight, out of mind." <grin>
-
- Bag of Holding
-
- Like the Advanced Dungeons and Dragons item, we need a place to put this
- information that is out of sight of any hackers. What better place to put it
- than in the extended attributes of a file? This is the best place, that I
- could think of, to put it.
-
- Note: originally, I thought I could attach EAs to the root-directory of the
- diskette, like you can a subdirectory, but that returned ERROR_ACCESS_DENIED,
- so I had to settle on attaching them to the EAs of a hidden file instead.
-
- Coding for Dollars: Copy Protection and Prevention - EDM/2 - Dec 1994 - Volume
- 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 2.4. Hackers, Start Your Keyboards ΓòÉΓòÉΓòÉ
-
- Hackers, Start Your Keyboards
-
- We now have enough information to write a complete function to handle
- installation diskettes. Let us look at the four actions that can be performed
- and the logic for each.
-
- Create an Installation Diskette
-
- 1. Use DosQueryFSInfo() to get the VSN and the volume label of the diskette to
- be initialized.
- 2. Write the VSN, volume label, and the initial number of licenses to the EAs
- of a file on the diskette.
-
- Decrementing the Number of Licenses
-
- 1. Use DosQueryFSInfo() to get the VSN and the volume label of the "original"
- installation diskette.
- 2. Read the EA data for the file on the diskette.
- 3. Compare the information returned from DosQueryFSInfo() with that from the
- EA data and return an error if there is a mismatch.
- 4. If there is are no more available licenses, return an error.
- 5. Decrement the license count and write the EA data back to the file.
-
- Incrementing the Number of Licenses
-
- 1. Use DosQueryFSInfo() to get the VSN and the volume label of the "original"
- installation diskette.
- 2. Read the EA data for the file on the diskette.
- 3. Compare the information returned from DosQueryFSInfo() with that from the
- EA data and return an error if there is a mismatch.
- 4. Increment the license count and write the EA data back to the file.
-
- Determing the Number of Licenses
-
- 1. Use DosQueryFSInfo() to get the VSN and the volume label of the "original"
- installation diskette.
- 2. Read the EA data for the file on the diskette.
- 3. Compare the information returned from DosQueryFSInfo() with that from the
- EA data and return an error if there is a mismatch.
- 4. Return the number of available licenses.
-
- Easy, huh? The code corresponding to the above is shown below, is provided in
- cpyprt.zip, and has also been integrated into Common/2 which will eventually be
- sent to hobbes.nmsu.edu.
-
- typedef struct FCIINSTALLINFO {
- ULONG ulSzStruct;
- CHAR achVolLabel[12];
- ULONG ulVolSerial;
- ULONG ulNumLicenses;
- } FCIINSTALLINFO, *PFCIINSTALLINFO;
-
- ULONG EXPENTRY CmnFilInstallDisk(PCHAR pchFile,
- PCHAR pchVendor,
- PCHAR pchApp,
- PCHAR pchName,
- PULONG pulNumLicenses,
- ULONG ulRequest)
- //-------------------------------------------------------------------------
- // This function performs one of the available actions on a diskette
- // which is intended to be an install diskette for an application. The
- // action to be performed is specified in ulRequest:
- //
- // CFID_REQ_CREATE - initialize the install diskette with a specified
- // number of licenses
- // CFID_REQ_DECREMENT - decrement the number of licenses
- // CFID_REQ_INCREMENT - increment the number of licenses
- // CFID_REQ_QUERY - query the number of licenses
- //
- // On all actions but create, the diskette is checked to insure that
- // it is the original diskette initialized with the create action and
- // an error code is returned if not.
- //
- // Input: pchFile - points to the name of a file to contain the
- // installation information.
- // pchVendor - points to the name of the company producing the
- // product.
- // pchApp - points to the name of the application.
- // pchName - points to an arbitrary name.
- // pulNumLicenses - if ulRequest=CFID_REQ_CREATE, this points
- // to a variable specifying the initial number
- // of licenses for this installation diskette.
- // Otherwise, it points to a variable to receive
- // the updated number of available licenses or
- // is NULL meaning that the information isn't
- // needed.
- // ulRequest - one of the CFID_REQ_* constants
- // Output: pulNumLicenses - if non NULL, this contains the updated number
- // of licenses after the request was performed.
- // Returns: CFID_ERR_NOERROR if successful, a CFID_ERR_* constant otherwise.
- //-------------------------------------------------------------------------
- {
- APIRET arRc;
- CHAR achFullFile[CCHMAXPATH];
- CHAR chDrive;
- FSINFO fsiInfo;
- BYTE bNumDrives;
- ULONG ulVolSerial;
- USHORT usAttr;
- USHORT usSzData;
- FCIINSTALLINFO fiiInstall;
- BOOL bReturn;
-
- //----------------------------------------------------------------------
- // Get the fully qualified name of the file so that we can get the
- // drive letter. FIL_QUERYFULLNAME does require the diskette to be in
- // the drive so that OS/2 can query the current directory on the drive.
- //----------------------------------------------------------------------
- DosError(FERR_DISABLEHARDERR);
-
- arRc=DosQueryPathInfo(pchFile,
- FIL_QUERYFULLNAME,
- achFullFile,
- sizeof(achFullFile));
- if (arRc!=0) {
- DosError(FERR_ENABLEHARDERR);
- return CFID_ERR_DRIVENOTREADY;
- } /* endif */
-
- DosError(FERR_ENABLEHARDERR);
-
- chDrive=toupper(achFullFile[0])-'A'+1;
-
- //----------------------------------------------------------------------
- // Verify that the drive specified is a diskette drive.
- //----------------------------------------------------------------------
- DosDevConfig(&bNumDrives,DEVINFO_FLOPPY);
-
- if (chDrive>bNumDrives) {
- return CFID_ERR_NOTFLOPPY;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Query the file system information on the diskette.
- //----------------------------------------------------------------------
- if (DosQueryFSInfo(chDrive,
- FSIL_VOLSER,
- &fsiInfo,
- sizeof(fsiInfo))!=0) {
- return CFID_ERR_READFAILED;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Get the volume serial number of the diskette.
- //----------------------------------------------------------------------
- ulVolSerial=*((PULONG)&fsiInfo.fdateCreation);
-
- usAttr=EAT_BINARY;
- usSzData=sizeof(fiiInstall);
-
- switch (ulRequest) {
- case CFID_REQ_CREATE:
- //-------------------------------------------------------------------
- // pulNumLicenses cannot be NULL if we are initializing the diskette.
- //-------------------------------------------------------------------
- if (pulNumLicenses==NULL) {
- return CFID_ERR_BADPARM;
- } /* endif */
-
- //-------------------------------------------------------------------
- // Setup the intended EA data and write it to the file.
- //-------------------------------------------------------------------
- fiiInstall.ulSzStruct=sizeof(fiiInstall);
- strcpy(fiiInstall.achVolLabel,fsiInfo.vol.szVolLabel);
- fiiInstall.ulVolSerial=ulVolSerial;
- fiiInstall.ulNumLicenses=*pulNumLicenses;
-
- bReturn=CmnFilSetExtAttribute(achFullFile,
- usAttr,
- pchVendor,
- pchApp,
- pchName,
- (PCHAR)&fiiInstall,
- usSzData);
- if (!bReturn) {
- return CFID_ERR_WRITEFAILED;
- } /* endif */
- break;
- case CFID_REQ_DECREMENT:
- //-------------------------------------------------------------------
- // Get the current information from the file.
- //-------------------------------------------------------------------
- bReturn=CmnFilQueryExtAttribute(achFullFile,
- pchVendor,
- pchApp,
- pchName,
- &usAttr,
- (PCHAR)&fiiInstall,
- &usSzData);
- if (!bReturn) {
- return CFID_ERR_READFAILED;
- } /* endif */
-
- //-------------------------------------------------------------------
- // If the data is incorrect or the volume serial numbers do not
- // match, then this isn't the original install disk.
- //-------------------------------------------------------------------
- if ((fiiInstall.ulSzStruct!=sizeof(fiiInstall)) ||
- (strcmp(fiiInstall.achVolLabel,fsiInfo.vol.szVolLabel)!=0) ||
- (fiiInstall.ulVolSerial!=ulVolSerial)) {
- return CFID_ERR_NOTINSTALLDISK;
- } /* endif */
-
- //-------------------------------------------------------------------
- // Insure that we have at least one more license left.
- //-------------------------------------------------------------------
- if (fiiInstall.ulNumLicenses==0) {
- return CFID_ERR_NOMORELICENSES;
- } /* endif */
-
- //-------------------------------------------------------------------
- // Update and write the new information back to the diskette.
- //-------------------------------------------------------------------
- fiiInstall.ulNumLicenses--;
-
- if (pulNumLicenses!=NULL) {
- *pulNumLicenses=fiiInstall.ulNumLicenses;
- } /* endif */
-
- bReturn=CmnFilSetExtAttribute(achFullFile,
- usAttr,
- pchVendor,
- pchApp,
- pchName,
- (PCHAR)&fiiInstall,
- usSzData);
- if (!bReturn) {
- return CFID_ERR_WRITEFAILED;
- } /* endif */
- break;
- case CFID_REQ_INCREMENT:
- //-------------------------------------------------------------------
- // Get the current information from the file.
- //-------------------------------------------------------------------
- bReturn=CmnFilQueryExtAttribute(achFullFile,
- pchVendor,
- pchApp,
- pchName,
- &usAttr,
- (PCHAR)&fiiInstall,
- &usSzData);
- if (!bReturn) {
- return CFID_ERR_READFAILED;
- } /* endif */
-
- //-------------------------------------------------------------------
- // If the data is incorrect or the volume serial numbers do not
- // match, then this isn't the original install disk.
- //-------------------------------------------------------------------
- if ((fiiInstall.ulSzStruct!=sizeof(fiiInstall)) ||
- (strcmp(fiiInstall.achVolLabel,fsiInfo.vol.szVolLabel)!=0) ||
- (fiiInstall.ulVolSerial!=ulVolSerial)) {
- return CFID_ERR_NOTINSTALLDISK;
- } /* endif */
-
- //-------------------------------------------------------------------
- // Update and write the new information back to the diskette.
- //-------------------------------------------------------------------
- fiiInstall.ulNumLicenses++;
-
- if (pulNumLicenses!=NULL) {
- *pulNumLicenses=fiiInstall.ulNumLicenses;
- } /* endif */
-
- bReturn=CmnFilSetExtAttribute(achFullFile,
- usAttr,
- pchVendor,
- pchApp,
- pchName,
- (PCHAR)&fiiInstall,
- usSzData);
- if (!bReturn) {
- return CFID_ERR_WRITEFAILED;
- } /* endif */
- break;
- case CFID_REQ_QUERY:
- //-------------------------------------------------------------------
- // Get the current information from the file.
- //-------------------------------------------------------------------
- bReturn=CmnFilQueryExtAttribute(achFullFile,
- pchVendor,
- pchApp,
- pchName,
- &usAttr,
- (PCHAR)&fiiInstall,
- &usSzData);
- if (!bReturn) {
- return CFID_ERR_READFAILED;
- } /* endif */
-
- //-------------------------------------------------------------------
- // If the data is incorrect or the volume serial numbers do not
- // match, then this isn't the original install disk.
- //-------------------------------------------------------------------
- if ((fiiInstall.ulSzStruct!=sizeof(fiiInstall)) ||
- (strcmp(fiiInstall.achVolLabel,fsiInfo.vol.szVolLabel)!=0) ||
- (fiiInstall.ulVolSerial!=ulVolSerial)) {
- return CFID_ERR_NOTINSTALLDISK;
- } /* endif */
-
- if (pulNumLicenses!=NULL) {
- *pulNumLicenses=fiiInstall.ulNumLicenses;
- } /* endif */
- break;
- default:
- return CFID_ERR_BADPARM;
- } /* endswitch */
-
- return CFID_ERR_NOERROR;
- }
-
- Coding for Dollars: Copy Protection and Prevention - EDM/2 - Dec 1994 - Volume
- 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 2.5. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- What has been presented is simply an enabler. The code to call this function
- is still the responsibility of the application developer.
-
- o When you are installing the application, call CmnFilInstallDiskette()
- specifying CFID_REQ_DECREMENT to decrement the license count and check the
- return code.
-
- o When you are uninstalling the application, call CmnFilInstallDiskette()
- specifying CFID_REQ_INCREMENT to increment the license count and check the
- return code.
-
- Limitation
-
- You probably have already noted a major limitation of this scheme: since the
- VSN of the install diskette is stored in the EAs, the preparation of the
- install diskette cannot be done before duplication, but must be done - diskette
- by diskette - after duplication has been completed. The makes distribution of
- commercial software using this scheme much more cumbersome, but you did want
- that money, didn't you?
-
- Also, it is fairly easy to hack the VSN of a diskette if the pirate does enough
- research to find out where on the diskette it is stored. This is the weakest
- point in the scheme, but given that the data could be stored anywhere, there is
- nothing to indicate that it is this scheme which is being used, so your
- application should still be fairly safe.
-
- Feedback on this article will be greatly appreciated.
-
- Coding for Dollars: Copy Protection and Prevention - EDM/2 - Dec 1994 - Volume
- 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 3. Controlling Yourself: A Framework for Configurable Options ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 3.1. Introduction ΓòÉΓòÉΓòÉ
-
- Controlling Yourself: A Framework for Configurable Options
-
- Written by John Holt
-
- Introduction
-
- Most programs have a set of persistent options that are under user control.
- These options must be managed. This article discusses an approach to uniform
- management of option sets that may reside in a profile (INI file) or on a
- file's extended attributes (EA's).
-
- The home for user specified general application defaults varies by system. In a
- UNIX system, environment variables or entries in .mwmrc (the Motif resource
- file) are used for system-wide defaults. In Windows and OS/2, INI files are
- used to hold the general application defaults. The OS/2 file system also
- provides an additional means of keeping file specific default settings.
-
- Problem and Environment Description
-
- Any general framework of classes must have certain attributes. Two attributes
- that are germane to this article are programmer-extensibility and harmony with
- the external environment. The facility for programmer extensions is simply
- providing a capability for the programmer to add new classes to be stored in
- the profile or extended attributes. The attribute of harmony with the external
- environment in this case is using profiles and extended attributes in a way
- that facilitates the use of existing tools.
-
- Several base and implementation classes were developed. The task of managing
- persistent option sets is common to many programs, and therefore is an
- excellent candidate for reusable objects. The classes developed for the
- article represent an attempt to divide the implementation into classes so as to
- reuse common behaviors. The model for implementation is individual objects
- grouped into a set. The set is then stored on either a profile or in EAs.
-
- Controlling Yourself: A Framework for Configurable Options - EDM/2 - Dec 1994
- - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 3.2. Class Relationship Structure ΓòÉΓòÉΓòÉ
-
- Class Relationship Structure
-
- Overview
-
- The class structure is depicted in the diagram below. The relationship marked
- IS-A denotes class derivation. The relationship marked HAS-A shows that the
- class contains an object of the class. The KeyedOptionSet class is the result
- of a template generation using the KeyedSequentialSet class in the compiler
- collection classes library.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé BOptionSet Γöé Γöé BOptionItem Γöé
- ΓööΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÿ ΓööΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
- Γöé Γöé Γöé
- ISΓöéA HASΓöéA ISΓöéA
- Γöé Γöé Γöé
- Γöé ΓöéΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ ΓöéΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé ΓööΓöñ KeyedOptionSet Γöé Γö£Γöñ StrOptionItem Γöé
- Γöé Γöé <IKeySet> Γöé ΓöéΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
- Γöé ΓööΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ ΓöéΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé Γöé ΓööΓöñ Programmer Item Γöé
- Γöé HASΓöéA ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
- Γöé ΓöéΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé ΓööΓöñ OptionSetElem Γöé
- Γöé ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
- ΓöéΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γö£Γöñ EAOptionSet Γöé
- ΓöéΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
- ΓöéΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓööΓöñ INIOptionSet Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
- Set Classes
-
- The option set behaviors have been factored into a base class (BOptionSet) and
- two implementation classes (INIOptionSet and EAOptionSet). The behaviors
- specific to manipulation of EAs or profiles is in EAOptionSet and INIOptionSet
- respectively.
-
- BOptionSet is concerned with the maintenance of the list of items to be stored
- or retrieved. The following public methods are implemented:
-
- addItem Adds an item in the form of a pointer to a BOptionItem and
- a name for the option
- delItem Removes an item from the set
- applName The character string used as the high order name qualifier
- for EAs or the application name parameter for INI calls.
- ~BOptionSet The virtual destructor used to clean up.
-
- The BOptionSet object implements several protected methods used by the derived
- classes to access and manipulate the private data members. Those behaviors are:
-
- firstItem Position the set cursor to the first item
- nextItem Advance the set cursor to the next item in the set
- item Returns the pointer to an item in the set that is at the
- current cursor position.
- copy Makes this set a copy of another set.
- keySpace Returns the number of bytes needed to store the item key
- names.
- flatSpace Returns the number of bytes needed to store a flat version
- of the set of items.
- itemCount Returns the number of items in the set.
- BOptionSet The object constructors. There is a copy constructor and a
- constructor taking the application name and producing an
- empty set.
-
- The KeyedOptionSet is generated from the IKeySet template class which is a
- keyed sequential set class in the IBM collection classes. A cursor is provided
- by the template. The object is a set of OptionSetElem objects.
-
- The OptionSetElem is a simple object holding only the name of the option and a
- pointer to a BOptionItem object.
-
- The derived classes EAOptionSet and INIOptionSet provide the implementations
- for the loadSet, storeSet, and resetSet as well as the usual expected
- complement of constructors and an equal operator.
-
- The loadSet method updates each item with the value stored for that item's
- name. For the case of the items stored as EAs, the name is <application
- name>.<item name> and is mono-case. For objects stored in profiles, the name
- is forced to be in uppercase for consistency. The storeSet method is the
- reverse of the loadSet.
-
- The resetSet method performs two operations. First, the set of names in the
- profile or EAs is made to correspond with the set of names in the set. Any
- names with a prefix other than <application name> are ignored. The second
- operation is to perform a storeSet.
-
- Item Classes
-
- The BOptionItem class provides some default implementations for the behaviors.
- The class interface is primarily intended to be the communication portal
- between an option set and the real data objects that are the elements of that
- set. The interface is:
-
- itemType Returns an enum indicating that the object is a character string
- or is binary data
- itemSize Returns the size of the item in bytes
- exportData Returns a flattened version of the item consisting of a length
- and a pointer to a string of bytes.
- importData Accepts a flattened version of the item for updating the real
- data object.
-
- The StrOptionItem is a class definition for a string data object. The
- definition provides for the normal string behaviors.
-
- Interface to Programmer Supplied Objects
-
- The interface used by the option set to manipulate the items in memory is
- BOptionItem. Because all option items are derived from BOptionItem, the
- correct method is invoked.
-
- When an addItem method is invoked on a set, the set obtains a BOptionItem type
- pointer to that item. When the set needs the size of the item, e.g. to
- allocate a buffer, the pointer to a BOptionItem is used to invoke the correct
- method. Similarly, the importData and exportData methods are invoked to move
- the value to and from the persistent store.
-
- Adding New Object Classes
-
- There are two different strategies that can be employed for extending the range
- of types of items that can be used in option sets. The programmer may
- implement interface behaviors directly in the object to be added, or the
- programmer can implement a wrapper class. If the class is under control of the
- programmer, direct implementation is usually the best approach. If the object
- to be used is provided by a third party class library, or is not a first class
- object (e.g., an INT) then a wrapper class is the right approach. The sample
- program uses the later approach because it is the most non-obvious of the two
- approaches. The reader will notice that the example is contrived.
-
- Controlling Yourself: A Framework for Configurable Options - EDM/2 - Dec 1994
- - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 3.3. Walkthrough the Sample/Test Program ΓòÉΓòÉΓòÉ
-
- Walkthrough the Sample/Test Program
-
- The sample/test program illustrates how to create a set, add option items to
- that set, and store the set of option items. To exercise the code, these tasks
- were performed for both profile and EA based option sets. The file test.cpp
- [see test_src.zip within options.zip - Editor] should be followed for this
- discussion. You may also want look at BOptionSet.cpp and StrOptionItem.cpp [see
- source.zip within options.zip - Editor] for additional detail.
-
-
- Housekeeping test.cpp Initialize several variables,
- get an anchor block, and open
- the test profile.
-
- create empty set test.cpp Declare object of type
- INIOptionSet with a string and
- handle for the profile
-
- INIOptionSet.cpp Constructor for string and
- handle pass string to the
- BOptionSet for the application
- name, then hold onto the
- handle for subsequent file
- operations.
-
- create items test.cpp Declares for a StrOptionItem
- and two Option items. Option
- is a contrived class defined
- in the file option.h. Both of
- these objects take a value and
- a string used as the name of
- the option. The name is
- passed on to the BOptionItem
- parent class.
-
- Add items to the test.cpp The addItem method is invoked
- set for each item.
-
- BOptionSet.cpp The addItem method allocates
- an OptionSetElem object to
- hold the BOptionItem * and the
- name of the item. The element
- is then added to the set or
- replaces a previous item of
- the same name. The size of
- the item name is recorded.
-
- store the set INIOptionSet.cpp The items are stored on the
- profile test.ini. The set is
- traversed and each item is
- individually written to the
- profile. The exportData
- method is invoked for the
- BOptionItem involved. In the
- case of Item3,
- StrOptionItem::exportData is
- invoked.
-
- StrOptionItem.cpp A FlatItem data structure is
- allocated along with a buffer
- to hold the string value. The
- pointer to this is returned.
- It will be the callers
- responsibility to free the
- areas.
-
- change the values test.cpp The item values are changed
- of the items via the operator= method
-
- reset the items test.cpp The loadSet method is invoked
- from the store to update the items from the
- values held in the INI file.
- This restores them to their
- original values
-
- INIOptionSet.cpp For each item in the option
- set: the size of the item is
- obtained via the
- PrfQueryProfileItemSize()
- call; the item is read from
- the profile; the importData
- method for that item is
- invoked to update the item
- value in memory.
-
- StrOptionItem.cpp The importData method receives
- a FlatItem structure. The
- current string data is freed,
- and the new value is kept.
-
- delete some items test.cpp Items 1 and 2 are deleted from
- the set, and the version of
- the set on the profile is
- updated via resetSet so that
- only Item3 remains.
-
- Housekeeping test.cpp The profile data set is
- closed, and a regular
- sequential file is opened for
- the subsequent EA object
- testing.
-
- Create an test.cpp The EAOptionSet constructor is
- EAOptionSet invoked, using the
- INIOptionSet object from
- above, and the file handle for
- the sequential dataset opened
- above.
-
- EAOptionSet.cpp The constructor sends the set
- name to the BOptionSet
- constructor for later use as
- the application name. The
- handle of the file is retained
-
- reset EAs to known test.cpp The resetSet operation is
- values invoked which eliminates all
- option items currently stored
- as EAs, and replaces them with
- the current set contents, in
- this case, Item3.
-
- Exercise the EA test.cpp Items are added to the set;
- methods the set is stored; values are
- changed and reset in a manner
- similar to the tests for the
- INIOptionSet.
-
- There are several things worth keeping in mind. The flow for the above example
- is designed to test the logic, and not how the objects would be used in a real
- application. In a real application, the steps for use would be:
-
- 1. The data objects for all of the program options are declared, and initial
- values are given. All of these items must be derived from BOptionItem. The
- object may be derived from more than one class.
- 2. The INIOptionSet item is declared using either the handle to an INI file
- just for this application, or the handle to the user ini file
- (HINI_USERPROFILE).
- 3. The loadSet operation is invoked to pick up any defaults established by the
- user.
-
- If there are file specific options, then the EAOptionSet object is used as
- well. The EAOptionSet object would be created from the INIOptionSet object,
- and if there were any non-file related options, those option items would be
- removed from the EAOptionSet via the delItem operation.
-
- At an appropriate time, the option sets would be written to either the profile
- or the EAs or both.
-
- Controlling Yourself: A Framework for Configurable Options - EDM/2 - Dec 1994
- - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 3.4. Implementation notes ΓòÉΓòÉΓòÉ
-
- Implementation notes
-
- This section discusses some of the less obvious aspects of the set classes. To
- warrant the appellation of "less obvious," it had to be something I needed some
- effort to figure out. Which of course means that they may be completely
- obvious to you.
-
- Profiles
-
- The API for the profile was just a joy to use (compared to EAs), and the
- documentation makes everything pretty clear.
-
- EAs
-
- The EAs are not at all the same story. I used two books, and the
- documentation, to puzzle my way through how EAs worked. The books used were
- The Art of OS/2 2.1 C Programming, by Panov, Salomon, and Panov; the other book
- was OS/2 2.1 Application Programmers Guide, by Kelly et. al.
-
- The EAOptionSet operations work on all of the EAs at once. That way there are
- no windows where a a particular EA may change, or the ordinal positions of the
- EAs change.
-
- The layout of the EA buffer is as follows:
-
- FEA2 The head for each item in the buffer. The cbName contains the
- length of the name field (NULL terminated) and cbValue contains
- the length of the data portion. The offset to the next item is
- sizeof(FEA2) + cbValue + cbName + this position + enough to get
- you to the next mod 4 offset. The value of the cbValue element
- is the size of the flat data item + two SHORTs.
- ItemType At FEA2 + cbName + 1 is the EAT value. In our case it is either
- EAT_BINARY or EAT_ASCII. There are other options available, but
- the remainder of this discussion would not apply.
- Size The is the size in bytes of the flattened data item
-
- Controlling Yourself: A Framework for Configurable Options - EDM/2 - Dec 1994
- - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 3.5. Wrap-up ΓòÉΓòÉΓòÉ
-
- Wrap-up
-
- This article has present a set of classes that can be used to manage an
- application's set of options items. The basic model is that there exists a set
- of default values for the options of an application; the user is permitted to
- modify those options in a persistent manner; and that there may be some sub-set
- of options that are associated with particular files.
-
- Industrial Strength.
-
- There are several obvious features lacking which are required for an industrial
- strength implementation. In the case of EAs, there are no checks for exclusive
- control while writing or reading the set of EAs from the file. In the realm of
- memory management, there are no safeguards against bad pointers.
-
- One extension worthwhile making is that BOptionItems could have reference
- counts and perhaps references lists of the option sets where they are members.
-
- Useful Test Tools
-
- There are a couple of REXX scripts included in the zip file. In addition,
- there are several very useful tools at ftp-os2 such as EABrowse. The REXX
- script to print EAs only works when the the test program has closed the file,
- but I have no idea why I could not get it to share read access.
-
- Controlling Yourself: A Framework for Configurable Options - EDM/2 - Dec 1994
- - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 4. The Design and Implementation of VIOWIN: Part 4 ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 4.1. Introduction ΓòÉΓòÉΓòÉ
-
- The Design and Implementation of VIOWIN: Part 4
-
- 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 finished looking at the remaining functions that are called from
- within the main() function, and realized that everything so far was quite
- trivial in nature. This month, we will delve into the window management
- functions including vwSendMsg() and vwPostMsg().
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ 4.2. Window Management ΓòÉΓòÉΓòÉ
-
- Window Management
-
- Window management functions are, in my opinion, functions which act upon
- windows in some fashion. The list of functions within VIOWIN that fall into
- this category are listed below:
-
- o (MRESULT)vwDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- o (BOOL)vwEnableWindow(hwndWnd,bEnable);
- o (BOOL)vwInSendMsg(VOID);
- o (BOOL)vwIsWindow(hwndWnd);
- o (BOOL)vwIsWindowEnabled(hwndWnd);
- o (BOOL)vwPostMsg(hwndWnd,ulMsg,mpParm1,mpParm2);
- o (LONG)vwQueryBackColor(hwndWnd);
- o (HVWWND)vwQueryFocus(VOID);
- o (LONG)vwQueryForeColor(hwndWnd);
- o (HVWWND)vwQueryWindow(hwndWnd,lCmd);
- o (BOOL)vwQueryWindowPos(hwndWnd,pswpSwp);
- o (PVOID)vwQueryWindowPtr(hwndWnd,ulPtr);
- o (BOOL)vwQueryWindowRect(hwndWnd,prclRect);
- o (BOOL)vwQueryWindowText(hwndWnd,ulSzBuf,pchBuf);
- o (ULONG)vwQueryWindowTextLength(hwndWnd);
- o (LONG)vwQueryWindowULong(hwndWnd,lIndex);
- o (SHORT)vwQueryWindowUShort(hwndWnd,lIndex);
- o (MRESULT)vwSendMsg(hwndWnd,ulMsg,mpParm1,mpParm2);
- o (LONG)vwSetBackColor(hwndWnd,lColor);
- o (BOOL)vwSetFocus(hwndWnd);
- o (BOOL)vwSetForeColor(hwndWnd,lColor);
- o (BOOL)vwSetWindowPtr(hwndWnd,ulPtr,pvData);
- o (BOOL)vwSetWindowText(hwndWnd,pchText);
- o (BOOL)vwSetWindowULong(hwndWnd,lIndex,ulValue);
- o (BOOL)vwSetWindowUShort(hwndWnd,lIndex,usValue);
- o (BOOL)vwUpdateWindow(hwndWnd);
- o (HVWWND)vwWindowFromID(usId);
-
- What a list! Fortunately, many of these functions are quite small in their
- implementation, so they will not occupy much space or take up too much time in
- their discussion.
-
- Note!
-
- It needs to be pointed out again that color support differs greatly from PM,
- due to the lack of a Gpi component.
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ 4.3. Out Comes Our Spectacles ΓòÉΓòÉΓòÉ
-
- Out Comes Our Spectacles
-
- Let us take a closer look at each of the functions.
-
- vwDefWindowProc
-
- This is probably one of the more interesting functions, since its corresponding
- function in PM is not well-documented. Notice that only three messages are
- actually processed and the rest are simply ignored. Another important note is
- that this function actually handles the allocation of the window text in the
- WM_SETWINDOWPARAMS message.
-
- vwEnableWindow
-
- VIOWIN does nothing with the WS_DISABLED bit, though it probably should check
- this before allowing keystrokes to go to the window.
-
- vwInSendMsg
-
- One of the many trivial functions.
-
- vwIsWindow
-
- Another of the many trivial functions.
-
- vwIsWindowEnabled
-
- Another of the many trivial functions.
-
- vwPostMsg
-
- This function initializes the VWQMSG structure directly in the message queue,
- after first checking that there is space to store the message. In the first
- part of this series, you saw that the size of the queue was defined to be
- VW_SIZEQUEUE. This can be anything, and it is currently defined to be 50.
-
- vwQueryBackColor
-
- Another of the many trivial functions.
-
- vwQueryFocus
-
- Another of the many trivial functions.
-
- vwQueryForeColor
-
- Another of the many trivial functions.
-
- vwQueryWindow
-
- Another of the many trivial functions, if you are familiar with the linked-list
- routines of Common/2.
-
- vwQueryWindowText
-
- This function is how I envisioned PM performing the same task.
-
- vwQueryWindowPos
-
- Another of the many trivial functions.
-
- vwQueryWindowPtr
-
- Another of the many trivial functions. Note the restriction on the index of
- the pointer to be retrieved.
-
- vwQueryWindowRect
-
- Another of the many trivial functions.
-
- vwQueryWindowTextLength
-
- This function is how I envisioned PM performing the same task.
-
- vwQueryWindowULong
-
- Note that only QWL_STYLE is accepted. I probably could have added QWL_HMQ and
- QWL_USER, but I was lazy.
-
- vwQueryWindowUShort
-
- Note that only QWS_ID is accepted. I probably could have added QWS_USER here
- also.
-
- vwSendMsg
-
- This is fairly trivial, once you see what it is doing, but I never really
- thought about this function until I had to implement it. PM's version of this
- function is significantly more complicated, since I has to address sending
- across processes, etc.
-
- vwSetBackColor
-
- Another of the many trivial functions.
-
- vwSetFocus
-
- Note that I do not send the WM_SETSELECTION nor the WM_ACTIVATE message.
-
- vwSetForeColor
-
- Another of the many trivial functions.
-
- vwSetWindowPtr
-
- Another of the many trivial functions.
-
- vwSetWindowText
-
- This function is how I envisioned PM performing the same task, with the
- exception that PM uses heaps for memory allocation and I use the memory
- management routines within Common/2.
-
- vwSetWindowULong
-
- Note that only QWL_STYLE is accepted.
-
- vwSetWindowUShort
-
- This is a stub in case I decide to accept QWS_USER in the future.
-
- vwUpdateWindow
-
- This is an interesting function. If the window is the desktop, we cannot
- simply send it a WM_PAINT message, since it will erase its children in the
- process. So, we send the desktop first and then the children each a WM_PAINT
- message.
-
- vwWindowFromID
-
- Another of the many trivial functions.
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ 4.4. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- This month, much code was presented (see viowin4.zip) and the interesting
- details were discussed. I do realize that I have probably glossed over a lot
- of things; if there is something more you would like me to discuss, please send
- me email. I must add, though, that a lot of the "way it fits together" didn't
- actually occur to me until I needed to use the functions that I wrote, which
- resulted in modifications to the original attempts at the implementation of
- these functions.
-
- Next month, we will look at the remaining sections of the base library:
- timers, cursors, drawing, rectangles, and anything else I have missed. The
- following parts will then begin to look at the implementation of the window
- classes: buttons, entryfields, and static controls.
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwDefWindowProc ΓòÉΓòÉΓòÉ
-
- vwDefWindowProc
-
- MRESULT EXPENTRY vwDefWindowProc(HVWWND hwndWnd,
- ULONG ulMsg,
- MPARAM mpParm1,
- MPARAM mpParm2)
- //-------------------------------------------------------------------------
- // This is the default window procedure for windows. It processes certain
- // messages only. Others, it passes to the desktop window, unless it is
- // the desktop window which is calling this function.
- //-------------------------------------------------------------------------
- {
- HVWWND hwndDesktop;
-
- if (!vwIsWindow(hwndWnd)) {
- return MRFROMLONG(0);
- } /* endif */
-
- hwndDesktop=vwWindowFromID(VWWID_DESKTOP);
-
- switch (ulMsg) {
- case WM_QUERYWINDOWPARAMS:
- {
- PWNDPARAMS pwpParms;
-
- pwpParms=(PWNDPARAMS)PVOIDFROMMP(mpParm1);
-
- switch (pwpParms->fsStatus) {
- case WPM_CCHTEXT:
- pwpParms->cchText=strlen(hwndWnd->pchText)+1;
- return MRFROMLONG(TRUE);
- case WPM_TEXT:
- *pwpParms->pszText=0;
- strncat(pwpParms->pszText,hwndWnd->pchText,pwpParms->cchText-1);
- return MRFROMLONG(TRUE);
- default:
- break;
- } /* endswitch */
- }
- break;
- case WM_SETWINDOWPARAMS:
- {
- PWNDPARAMS pwpParms;
-
- pwpParms=(PWNDPARAMS)PVOIDFROMMP(mpParm1);
-
- switch (pwpParms->fsStatus) {
- case WPM_TEXT:
- {
- PCHAR pchText;
-
- CmnMemAllocate(habAnchor->hcmWork,
- pwpParms->cchText,
- (PPVOID)&pchText);
- if (pchText==NULL) {
- return FALSE;
- } /* endif */
-
- strcpy(pchText,pwpParms->pszText);
-
- if (hwndWnd->pchText!=NULL) {
- CmnMemFree(habAnchor->hcmWork,hwndWnd->pchText);
- } /* endif */
-
- hwndWnd->pchText=pchText;
- return MRFROMLONG(TRUE);
- }
- default:
- break;
- } /* endswitch */
- }
- break;
- case WM_CLOSE:
- vwPostMsg(hwndWnd,WM_QUIT,0,0);
- return MRFROMLONG(0);
- default:
- break;
- } /* endswitch */
-
- if (hwndWnd!=hwndDesktop) {
- //-------------------------------------------------------------------
- // If the message wasn't processed and the window isn't the desktop,
- // pass the message up the chain. Some messages get sent; the rest
- // get posted.
- //-------------------------------------------------------------------
- switch (ulMsg) {
- case WM_COMMAND:
- case WM_CONTROL:
- case WM_CHAR:
- if (vwInSendMsg()) {
- return vwSendMsg(hwndDesktop,ulMsg,mpParm1,mpParm2);
- } else {
- vwPostMsg(hwndDesktop,ulMsg,mpParm1,mpParm2);
- return MRFROMLONG(0);
- } /* endif */
- default:
- return MRFROMLONG(0);
- } /* endswitch */
- } else {
- return MRFROMLONG(0);
- } /* endif */
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwEnableWindow ΓòÉΓòÉΓòÉ
-
- vwEnableWindow
-
- BOOL EXPENTRY vwEnableWindow(HVWWND hwndWnd,BOOL bEnable)
- //-------------------------------------------------------------------------
- // This function sets or resets the WS_DISABLED bit for the window.
- //
- // Input: hwndWnd - specifies the window handle
- // bEnable - flag indicating the desired enabled state
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- if (bEnable) {
- hwndWnd->ulStyle&=~WS_DISABLED;
- } else {
- hwndWnd->ulStyle|=WS_DISABLED;
- } /* endif */
-
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwInSendMsg ΓòÉΓòÉΓòÉ
-
- vwInSendMsg
-
- BOOL EXPENTRY vwInSendMsg(VOID)
- //-------------------------------------------------------------------------
- // This function determines if the system is in the middle of processing
- // a vwSendMsg() call.
- //
- // Returns: TRUE if in vwSendMsg(), FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (hmqQueue==NULL) {
- return FALSE;
- } /* endif */
-
- return habAnchor->bIsSendMsg;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwIsWindow ΓòÉΓòÉΓòÉ
-
- vwIsWindow
-
- BOOL EXPENTRY vwIsWindow(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function determines if the specified handle is a valid window
- // handle or not.
- //
- // Input: hwndWnd - handle to query
- // Returns: TRUE if the handle is valid, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- ULONG ulNumItems;
- ULONG ulIndex;
- HVWWND hwndList;
-
- if (hmqQueue==NULL) {
- return FALSE;
- } /* endif */
-
- 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 */
-
- if (hwndList==hwndWnd) {
- return TRUE;
- } /* endif */
- } /* endfor */
-
- return FALSE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwIsWindowEnabled ΓòÉΓòÉΓòÉ
-
- vwIsWindowEnabled
-
- BOOL EXPENTRY vwIsWindowEnabled(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function determines if the window is enabled or not.
- //
- // Input: hwndWnd - handle to query
- // Returns: TRUE if the window is enabled, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- return ((hwndWnd->ulStyle & WS_DISABLED)==0);
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwPostMsg ΓòÉΓòÉΓòÉ
-
- vwPostMsg
-
- BOOL EXPENTRY vwPostMsg(HVWWND hwndWnd,
- ULONG ulMsg,
- MPARAM mpParm1,
- MPARAM mpParm2)
- //-------------------------------------------------------------------------
- // This function sends a message to the window. This is done by
- // building a VWQMSG structure and placing it in the queue.
- //
- // Input: hwndWnd - specifies the window handle
- // ulMsg - specifies the message
- // mpParm1, mpParm2 - specify the message parameters
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- PVWQMSG pqmMsg;
-
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- if (((hmqQueue->ulHead==0) && (hmqQueue->ulTail==VW_SIZEQUEUE)) ||
- (hmqQueue->ulHead==hmqQueue->ulTail+1)) {
- return FALSE;
- } /* endif */
-
- hmqQueue->ulTail++;
- if (hmqQueue->ulTail==VW_SIZEQUEUE) {
- hmqQueue->ulTail=0;
- } /* endif */
-
- pqmMsg=&hmqQueue->aqmMsgs[hmqQueue->ulTail];
-
- pqmMsg->hwndWnd=hwndWnd;
- pqmMsg->ulMsg=ulMsg;
- pqmMsg->mpParm1=mpParm1;
- pqmMsg->mpParm2=mpParm2;
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryBackColor ΓòÉΓòÉΓòÉ
-
- vwQueryBackColor
-
- LONG EXPENTRY vwQueryBackColor(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function returns the background color of the window.
- //
- // Input: hwndWnd - specifies the window handle
- // Returns: VWCLR_* constant if successful, -1 otherwise
- //-------------------------------------------------------------------------
- {
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return -1;
- } /* endif */
-
- return hwndWnd->lBackClr;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryFocus ΓòÉΓòÉΓòÉ
-
- vwQueryFocus
-
- HVWWND EXPENTRY vwQueryFocus(VOID)
- //-------------------------------------------------------------------------
- // This function returns the handle of the window currently with the
- // focus.
- //
- // Returns: window handle or NULLHANDLE if no window has the focus
- //-------------------------------------------------------------------------
- {
- //----------------------------------------------------------------------
- // Make sure we were initialized
- //----------------------------------------------------------------------
- if (hmqQueue==NULL) {
- return NULL;
- } /* endif */
-
- return habAnchor->hwndFocus;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryForeColor ΓòÉΓòÉΓòÉ
-
- vwQueryForeColor
-
- LONG EXPENTRY vwQueryForeColor(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function returns the foreground color of the window.
- //
- // Input: hwndWnd - specifies the window handle
- // Returns: VWCLR_* constant if successful, -1 otherwise
- //-------------------------------------------------------------------------
- {
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return -1;
- } /* endif */
-
- return hwndWnd->lForeClr;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindow ΓòÉΓòÉΓòÉ
-
- vwQueryWindow
-
- HVWWND EXPENTRY vwQueryWindow(HVWWND hwndWnd,LONG lCmd)
- //-------------------------------------------------------------------------
- // This function returns the handle of a window relative to the specified
- // window.
- //
- // Input: hwndWnd - specifies the window handle
- // lCmd - specifies a QW_* constant
- // Returns: window handle if successful, NULLHANDLE otherwise
- //-------------------------------------------------------------------------
- {
- ULONG ulNumRecs;
- HVWWND hwndReturn;
-
- if (!vwIsWindow(hwndWnd)) {
- return NULL;
- } /* endif */
-
- ulNumRecs=CmnLstQueryRecordCount(habAnchor->hclWindows);
-
- switch (lCmd) {
- case QW_NEXT:
- hwndReturn=CmnLstQueryRelative(hwndWnd,LQR_NEXT);
- break;
- case QW_PREV:
- hwndReturn=CmnLstQueryRelative(hwndWnd,LQR_PREVIOUS);
-
- if (hwndReturn==vwWindowFromID(VWWID_DESKTOP)) {
- hwndReturn=NULL;
- } /* endif */
- break;
- case QW_TOP:
- hwndReturn=CmnLstQueryRecord(habAnchor->hclWindows,1);
- break;
- case QW_BOTTOM:
- hwndReturn=CmnLstQueryRecord(habAnchor->hclWindows,ulNumRecs-1);
- break;
- default:
- return NULL;
- } /* endswitch */
-
- return hwndReturn;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowText ΓòÉΓòÉΓòÉ
-
- vwQueryWindowText
-
- BOOL EXPENTRY vwQueryWindowText(HVWWND hwndWnd,ULONG ulSzBuf,PCHAR pchBuf)
- //-------------------------------------------------------------------------
- // This function returns the window text by sending the window a
- // WM_QUERYWINDOWPARAMS message.
- //
- // Input: hwndWnd - specifies the window handle
- // ulSzBuf - specifies the size of the buffer
- // pchBuf - points to the buffer to receive the text
- // Output: pchBuf - points to the buffer containing the text
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- WNDPARAMS wpParms;
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- if (pchBuf==NULL) {
- return FALSE;
- } /* endif */
-
- wpParms.fsStatus=WPM_TEXT;
- wpParms.cchText=ulSzBuf;
- wpParms.pszText=pchBuf;
-
- if (SHORT1FROMMP(vwSendMsg(hwndWnd,
- WM_QUERYWINDOWPARAMS,
- MPFROMP(&wpParms),
- 0))) {
- return TRUE;
- } else {
- return FALSE;
- } /* endif */
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowPos ΓòÉΓòÉΓòÉ
-
- vwQueryWindowPos
-
- BOOL EXPENTRY vwQueryWindowPos(HVWWND hwndWnd,PVWSWP pswpSwp)
- //-------------------------------------------------------------------------
- // This function returns the size and position of the window.
- //
- // Input: hwndWnd - specifies the window handle
- // pswpSwp - points to the VWSWP structure to receive the result
- // Output: pswpSwp - points to the VWSWP structure containing the result
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- (*pswpSwp)=hwndWnd->swpSwp;
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowPtr ΓòÉΓòÉΓòÉ
-
- vwQueryWindowPtr
-
- PVOID EXPENTRY vwQueryWindowPtr(HVWWND hwndWnd,ULONG ulPtr)
- //-------------------------------------------------------------------------
- // This function returns the specified window pointer.
- //
- // Input: hwndWnd - specifies the window handle
- // ulPtr - specifies 0 or 1
- // Returns: specified window pointer if successful, NULL otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return NULL;
- } /* endif */
-
- if (ulPtr>1) {
- return NULL;
- } /* endif */
-
- return hwndWnd->pvData[ulPtr];
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowRect ΓòÉΓòÉΓòÉ
-
- vwQueryWindowRect
-
- BOOL EXPENTRY vwQueryWindowRect(HVWWND hwndWnd,PRECTL prclRect)
- //-------------------------------------------------------------------------
- // This function returns the size of the window.
- //
- // Input: hwndWnd - specifies the window handle
- // prclRect - points to the RECTL structure to receive the result
- // Output: prclRect - points to the RECTL structure containing the result
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- prclRect->xLeft=0;
- prclRect->yBottom=0;
- prclRect->xRight=hwndWnd->swpSwp.ulCx;
- prclRect->yTop=hwndWnd->swpSwp.ulCy;
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowTextLength ΓòÉΓòÉΓòÉ
-
- vwQueryWindowTextLength
-
- ULONG EXPENTRY vwQueryWindowTextLength(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function returns the length of the window text.
- //
- // Input: hwndWnd - specifies the window handle
- // Returns: length if successful, 0 otherwise
- //-------------------------------------------------------------------------
- {
- WNDPARAMS wpParms;
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- wpParms.fsStatus=WPM_CCHTEXT;
-
- if (SHORT1FROMMP(vwSendMsg(hwndWnd,
- WM_QUERYWINDOWPARAMS,
- MPFROMP(&wpParms),
- 0))) {
- return wpParms.cchText;
- } else {
- return 0;
- } /* endif */
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowULong ΓòÉΓòÉΓòÉ
-
- vwQueryWindowULong
-
- LONG EXPENTRY vwQueryWindowULong(HVWWND hwndWnd,LONG lIndex)
- //-------------------------------------------------------------------------
- // This function returns the value of the specified window variable.
- //
- // Input: hwndWnd - specifies the window handle
- // lIndex - specifies a QWL_* constant
- // Returns: value of the variable if successful, -1 otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return -1;
- } /* endif */
-
- switch (lIndex) {
- case QWL_STYLE:
- return hwndWnd->ulStyle;
- default:
- return -1;
- } /* endswitch */
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwQueryWindowUShort ΓòÉΓòÉΓòÉ
-
- vwQueryWindowUShort
-
- SHORT EXPENTRY vwQueryWindowUShort(HVWWND hwndWnd,LONG lIndex)
- //-------------------------------------------------------------------------
- // This function returns the value of the specified window variable.
- //
- // Input: hwndWnd - specifies the window handle
- // lIndex - specifies a QWS_* constant
- // Returns: value of the variable if successful, -1 otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return -1;
- } /* endif */
-
- switch (lIndex) {
- case QWS_ID:
- return hwndWnd->usId;
- default:
- return -1;
- } /* endswitch */
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSendMsg ΓòÉΓòÉΓòÉ
-
- vwSendMsg
-
- MRESULT EXPENTRY vwSendMsg(HVWWND hwndWnd,
- ULONG ulMsg,
- MPARAM mpParm1,
- MPARAM mpParm2)
- //-------------------------------------------------------------------------
- // This function sends a message to the window. This is done by
- // dereferencing the class and calling the window class procedure
- // directly.
- //
- // Input: hwndWnd - specifies the window handle
- // ulMsg - specifies the message
- // mpParm1, mpParm2 - specify the message parameters
- // Returns: value specific to the message sent
- //-------------------------------------------------------------------------
- {
- BOOL bOldSendMsg;
- MRESULT mrRc;
-
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return MRFROMLONG(0);
- } /* endif */
-
- bOldSendMsg=habAnchor->bIsSendMsg;
- habAnchor->bIsSendMsg=TRUE;
-
- mrRc=(*(hwndWnd->pciClass->pfnWndProc))(hwndWnd,ulMsg,mpParm1,mpParm2);
-
- habAnchor->bIsSendMsg=bOldSendMsg;
- return mrRc;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetBackColor ΓòÉΓòÉΓòÉ
-
- vwSetBackColor
-
- LONG EXPENTRY vwSetBackColor(HVWWND hwndWnd,LONG lColor)
- //-------------------------------------------------------------------------
- // This function sets the background color of the window.
- //
- // Input: hwndWnd - specifies the window handle
- // lColor - specifies the new color
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- hwndWnd->lBackClr=lColor;
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetFocus ΓòÉΓòÉΓòÉ
-
- vwSetFocus
-
- BOOL EXPENTRY vwSetFocus(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function sets the focus to another window.
- //
- // Input: hwndWnd - specifies the handle of the window to receive the
- // focus
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- HVWWND hwndLose;
-
- //----------------------------------------------------------------------
- // Validate the window handle
- //----------------------------------------------------------------------
- if ((hwndWnd!=NULL) && !vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- hwndLose=habAnchor->hwndFocus;
-
- //----------------------------------------------------------------------
- // Send a WM_SETFOCUS message to the window losing the focus. Also,
- // send a WM_PAINT message (this deviates from PM).
- //----------------------------------------------------------------------
- if (hwndLose!=NULL) {
- habAnchor->hwndFocus=NULL;
- vwSendMsg(hwndLose,WM_SETFOCUS,MPFROMHWND(hwndWnd),MPFROMLONG(FALSE));
- vwSendMsg(hwndLose,WM_PAINT,0,0);
- } /* endif */
-
- //----------------------------------------------------------------------
- // Send a WM_SETFOCUS message to the window gaining the focus. Again,
- // also send a WM_PAINT message (deviation).
- //----------------------------------------------------------------------
- if (hwndWnd!=NULL) {
- vwSendMsg(hwndWnd,
- WM_SETFOCUS,
- MPFROMHWND(hwndLose),
- MPFROMLONG(TRUE));
- habAnchor->hwndFocus=hwndWnd;
- vwSendMsg(hwndWnd,WM_PAINT,0,0);
- } else {
- habAnchor->hwndFocus=NULL;
- } /* endif */
-
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetForeColor ΓòÉΓòÉΓòÉ
-
- vwSetForeColor
-
- BOOL EXPENTRY vwSetForeColor(HVWWND hwndWnd,LONG lColor)
- //-------------------------------------------------------------------------
- // This function sets the foreground color of the window.
- //
- // Input: hwndWnd - specifies the window handle
- // lColor - specifies the new color
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- hwndWnd->lForeClr=lColor;
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetWindowPtr ΓòÉΓòÉΓòÉ
-
- vwSetWindowPtr
-
- BOOL EXPENTRY vwSetWindowPtr(HVWWND hwndWnd,ULONG ulPtr,PVOID pvData)
- //-------------------------------------------------------------------------
- // This function set the specified window pointer.
- //
- // Input: hwndWnd - specifies the window handle
- // ulPtr - specifies 0 or 1
- // pvData - specifies the window pointer
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- if (ulPtr>1) {
- return FALSE;
- } /* endif */
-
- hwndWnd->pvData[ulPtr]=pvData;
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetWindowText ΓòÉΓòÉΓòÉ
-
- vwSetWindowText
-
- BOOL EXPENTRY vwSetWindowText(HVWWND hwndWnd,PCHAR pchText)
- //-------------------------------------------------------------------------
- // This function attempts to set the window text by sending the window
- // a WM_SETWINDOWPARAMS message. It is the responsibility of the window
- // class to copy the text to its own workspace.
- //
- // Input: hwndWnd - specifies the window handle
- // pchText - points to the new text
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- WNDPARAMS wpParms;
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- if (pchText!=NULL) {
- wpParms.pszText=pchText;
- } else {
- wpParms.pszText="";
- } /* endif */
-
- wpParms.fsStatus=WPM_TEXT;
- wpParms.cchText=strlen(pchText)+1;
-
- if (SHORT1FROMMP(vwSendMsg(hwndWnd,
- WM_SETWINDOWPARAMS,
- MPFROMP(&wpParms),
- 0))) {
- return TRUE;
- } else {
- return FALSE;
- } /* endif */
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetWindowULong ΓòÉΓòÉΓòÉ
-
- vwSetWindowULong
-
- BOOL EXPENTRY vwSetWindowULong(HVWWND hwndWnd,LONG lIndex,ULONG ulValue)
- //-------------------------------------------------------------------------
- // This function sets the value of the specified window variable.
- //
- // Input: hwndWnd - specifies the window handle
- // lIndex - specifies a QWL_* constant
- // ulValue - specifies the new value
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- switch (lIndex) {
- case QWL_STYLE:
- hwndWnd->ulStyle=ulValue;
- break;
- default:
- return FALSE;
- } /* endswitch */
-
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwSetWindowUShort ΓòÉΓòÉΓòÉ
-
- vwSetWindowUShort
-
- BOOL EXPENTRY vwSetWindowUShort(HVWWND hwndWnd,LONG lIndex,USHORT usValue)
- //-------------------------------------------------------------------------
- // This function sets the value of the specified window variable.
- //
- // Input: hwndWnd - specifies the window handle
- // lIndex - specifies a QWS_* constant
- // usValue - specifies the new value
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- switch (lIndex) {
- default:
- return FALSE;
- } /* endswitch */
-
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwUpdateWindow ΓòÉΓòÉΓòÉ
-
- vwUpdateWindow
-
- BOOL EXPENTRY vwUpdateWindow(HVWWND hwndWnd)
- //-------------------------------------------------------------------------
- // This function updates the specified window. If the window is the
- // desktop, it updates all of the children also.
- //
- // Input: hwndWnd - specifies the window handle
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- if (hwndWnd==VWHWND_DESKTOP) {
- hwndWnd=vwWindowFromID(VWWID_DESKTOP);
- } /* endif */
-
- if (!vwIsWindow(hwndWnd)) {
- return FALSE;
- } /* endif */
-
- if (vwQueryWindowUShort(hwndWnd,QWS_ID)==VWWID_DESKTOP) {
- //-------------------------------------------------------------------
- // Since the desktop is first in the list, traverse the list and
- // send each window a WM_PAINT message.
- //-------------------------------------------------------------------
- CmnLstTraverseList(habAnchor->hclWindows,(PFNRECFUNC)paintWindow);
- } else {
- paintWindow(hwndWnd);
- } /* endif */
-
- return TRUE;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ <hidden> vwWindowFromID ΓòÉΓòÉΓòÉ
-
- vwWindowFromID
-
- HVWWND EXPENTRY vwWindowFromID(USHORT usId)
- //-------------------------------------------------------------------------
- // This function returns the handle of the window with the specified id.
- //
- // Input: usId - specifies the id to search for
- // Returns: handle of the window with the specified id if found, NULLHANDLE
- // otherwise
- //-------------------------------------------------------------------------
- {
- HVWWND hwndFound;
-
- if (hmqQueue==NULL) {
- return NULL;
- } /* endif */
-
- //----------------------------------------------------------------------
- // If the id is -1, then the caller doesn't care about the window id,
- // so we should return NULL to allow for multiple windows with this
- // id can be used multiple times.
- //----------------------------------------------------------------------
- if (usId==(USHORT)-1) {
- return NULL;
- } /* endif */
-
- hwndFound=(HVWWND)CmnLstQueryRecord(habAnchor->hclWindows,0);
- hwndFound=(HVWWND)CmnLstSearchRecord(hwndFound,
- &usId,
- (PFNRECCOMP)_findWindowId);
- return hwndFound;
- }
-
- The Design and Implementation of VIOWIN: Part 4 - EDM/2 - Dec 1994 - Volume 2,
- Issue 11
-
-
- ΓòÉΓòÉΓòÉ 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, but
- intermediate REXX programmer's eyes. 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 gets read and responded to.
-
- OS/2 Presentation Manager Programming is perhaps the most awaited book in the
- history of OS/2. Charles Petzold wrote a version of this book way back when,
- but for a long time it looked like he might never write another, perhaps due to
- pressure from Microsoft. Well, all the hopefuls will have to revise their
- opinion now as the updated version is finally out. This is a PM programming
- book for beginners.
-
- /dev/EDM2/BookReview - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 5.2. Errata ΓòÉΓòÉΓòÉ
-
- Errata
-
- I am still waiting for OS/2 Warp 3.0, and I can hardly contain myself
- (well...). I have heard much good about it, but also that it is less stable
- than OS/2 2.11. I'll just have to wait until it arrives before I judge.
- Meanwhile, I unfortunately sold my OS/2 2.1, so I am running on OS/2 Warp Beta
- II, which has had its down-sides. I purchased a Promise DC4030VL-2 with 2Mb of
- cache RAM, but due to driver bugs, I lost my Warp. Later on the card went
- AWOL, so I had to return it. When the replacement finally came, it was also
- broken, but I noticed that the packaging had been opened, so I am wondering
- whether it was the same card. Back to the store it goes, but this time I wrote
- down the serial number, so I can tell whether the supplier really is giving me
- a new one. Sigh.
-
- The format I have been using so far in reviewing books requires that I read
- every line in the whole book, which is very time-consuming, and difficult,
- considering that I am not an expert in every field. It makes it very difficult
- for me to evaluate material with which I am not familiar, so I am going to
- change format slightly. I will concentrate a bit more on filling in the tables
- at the end of the review accurately, and slightly less on writing a detailed
- review of every section in every chapter. This lets me skim the material a
- little more, but still lets you find what you are looking for. Expect the
- tables to grow a fair amount, and perhaps even change format a bit from time to
- time.
-
- /dev/EDM2/BookReview - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 5.3. OS/2 Presentation Manager Programming ΓòÉΓòÉΓòÉ
-
- OS/2 Presentation Manager Programming
-
- OS/2 Presentation Manager Programming is a very thorough introductory PM
- programming book. Many programmers have been clamouring for this book for a
- long time, knowing that the author covers his material very well, and writes
- very lucidly. Well, it is finally here, and these are the chapters:
-
- 1. OS/2 and the Presentation Manager
- 2. Welcome to Presentation Manager Programming
- 3. More Fun with Windows
- 4. An Exercise in Text Output
- 5. The Five GPI Primitives
- 6. Bitmaps and BitBlts
- 7. Advanced Graphics
- 8. Tapping into the Keyboard
- 9. Taming the Mouse
- 10. Setting the Timer
- 11. Control Windows: Putting the Children to Work
- 12. Bitmaps, Icons, Pointers, and Strings
- 13. Menus and Keyboard Accelerators
- 14. Dialog Boxes
- 15. Cut, Copy, and Paste: The Clipboard
- 16. Dynamic Link Libraries
- 17. Multithreaded Programming Techniques
- 18. Printing Graphics and Text
- 19. Appendix A: About the Accompanying Disk
-
- The book is divided into sections as follows:
-
- 1. Basic Concepts - chapters one through three
- 2. Painting the Client Window - chapters four through seven
- 3. Getting Input - chapters eight through eleven
- 4. Using Resources - chapters twelve through fourteen
- 5. Miscellaneous Topics - chapters fifteen through eighteen
-
- Before I get started I have to express dissatisfaction that the author chose
- only to support the IBM and Borland compilers (and then there is the cheesy
- install program, ie. PKZIP). I use the Watcom compiler which is better quality
- than the Borland compiler, and which has been around for quite a while. It
- really shouldn't take that much time for an author to ask a couple of friends
- who use the Watcom compiler if they can come up with a .CMD file to set the
- Watcom options. With that off my chest, here is the review...
-
- In addition to a brief history of OS/2, the first three chapters have the
- obligatory "this is a window, this is how you open it" introduction. What sets
- it apart from other books is the depth in which the WinCreateWindow call is
- treated. Many, if not all of the options to this API are listed and explained,
- which is unusual. The treatment is usually biased towards WinCreateStdWindow
- instead, so this change is refreshing and educational. By the way, Petzold
- seems to have made it a habit to pull out the constants when he describes a new
- call, and explain them as well, including the ones he doesn't actually use.
- This is a good thing in my opinion, and only some books do that, not all.
-
- Section two describes some of the GPI calls commonly used to do fairly mundane
- tasks, and also gets into a bit of advanced GPI programming. Those of you who
- intend to write the next Doom (Copyright 1994 iD Software) should probably wait
- for the new version of OS/2 Presentation Manager GPI, Winn, or take a look at
- the new DIVE API, however. The basic lines, curves, and so on are described,
- and some of the more advanced calls like Bezier splines, paths, and transforms,
- but do not expect to be able to write the next graphing program after reading
- this section. Surprisingly, however, he does go into mathematics to explain
- the various functions, and this makes this advanced section a good GPI
- introduction for intermediate and advanced programmers. This is probably a
- section you'll want to come back to when you have mastered more of the rest of
- the book. Many of the compromises inherent to both raster (pixel) and vector
- (line) graphics are explained in detail, and you will learn a lot about the
- basics of graphics programming even you don't actually do any.
-
- Fonts are treated in the GPI section as well, and they are explained in fairly
- good depth. You should be able to find a solution to most text problems here.
- The various shears, rotations, and so on are all explained patiently, with many
- little sample programs. In addition, many different types of shadows and
- fillings are demonstrated in quite a bit of detail, as is text justification.
-
- Part three covers the keyboard and the mouse, and getting input from them. The
- keyboard is covered first, not surprisingly. A program called TYPEAWAY is used
- to demonstrate these concepts. It is basically a brain-damaged editor with a
- few crucial design flaws, so if you ever wanted to write a word-processor or an
- editor, this would be a good place to start. The flaws, by the way, are
- intended.
-
- The mouse material is introduced with a neat program called WEB, which draws
- lines from the corner of the window to the current mouse position. It is a
- little gimmicky, but quite a fun little program. It is followed up by another
- neat little program called CHECKER1 (CHECKER2 for the keyboard enabled
- version). These programs are basic, but demonstrate how to use the mouse
- position and buttons to do various things in your client window. CHECKER3 then
- demonstrates how to use the divide and conquer strategy in your window, and
- divide the window into sections which each handle their own input. These are
- followed by programs which keep track of mouse movement, and do something at
- the same time, i.e. draw blocks the size of a click-and-drag area, and then by
- a sketching program which draws when you click-and-drag. These are all
- educational programs which really drive home the point of certain types of
- interaction.
-
- The last chapter in the input section is the chapter on the timer. Petzold
- shows both how to set a repeating timer, how to get around the basic timer
- functionality to set one-time timers, and how to get around the 65.5 second
- maximum timer duration limit. The logic necessary to distinguish between the
- timers of cursor blinkers and clock and so on are also demonstrated. A little
- program which uses a timer to display free memory at fixed intervals is shown,
- and finally a plain digital clock and an analog clock are shown. The analog
- clock makes me think that he had a hand in the design of the OS/2 system clock
- :)
-
- Chapter eleven seems a little out of place in the input section, but since many
- of the controls are aimed at getting input from the user, it isn't so odd after
- all. This chapter is fairly basic, and goes through a number of small programs
- which create buttons, sliders, text, and other small windows. It skips a
- detailed treatment of the MLE, as well as lists, drop-down lists, text-entry
- fields and others. Some of these are introduced along the way in the book, but
- not in any real depth. In fact, now that I look closer at the book, this is
- the only really serious short-coming of the book that isn't just a matter of
- opinion. Yes, many of these controls are shown in various examples here and
- there, but there is no real in-depth treatment anywhere. There really should be
- a good thick chapter on these things, and that chapter should have been chapter
- eleven, but isn't. This is the bread and butter type stuff that applications
- are made of. There is a large section on GPI that most people will never use,
- but no collection of controls? Hmm, well, onwards we go...
-
- Part four is on using resources such as bitmaps, icons, accelerator keys and so
- on. It starts out by showing what the various resources are, and how they get
- into the EXE via the different stages of compilation. This entails explaining
- resource scripts, which is then promptly done. A couple of examples are given,
- but without much detail pertaining to the different options.
-
- The next chapter is devoted to menus and accelerator keys. Regular menus,
- checked/unchecked items, enabled/disabled items, help menus, and accelerators
- are all demonstrated, but the first example shows how to add items to the
- system menu. This is called the poor person's menu :) The next example is a
- nice introductory pop-up menu. This is a nicely thought-out piece with a few
- items with more than one level to them. The third example has an amusing
- bitmap as the last item. This bitmap is a cheesy bitmap of a children's
- handwriting rendition of the word help :) A game called TAQUIN follows (more
- commonly known as PUZZLE). This game is a good demonstration of a combination
- of the techniques learned earlier in the book, as it combines menus, graphics,
- and mouse tracking programming techniques. Finally, a decent implementation of
- The Game of Life is given. These programs are both interesting and give good
- real-life examples of menu usage. This is how it should be done.
-
- Chapter fourteen discusses dialog boxes. Dialog boxes aren't the most
- interesting of PM possibilities, but they are probably the most ubiquitous.
- There is probably at least one dialog box in almost every PM program ever
- written! This chapter gives a nice variety of the possible features of a
- dialog box.
-
- The final section in the book consists of various topics which didn't fit the
- neat, boxed labels that the other chapters did. An introduction to the
- clipboard, dynamic link libraries, multi-threaded programs and printing can be
- found here. Given the importance of multi-threading, I would have liked to see
- a larger chapter on it, and perhaps the same goes for printing. Multi-threading
- is a topic which even an introductory volume should have, since it is the key
- area which differentiates PM from the more mundane Windows API. There is a
- nice section with a multi-tasking explanation, including the differences
- between Windows' and OS/2's way of doing things, however.
-
- /dev/EDM2/BookReview - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 5.4. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- OS/2 Presentation Manager Programming is a very thorough beginners' book with a
- lot of emphasis on the comprehension of basic PM calls, and their parameters.
- It has a good introduction to almost every API call that you are likely to come
- across initially when learning to program PM, and in addition it has an
- introduction to some advanced techniques. The advanced material is frequently
- not covered in any real depth, but some examples are given for the usage of
- various APIs, and you will learn what type of problems you can solve with the
- different parts of the PM API. I especially like the little motivational
- sections given at the start of each chapter, and wished that he had done
- similarly for each subsection. They really help you understand why you are
- doing this, and the meat of the chapter then ensures that you really understand
- how the nuts and bolts work.
-
- I like the fact that the book is divided into sections as well as chapters. It
- makes it easier to get a good overview, or to skip the heavier sections if you
- are getting bogged down in something you don't need. Overall, the book is very
- well organized indeed, and very easy to jump around in. The index is quite
- good if not perfect, but it is probably the best of any PM programming book I
- have seen, so guess I'll have to say that this is the mark for potential
- authors to aim for.
-
- Many of the programs were a little mundane, but in a beginners' book that is
- inevitable, so I really can't fault it for that. The overriding impression of
- this book is that of lucid, accurate, and thorough coverage. It isn't as
- humorous as some, but not as dry as others. It is simply competent, as you
- would expect from a master of the trade.
-
- The only things I could fault were the use of Windows graphics instead of PM
- graphics here and there in the figures of the book, and the numerous references
- to OS/2 2.0 instead of OS/2 2.1. This book is updated for OS/2 2.1, but
- sometimes you wouldn't know it. MINMAX3 didn't work for me, but that is
- probably attributable to Warp Beta II which has the occasional glitch in the
- graphics subsystem. Apart from that, only the lack of in-depth treatment of
- control windows and common dialog boxes keep it from being perfect.
-
- Overall, this book is rock-solid, and a good start for anyone who hasn't seen
- or tried GUI programming before. I would rate this a solid A if it wasn't for
- the lack of depth in the above mentioned fields. Therefore it gets an A-.
-
- /dev/EDM2/BookReview - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 5.5. Books Reviewed ΓòÉΓòÉΓòÉ
-
- Books Reviewed
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé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 Γöé Γöélook elsewhere, but if you need an Γöé
- Γöé Γöébeginning Γöé Γöéeasily read, well-explained beginner's Γöé
- Γöé Γöéprogrammers Γöé Γöé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 Γöéadvanced Γöé Γöéuseful information. Includes chapters Γöé
- Γöé0-9639854-1-8. US$20, CAN$25 ΓöéREXX Γöé Γöéon both built-in and some popular Γöé
- Γöé Γöéprogrammers Γöé Γöécommercial libraries. Well-written andΓöé
- Γöé Γöé Γöé Γöécomprehensively indexed. A must for Γöé
- Γöé Γöé Γöé ΓöéREXX programmers. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéApplication Development Using OS/2ΓöéIntermediateΓöéA- ΓöéExcellent coverage of everything REXX, Γöé
- ΓöéREXX, Rudd, Wiley-QED. ISBN Γöéto advanced Γöé Γöéwith the occasional sparse section. It Γöé
- Γöé0-471-60691-X. US$40, CAN$50 ΓöéREXX Γöé Γöéis a decent reference book, and has Γöé
- Γöé Γöéprogrammers Γöé Γöéenough unusual material that it will Γöé
- Γöé Γöé Γöé Γöéprobably find its way into many REXX Γöé
- Γöé Γöé Γöé Γöéprogrammers' libraries. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéOS/2 Presentation Manager ΓöéBeginning PMΓöéA- ΓöéThis book has the most thorough Γöé
- ΓöéProgramming, Petzold, Ziff-Davis ΓöéC Γöé Γöéintroduction to PM basics in any book IΓöé
- ΓöéPress. ISBN 1-56276-123-4. US$30,Γöéprogrammers Γöé Γöéhave read so far. It leaves the field Γöé
- ΓöéCAN$42 Γöé Γöé Γöéwide open for a more thorough advanced Γöé
- Γöé Γöé Γöé ΓöéPM book later. Very well written, veryΓöé
- Γöé Γöé Γöé Γöéthorough, and very understandable. OnlyΓöé
- Γöé Γöé Γöé Γöéa lack of in-depth treatment of controlΓöé
- Γöé Γöé Γöé Γöéwindows and common dialog boxes keep itΓöé
- Γöé Γöé Γöé Γöéfrom being perfect. Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- 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.
-
- 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 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 5.6. Content Index ΓòÉΓòÉΓòÉ
-
- Content Index
-
- This Content Index is designed to let you find the book that covers the topics
- you need to learn about. It will eventually have a lot of categories, with
- each book being rated along each row. This table will be quite large, and will
- continually grow, so please give me your feedback regarding what categories you
- would like to see, and which you don't. It may take me a while to fill it, so
- have a little patience.
-
- NOTE: Books which cover the same material can look similar in this table, but
- be different in real life. The style of a book, for example, can not be seen
- from a quick table, so make sure that you follow up by reading the reviews of
- the books you find here. Finally, be sure that the books you are comparing are
- aimed at the same audiences.
-
- PM BOOKS:
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéBOOK ΓöéMARK ΓöéPM ΓöéKernel ΓöéGPI ΓöéFonts ΓöéDevice ΓöéPrint Γöé
- Γöé Γöé ΓöéIntro ΓöéBasics Γöé Γöé ΓöéDriver Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéRWP ΓöéB+ Γöé4 Γöé2 Γöé4 Γöé4 Γöé0 Γöé3 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPME ΓöéB- Γöé2 Γöé1 Γöé2 Γöé2 Γöé0 Γöé0 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéODD ΓöéA Γöé0 Γöé0 Γöé1 Γöé0 Γöé5 Γöé1 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéGPI ΓöéC+ Γöé0 Γöé0 Γöé5 Γöé2 Γöé0 Γöé3 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéTAO ΓöéB+ Γöé4 Γöé3 Γöé1 Γöé2 Γöé0 Γöé2 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPMP ΓöéA- Γöé5 Γöé1 Γöé3 Γöé4 Γöé0 Γöé2 Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- REXX BOOKS:
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéBOOK ΓöéMARK ΓöéREXX ΓöéWPS ΓöéReferenceΓöé
- Γöé Γöé ΓöéIntro Γöé Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMOR ΓöéB Γöé4 Γöé0 Γöé2 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéRSH ΓöéA Γöé1 Γöé2 Γöé5 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéADO ΓöéA- Γöé3 Γöé0 Γöé4 Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- BOOK LEGEND:
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéReal-World Programming for OS/2 2.1 ΓöéRWP Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéLearning to Program OS/2 2.0 Presentation Manager by Example ΓöéPME Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéWriting OS/2 2.1 Device Drivers in C, 2nd Edition ΓöéODD Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéOS/2 Presentation Manager GPI ΓöéGPI Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéThe Art of OS/2 2.1 C Programming ΓöéTAO Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMastering OS/2 REXX ΓöéMOR Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéREXX Reference Summary Handbook ΓöéRSH Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéApplication Development Using OS/2 REXX ΓöéADO Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéOS/2 Presentation Manager Programming ΓöéPMP Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- RATINGS LEGEND:
-
- ΓöîΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé0ΓöéNo coverage Γöé
- Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- Γöé1ΓöéVery light coverage Γöé
- Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- Γöé2ΓöéIntroductory coverage Γöé
- Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- Γöé3ΓöéGood Coverage Γöé
- Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- Γöé4ΓöéIn-depth coverage Γöé
- Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- Γöé5ΓöéAuthoritative Γöé
- ΓööΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- /dev/EDM2/BookReview - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 5.7. Coming Up ΓòÉΓòÉΓòÉ
-
- Coming Up
-
- Next month I will be looking at Designing OS/2 Applications, Reich. There is a
- new version of this coming out in the new year, but the author requested that I
- review this now, and the new one when it comes out, so that is what I am going
- to try to do. The books I intend to review are (not necessarily in this
- order):
-
- o Designing OS/2 Applications, Reich
- o OS/2 Unleashed, Moskowitz and Kerr
- o The Design of OS/2, 2nd Edititon, Kogan and Deitel
-
- I am considering reviewing the IBM OS/2 Redbooks, since they are readily and
- cheaply available, and look like good reference.
-
- If anyone has a book they want to see reviewed, I will be happy to oblige, as
- long as I can afford it. 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 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 6. Introduction to PM Programming ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 6.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 looked at the ownerdraw concept and how it specifically applies
- to the WC_BUTTON class. This month, we will begin looking at a new window
- class, the listbox (WC_LISTBOX).
-
- Introduction to PM Programming - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 6.2. Purpose and Variations on a Theme ΓòÉΓòÉΓòÉ
-
- Purpose and Variations on a Theme
-
- The purpose of the listbox is to store a list of items; no surprise there.
- Unfortunately, the original design (which had to be adhered to, for backward
- compatibility) only allowed for textual items to be stored. It is possible
- through "black magic" (read as ownerdraw) to display other items, however, but
- there is a lot more work involved, as we will see in the near future.
-
- The styles of the listbox are described below:
-
- LS_EXTENDEDSEL Selection of items follows the CUA '91 specification.
- LS_HORZSCROLL A horizontal scrollbar should be provided, which is managed
- by the listbox.
- LS_MULTIPLESEL One or more items may be selected at any time. See below
- for more information.
- LS_NOADJUSTPOS The listbox should not adjust its height to be a integral
- multiple of the item height.
- LS_OWNERDRAW The listbox should allow the application to draw each item.
-
- The difference between LS_MULTIPLESEL and LS_EXTENDEDSEL is that the former is
- brain-dead and utterly useless, while the latter is only somewhat useless.
- Seriously, try changing the sample in this issue to use the former and use it
- some. You will agree that it is quite cumbersome and that the latter is much
- easier from a usability point-of-view. The reasoning for the "(somewhat)
- useless" labelling will be seen later; I alluded to something similar last
- month with the WC_BUTTON class.
-
- More Bad Design
-
- So far we have...
-
- 1. Text only allowed
-
- 2. (Somewhat) useless selection strategies
-
- What else is there?
-
- IBM and Microsoft originally designed the listbox to hold modest amounts of
- data, but its ease-of-use quickly encouraged programmers to "push it to the
- limit." They quickly found out that the listbox will hold only so much. How
- much exactly depends on the length of each item, but it is generally accepted
- that you cannot - without some hokey-pokey - get more than 32K of items in a
- listbox, and that is only if every item is 1 character in length. The answer
- to why this is true deals with memory allocation within the original 16-bit PM
- subsystem and is beyond the scope of this article (as well as the hokey-pokey
- needed to circumvent it).
-
- Don't Get Me Wrong
-
- In spite of all of these shortcomings, there is no doubt that the listbox gives
- you the most "bang for the buck." It is very easy to use for most purposes and
- it is used quite frequently, so this ease-of-use saves you lots of heartache.
-
- Final Notes
-
- Each item within a listbox can have associated with it a ULONG. Typically, this
- is cast to a pointer to an application-specific structure for application
- housekeeping. These are referred to as item handles.
-
- It is also important to note that all indices are 0-based.
-
- Introduction to PM Programming - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 6.3. The Days of Yesteryear ΓòÉΓòÉΓòÉ
-
- The Days of Yesteryear
-
- Let's go back to the HELLO.C program that was presented in volume 2, issue 3.
-
- Figure 1) HELLO in action
-
- If you'll remember, whenever a name was selected from the listbox, it appeared
- in the entryfield beneath it. We will finish the dangling ends of this
- application in the next issue or two, so keep this handy.
-
- But First
-
- First, let's list the listbox messages that can be sent to the control.
-
- LM_DELETEALL Deletes all of the items within the listbox.
- LM_DELETEITEM Deletes a single item within the listbox.
- LM_INSERTITEM Inserts a signle item within the listbox.
- LM_QUERYITEMCOUNT Returns the number of items within the listbox.
- LM_QUERYITEMHANDLE Returns a ULONG associated with an item within the listbox.
- LM_QUERYITEMTEXT Returns the text of an item within the listbox.
- LM_QUERYITEMTEXTLENGTH Returns the length of the text of an item within the
- listbox.
- LM_QUERYSELECTION Returns the index of the first item selected within the
- listbox after the one specified.
- LM_QUERYTOPINDEX Returns the index of the item shown at the top of the
- listbox.
- LM_SEARCHSTRING Searches for a string in the item text.
- LM_SELECTITEM Sets the selection state of an item within the listbox.
- LM_SETITEMHANDLE Associates a ULONG with an item within the listbox.
- LM_SETITEMHEIGHT Never implemented by IBM, but never removed from the
- Toolkit header files.
- LM_SETITEMTEXT Sets the text of an item within the listbox.
- LM_SETTOPINDEX Specifies the item to be displayed at the top of the
- listbox.
-
- A Closer Look, Please
-
- Let's now take a closer look at the more frequently used messages.
-
- LM_DELETEALL
-
- Purpose
-
- Deletes all of the items within the listbox.
-
- Parameters
-
- This message accepts no parameters.
-
- Returns
-
- SHORT1FROMMR()
-
- TRUE Success
- FALSE Failure
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- LM_DELETEITEM
-
- Purpose
-
- Deletes a single item within the listbox.
-
- Parameters
-
- SHORT1FROMMP(mpParm1) Index of the item to delete.
-
- Returns
-
- SHORT1FROMMR()
-
- Number of items remaining.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- LM_INSERTITEM
-
- Purpose
-
- Inserts a single item within the listbox.
-
- Parameters
-
- SHORT1FROMMP(mpParm1) Index at which to insert the item.
- PVOIDFROMMP(mpParm2) Pointer to the item text.
-
- Notes
-
- The insertion point can also be one of the following values:
-
- LIT_END Insert the item at the end of the listbox.
- LIT_SORTASCENDING Insert the item in ascending sorted order.
- LIT_SORTDESCENDING Insert the item in descending sorted order.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- LM_QUERYITEMCOUNT
-
- Purpose
-
- Returns the number of items within the listbox.
-
- Parameters
-
- This message accepts no parameters.
-
- Returns
-
- SHORT1FROMMR()
-
- Number of items.
-
- Introduction to PM Programming - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 6.4. Cleanliness ΓòÉΓòÉΓòÉ
-
- Cleanliness
-
- If you modify HELLO.C to insert "Tom" 100 times, you'll see that the
- initialization phase of the listbox looks quite ugly. It would be nice if the
- listbox would "pop-up" with everything already in it. The way to do this is to
- disable the update of the listbox before we begin and re-enable it after we
- finish the initialization. This brings us to our next API.
-
- (BOOL)WinEnableWindowUpdate(hwndWnd,bEnable);
-
- hwndWnd is the window to enable or disable. bEnable is the new enable state of
- the window. The function returns a success indicator.
-
- Introduction to PM Programming - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 6.5. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- This month, we looked at our next conquest - the listbox. We saw the various
- styles it has and the design limitations that accompany it. We also began
- looking at the listbox messages, and it is with this that we will continue next
- month.
-
- Introduction to PM Programming - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 7. 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 John Holt
- o Larry Salomon, Jr.
- o Carsten Whimster
- o Network distributors
-
- Contributors - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 7.1. John Holt ΓòÉΓòÉΓòÉ
-
- John Holt
-
- John Holt is a graduate student at Wright State University, and is employed by
- LEXIS/NEXIS in Dayton, Ohio as a software engineer. John develops distributed
- systems in both an MVS and UNIX environment. He can be reached via the
- internet at either johnh@meaddata.com or jholt@cs.wright.edu; or via Compuserve
- at 71324,3400.
-
-
- ΓòÉΓòÉΓòÉ 7.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 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 7.3. Carsten Whimster ΓòÉΓòÉΓòÉ
-
- Carsten Whimster
-
- Carsten is an undergraduate Computer Science student at the University of
- Waterloo. He is currently in third year, and is enjoying it immensely.
-
- Carsten 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.
-
- Carsten is the author of POV-Panel/2, a popular shareware dashboard-like
- front-end for the POV-Ray 2.x compilers, and some commandline utilities.
- POV-Panel/2 can be found on ftp-os2.cdrom.com in pub/os2/32bit/graphics and
- some of the other major OS/2 ftp sites. Carsten is also a TEAM-OS/2 member,
- and has adopted a little store in Waterloo.
-
- You may reach Carsten...
-
- ...via email:
-
- bcrwhims@undergrad.math.uwaterloo.ca - Internet
-
- ...Web homepage (I am just setting it up, so it may or may not be on-line):
-
- http://www.undergrad.math.uwaterloo.ca/~bcrwhims - WWW
-
- ...via snail mail (notice the changed address):
-
- Carsten Whimster
- 318A Spruce Street
- Waterloo, Ontario
- Canada
- N2L 3M7
-
- Contributors - EDM/2 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 7.4. 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 - Dec 1994 - Volume 2, Issue 11
-
-
- ΓòÉΓòÉΓòÉ 8. 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 in the /pub/newsletters/edm2 directory.
-
- 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 - Dec 1994 - Volume 2, Issue 11