How do I? - Part 4
by Eric Slaats
Hi, welcome to the next lesson on PM programming. In this column simple Presentation Manager programming problems and philosophies will be discussed. This column is aimed at people who are interested in PM programming or are simply curious what makes PM programs tick. To understand this column a little programming experience (preferably in C) is recommended.
Last month we took a small peek at resources. We found that resources can make life a lot easier. For example, we don't have to program menus, we simply define them and let the PM do the rest. Before we delve further into the possibilities of other resources, we will explore the resource MENU some more.
Menu's are a very important part of your application. They must be treated with some respect and usually require some thinking before they are created. Most of you will have experience with mastodon programs like WordPerfect or Microsoft Word. These programs have enormous menu trees and it's often very hard (if not impossible) to find what you're looking for. The menus of a lot of programs are overfull, illogical, devoid of accelerator hints, have no key shortcuts, etc.
In this months article we will take a look at techniques that will make menus more attractive and easier to use. But before we do that, let's find out something about the CUA guidelines.
CUA stands for Common User Access. CUA is a set of guidelines that are a piece of IBM's SAA (System Application Architecture). These guidelines were introduced in 1987 and have seen a number of changes through the years. New controls are invented constantly and the way they should look is added to the CUA guidelines. Basically, CUA is an attempt to make user interfaces look coherent in such a way that users will find what they have come to expect.
CUA also describes menu appearances. An example of this is that CUA says that a menu that will invoke a dialog should be followed by three dots (...). In the samples handled in this article we will try to follow the CUA guidelines.
Back to menus. What do we have available to make menus? Unfortunately not everything can be handled with resources, but the amount of code needed will be kept to an absolute minimum. Remember, don't do anything the system can do for you. In addition to what's handled in last month's column, we will take a look at the following:
- Mnemonic keys
- Breaks and break separators
- Bitmaps in menus
- Columns in menus (adding accelerator hints)
- No-dismiss (handled next month)
The following topics will also be covered (next month), but they will need a little programming:
- Checked menu items
- Conditional cascades
- Disabling/enabling menus
It's handy to start the sample in the sample4.zip [ZIP, 16k]) when you're reading this. This way, all the discussed styles can be viewed as you are reading about them. If you're also viewing the RC file, some notes may be in place. Now, let's take the above items one at the time.
Mnemonic keys work almost like accelerators; they activate a menu with keystrokes. The difference here is that an accelerator will immediately trigger the attached action. A mnemonic key will only trigger the menu action it is attached to when its menu is visible. Mnemonic keys can be recognized in menus because they are underlined. In most cases it's the first letter of the menu item and that menu item can then be triggered by pressing the underlined key. If two items in a menu have the same mnemonic, the key won't activate a menu option so doubles should be avoided. This effect can be observed in the separators menu where there are two "8" mnemonic keys.
Mnemonics are very easy to create, just place a ~ (tilde) before the letter of the menu item you want to be the mnemonic key. It's a good practice to implement mnemonics for all your menu items.
Note: mnemonics can also be used in dialogs for buttons, etc.
Separators are lines between menu items. OS/2 resources support three different kinds of separators. (As a fourth one the normal BREAK can also be regarded as a separator).
MENUITEM SEPARATOR - a separator is usually used to draw a line between sets of menu items that form a functional cluster. For example, in an edit submenu the items clear, copy, cut and paste are separated from other menu items by a separator line. In the separators submenu these lines can be observed. Such a line can be placed by creating a menu item with the name "separator".
MIS_BUTTONSEPARATOR - a separator that most programs use to give the Help menu item a place on the right side of the menu with a small line in front of it. The Help submenu in sample4.exe is placed this way. CUA says the menus must be done this way, but personally I think it's a matter of taste (Smalled doesn't have this).
MIS_BUTTONSEPARATOR is a menu-item-style component. (That is why it begins with a MIS_ prefix.) The SEPARATOR is a real menu item, although one that can't be selected. MIS_ items can only be applied to existing menu items.
MIS_BREAKSEPARATOR - breaks a submenu before the item to which it is applied. This way more columns (or menu lines) can be created. The BREAKSEPARATOR draws a line between the columns. It's also possible to use MIS_BREAK. With this option the line won't be drawn. In the separators submenu in Sample4, both styles are displayed.
One of the nice things about menus is that they can also contain bitmaps. This makes an easy way to implement the buttonbars we see on many applets today. (The Smalled buttonbar is a nice sample of this. It's a menu with bitmaps and acts as such. If you're interested in how that was done, check EDM/2 3.4, "Building custom controls" and EDM/2 3.8, "Easy Buttonbars".) In a future column I will discuss how to easily build a buttonbar; for now we will look at simply putting a bitmap in a menu.
Bitmaps can also be treated as resources. For this month's sample I created two bitmaps with the standard icon editor and included them in the RC file. To do this the following lines were added:
// Bitmap identifiers BITMAP 1001 "FILEBUT.BMP" BITMAP 1002 "DIRBUT.BMP"
With these lines inserted, the bitmaps can be handled as resources. To place these bitmaps on a menu item the first thing that has to be done is create a menu item with the bitmap style. Two of the menu items in the Bitmaps submenu are created like this. The text-items are added to show that text and bitmaps can be combined. Also you can observe that a bitmapped menu is sized according to the bitmap it contains.
SUBMENU "~Bitmaps", IDM_MENU BEGIN MENUITEM "Text", IDM_ITEM MENUITEM "#1001", IDM_ITEM, MIS_BITMAP MENUITEM "#1002", IDM_ITEM, MIS_BITMAP, MIA_FRAMED MENUITEM "Text", IDM_ITEM END
In the sample you can see that the text for the bitmapped menu items contain a # sign followed by the ID of the bitmap placed on it. The # is a directive for the resource compiler that tells it which bitmap to use.
The second bitmapped item also has an attribute attached to it. This is the MIA_FRAMED attribute. If the bitmap submenu is examined, the effect of this attribute can be observed, it draws a small line around the menu item. This gives a nice visual effect that is especially useful with bitmapped items.
In most applications, accelerator keys are used. It's good practice to mention these keys with the menu items that can trigger the same action. Usually the menu name is displayed on the left and the accelerator key is listed on the right side. The OS/2 resource compiler supports two ways of handling this. In the columns menu these two methods can be observed. In short, it comes down to left-align the right column (the left example) or right-align the right column (the right example).
To left align a piece of text, we add a \t in the declaration. (You may recognize this as the escape sequence for a Tab in the C printf() statement.) To right align a column, add "\a" in the declaration.
SUBMENU "~Columns", IDM_MENU BEGIN MENUITEM "1 \t****", IDM_ITEM MENUITEM "22 \t***", IDM_ITEM MENUITEM "333 \t**", IDM_ITEM MENUITEM "4444 \t*", IDM_ITEM MENUITEM "5 \a****", IDM_ITEM, MIS_BREAKSEPARATOR MENUITEM "66 \a***", IDM_ITEM MENUITEM "777 \a**", IDM_ITEM MENUITEM "8888 \a*", IDM_ITEM END
Menu cascades are a way to elegantly add sub-sub-menus with a visual clue that there is a submenu available. The clue is given by a small arrow on the right side of the menu item. These arrows come in two flavours, a simple bitmap and one that's also a button. If you pop up the Desktop popup menu there are samples of both. The "Select" item has a simple arrow, the "Open" item has a small button. The first one is a normal (or simple) cascade, the one with the button is called a conditional cascade. Each reacts differently when selected: the normal cascade simply displays the submenu that is attached; the conditional cascade will activate the first item in the submenu without showing it. To display the submenu on a conditional cascade menu item, the small button has to be clicked. This month we only deal with the normal cascade. (The conditional cascade needs a little additional programming and will be covered next month.)
What do we have to do to create a cascade menu? Well, nothing. If we create a submenu in a submenu the resource compiler will automatically add the little arrow and so provide us with the visual clue that another submenu exists.
That's all for now. Next month we'll delve further into the possibilities of menus. A little programming will be added and we will see that a lot more can be done with menu resources.