Easy Buttonbars: Difference between revisions
Created page with "Written by Eric Slaats ==Introduction== When I started programming PM applications I was really amazed that simple, common things that most application feature like buttonb..." |
No edit summary |
||
Line 1: | Line 1: | ||
Written by [[Eric Slaats]] | ''Written by [[Eric Slaats]]'' | ||
==Introduction== | ==Introduction== | ||
When I started programming PM applications I was really amazed that simple, common things that most application feature like buttonbars, multi windowing (tile, cascade etc.) weren't standard features. On my first attempt to build an application, I wanted to include a buttonbar so I started looking for an API call that would place all the buttons for me in the right place. There isn't such a call! The lack of this call made me construct a method like Marc and I described in "[[Building an Editor - Part 1|Building Custom Controls]]" (see EDM/2 3-4). The method described in that article is complete and does everything it should do. However, I wasn't satisfied with the amount of code it took when writing another (very small) application. So I started to experiment with the menu styles and found a very simple way to implement a buttonbar. | |||
When I started programming PM applications I was really amazed that simple, common things that most application feature like buttonbars, multi windowing (tile, cascade etc.) weren't standard features. On my first attempt to build an application, I wanted to include a buttonbar so I started looking for an API call that would place all the buttons for me in the right place. There isn't such a call! The lack of this call made me construct a method like Marc and I described in "Building Custom Controls" | |||
In this (short) article I'll describe this very simple approach to build a buttonbar. It functions very well, but it also has some drawbacks (see the section Concluding Notes). If you're willing to accept this, you'll be rewarded with a toolbar which is very very easy to implement. | In this (short) article I'll describe this very simple approach to build a buttonbar. It functions very well, but it also has some drawbacks (see the section Concluding Notes). If you're willing to accept this, you'll be rewarded with a toolbar which is very very easy to implement. | ||
==Bitmap Buttons In A Menu== | ==Bitmap Buttons In A Menu== | ||
In the introduction I stated that there isn't a API call to build a buttonbar. In fact this isn't true. We can build a menu filled completely with buttons containing a bitmap. So, in fact, OS/2 has a method to build a buttonbar! (This approach is already been handled in "Building Custom Controls" in EDM/2 3-4.) | In the introduction I stated that there isn't a API call to build a buttonbar. In fact this isn't true. We can build a menu filled completely with buttons containing a bitmap. So, in fact, OS/2 has a method to build a buttonbar! (This approach is already been handled in "Building Custom Controls" in EDM/2 3-4.) | ||
To use bitmaps in a menu, the bitmaps should be known in the .RC file. To accomplish this we need to do two things. First we need to create identifiers for all the the bitmaps we want to use. These are usually kept in the header file. | To use bitmaps in a menu, the bitmaps should be known in the .RC file. To accomplish this we need to do two things. First we need to create identifiers for all the the bitmaps we want to use. These are usually kept in the header file. | ||
<pre> | |||
// Bitmap identifiers | // Bitmap identifiers | ||
#define ONE 101 | #define ONE 101 | ||
Line 20: | Line 17: | ||
#define FOUR 104 | #define FOUR 104 | ||
#define FIVE 105 | #define FIVE 105 | ||
</pre> | |||
''Figure 1) Bitmap identifiers'' | |||
These declarations are used in the RC file to associate the bitmaps with an identifier. | These declarations are used in the RC file to associate the bitmaps with an identifier. | ||
<pre> | |||
// Bitmap declaration | // Bitmap declaration | ||
BITMAP ONE "ONE.BMP" | BITMAP ONE "ONE.BMP" | ||
Line 33: | Line 28: | ||
BITMAP FOUR "FOUR.BMP" | BITMAP FOUR "FOUR.BMP" | ||
BITMAP FIVE "FIVE.BMP" | BITMAP FIVE "FIVE.BMP" | ||
</pre> | |||
''Figure 2) Bitmap filename declaration'' | |||
The next step in creating a menu with bitmaps is building the actual menu. The following lines in the .RC file describe the buttonbar menu. | The next step in creating a menu with bitmaps is building the actual menu. The following lines in the .RC file describe the buttonbar menu. | ||
<pre> | |||
// Menu declaration | // Menu declaration | ||
MENU TOOLMENU | MENU TOOLMENU | ||
Line 49: | Line 42: | ||
MENUITEM "", MIS_SEPARATOR | MENUITEM "", MIS_SEPARATOR | ||
MENUITEM "#105", IDM_FIVE, MIS_BITMAP END | MENUITEM "#105", IDM_FIVE, MIS_BITMAP END | ||
</pre> | |||
''Figure 3) Menu template'' | |||
The menustyle for each of the buttons is MIS_BITMAP. This means the menuitem will display as a bitmap and the RC compiler expects the identifiers of the bitmaps in the textarea of the menuitems. We'll put the identifier of the bitmap preceded by a `#' in the text area. | The menustyle for each of the buttons is MIS_BITMAP. This means the menuitem will display as a bitmap and the RC compiler expects the identifiers of the bitmaps in the textarea of the menuitems. We'll put the identifier of the bitmap preceded by a `#' in the text area. | ||
Line 58: | Line 50: | ||
If a window is built using the menu described above, we'll get a window which will look like this: | If a window is built using the menu described above, we'll get a window which will look like this: | ||
[[Image:butt1.gif|thumb|Figure 4) Window with a simple buttonbar]] | |||
In this example button 32X32 bitmaps are used. These bitmaps are shaped as a button. Of course any bitmap can be used. The bitmaps used in this example can be found in the toolbar2.zip file. [Editor's note - Eric forgot to send this file with the article. It will be placed on the EDM/2 ftp site as soon as possible.] | In this example button 32X32 bitmaps are used. These bitmaps are shaped as a button. Of course any bitmap can be used. The bitmaps used in this example can be found in the toolbar2.zip file. [Editor's note - Eric forgot to send this file with the article. It will be placed on the EDM/2 ftp site as soon as possible.] | ||
==Adding 'Normal' Menu Items== | ==Adding 'Normal' Menu Items== | ||
Well I promised a simple buttonbar. The 'trick' is indeed very simple. We add the normal menuitems to the menu defined in the previous section. The thing to do is to give the 'normal' menu items the same identifier as the corresponding button. (It isn't forbidden to have more than one item with the same identifier in one menu!) This way we're sure the button and the menuitem trigger the same case item in the window procedure. | Well I promised a simple buttonbar. The 'trick' is indeed very simple. We add the normal menuitems to the menu defined in the previous section. The thing to do is to give the 'normal' menu items the same identifier as the corresponding button. (It isn't forbidden to have more than one item with the same identifier in one menu!) This way we're sure the button and the menuitem trigger the same case item in the window procedure. | ||
If we leave the menu like this, the buttons and the menuitems are displayed in one row (given a large enough window). If we want a buttonbar, we want it to be displayed underneath the normal menu items. This effect can be accomplished to ad the MIS_BREAK stye to the first menuitem that has to be displayed on the second row. The menu code in the RC file should look something like this: | If we leave the menu like this, the buttons and the menuitems are displayed in one row (given a large enough window). If we want a buttonbar, we want it to be displayed underneath the normal menu items. This effect can be accomplished to ad the MIS_BREAK stye to the first menuitem that has to be displayed on the second row. The menu code in the RC file should look something like this: | ||
<pre> | |||
// Menu declaration | // Menu declaration | ||
MENU TOOLMENU | MENU TOOLMENU | ||
Line 84: | Line 73: | ||
MENUITEM "#105", IDM_FIVE, MIS_BITMAP | MENUITEM "#105", IDM_FIVE, MIS_BITMAP | ||
END | END | ||
</pre> | |||
''Figure 5) New menu template'' | |||
The MIS_BREAK style is normally used to build a submenu with two or more columns. Using it like this we create a menu with two rows, thus separating the menu items from the button items. Used in a window this should look something like this: | The MIS_BREAK style is normally used to build a submenu with two or more columns. Using it like this we create a menu with two rows, thus separating the menu items from the button items. Used in a window this should look something like this: | ||
[[Image:butt2.gif|thumb|Figure 6) New buttonbar appearance]] | |||
A complete working example can be found in the toolbar2.zip file. | A complete working example can be found in the toolbar2.zip file. | ||
Line 98: | Line 84: | ||
==Concluding Notes== | ==Concluding Notes== | ||
That was simple enough, but what are the drawbacks? | That was simple enough, but what are the drawbacks? | ||
* There isn't a line drawn between the buttonbar and the menubar. Of course this is a cosmetic effect, but I think it should be there. MIS_BREAKSEPARATOR should work, but it doesn't. I haven't fixed this yet, but it should be possible with an owner drawn menuitem (MIS_OWNERDRAWN). | * There isn't a line drawn between the buttonbar and the menubar. Of course this is a cosmetic effect, but I think it should be there. MIS_BREAKSEPARATOR should work, but it doesn't. I haven't fixed this yet, but it should be possible with an owner drawn menuitem (MIS_OWNERDRAWN). | ||
* This is just one menu. That means it can't be split (buttons at the bottom or side of the frame window, normal menu on top). | * This is just one menu. That means it can't be split (buttons at the bottom or side of the frame window, normal menu on top). | ||
Line 106: | Line 90: | ||
* Adding two toolbars, one on top, one at the bottom or side of the window is impossible | * Adding two toolbars, one on top, one at the bottom or side of the window is impossible | ||
Of course, this method hasn't the flexibility of a toolbar as it was described in | Of course, this method hasn't the flexibility of a toolbar as it was described in "Building Custom Controls", let alone the flexibility of a (great) package like UCMENU (see OS/2 Developer in the January/February 1995 issue). But if you can live with these drawbacks there are a number of pro's. | ||
* It's very simple | * It's very simple | ||
Line 112: | Line 96: | ||
* No subclassing required | * No subclassing required | ||
A working example of a buttonbar created with this method is found in the file toolbar2.zip. This example is created and compiled with Borland C++ 2.0. | A working example of a buttonbar created with this method is found in the file [http://www.edm2.com/zips/edm0309s.zip toolbar2.zip]. This example is created and compiled with Borland C++ 2.0. | ||
Feel free to use the code any way you like and send me your comments. | Feel free to use the code any way you like and send me your comments. | ||
[[Category:PM Articles]] | [[Category:PM Articles]] |
Revision as of 18:22, 8 December 2016
Written by Eric Slaats
Introduction
When I started programming PM applications I was really amazed that simple, common things that most application feature like buttonbars, multi windowing (tile, cascade etc.) weren't standard features. On my first attempt to build an application, I wanted to include a buttonbar so I started looking for an API call that would place all the buttons for me in the right place. There isn't such a call! The lack of this call made me construct a method like Marc and I described in "Building Custom Controls" (see EDM/2 3-4). The method described in that article is complete and does everything it should do. However, I wasn't satisfied with the amount of code it took when writing another (very small) application. So I started to experiment with the menu styles and found a very simple way to implement a buttonbar.
In this (short) article I'll describe this very simple approach to build a buttonbar. It functions very well, but it also has some drawbacks (see the section Concluding Notes). If you're willing to accept this, you'll be rewarded with a toolbar which is very very easy to implement.
Bitmap Buttons In A Menu
In the introduction I stated that there isn't a API call to build a buttonbar. In fact this isn't true. We can build a menu filled completely with buttons containing a bitmap. So, in fact, OS/2 has a method to build a buttonbar! (This approach is already been handled in "Building Custom Controls" in EDM/2 3-4.)
To use bitmaps in a menu, the bitmaps should be known in the .RC file. To accomplish this we need to do two things. First we need to create identifiers for all the the bitmaps we want to use. These are usually kept in the header file.
// Bitmap identifiers #define ONE 101 #define TWO 102 #define THREE 103 #define FOUR 104 #define FIVE 105
Figure 1) Bitmap identifiers
These declarations are used in the RC file to associate the bitmaps with an identifier.
// Bitmap declaration BITMAP ONE "ONE.BMP" BITMAP TWO "TWO.BMP" BITMAP THREE "THREE.BMP" BITMAP FOUR "FOUR.BMP" BITMAP FIVE "FIVE.BMP"
Figure 2) Bitmap filename declaration
The next step in creating a menu with bitmaps is building the actual menu. The following lines in the .RC file describe the buttonbar menu.
// Menu declaration MENU TOOLMENU BEGIN MENUITEM "#101", IDM_ONE, MIS_BITMAP MENUITEM "#102", IDM_TWO, MIS_BITMAP MENUITEM "#103", IDM_THREE, MIS_BITMAP MENUITEM "#104", IDM_FOUR, MIS_BITMAP MENUITEM "", MIS_SEPARATOR MENUITEM "#105", IDM_FIVE, MIS_BITMAP END
Figure 3) Menu template
The menustyle for each of the buttons is MIS_BITMAP. This means the menuitem will display as a bitmap and the RC compiler expects the identifiers of the bitmaps in the textarea of the menuitems. We'll put the identifier of the bitmap preceded by a `#' in the text area.
Besides the declaration of the menuitems a MIS_SEPARATOR is included. This line in the RC file will put a blank between the buttons FOUR and FIVE. This way we have a method to separate groups of buttons.
If a window is built using the menu described above, we'll get a window which will look like this:

