Windows API Tutorial - Part Two, Page 2
Go take a peek at Microsoft Word. Doesn't it look groovy with all those floating toolbars and 3D buttons?
Yet unfortunately Visual Basic doesn't support them instead, we get the completely boring and annoyingly unconfigurable Menu Builder. Perhaps we'll see such wizzy features in a few years time, when everyone has moved onto the latest user interface fad but for now, we're stuck.
Unless of course you spell 'stuck', A-P-I.
Let's do something with Visual Basic you simply couldn't without the Windows API. We're going to add pretty little pictures to our menus, just as the Microsoft products do.
OK, let's get straight down to business:
- Load the API Viewer
To perform this feat, I've learned that I'll need to use a staggering four separate API calls. You can find out this type of information from www.vb-world.net/api/ or perhaps www.vbapi.com/ref/ - or maybe one of the other sources mentioned last week. Books are also an excellent starting point for such info we'll be reviewing a couple later. But for now, let's continue:
- Locate the following functions and add each to the 'Selected Items' box: GetMenu, GetSubMenu, GetMenuItemID, SetMenuItemBitmaps
Great you now have the required API 'declarations' on the clipboard.
- Create a new Standard Exe in Visual Basic
- Add a Command Button to Form1
- Insert a module in the project and paste the clipboard declarations:
Public Declare Function GetMenu Lib "user32" _(ByVal hwnd As Long) As LongPublic Declare Function GetSubMenu Lib "user32" _(ByVal hMenu As Long, ByVal nPos As Long) As LongPublic Declare Function GetMenuItemID Lib "user32" _(ByVal hMenu As Long, ByVal nPos As Long) As LongPublic Declare Function SetMenuItemBitmaps Lib "user32" _(ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As _Long, ByVal hBitmapUnchecked As Long, ByVal hBitmapChecked _As Long) As Long
Each of these functions perform a special task that take us one step further toward our final goal of getting images on our menus. The first three simply help get a 'pointer' to the menu item you want to add a picture to, while the last one does the actual work.
Let's briefly explain each of these four calls now. Don't worry if some areas feel a little grey at the moment they'll become clearer later:
- GetMenu This function accepts just one argument, hwnd, the window handle (eg Form1.hWnd). It then follows that handle to find a collection of menus (eg your form menus). If it doesn't find such menu(s), it returns a zero. If it finds any, it returns a number a 'handle' (pointer) to the menu(s)
- GetSubMenu This function accepts two arguments first off, the menu collection 'handle' (hMenu) obtained from the above. Plus, it requires nPos. Don't forget that each 'menu collection' usually includes a number of menus ie, File, Edit, View and Help to name but a few. That nPos specifies the number of the menu you're referring to start with 0 for the first one (which may be, say, File). This function returns the 'ID' of that particular menu
- GetMenuItemID This accepts the sub menu ID from above, plus nPos, the position of the item within that menu. In other words, if you were playing with the File menu, you'd typically have 'New' right at the top (number 0), with 'Open' just below it (number 1), and so on. This call returns the 'ID' of that particular menu item
- SetMenuItemBitmaps This is the function that does the work. With all the above calls, we've been able to gather an exact API-friendly 'pointer' to the menu item we want to add the picture to. This call takes a few parameters (such as the 'handles' we collected above), attempts to add the picture - and returns a 1 if successful
Seems a little long-winded just to add a picture to your menu, doesn't it? I agree. But it's the only way, unless you're willing to get out your cheque book and invest in some expensive third party solution. And there's a big gaping chasm where my wallet used to be, so that option's out the window.
But hey, once you've written this code you can reuse it as many times as you like. So an investment now could mean a payoff later.
Let's carry on with our project:
- Open and click on your form
- Press CTRL + E to load the Menu Editor
Let's add a basic menu to our application:
- In the Caption box, enter: &File
- Tab down and in the Name box, enter: mnuFile
- Click the Next button
You've just created the very top-level menu, File. The ampersand (&) underlines the character after it, turning that letter into a hot key in the instance, File. You'll see what I mean when we get the menu up-and-running.
- Enter the next Caption: &Open
- Type in the name: mnuFileOpen
- Click the à button
Your Open menu should be just below and slightly indented of the File option. This Open is a sub item of the File menu.
- Click the Next button
- Enter a single dash as the Caption
Later, you'll see this dash automatically turns into a separator!
- Enter a name of mnuSep
- Click Next
- Enter the caption: &Exit
- Type in the name: mnuFileExit
Phew! That's your basic menu sorted.
- Click OK
- Press F5 to run your application
Test your menu. It should look something like this:
- Stop the project when you've finished
Note: I understand this is getting a little dry now, so it's time for a quick joke to keep you giggling: A guy joins a monastery and takes a vow of silence. He's allowed to say only two words every 7 years. After the first 7 years, the elders bring him in and ask him for his 2 words. "Cold floors", he says. They nod and send him away. 7 more years pass and they bring him in for his 2 words. He clears his throat and says, "Bad food" They nod and send him away. 7 more years pass and they bring him in for his 2 words. "I quit", he says. "That's not surprising", the elders say... "You've done nothing but complain since you got here!"
Now let's add a picture to your application. This will be the little image to appear on your menu.
- Draw a small PictureBox control on your Form
- Changes its' Visible property to False
It's now time for you to choose the picture you want to appear on your menu. Ideally, you want something with a size of 13 x 13 pixels anything else may become a little distorted. You can easily create your own mini graphics in MSPaint or Paint Shop Pro.
If you're having problems, check out the mini Da Vinci I created in the download below or have a browse in the less-than-ideal folder - Program Files/Microsoft Visual Studio/Common/Graphics/Bitmaps/TlBr_W95/
- Change the Picture property of the PictureBox control to hold your image
Your screen should look something like this:
Wow, this is getting to be one heckuva long webpage so let's start afresh...