Home

News

Downloads

Forums

Notes

Readme

Links

Foro en Espaņol


ctl32_balloontip

ctl32_datepicker

ctl32_formstate

ctl32_ftp

ctl32_gripper

ctl32_monthcalendar

ctl32_progressbar

ctl32_scontainer

ctl32_statusbar

ctl32_trackbar


ctl32_contextmenu: work in progress!

Introduction

The purpose of the ctl32_contextmenu class is to provide a nice and easy to create a shortcut menu in VFP. The menus should look like the standard operating system menus. The Windows API is used, so most of the work is done by the operating system itself.

The native VFP shortcut menus have many problems:

  • They look very bad.
  • They behave badly; if you move the mouse around a VFP shortcut menu, it is jerky and "gets stuck".
  • The use of mrow and mcol is very problematic. ROW and COLUMN? are you kidding me? We went GUI last century!
  • I have not been able to use a shortcut menu in a top level form, it always shows in the screen.
  • The menu builder, we all know, sucks.

It is not the intention of this project to have an object oriented menu framework (yet), but to be able to create shortcut menus quickly and easily in code, and maybe even data-drive the creation of shortcut menus.

The second stage will be to provide full menu support for VFP apps. Nothing fancy like Office style menus or anything like that, just menus that look like any other Windows standard menu.

We don't even have standard looking menus in our VFP apps, let's focus on getting that, and maybe later we can think about fancy stuff like Office style menus.

I must confess I dislike very much the non-standard Office menus introduced around Office 2000 or was it 97?, they totally deviate from the operating system standards, and had every developer on earth wasting it's time trying to emulate them, only because Office had them.


Windows and GDI+ and more

After spending the last 2-3 weeks trying to understand GDI+, and stumbling upon one bug after another, I have concluded that GDI+ is just a BIg Ball Of Mud, and that GDIPLUSX is a very well done port of a Big Ball Of Mud, that inherits all of the bugs, design errors and horror stories of gdi+ and the .Net GDI+ classes.

The bugs in the way the HBMMENU_CALLBACK method works in Windows 2000, XP, Vista, also drove me crazy; can we please have something that works the same way in all operating systems versions? I mean: broken in Windows 2000, fixed in XP, broken AGAIN in Vista?

The whole bitmaps in menus implementation in Windows is so sloppy and bug-ridden, I think they just implemented this in a rush so they could get the icons in the start menu items in Windows 95, and latter added some additional capabilities, with no testing at all.

For now, I have decided to stop trying to have bitmaps in menu items, it is not worth it, there is no way I can do it in a way that will satisfy me as being right.

In the process, I have discovered that the way images in general are handled in Windows... what can I say, they could not make it more complicated that what they have right now, everything is so convoluted, unnatural, messy, overly complex, half the things don't work, I canīt believe the way things are in this area. For starters, do we need bmp, dib, cur, ani, ico, jpg, gif, gfa, tif, exif, png, wmf, emf, and one thousand more image file formats? What' s wrong with these people? Do we need DIBs, DDBs, DCs, and one thousand more objects and classes? Do we need 600+ API functions to draw little pictures on the screen?

Spare me from the details! just draw the damn image the way I want, where I want it, don't make me sweat like a pig to have a miserable tiny 16x16 icon drawn in a menu item!

I will just post here some examples of things I found:

This is how Windows XP displays an icon that has 256 colors and an Alpha channel, this is in Windows Explorer. As you can see, the alpha channel information was lost somewhere.

This is how it should look like, quite a difference. And XP was supposed to bring us icons with alpha channel? And it has THIS bug?

The same thing happens in NET, unless you run thru hoops to get a workaround, check this link: http://dotnetrix.co.uk/misc.html

Same thing happens in Office 2007:

http://blogs.msdn.com/andreww/archive/2007/10/10/preserving-the-alpha-channel-when-converting-images.aspx

More GDI+ links, all talk about bugs, frustration, problems, etc

http://groups.google.com.ar/group/microsoft.public.win32.programmer.gdi/msg/fa5de1f2bc9a04d3

http://forums.winstep.net/phpBB2/viewtopic.php?p=4275&sid=e1f5209d169393b87fcaeffc83259ceb

http://groups.google.com.ar/group/comp.os.ms-windows.programmer.win32/...5e

 

Also we have the blue background bug for transparent images, what you see blue in this image should be really white, but guess what? Another "minor" GDI+ bug!

http://groups.google.com.ar/group/microsoft.public.dotnet.framework.windowsforms/...0f

