Visual Basic Menu API Routines
Pure VB: Mimic WordPerfect Style Popup Button Menus
     
Posted:   Thurdsay March 26, 1998
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB4-32, Windows 95
OS restrictions:   None
Author:   VBnet - Randy Birch
   
Related:   SetWindowLong: Changing Button Caption Alignment (non-graphical only)
     
 Prerequisites
None.

A long time ago now, WordPerfect for Windows version 5 introduced the novel use of popup menus to display options via a menu when a command button was clicked. The command button never actually depresses; the menu appeared in response to the button's MouseDown event. In VB the easiest way to create the non-depressed button state - and simulate the WordPerfect button look - was by using the SSPanel controls provided in the Sheridan 3D Controls contained in Threed.ocx.

Threed is a pretty outdated control now that can not show XP styles as the old demo's illustration below shows, so the code for this demo page has been revised to use a standard Command button instead. (Threed could still be used, if you prefer).  

WordPerfect used the first style shown- "Checkmark tracking" pretty well exclusively, but did use some of the other styles shown as well.  Each presents the menu in a different manner.

As the first two styles shown draws the menu overtop the button, it is offset in this illustration to show the relative alignment of the menu in relation to its button. The solid red dot indicates the "anchor" point for each of the four styles. The Checkmark Tracking menu will always align the currently selected (checked) item centered overtop the button text causing the menu to reposition up or down on re-showing, depending on the last item selected (the checked item).

The arrows used in the old VB4 demo illustration shown below are tiny bitmaps in an image control that are contained inside the 3D panel used for the original demo. Naturally, displaying image controls overtop a VB button isn't possible so another method would need to be employed, perhaps creating images with text for a graphical-style button. For a button-only appearance (no text) the font could be changed to Marlett with one of the following characters (14pt normal font size shown):
 
3 3
4 4
5 5
6 6
7 7
8 8
9 9
t t
u u
v v
w w

And if you wanted to offset the button caption to one side of the control, there's even a button style tweak to do that! See SetWindowLong: Changing Button Caption Alignment (non-graphical only).

 BAS Module Code
None.

 Form Code
To a new form, add four command buttons (Command1 through Command4) (or four Threed32.ocx panels if that control is preferred) as shown in the 'left column' of buttons in the illustration above. The first button is Command1 and so on down the form.

Create a menu with several choices on it to serve as the popup menu. So the code works as shown, name the main menu mnuOptions. The menu items are members of a menu array with the names mnuOpt(0) through mnuOpt(3). With the menu and command buttons on the form, add the following code:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const SM_CYMENU As Long = 15
Private prevSelection As Long
Private SysMenuHeight As Long

Private Declare Function GetSystemMetrics Lib "user32" _
   (ByVal nIndex As Long) As Long


Sub Form_Load()

  'get the height of a single menu line
  'for use in the wpTrack menu routine
   SysMenuHeight = GetSystemMetrics(SM_CYMENU)
   
   Command1.Height = (SysMenuHeight * Screen.TwipsPerPixelY)
   Command3.Height = (SysMenuHeight * Screen.TwipsPerPixelY)
   Command2.Height = (SysMenuHeight * Screen.TwipsPerPixelY)
   Command4.Height = (SysMenuHeight * Screen.TwipsPerPixelY)
   
  'this tweak ensures the Checkmark Tracking
  'alignment is correct
   SysMenuHeight = (SysMenuHeight * 0.9)
   
End Sub


Private Sub Command1_MouseDown(Button As Integer, _
                                 Shift As Integer, _
                                 X As Single, _
                                 Y As Single)
  'Checkmark tracking
  '  The popup menu displayed completely
  '  covers the activating button when called.
  '  The previously selected item is aligned 
  '  to the centre of the button, with the 
  '  remaining menu items above and below the 
  ' button. This alignment changes as the 
  '  selection changes.
  PopupMenu mnuOptions, _
            0, _
            Command1.Left, _
            Command1.Top - (SysMenuHeight * prevSelection) * Screen.TwipsPerPixelX

End Sub


Private Sub Command2_MouseDown(Button As Integer, _
                                 Shift As Integer, _
                                 X As Single, _
                                 Y As Single)

  'Drop-down, top aligned
  '  Intended for popup menus calling dialogs.
  '  The popup menu displayed completely
  '  covers the activating button when called.
  '  A Drop-down, top aligned button displays the 
  '  popup menu aligned to the top of the button, 
  '  against the button's left margin.
   PopupMenu mnuOptions, 0, Command2.Left, Command2.Top

End Sub


Private Sub Command3_MouseDown(Button As Integer, _
                                  Shift As Integer, _
                                  X As Single, _
                                  Y As Single)
   
  'Drop-down normal
  '  displays the popup menu aligned 
  '  to the bottom of the button, against 
  '  the left margin.
   PopupMenu mnuOptions, _
             0, _
             Command3.Left - 15, _
            (Command3.Top + Command3.Height) - 8

End Sub


Private Sub Command4_MouseDown(Button As Integer, _
                                   Shift As Integer, _
                                   X As Single, _
                                   Y As Single)

  'Flyout style: 
  '  Intended for popups calling dialogs or list selection.
  '  A flyouy menu button displays the popup
  '  menu aligned to the top of the
  '  button, outside the right margin.
   PopupMenu mnuOptions, 0, _
             (Command4.Left + Command4.Width) - 8, _
              Command4.Top - 15

End Sub


Private Sub mnuOpt_Click(Index As Integer)

    mnuOpt(prevSelection).Checked = False
    mnuOpt(Index).Checked = True
    prevSelection = Index

End Sub
 Comments
Run the project and click on a button (or Threed panel if the SSPanel is used.). The popup menu will appear aligned differently for each button.

Depending on whether standard buttons or Threed panels were used, the numbers in each PopupMenu statement may need to be tweaked to assure the menu aligns correctly against the button's edge or top.

With the Track button, the currently checked item will be aligned with the button text. If nothing has yet been selected (checked), the popup will left and top align to the button.


 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter