Welcome to the new Friends-of-FPC!

Here you can find all kinds of information about the FreePascal Compiler. We have many tutorials and howtos as well as a selection of tools to help you with your programming. We also have some example codes for you. And if you want to contribute some information/ sources/ tools yourself you can do so.
Also we have finally relaunched the FoFPC forum. It's your chance for some Q&A about everything FreePascal.

Friends-of-FPC

Tutorials: Learn how to code with FreePascal.

Source Codes: A collection of examples, miscellaneous source codes and open source stuff.

Tools and Help Files: Intro- duction of some tools that might help you with FPC.

Community

Forum: Ask or answer questions about the FreePascal Compiler, programming or just babble about coding.

Contribute! Contribute your own Tutorial, Source Codes or Tools and send them to us!

Website

About: Information about Friends-of-FPC.org.

Win32/ FPC - Chapter 11 - by Delax

This chapter is about Windows menus. You know - the menus on top of the window, that you can control with the ALT-key, usually something like "File", "Edit" or "About"/ "Help" or something like that. Those menus ar quite essential. The contain the functions and features of your Windows application. All users will expect some kind of menu to work with the application.

Because these menus are so essential they are quite easy to implement in your application. All you need is to define the content of the menu inside your resource script and tell Windows in your Window Class to use this menu. Of course you also have to code some stuff that has to de done if a menu item was clicked - otherwise it would be pretty pointless.

Let's start out with the definitions inside your resource script. As we learned in the last chapters, the resource script works like this: first the ID of the resource, followed by the type and the content. This time we use "MENU" as the type. Then we have to define the content of the menu. Blocks of code in resource scripts are much like in Pascal. They have to be nested into BEGIN and END (Pascal style) or you may use { .. } (which is used by many other programming languages). So an empty menu would look something like this.

10 MENU BEGIN 

 // .. content of the menu goes here

 END

Now we have to add some items. First you have to define a group of items. This is the top level element and will be shown in the menu. You define this groups of items with "POPUP". Here is an example of a menu class. I'm sure it will seem familiar.

 POPUP "&File" 
  BEGIN
   MENUITEM "&New", 11
   MENUITEM "&Open", 12
   MENUITEM "Close", 13
   MENUITEM "Close All", 14
    MENUITEM SEPARATOR
   MENUITEM "&Save", 20
   MENUITEM "Save As", 21
   MENUITEM "Save All", 22
    MENUITEM SEPARATOR   
   MENUITEM "&Print", 30
   MENUITEM "Print Preview", 31
    MENUITEM SEPARATOR
   MENUITEM "Save and Exit", 41
   MENUITEM "&Exit", 42
  END

This is a normal item list for the "File" element. You have some file operations like "open file" or "close file", something to save, something to print and then items to exit the application. You should have seen this a couple of times while working with different Windows applications.

It all starts with the defintion of the top level element, which is called "File" in this example. This is not a menu item but the name of this group of icons. When you click on it, the group items will appear. Now take a close look. There is an "&" in front of it. This tells Windows that this is the shortcut key for this group. So if the user presses ALT+F it will open this group. It takes the first sign after the "&" as the shortcut. It does not need to be the first charakter, something like 'POPUP "Fil&e"' would work as well. But think about the user and give your groups somewhat logical shortcuts.

Following the group name are the items of the group. Every group has to be in a logical block as well. Individual items are defined with "MENUITEM", followed by the name of the item and the ID of the item. Every item needs to have its own ID as this is the number that Windows sends to your application as "Item-Number-x-was-pressed" message. Then you would react to this message by doing whatever the user has clicked

Items inside a group can also have shortcuts. But these won't be accessible from the application straight away, but only if you opened the group first. So you would have to press "ALT+F" first and then you could use the shortcuts inside that group.

There is also a menu item called "SEPERATOR". It's a simple line to seperate some items in a group from others in the same group. Users may find it helpfull if some blocks of logical connected items are seperated from others.

For our example we will use a far simpler menu. Here it is.

10 MENU // main window menu
 BEGIN 
 POPUP "&File" 
  BEGIN
   MENUITEM "Message 1", 11
   MENUITEM "Message 2", 12
    MENUITEM SEPARATOR
   MENUITEM "&Exit", 19
  END

 POPUP "&About" 
  BEGIN
   MENUITEM "About", 21
  END
 END

As you can see I defined 2 groups. The first group is "File" and contains 3 items. The second one is "About" and it contains just one item. Right now we don't have anything connected with these items. You have to plan in advance what items you need and what they should do in your application. These items should be well planned as they define the work-flow of your application. If they are not clear and intuitive your application is doomed.

Now we will include this new resource script into the example source. Get the new resource script here and compile it as you have learned it in the last chapters. Then let's have a look at our source from last time. Up until now we did not have a menu and used the line " WinClass.lpszMenuName := nil;". Now we have one and we use the ID of the menu to register it: " WinClass.lpszMenuName := 10;". And that is all to bind a menu to a window of an application. Our complete Window Class now looks like this.

  WinClass.cbSize		:= Sizeof(WndClassEx);
  WinClass.Style		:= cs_hRedraw OR cs_vRedraw;
  WinClass.lpfnWndProc		:= WndProc(@WindowProc);
  WinClass.cbClsExtra		:= 0;
  WinClass.cbWndExtra		:= 0;
  WinClass.hInstance		:= system.MainInstance;
  WinClass.hIcon		:= LoadIcon(system.MainInstance, makeintresource(1));
  WinClass.hCursor		:= LoadCursor(0, idc_Arrow);
  WinClass.hbrBackground	:= GetStockObject(LTGRAY_BRUSH);
  WinClass.lpszMenuName		:= 10;
  WinClass.lpszClassName	:= 'WindowClass';
  WinClass.hIconSm		:= LoadIcon(system.MainInstance, makeintresource(1));

If we would compile this, our apllication would have a menu. But nothing else. We haven't told our program what to do if any item was chosen from this menu. As I said earlier, Windows will create a message if an item from the menu was clicked by the user. This message is put into the normal message queue. And this means we can handle it in the WinProc just like any other message from Windows.

Windows has a special message, that is created when something like a menu or a dialog is clicked or changed. This message is "WM_COMMAND". In the case of a menu, WM_COMMAND contains the ID of the item that was clicked as the loword of wParam. I'll just post the new part of the WinProc.

   WM_COMMAND : begin
		  case (LOWORD(wParam)) of

		  11 : begin // message 1
		   MessageBox(0, 'This is message 1.', 'Message', MB_OK);
		  end;

		  12 : begin // message 2
		   MessageBox(0, 'This is message 2.', 'Message', MB_OK);
		  end;

		  19 : begin // exit application
		   active := false;
		  end;

		  21 : begin // about
		   MessageBox(0, 'This is a simple example to show you 
		              how menus work.', 'About', MB_OK);
		  end;

		 end; // case

		end; // wm_command

It's pretty straight forward. If the command is 11 (Message 1) or 12 (Message 2) or 21 (About) I'll pop up a Message Box. If it is 19, I'll set the active flag to false, thus ending the application. And that's it. Of course real applications would do real work here, but this should be enough to give you the idea how it works.

And that's it for now. Get the source code here and if you haven't downloaded it so far here is the resource script. As usual, compile the script first and then compile the source. Have fun.

Delax/ Sundancer Inc.
[delax@sundancerinc.de]

Back to previous page

Useful Links









Link to us