, , , , ,

Join The Works program to have access to the most current content, and to be able to ask questions and get answers from Revelation staff and the Revelation community

Hiding Whole Menus & Sub-Menus (OpenInsight 32-Bit)

At 15 APR 2004 09:01:20AM Matthew Jones wrote:

There's been previous discussion on this topic, but after much searching and testing, I'm still coming up short.

I would like to hide whole sub-menus on a window (based on user privileges). So far, using either:

a) Send_Message( @window, 'MENU_DELETE', menuitem:@fm:0 )

b) Set_Property( menuitem, 'VISIBLE', 0 ) ;* '' also works

will remove most menu items.

The two remaining problems I haven't been able to solve are:

1. Menu separators - these remain, so I am left with a menu sub-tree containing just separators!

2. Top level menus - when a menu sub-tree has no separators, I am able to remove all sub-items, but the top level entry stays.

Can anyone throw light on this?

Thanks.

A previous response referred to source for CS and UI MDI frames as examples of use of DELETE_MENU. I couldn't find this either!

Using OI 7.0.1.


At 15 APR 2004 09:54AM John Bouley wrote:

Just another thought. How about disabling the menu or item instead of deleting it. The user will still see the item but will not be able to choose.

HTH,

John Bouley


At 15 APR 2004 10:06AM Matthew Jones wrote:

These are whole areas of functionality that users may not have access to, based on their privileges.

It's not acceptable to display these disabled, they need to be hidden or removed from view.


At 15 APR 2004 02:50PM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:

Matthew,

I don't believe that the MENU_DELETE and MENU_INSERT messages have ever been documented offically, but here's what we know about them from the source supplied for the CS and UI Workspace MDI's and our own research (well from distant memory anyway ;)

MENU_INSERT

===========

This only appears to work when inserting a separator item into a menu and is used like so:

EQU ITEM_NAME$ TO 1

EQU ITEM_POS$ TO 2

EQU ITEM_TEXT$ TO 3

EQU ITEM_STATE$ TO 4

EQU MF_SEPARATOR$ TO 2048

menuSep ="

menuSep =@Window : ".MENU.VIEW.TOOLPANELS.CONFIGURE"

menuSep =1

menuSep=MF_SEPARATOR$

call send_Message( @Window, "MENU_INSERT", menuSep )

Note the ITEM_POS value. This is the relative position to insert the separator at AFTER the menu item identified by the ITEM_NAME value.

MENU_DELETE

===========

This allows you to delete a menu item relative to a another named item

menuItem="

menuItem =@Window : ".MENU.VIEW.TOOLPANELS.CONFIGURE"

menuItem =1

call send_Message( atWindow, "MENU_DELETE", menuItem )

Deletes the first menu item AFTER the menu item specified in the ITEM_NAME field. So remove your separators first by using a normal item 'above' them, and then remove the normal items afterwards…

Removing a top level menu item is a little more tricky and you'll need to use the Windows API

Take a look at the GetMenu and DeleteMenu API functions - basically you get the handle to the top level window menu via GetMenu() and once you've got the handle you can delete by relative position using DeleteMenu()

eg…

declare function GetMenu, DeleteMenu, DrawMenuBar

equ MF_BYCOMMAND$ to 0x0000

equ MF_BYPOSITION$ to 0x0400

hwnd=get_Property( @window, "HANDLE" )

hMenu=GetMenu( hwnd )