So what started as a humble shortcut menu replacement project degenerated into a gdi+ ordeal of three weeks, and I really lost so much energy that I donīt want to proceed any further with this, really.

And do you think all this problems are fresh bugs? this problems are 4-5 years old at least!


Windows XP menus

In XP menus can be either drawn by the operating system, can be drawn partially by the application, or totally bu the application. Even menus drawn by Windows XP itself have some problems.

The is part of the Right-Click - File - New menu of Windows XP, you can see this menu by right-clicking in the desktop and choosing "New". This menu does not have the standard height of the rest of the system menus, and the highlighted menu item text remains black instead of turning white. This is a Windows XP menu. The same thing happens to the file context menu "Send To"

 

Now lets see a detailed zoom of a control menu, the one you get when clicking in the Window menu (formerly known as the system or control menu) that is, the top right icon of a program.

As can be seen, the menu items with no images ara shorter than the menu items with images, by a full 4 pixels!

One feature of menus is that a program cannot change the font size of its menus. The font menu is the same for all aplications and is configurable by the user. The only thing that we can change in a program is the menu backcolor.

The ability to display images in menu items is a feature that was added later, and is not fully functional.

In all the menus with images, the images do not scale when the user changes the font of the menus:

 


Native VFP menus

Lets have a look at the native VFP shortcut menus. This is how a shortcut menu looks like in Visual FoxPro:

Windows XP

Windows Vista

 

In Windows, menus can be drawn by the operating system, or can be drawn by the program that owns the menus.

In VFP the menus are owner drawn, and they don't look very nice, my view is that they look awful.

The above pictures show a shortcut menu in VFP. What can be said?

Look how the menu icon overlaps the highlight, how we can see what it looks like a gray border around the highlighted menu item icon.

Also notice the thick border after the last menu item in Vista. Not nice.

On the left, a standard Windows context menu, on the right, a VFP context menu. Can you spot the differences?

Notice the border, the shadow, everything looks wrong.

By the way, the menu on the left is a ctl32_menu inside VFP, so it wasn't so hard was it?


Creating a context menu for a textbox, an example.

To display a shortcut menu for a textbox, the code in the textbox RightClick would be something like:

With This.oContextMenu

.MenuAdd(Thisform.HWnd, 10, 0)

.MenuAdd(10, 1001, 1, "&Deshacer")
.MenuAdd(10, 0000, 1, "-")
.MenuAdd(10, 1002, 1, "Co&rtar")
.MenuAdd(10, 1003, 1, "&Copiar")
.MenuAdd(10, 1004, 1, "&Pegar")
.MenuAdd(10, 1005, 1, "&Eliminar")
.MenuAdd(10, 0000, 1, "-")
.MenuAdd(10, 1006, 1, "Seleccionar &todo")


*!* Set menu items state:
If This._CurrentText = This.Text
.MenuSetEnabled(1001, .F.)
Endif

If This.ReadOnly Then
.MenuSetEnabled(1002, .F.)
Endif

If This.SelLength = 0 Then
.MenuSetEnabled(1002, .F.)
.MenuSetEnabled(1003, .F.)
.MenuSetEnabled(1005, .F.)
Endif

If Len(_Cliptext) = 0 Then
.MenuSetEnabled(1004, .F.)
Endif

Endwith

m.lnKey = Val(This.oContext.MenuShow(m.lnX, m.lnY))

Do Case

*!* Undo
Case m.lnKey = 1001
Sys(1500, '_MED_UNDO', '_MEDIT')

*!* Cut
Case m.lnKey = 1002
If This.ReadOnly Then
Sys(1500, '_MED_COPY', '_MEDIT')
Else
Sys(1500, '_MED_CUT', '_MEDIT')
Endif

*!* Copy
Case m.lnKey = 1003
Sys(1500, '_MED_COPY', '_MEDIT')

*!* Paste
Case m.lnKey = 1004
Sys(1500, '_MED_PASTE', '_MEDIT')

*!* Delete
Case m.lnKey = 1005
Sys(1500, '_MED_CLEAR', '_MEDIT')

*!* Select all
Case m.lnKey = 1006
Sys(1500, '_MED_SLCTA', '_MEDIT')

Endcase

The result of this code? Here:

 

 

Not so hard was it? Easy to follow and understand, even with the menu item captions in spanish.

  1. Create the menu and menu items.
  2. Set the desired state of the menu items (Enabled, disabled, check mark, radio mark)
  3. Show the menu modally
  4. Get the user choice and proceed acordingly.

