Feedback Search Top Backward Forward
EDM/2

Questions and Answers

Written by Larry Salomon, Jr.

 

Introduction

Welcome to the first "Questions and Answers"! Each month, I collect various questions sent to me via e-mail and try to answer each directly; the ones that I feel contribute the most to developers, whether in terms of information or as a nifty trick to tuck into your cap, get published in this column.

Smart Icons

Stefan Gruendal (Stefan_Gruendel@wue.maus.de) writes:

But to my question: How do I build my own "smart icons", i.e. bitmaps on pushbuttons, that optically "move into the screen"? I didn't find any way to achieve this with the Toolkit's Dialog Editor. But as mentioned above, I know there's a way.

Starting with OS/2 2.0, a new button style was added - BS_ICON - which allows you to do what you are trying to accomplish. It works, as far as I know, only for pushbuttons, and the icon or bitmap is taken from the resource file, whose resource id is specified in the pushbutton text.

For example:

In FOO.H:


 #define IDBM_BUTTON 256
 #define IDPB_BUTTON 257

In FOO.RC:


 BITMAP IDBM_BUTTON BUTTON.BMP

In FOO.C:


 sprintf(achText,"#%d",IDBM_BUTTON);

 hwndButton=WinCreateWindow(hwndClient,
                            WC_BUTTON,
                            achText,
                            WS_VISIBLE |
                               BS_PUSHBUTTON |
                               BS_ICON,
                            10,
                            10,
                            32,
                            32,
                            hwndClient,
                            HWND_TOP,
                            IDPB_BUTTON,
                            NULL,
                            NULL);

The bitmap is stretched or compressed to fill the button.

Finding Yourself

Raja Thiagarajan (sthiagar@bronze.ucs.indiana.edu) writes:

Can a PM program tell if there's a previous instance of itself running? In Win3.x (but apparently NOT Win32), there's a hPrevInst handle; is there an OS/2 2.0 equivalent? Basically, I'm thinking in terms of a program that would try to borrow resources from a previous instance if a previous instance is running. (Specifically, if my palette animation program gets started twice, the second instance ought to share palettes with the first instance!)

What you're really asking is two questions:

1. How can I determine if a previous instance of my application is already running? 2. How can I share resources between multiple instances of my application?

To answer your first question, you need to enumerate all of the main windows present on the desktop, and figure out if any of them are yours. This is achieved using the following code:


 HWND queryAppInstance(PCHAR pchClassWanted)
 {
    HENUM heEnum;
    HWND hwndTop;
    HWND hwndClient;
    CHAR achClass[256];

    heEnum=WinBeginEnumWindows(HWND_DESKTOP);

    hwndTop=WinGetNextWindow(heEnum);
    while (hwndTop!=NULLHANDLE) {
       hwndClient=WinWindowFromID(hwndTop,
                                  FID_CLIENT);
       if (hwndClient!=NULLHANDLE) {
          WinQueryClassName(hwndClient,
                            sizeof(achClass),
                            achClass);
          if (strcmp(achClass,
                     pchClassWanted) == 0) {
             WinEndEnumWindows(heEnum);
             return hwndClient;
          } /* endif */
       } /* endif */

       hwndTop=WinGetNextWindow(heEnum);
    } /* endwhile */

    WinEndEnumWindows(heEnum);
    return NULLHANDLE;
 }

To answer your second question, the only way that I know of to share resources is to place them in a DLL. The procedure to do this is as follows:

  • Create a dummy source file with an empty procedure in it.
  • Compile the source file and link as a DLL.
  • Add your resources to the DLL in the same manner as you would to an executable.

Then, when your application starts, you simply call WinLoadLibrary (the preferred way) or DosLoadModule to load the DLL. These functions return a handle to the DLL which must then be used in any function which loads resources (e.g. GpiLoadBitmap, WinLoadPointer, etc.).

Note that this procedure does not require knowing the window handle of any previous instance of your application because OS/2 implements DLLs in a shared fashion (which I suspect is one of the reasons they were created in the first place). All you need to know is the name of the DLL. This technique can also be used to share resources between different applications.

Device Independence

A reader who desires to remain anonymous writes:

Generally: My understanding was that OS/2 would handle printing for me. That is to say that I wouldn't have to create separate printer drivers for every printer under the sun (or any for that matter). Since I am creating an image on the screen that is device independent (well, mostly anyway), is there an easy way to get printer output?

PM achieves a level of device independence by defining a logical output space. This logical output space is then bound to a physical output space, which creates a mapping of logical characteristics to their physical counterparts. The logical and physical output spaces are referred to as the presentation space and the device context (HPS and HDC) and are bound to one another by using either the GpiAssociate function or by specifying GPIA_ASSOC to the GpiCreatePS function.

The easiest way to accomplish what you desire is to organize your drawing code into one or more functions with a single entrypoint that accepts an HPS as a parameter. Then, when you want to draw to the screen, you can call WinGetPS/WinBeginPaint to get an HPS and call the function. When you want hardcopy, you call DevOpenDC to get an HDC and GpiCreatePS to get an HPS and call the function.

Note that to get hardcopy, you need to perform some additional setup to get things to work properly. The two most important things are that you initialize the DEVOPENSTRUC structure properly before calling DevOpenDC and that you send the following escape codes (via DevEscape) at the following times:


 hdcPrn=DevOpenDC(...);
 hpsPrn=GpiCreatePS(...);

 DevEscape(...,DEVESC_STARTDOC,...);

 if (!doDraw(hpsPrn)) {
    DevEscape(...,DEVESC_ABORTDOC,...);
 } /* endif */

 DevEscape(...,DEVESC_ENDDOC,...);

 GpiDestroyPS(hpsPrn);
 DevCloseDC(hdcPrn);

I'm not sure because I can't seem to find my copy anywhere, but I believe that the book by Graham Winn (entitled something to the effect of "Building applications using the OS/2 Presentation Manager") dedicates a chapter to the nuances of printing.