* delete the second item call DeleteMenu( hMenu, 2, MF_BYPOSITION$ ) call DrawMenuBar( hwnd ) You need to prototype the functions in DLL_USER32 as HANDLE STDCALL GetMenu( HANDLE ) LONG STDCALL DeleteMenu( HANDLE, UINT, UINT ) LONG STDCALL DrawMenuBar( HANDLE ) The Sprezzatura Group World leaders in all things RevSoft </QUOTE> —- === At 16 APR 2004 05:42AM Colin Rule wrote: === <QUOTE>Just a thought, how about not deleting menus, but just have the basic framework and buildup the valid options *only* based on the priveledges of the user. I have not tried this myself, too busy at the moment I am very interested in how you tackle this problem, I too want to do the same, and having disabled options is not a good solution. Colin </QUOTE> —- === At 16 APR 2004 06:29AM The Sprezzatura Group wrote: === <QUOTE>Colin, We have written a function in the past to "copy" a menu from template window and "attach" it to another window that doesn't already have one, so it is possible to create them at runtime - the trick is remembering to put the required event information into the window common area as well as making a Utility CREATE call… The Sprezzatura Group World Leaders in all things RevSoft </QUOTE> —- === At 16 APR 2004 08:04AM Matthew Jones wrote: === <QUOTE>Thanks Sprezzatura. I've got the DeleteMenu API call working beautifully now for top level menus, which was my first starting point. I haven't found a "nice" relationship between menu items in ControlList@ ($Insert OIWin_Comm_Init) and menu items returned by the API calls though. ControlList@ is one big array of positions and STRING based id's, whereas the API allocates positions from zero for each menu or sub-menu, and uses LONG id's. So no commonality there as far as I can see. The only way I've found to relate them is to check the menu text of each (better make sure it's unique), and this requires more complex GetMenuItemInfo API calls, although I have managed to get that to work thankfully! My concept was to lay out a complete menu structure in the design of the window, then strip out menus, sub-menus and items that a user is not authorised to see. I thought this would be easier than to plug items back in using code at run-time. So, I've just got this working at the top level, which disables whole modules, if you like, from a user. The next step will be to mask out sub-items and items, which I've played with, but still in progress. I'd be happy to hear other comments and suggestions, especially re identifying the same menu item in ControlList@ and by API, or maybe a simpler method if I'm using a sledge-hammer on a walnut, so to speak! Also happy to share the code once I've proved the various aspects of it. Thanks, Matthew Jones. </QUOTE> —- === At 16 APR 2004 08:35AM The Sprezzatura Group wrote: === <QUOTE>Matthew, You should only need API calls to remove top level menus, and you can use send_Message( MENU_DELETE ) to get rid of any sub menu items… You don't really *have* to remove any menu item info from the window common area - all it's there for is event processing and if you've deleted the menu item it'll never get fired in any case… As for a relationship - I know there's no *nice* way of handling menus - have you looked at the POSITION and POPUP_LIMIT properties of a menu item? Could you use this information when using API calls based on position? The Sprezzatura Group World Leaders in all things RevSoft </QUOTE> —- === At 16 APR 2004 09:58AM Matthew Jones wrote: === <QUOTE>I will use MENU_DELETE for sub-menus & items - I just wanted to handle the top level case first, and I hadn't quite figured out my strategy for the rest. I'm not trying to remove anything from the window common. My thought was to have a user's set of allowable menus, and these would be defined using the unique menu item STRING id's (perhaps) that end up in the window common structure. I will have a user security maintenance window that loads up the full menu definition and allows an administrator to flag menus and items as viewable / not viewable. I've got part of this done, using a hierarchical list box to display the menu - looks really neat, but not finished yet. So the basis of the user privileges will be a list of STRING menu id's from that window common area. In the meantime, until the individual users' templates are available via that maintenance window, I was using the window common variables as proxy data to prove the menu delete process. I had seen POPUP_LIMIT, but not POSITION. Thanks for that. That should make life a lot easier. Matthew Jones. </QUOTE> —- === At 16 APR 2004 11:13AM Richard Hunt wrote: === <QUOTE>Matthew, If I am understanding you correctly, you are planning to rebuild menus based upon login users. If that is so, I have done that. What I have done was to have the login routine create a taskbar. The menu on the taskbar is appropiate for each individual user based upon user level and/or userid. Its not really hard to do. The menu structure is a bit tricky when getting into sub menus. I use a promoted menu event to handle all menu options. That is how I handle my taskbar. I just wanted to be short and brief. Let me know if you want more info. </QUOTE> —- === At 16 APR 2004 12:37PM Matthew Jones wrote: === <QUOTE>Still problems using MENU_DELETE: 1. Can't delete a POPUP in first position of a sub-menu. 2. Can't delete a separator after a POPUP item at the same level. Success though using API DeleteMenu call for sub-menus, items and separators in any position. I now have a routine that receives a list of menu id exclusions, as per menu ids in window common, removes these from the menu tree, then goes back and removes any duplicate separators (or separators that are now in first and/or last position) as a result of surrounding deletions. Seems to work a treat! </QUOTE> —- === At 16 APR 2004 01:04PM Matthew Jones wrote: === <QUOTE>Richard, My idea is to have a standard MDI window with a full set of all menu options built at design time. Each user or user security group has a list of menu exclusions. When the window is loaded the exclusions are removed. This way the form and menu design, and event processing are done via standard means. It also makes development changes very simple as just the one form and one standard menu structure are maintained. For the administrator using the software, they just have a simple menu layout to enable or disable items as required for each user or group. I like this because it gives me one simple method to maintain, and it gives my customers the ability, also with a simple method, to easily customise access to software options for their users as they need. So, it seems to work beautifully anyway. I just need to finish the administrator maintenance function that creates the exclusion lists and it'll be ready to go. </QUOTE> View this thread on the Works forum...