Here we have used numeric identifiers for the menus, the class converts them to string values, and returns us the identifier of the chosen option, or the empy string if no option is clicked.


ctl32_menu in Windows Vista

ctl32_shorcut menus in Windows Vista, with and without themes. I personally prefer the no-themes versions, they look better to me.

The menus are using bitmaps in 13x13, 16x16, 24x24, 32x32, 48x48 and 64x64 sizes. Only one set of 64x64 png files is used, GDI+X does all the resizing on the fly, that is why the 16x16, 32x32 and 64x64 versions look better. If you wanted to the the most flexibility tothe end user with quality, maybe a 64x64 and a 48x48 set of bitmap files could be included in the application.

The 13x13 size stems from the fact that it is the default size of bitmaps in Windows XP menus. Default size for bitmaps in Vista menus is 16x16.


ctl32_menu in Windows XP

 

In Windows XP the default menu size is smaller than in Vista, I guess the reason for bigger menus in Vista is that most people now have bigger monitors.

 

a example of a right-click in form context menu

 

an editbox context menu

 

A grid header context menu

 

A very tall menu, with scroll arrows, XP

A very tall menu, with scroll arrows, Vista

 


Windows XP menus

 

Minimum Item Height 17

Default bitmap height 13

1 pixel margin around bitmap for owner drawn bitmap. if bitmap canvas is 18, menu item height will be 20


Windows Vista menus:

Vista menus, unlike XP menus, are styled. Menu items have a standard height of 22 pixels, menu item bitmaps are 16x16.

Vista owner drawn menus default height is 20, bitmap size is 16x16.

The ctl32_shorcut menus will be the same size themed or owner drawn: 22 pixels high, 16x16 bitmap. To set bitmaps in menu items in Vista there is no need to do owner-drawn menus any more.

 

 

Internet Explorer 7 on Windows Vista, the Favorites menu is owner drawn, so it is not rendered using the visual styles engine, maybe the IE7 folks at MS should read the article at the MS Shell Blog regarding Vista menus.

 

The right-click on Explorer - New menu has been fixed from XP, where the text stayed black in the highlighted menu item.

 

The File - Send to menu has also been fixed from XP:

 

Using Alpha-Blended Menu Bitmaps

Windows Vista provides alpha-blended bitmaps, which enables menu items to be shown without using owner-draw menu items. Windows Vista also provides visual style APIs that can be used to render owner-draw menus. For detailed information about owner-draw menus, see Owner-Draw Menus.

A common reason for using owner-draw menus is to show icons. It seems logical to add an hIcon field to the MENUITEMINFO structure and then add the code that does the drawing using hIcon, but Windows Vista does not support hIcon. Windows Vista was designed to support alpha-blended menu bitmaps to prevent application compatibility issues.

Alpha-blended menu bitmaps allow icons to be displayed and provide more flexibility than simply specifying hIcon. Windows Vista is designed to apply alpha-blend to a menu bitmap that satisfies all the following requirements:

  • The bitmap is a 32bpp DIB section.
  • The DIB section has BI_RGB compression.
  • The bitmap contains pre-multiplied alpha pixels.
  • The bitmap is stored in hbmpChecked, hbmpUnchecked, or hbmpItem fields.

http://msdn2.microsoft.com/en-us/library/bb757020.aspx

 


Understanding the menu system

To better understand how to use this class, lets first present an explanation of how this class considers the menu system of a VFP application.

This class just provides for the creation of shortcut or context menus at the moment, but the idea is to extend it to cover the whole menu system.

Any menu system consists of basically two types of objects:

  • menu containers, that contain menu items.

  • menu items.

There are no more basic types of objects in a menu system. For example the main menu bar of an application is a menu container with menu items, arranged horizontally in the screen.

Each drop down menu is a menu container, that contains menu items. Some menu items can be linked to sub menus, that are just menu containers.

 

In Object oriented menu classes in VFP 6.0, Colin Nicholls defines a menu object model like this:

The menu object model proposed here is a simplified version, where the menu bar is just another menu, and the menu pads are just bars, like this:

But this model still does not fully represent the menu system, since menu containers are not really contained one inside the other, but they are all logically at the same level, only conected by a link stored in some menu items, like this:

The fact that the menu bar is horizontally arranged in the screen, and the dropdown menus are arranged vertically does not prevent us from considering them the same type of objects.

(By now you may have realized that this is just like tables with one to many relationships)

This abstraction model reflects the fact that a menu container can be linked by more that one menu item. Also that a shortcut menu is just a menu system that is not attached to a form.

