OpenNTF.org - Menu builder class for Win32 a
My Links (Not logged in)
Code Bin Search
 
Hosted by Prominic.NET
Rate This Code
5 - brilliant stuff
4 - very nice
3 - average
2 - needs work
1 - bad
   OpenNTF Code Bin
About This Code
Brief Description:
Menu builder class for Win32 apps 
Rating:
Not Rated Yet 
Contributor:
David B Bohlin 
Category:
Lotusscript 
Type:
Example Code 
Notes Version:
R6.x, R5.x, R7.x 
Last Modified:
27 Feb 2007 
OpenNTF Disclaimer

All of the program code and information presented in the OpenNTF.org Code Bin are provided "as-is", and should be used at your own risk. OpenNTF.org make no express or implied warranty about anything in the Code Bin, and OpenNTF.org will not be responsible or liable for any damage caused by the use or misuse of anything from this site. OpenNTF.org makes no guarantees about anything. Please thoroughly test all of the knowledge and code you find here before you attempt to use them in your production environment.

Code / Description
This is the Menu Builder class that Dallas Gimpel showed me and Andrew Jones posted here and I modified into a class object. This allows the use of cascading menus on a MS Windows PC. To use create an array of Entry objects then create a new MenuBulider passing in the array of Entry objects. The return from the menuBuilder object is the string of the menu select or an empty string if the user clicks off the menu. The number of cascading windows is infinite but probably should be held down to only 3 levels or so.


*************************************MenuBuilder Class Object Code ******************************************
Option Declare
Use "OpenLogFunctions"

Private Const MF_ENABLED = &H0&
Private Const MF_POPUP = &H10&
Private Const MF_STRING = &H0&
Private Const TPM_LEFTALIGN = &H0

Public Type RectangleTYPE
left As Long
top As Long
right As Long
bottom As Long
End Type

Public Type PointApiTYPE
x As Long
y As Long
End Type

Public Type MsgTYPE
hWnd As Long
message As Long
wParam As Long
lParam As Long
time As Long
pt As PointApiTYPE
End Type

'// PUBLIC API declarations
Declare Public Function W32CreatePopupMenu Lib "user32" Alias "CreatePopupMenu" (_
) As Long

Declare Public Function W32DestroyMenu Lib "user32" Alias "DestroyMenu" (_
Byval hMenu As Long _
) As Long

'// PRIVATE API declarations
Declare Private Function W32GetCursorPos Lib "user32" Alias "GetCursorPos" (_
lpPoint As PointApiTYPE _
) As Long

Declare Private Function W32AppendMenu Lib "user32" Alias "AppendMenuA" (_
Byval hMenu As Long, _
Byval wFlags As Long, _
Byval wIDNewItem As Long, _
Byval lpNewItem As Any _
) As Long

Declare Private Function W32TrackPopupMenu Lib "user32" Alias "TrackPopupMenu" (_
Byval hMenu As Long, _
Byval wFlags As Long, _
Byval x As Long, _
Byval y As Long, _
Byval nReserved As Long, _
Byval hWnd As Long, _
lprc As RectangleTYPE _
) As Long

Declare Private Function W32GetMessage Lib "user32" Alias "GetMessageA" (_
lpMsg As MsgTYPE, _
Byval hWnd As Long, _
Byval wMsgFilterMin As Long, _
Byval wMsgFilterMax As Long _
) As Long

Declare Private Function W32GetActiveWindow Lib "user32" Alias "GetActiveWindow" (_
) As Long

'// The "Entry" class represents one menu item in the cascaded menu. The data can be
'// retrieved from anywhere in anyway. The cascaded menu itself consists of a collection
'// of these objects. Each object has to know its level in the menu, whether or not it
'// is a menu itself, and what to display when the menu is rendered.
Public Class Entry
Private strLabel As String
Private intLevel As Integer
Private blnIsMenu As Boolean

Sub New(pintLevel As Integer, pstrLabel As String, pblnIsMenu As Boolean)
Me.intLevel% = pintLevel%
Me.strLabel$ = pstrLabel$
Me.blnIsMenu = pblnIsMenu
End Sub

Public Property Get Level As Integer
Level% = Me.intLevel%
End Property

Public Property Get Label As String
Label$ = Me.strLabel$
End Property

Public Property Get IsMenu As Boolean
IsMenu = Me.blnIsMenu
End Property
End Class

Public Class MenuBuilder
Private m_baseMenuHandle As Long
Private m_menuHandleArray() As Long
Private m_menuList List As String
Private m_cursor As pointApiType
Private m_rectangleData As rectangleType
Private m_msgData As msgType
Private m_index As Long
Private m_currentLevel As Integer

Sub New(pEntryArray() As Entry)
On Error Goto errorHandler
Dim tmpEntryValue As Entry
Dim arraySize As Integer
Dim counter As Integer
Dim currentLevel As Integer
Dim lngID As Long
Dim returnVal As Long

