How do I? - Part 15

From EDM2
Jump to: navigation, search
How Do I? / Part
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19

by Eric Slaats

Hello, hello, and welcome to another episode of "How Do I?" We'll fix our calculator further this month so that it becomes a more complete PM application. Unfortunately I didn't have much time to create OS/2 stuff this month, I'm fighting the local government at the moment. They trying to ruin my neighborhood of beautiful pre-W.W.II houses with a junkie care center. Can you imagine, there's even a large public school in the neighborhood. So I'm talking to the lawyers, and with a lot of people we're building a solid case against the local authorities. Looks like we could win, but it takes a lot of time. This means not too many computer adventures this month. One thing impressed me though. With my blues/rock band we're doing a demo CD which is recorded to a hard disk on a Mac. This technology impressed me with what's possible. It shows what will be in store for the coming years in terms of both film and music. I'm not into this stuff too much (I still use an old fashioned 8-track studio myself), but I'm pretty sure this technology could flourish on OS/2 with its superior multithreading.

What's in store for this month? Since this column is focused on PM, we'll dig into that the most. We'll take a look at how you can use presentation parameters on an application. This will give you the possibility to color your applet and to use different fonts. Besides that, there is a short entry in the list box control, and of course some plain C programming to create a better calculator. Stuff like dividing by zero and output formats are addressed. For those of you that want to dive directly into the code, the changes in the sample (ZIP, 25k) are marked with "/NEW-NEW."

Presentation parameters are frequently used by everyone who uses OS/2. I love these sides of OS/2, and to me it clearly presents the superiority of OS/2 over other operating systems. I guess everyone knows how to use the color, font or scheme palettes. You can simply drag a color or font and drop it on the target you want. If it's a well behaving OS/2 application, it will react to this by changing to that font or color. We all know the standard PM components such as folders, desktop, menu bars, scroll bars etc. will react to such an action. Some of them will even save the changes after a color or font drop (any good PM application should).

In a program we can use Presentation Parameters to change colors and fonts of our applet in a very simple way. In dialogs you can attach them by using the dialog editor. In programs you can use this by invoking one of the specialized API calls. The font and color of the Smalled bubble-help, for instance, are done in just this way. We'll be lazy once more and color the calculator application through Presentation Parameters with the dialog editor. (How convenient that the application is a dialog. <g> I used this technique to color the buttons on the calculator black with white letters on it. The background of the calculator itself is painted red. The entry field and list box are made white, and the font used in the entry fields is set to WarpSans (If you use Warp 3.0, this might not show, but more on PP fonts in a minute).

Most dialog editors have a dialog to attach Presentation Parameters to a control. Adding a PP to a control this way will add statements to the control description in the RC file. For example, the red color of the dialog is done by adding the following statement to the dialog creation line.

PRESPARAMS PP_BACKGROUNDCOLORINDEX , 2L

Setting the font in the entry field to Warp Sans 9 point is done by adding a font PP line to the entry field creation line. This looks like:

PRESPARAMS PP_FONTNAMESIZE "9.WarpSans"

As you can see, the form in which PP's are created is the same for colors and fonts. The parameter, however, is of a very different type. For PP_BACKGROUNDCOLORINDEX it's a short, for PP_FONTNAMESIZE it's a string. Things get more complicated when you realize that there are also PPs that take an RGB color description as a parameter. We'll dive into that some other time when doing PPs with API calls is handled.

OS/2 supports a very large set of PPs. There are separate PPs for active/non-active border colors. PPs to change the way menus look, highlights, inactive parts etc. To be short, PPs will give you an incredible range of possibilities. The strange thing is that this is seldom exploited. Check out the RC file of this month's sample and see how it's done. Run it through your own dialog editor (the sample was done with Borland C 2.00 for OS/2) to see. I use the most simple FOREGROUND and BACKGROUND indexed color PPs here. If you don't like my color setting, simply change it.

What else have we changed this month? As you use the calculator, you may notice that the results of the calculations are being shown in the list box that forms the upper part of the calculator. I guess now is as good as any time to make a small introduction to the list box.

The list box is one of my favorite controls, because you can use them for so many things. Besides that, it can be controlled in a very sophisticated way. (See, for example, what most of the Lotus apps do with list boxes.) I'll describe some simple stuff for the list box by examining what we need for the calculator.

What do we want in a tally-roll like function? It has to show the left and right members in an equation, show the type of operand used, and show a result. To do this we first have to know how to insert a line into a list box. The contents of a list box-line is a character string. This means if we want to insert a value it has to be a character string. When a line is inserted, we've got to tell the list box at what position this has to be done. All the lines in a list box are numbered like the members of an array. The first list box line is numbered 0. The entry can be made by sending the following message to the list box:

LM_INSERTITEM.
        MP1: the item-index
        MP2: pointer to the item text.
        return: the index of the inserted item.

We want to insert a new line on top of what's already there, how can this be done? We should have to count the number of entries already present in the list box, add one to that number and insert the new value at that position. Very straightforward, but lazy as we are, we search for something simpler. Logically it should be possible to simply add something to the top of the stack because this is such a common function. And indeed we can. <g> The creators of the OS/2 messages included the LIT_END value for the item-index. This value always contains the index of the stack plus one.

Simply adding a value this way isn't enough. Say we've inserted about 50 entries this way. The list box will still show the first item. So we've got to make sure the added item is visible in the list box. We can do this by selecting the inserted item. This can be done with the following message:

LM_SELECTITEM
        MP1: the item-index
        MP2: select flag (select or deselect)

What we want is the item to be visible. We don't want it highlighted. The nice thing is that if MP2 is false, the item won't be selected, but it will move to the visible range. At this point the return value for LM_INSERTITEM should make sense. We can use this return value to select the inserted item. Knowing this we can create a function that will put a value in the list box for us. In the sample it looks like this:

void PrintListboxLine (PSZ achLine, HWND hwndDlg)
        {
        short I;
        I = (short) WinSendDlgItemMsg(hwndDlg, LISTBOX1,
                                                        LM_INSERTITEM,
                                                        (MPARAM)LIT_END,
                                                        (MPARAM)achLine);
        WinSendDlgItemMsg(hwndDlg, LISTBOX1,
                                   LM_SELECTITEM,
                                   (MPARAM)I, 0L);
        }

In the sample I call this function every time a value is entered, but also after an '='. Besides that, we like to know which action is in progress, so the operand is also inserted after a ' ', '-', '*' or '/' is pressed. (Check out the exception on the '-' to handle negative numbers).

I used messages here, but OS/2 has a number of macros that will call messages for you. Check out WinInsertLboxItem for example.

As you may have noticed, even a simple calculator can become quite complex. And we aren't completely finished yet! This month I'll address two additions that make our calculator more usable. The first is making sure it can't do a division by zero. If we let this happen, the application would crash, giving an error-trap dialog. The solution I've chosen is simple though not completely correct. It also prohibits adding or subtracting a zero and multiplying by zero. These are valid actions, but they don't make any sense. When should this be forbidden? After pushing an '=' and the flRightMember is zero, or after pushing a action button ('-', ' ', '/', '*') when we're doing a cascading calculation. So on 2 points in the applet the

if (flRightMember != 0)

is placed. (You'll notice in the sample it's marked with "//NEW-NEW".)

Another thing that bothered me a lot in last month's version is the fact that there were always a bunch of numbers after the decimal dot is displayed, even if they were all zero. I've written a small function that will strip trailing zeros as well as the dot if they aren't necessary. For this the PrintOutput function is built. It takes care of some of the stuff formally done in the WM_COMMAND handler. When the value is already converted to a string, the following lines will take care of the stripping:

while (achOutput[strlen(achOutput)-1] == '0')   // Strip zero's
       achOutput[strlen(achOutput)-1] = 0;
if (achOutput[strlen(achOutput)-1] == '.')      // Strip dot
    achOutput[strlen(achOutput)-1] = 0;

The trick in this little piece of code lies in the fact that C closes the string with a zero. So if we place a zero somewhere in a string, this will become the string terminator. Also note that a zero in text form ('0') is different from the numerical zero that is the end of a string marker. Well, try to figure it out, I found these little parsing tricks very handy for a lot of stuff. The Smalled text-tools and Line-wrap functions rely heavily on these kind of functions.

That's it for this month. Next month we'll finish the calculator by putting some more functionality in it. After that, the first OS/2 e-Zine! HOW-DO-I application will be a fact. Wish me luck in my legal battles. See you all next month.