To follow this model, when creating a menu item that links to a sub menu, the correct procedure would be to create the menu item, the menu container, and then link one to the other, but to simplify things, this class manages two kind of menu items: standard menu items, and menu items with sub menus. There is no need to create the sub menu containers, they get created and linked to the menu item when the menu item is created.

From now on menu containers will be refered to as "menus", thah includes menu bars, drop down menus, pop up menus, sub menus and shortcut/context menus.


Steps to create a shortcut menu

You start by calling deleting any previously defined menus, then the first step is to add the main pop up menu. We have to pass the HWnd of our form, and give the main menu a name:

 

.Clear

.Add(Thisform.HWnd, "popup")

 

You may use numbers as keys, they will be internally converted to strings. Now we have to start adding menu items:

 

.MenuAdd("popup", "UNDO", 1, "&Undo")

.MenuAdd("popup", "", 1, "-")

.MenuAdd("popup", "CUT", 1, "Cu&t")

.MenuAdd("popup", "COPY", 1, "&Copy")

.MenuAdd("popup", "PASTE", 1, "&Paste")

.MenuAdd("popup", "CLEAR", 1, "Cle&ar")

.MenuAdd("popup", "", 1, "-")

.MenuAdd("popup", "SELECT ALL", 1, "Se&lect All")

 


Properties, Events, and Methods

Add(FormHwnd, Key, Type, Height)

Adds a menu

Add(ParentKey, Key, Type, Caption, Picture, Mark, MarkStyle, Disabled, Default,  StatusBarText)

Adds a menu or a menu item

ParentKey

Clear

Removes all menu and menu items

DefaultItemHeight

Specifies the default ItemHeight value for new menu items. Changing this value does not change the ItemHeight of existing menu items.

DefaultPictureSize

Specifies the default ItemPictureSize value for new menu items. Changing this value does not change the ItemPictureSize of existing menu items.

DefaultMenuHeight

Specifies the default menu height value for new menu menus. Changing this value does not change the height of existing menus.

DrawStyle

Specifies if the menu item pictures will be drawn by Windows or by the class itself

Remove

Removes an existing menus or menu items.


MenuPopUp Properties

DefaultItemHeight

Specifies the default height for menu items inside this menu

DefaultPictureSize

Specifies the default picture height and width for menu items iniside this menu

Handle

Specifies the system menu handle

Height

Specifies the maximum height of the menu, default value is 0 (screen height)

Key

Specifies an unique, alphanumeric (character type) expression that represents a key string for the object

ParentHandle

not used

ParentKey

not used


MenuItem Properties

Caption

 

DisabledPictureHandle

 

Enabled

 

Flags

 

Handle

 

ItemHeight

 

Key

 

KeyShortcut

 

MarkGroup

 

MarkStyle

Specifies the style of mark for a menu item.

1 Check mark

2 Bullet mark

MarkValue

 

ParentHandle

 

ParentKey

 

Picture

 

PictureHandle

 

ItemPictureSize

 

StatusBarTextKey

 


Type

Flags

MF_CHECKED 8
MF_GRAYED 1
MF_MENUBARBREAK 32
MF_MENUBREAK 64
MF_POPUP 16
MF_SEPARATOR 2048
MF_STRING 0
MFT_RADIOCHECK 512

Caption

Picture

MarkStyle

MarkGroup

Default


Reference:

Object oriented menu classes in VFP 6.0 by Colin Nicholls

Objectify Your Menus by Doug Hennig

VFPX OOP Menu Project Alpha

Themed menu’s icons, a complete Vista and XP solution

Vista Style Menus, Part 1 - Adding icons to standard menus

Vista Style Menus Part 2 – Custom menu drawing

Simple Menus that Display Icons - Minimalistic Approach

Adding and using 32 bit alphablended images and icons to the imagelist control

Cool Owner Drawn Menus with Bitmaps - Version 3.03

Owner drawn menus in two lines of code

SetMenuItemInfo: Custom Application Menu Colours

http://msdn2.microsoft.com/en-us/library/system.windows.forms.menu.aspx

http://msdn2.microsoft.com/en-us/library/system.windows.forms.menu.menuitemcollection.aspx

http://msdn2.microsoft.com/en-us/library/system.windows.forms.menuitem.aspx

http://msdn2.microsoft.com/en-us/library/system.windows.forms.mainmenu.aspx

http://msdn2.microsoft.com/en-us/library/system.windows.forms.contextmenu.aspx