In this example button 32X32 bitmaps are used. These bitmaps are shaped as a button. Of course any bitmap can be used. The bitmaps used in this example can be found in the toolbar2.zip file. [Editor's note - Eric forgot to send this file with the article. It will be placed on the EDM/2 ftp site as soon as possible.]
Adding 'Normal' Menu Items
Well I promised a simple buttonbar. The 'trick' is indeed very simple. We add the normal menuitems to the menu defined in the previous section. The thing to do is to give the 'normal' menu items the same identifier as the corresponding button. (It isn't forbidden to have more than one item with the same identifier in one menu!) This way we're sure the button and the menuitem trigger the same case item in the window procedure.
If we leave the menu like this, the buttons and the menuitems are displayed in one row (given a large enough window). If we want a buttonbar, we want it to be displayed underneath the normal menu items. This effect can be accomplished to ad the MIS_BREAK stye to the first menuitem that has to be displayed on the second row. The menu code in the RC file should look something like this:
// Menu declaration MENU TOOLMENU BEGIN MENUITEM "~One", IDM_ONE MENUITEM "~Two", IDM_TWO MENUITEM "Th~ree", IDM_THREE MENUITEM "~Four", IDM_FOUR MENUITEM "F~ive", IDM_FIVE MENUITEM "#101", IDM_ONE, MIS_BITMAP | MIS_BREAK MENUITEM "#102", IDM_TWO, MIS_BITMAP MENUITEM "#103", IDM_THREE, MIS_BITMAP MENUITEM "#104", IDM_FOUR, MIS_BITMAP MENUITEM "", MIS_SEPARATOR MENUITEM "#105", IDM_FIVE, MIS_BITMAP END
Figure 5) New menu template
The MIS_BREAK style is normally used to build a submenu with two or more columns. Using it like this we create a menu with two rows, thus separating the menu items from the button items. Used in a window this should look something like this:

A complete working example can be found in the toolbar2.zip file.
Note: The menu control also has a style called MIS_BREAKSEPARATOR. Using this style, the rows or columns separated by this style should be separated by a line. I found that this worked perfectly with columns, but it didn't work with rows! Maybe this is a bug, maybe my RC compiler is buggy? Who knows?
Concluding Notes
That was simple enough, but what are the drawbacks?
- There isn't a line drawn between the buttonbar and the menubar. Of course this is a cosmetic effect, but I think it should be there. MIS_BREAKSEPARATOR should work, but it doesn't. I haven't fixed this yet, but it should be possible with an owner drawn menuitem (MIS_OWNERDRAWN).
- This is just one menu. That means it can't be split (buttons at the bottom or side of the frame window, normal menu on top).
- This also means the buttonbar and the normal menu can't be given different colors.
- Adding two toolbars, one on top, one at the bottom or side of the window is impossible
Of course, this method hasn't the flexibility of a toolbar as it was described in "Building Custom Controls", let alone the flexibility of a (great) package like UCMENU (see OS/2 Developer in the January/February 1995 issue). But if you can live with these drawbacks there are a number of pro's.
- It's very simple
- No extra programming needed, everything can be done with a resource editor.
- No subclassing required
A working example of a buttonbar created with this method is found in the file toolbar2.zip. This example is created and compiled with Borland C++ 2.0.
Feel free to use the code any way you like and send me your comments.