If Not isWin32 Then End

arraySize = Ubound(pEntryArray)
If arraySize <= 0 Then End

Redim m_menuHandleArray(0) As Long
m_baseMenuHandle = W32CreatePopupMenu()
m_menuHandleArray(0) = m_baseMenuHandle
counter = 1
Forall ntry In pEntryArray
currentLevel% = ntry.Level%
If ntry.isMenu Then
Redim Preserve m_menuHandleArray(currentLevel% + 1) As Long
m_menuHandleArray(currentLevel% + 1) = addMenu(m_menuHandleArray(currentLevel%), ntry.Label$)
Else
returnVal = addItem(m_menuHandleArray(currentLevel%),lngID, ntry.Label$)
m_menuList(returnVal) = ntry.Label$
End If
End Forall

exitThis:
Exit Sub

errorHandler:
Messagebox LogError
End
End Sub

Private Function isWin32() As Boolean
Dim session As New NotesSession
isWin32 = True

If Not(Strcompare(session.Platform, "Windows/32",5) = 0 ) Then isWin32 = False

End Function

Private Function addMenu(plngParentMenu As Long, pstrLabel As String) As Long
On Error Goto errorHandler

Dim lngNewMenu As Long

lngNewMenu& = W32CreatePopupMenu()
Call W32AppendMenu(plngParentMenu&, MF_ENABLED Or MF_POPUP, lngNewMenu&, Byval pstrLabel$)
addMenu& = lngNewMenu&

exitThis:
Exit Function
errorHandler:
Messagebox LogError
End
End Function

Private Function addItem(plngMenu As Long, plngID As Long, pstrText As String) As Long
On Error Goto errorHandler

plngID& = plngID& + 1
Call W32AppendMenu(plngMenu&, MF_ENABLED Or MF_STRING, plngID&, Byval pstrText$)
addItem& = plngID&
Exit Function

exitThis:
Exit Function
errorHandler:
Messagebox LogError
End
End Function

Public Function getChoice() As String
Dim returnVal As Long

returnVal = trackMenu()
If returnVal <> 0 Then
getChoice = m_menuList(returnVal)
Else
getChoice = ""
End If
End Function

Private Function trackMenu() As Long
On Error Goto errorHandler

Dim lngRetCode As Long

Call W32GetCursorPos(m_cursor)

lngRetCode& = W32TrackPopupMenu(m_baseMenuHandle, TPM_LEFTALIGN, m_cursor.x, m_cursor.y, 0, W32GetActiveWindow(), m_rectangleData)
lngRetCode& = W32GetMessage(m_msgData, W32GetActiveWindow(), 0, 0)

lngRetCode& = Abs(m_msgData.wParam)
If m_msgData.message = 273 Then
trackMenu& = lngRetCode&
End If
exitThis:
Exit Function

errorHandler:
Messagebox LogError
End
End Function

Sub Delete
If m_baseMenuHandle <> 0 Then
Call W32DestroyMenu(m_baseMenuHandle)
End If
End Sub
End Class

Usage / Example
Dim entryArray(9) As Entry
Dim tempEntry As Entry
Dim tempMenu As MenuBuilder
Dim returnString As String

Set entryArray(0) = New Entry(0, LTR_INFOSHEET,False)
Set entryArray(1) = New Entry(0,LTR_HOWTOUSE,False)
Set entryArray(2) = New Entry(0,LTR_PRESSRELEASE,False)
Set entryArray(3) = New Entry(0,LTR_THANKYOU ,True)
Set entryArray(4) = New Entry(0,LTR_COVERLETTER,False)
Set entryArray(5) = New Entry(0,LTR_EVENTPACKET,False)
Set entryArray(6) = New Entry(1,LTR_THANKYOU_ARTIST ,False)
Set entryArray(7) = New Entry(1,LTR_THANKYOU_STORE ,False)
Set entryArray(8) = New Entry(1,LTR_THANKYOU_DM ,False)
Set entryArray(9) = New Entry(1,LTR_THANKYOU_REP ,False)

Set tempMenu = New MenuBuilder(entryArray)
If Not (tempMenu Is Nothing) Then
returnString = tempMenu.getChoice
End If
Code Attachments
MemuBuilderDemo.nsf (448 Kbytes)
 Comments
Posted by Patrick Williams on 02/26/2007 04:47:53 PMImplementation?
Can you post a db that shows the implementation of this? Thanks
Posted by David B Bohlin on 02/27/2007 01:21:05 PMPosted Demo
I posted a demo database to show how the menubuilder works.
However, take a look at Chris Blatnick of Interface Matters and his use of layers to build a menu for the Notes Client. A much better implementation as it should work in any environment and doesn't require the use of dll calls.
http://interfacematters.com/2006/08/its-got-layerscascading-menus-in-notes.html
 Add your comment!