Page 1 of 2

Button Menu Sample

Posted: Thu Jun 25, 2015 9:05 pm
by rdonnay
Here is a sample program that uses DCPUSHBUTTONXP buttons as the menu bar with DCSUBMENUs as the drop-down menus.

I think this is a better look than the standard DCMENUBAR.

Compile and run the below sample.

Code: Select all

#INCLUDE "dcdialog.CH"
#INCLUDE "appevent.CH"

#define MENU_BAR_BGCOLOR       GRA_CLR_BACKGROUND
#define MENU_BAR_FGCOLOR       GRA_CLR_BLACK
#define MENU_SUB_BGCOLOR       GRA_CLR_WHITE
#define MENU_SUB_FGCOLOR       GRA_CLR_BLACK
#define MENU_SUB_BARCOLORFG    GRA_CLR_WHITE
#define MENU_SUB_BARCOLORBG    GRA_CLR_PALEGRAY
#define MENU_SUB_OUTLINECOLOR  GRA_CLR_BLACK
#define MENU_SUB_VERTBARFONT   '12.Arial Bold'
#define MENU_SUB_CHECKFONT     '10.Marlett'
#define MENU_SUB_CHECKCHAR     'b'
#define MENU_BAR_BARFONT       '10.Arial'
#define MENU_SUB_ITEMFONT      '10.Arial'

#translate BUTTONMENU <m> => ;
  EVAL {|o|o:lbDown := {|a,b,o|oButton := o, ;
                               <m>:endMenu := {|a,b,o|Eval(oButton:killInputFocus,a,b,oButton)}, ;
                               <m>:PopUp( o:setParent(), o:currentPos(), 2, ;
                        XBPMENU_PU_DEFAULT + XBPMENU_PU_MOUSE_RBDOWN )}, ;
           o:keyboard := {|a,b,o|IIF(a==xbeK_ENTER,Eval(o:lbDown,a,b,o),nil)}, ;
           o:setInputFocus := {|a,b,o|PostAppEvent(xbeM_Enter,,,o)}, ;
           o:killInputFocus := {|a,b,o|PostAppEvent(xbeM_Leave,,,o)}}

FUNCTION Main()

LOCAL GetList[0], oStatTop, oMenuBar, oFileMenu, oEditMenu, oEditMenuSub, ;
      oConfig := DC_XbpPushButtonXPConfig():new(), ;
      aParams, cButtonFont := '12.Arial Bold', bEval, oButton

aParams := { MENU_SUB_BGCOLOR, ;
             MENU_SUB_BARCOLORFG, ;
             MENU_SUB_BARCOLORBG, ;
             MENU_SUB_OUTLINECOLOR, ;
             MENU_SUB_VERTBARFONT, ;
             .F., ;
             MENU_SUB_CHECKFONT, ;
             MENU_SUB_CHECKCHAR, ;
             MENU_BAR_FGCOLOR, ;
             MENU_BAR_BGCOLOR, ;
             MENU_SUB_FGCOLOR, ;
             MENU_BAR_BARFONT, ;
             MENU_SUB_ITEMFONT }

DC_XbpMenuConfig( aParams )

oConfig:radius := 10
oConfig:bgColor := GRA_CLR_PALEGRAY

DCSTATUSBAR oStatTop HEIGHT 22 ALIGN DCGUI_ALIGN_TOP

@ 0,0 DCTOOLBAR oMenuBar SIZE 1000,22 PIXEL PARENT oStatTop BUTTONSIZE 80,20 ;
      COLOR nil, GRA_CLR_PALEGRAY FONT '12.Arial Bold'

DCHOTKEY xbeK_RIGHT ACTION {||PostAppEvent(xbeP_Keyboard,xbeK_TAB,,oMenuBar)}
DCHOTKEY xbeK_LEFT ACTION {||PostAppEvent(xbeP_Keyboard,xbeK_SH_TAB,,oMenuBar)}

DCADDBUTTONXP CAPTION '&File' PARENT oMenuBar CONFIG oConfig ;
   BUTTONMENU oFileMenu TABSTOP

DCSUBMENU oFileMenu PROMPT 'File' OWNERDRAW
  DCMENUITEM 'Open File' PARENT oFileMenu ACTION {||MsgBox('Open File')}
  DCMENUITEM 'Close File' PARENT oFileMenu ACTION {||MsgBox('Close File')}

DCADDBUTTONXP CAPTION '&Edit' PARENT oMenuBar CONFIG oConfig ;
   BUTTONMENU oEditMenu TABSTOP

DCSUBMENU oEditMenu PROMPT 'Edit' OWNERDRAW
  DCMENUITEM 'Edit File' PARENT oEditMenu ACTION {||MsgBox('Edit File')}
  DCMENUITEM 'Save File' PARENT oEditMenu ACTION {||MsgBox('Save File')}
  DCSUBMENU oEditMenuSub PROMPT 'Sub File' PARENT oEditMenu
    DCMENUITEM 'Edit File Sub 1' PARENT oEditMenuSub ACTION {||MsgBox('EFS1')}
    DCMENUITEM 'Edit File Sub 2' PARENT oEditMenuSub ACTION {||MsgBox('EFS2')}
    DCMENUITEM 'Edit File Sub 3' PARENT oEditMenuSub ACTION {||MsgBox('EFS3')}

DCREAD GUI TITLE 'Menu Test'

RETURN nil

PROC appsys ; RETURN

Re: Button Menu Sample

Posted: Mon Jun 29, 2015 3:20 am
by sdenjupol148
Roger,

Finally!
I've been waiting for something like this for a while now.
As you know I use DCMENUBAR on my main page with a toolbar to simulate a 'windows' look and feel.
There are no DCPUSHBUTTONS on that screen.

However, I have DCPUSHBUTTONS on every other window and I have been trying to move away from that UI for a while.
With this code, I can add menubars to all my child and non-modal windows and remove all the bottom dwelling pushbuttons.
This will bring the UI more in-line with today's menu navigated software.

Awesome; Thanks! :clap:

Bobby

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 12:33 am
by skiman
Hi,

A little modification for the look:

Code: Select all

oConfig:radius := 5
oConfig:bgColor := GRA_CLR_PALEGRAY

DCSTATUSBAR oStatTop HEIGHT 22 ALIGN DCGUI_ALIGN_TOP

@ 0,0 DCTOOLBAR oMenuBar SIZE 1000,22 PIXEL PARENT oStatTop BUTTONSIZE 80,24 ;
      COLOR nil, GRA_CLR_PALEGRAY FONT '12.Arial Bold'
This way the buttons are looking as a tab.

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 2:58 am
by reganc
I can see the general idea here and I like it, but there are some behavioral differences that I can't get past.

1. The dcaddbuttonxp buttons do not stay highlighted (to look as if they have been selected) when the menu appears.
2. Accelkeys cannot be assigned/used as the button does not have an Action codeblock.
3. You cannot move left and right to the previous / next menu item if the dropdown menu is displayed.

I'm sure that these are all fixable, but I cannot see how. I guess my knowledge is a bit lacking here.

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 4:55 am
by skiman
The navigation of a menu is much better. Maybe it would be easier to modify the look of the top-menubar. Probably with ownerdrawing?

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 9:32 am
by rdonnay
The navigation of a menu is much better. Maybe it would be easier to modify the look of the top-menubar. Probably with ownerdrawing?
This sample was created to solve a technical problem, not necessarily a visual problem.

I agree that maybe adding some new features to the eXpress++ system could improve visual effects, but for now I am not ready to do this because it hasn't been requested by anyone.

Compile the below code and run the program.
Click on Window - Child Window 1 (notice there is no menu). This is a technical problem related to Windows.
Click on Window - Chile Window 2 (notice there is a menu). This solves the technical problem.

Code: Select all

#INCLUDE "dcdialog.CH"
#INCLUDE "appevent.CH"

FUNCTION Main()

LOCAL GetList[0], oMenuBar, oSubMenu1, oSubMenu2, oSubMenu3, oDlg, ;
      GetOptions

DCMENUBAR oMenuBar

  DCSUBMENU oSubMenu1 PROMPT 'Sub1' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu1 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu1 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu1 ACTION {||MsgBox('Item 3')}

  DCSUBMENU oSubMenu2 PROMPT 'Sub2' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu2 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu2 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu2 ACTION {||MsgBox('Item 3')}

  DCSUBMENU oSubMenu3 PROMPT 'Sub3' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu3 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu3 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu3 ACTION {||MsgBox('Item 3')}

  DCSUBMENU oSubMenu3 PROMPT 'Window' PARENT oMenuBar

    DCMENUITEM 'Child Window 1' PARENT oSubMenu3 ;
      ACTION {|o|o:=Thread():new(),o:start({||ChildWindow1(oDlg)})}

    DCMENUITEM 'Child Window 2' PARENT oSubMenu3 ;
      ACTION {|o|o:=Thread():new(),o:start({||ChildWindow2(oDlg)})}

DCGETOPTIONS WINDOWWIDTH 1000 WINDOWHEIGHT 900

DCREAD GUI TITLE 'Menu Test' EVAL {|o|oDlg := o} OPTIONS GetOptions

RETURN nil

* ------

PROC appsys ; RETURN

* ------

FUNCTION ChildWindow1( oParent )

LOCAL GetList[0], oMenuBar, oSubMenu1, oSubMenu2

DCMENUBAR oMenuBar

  DCSUBMENU oSubMenu1 PROMPT 'SubMenu1' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu1 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu1 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu1 ACTION {||MsgBox('Item 3')}

  DCSUBMENU oSubMenu2 PROMPT 'SubMenu2' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu2 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu2 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu2 ACTION {||MsgBox('Item 3')}

DCREAD GUI TITLE 'Child Window' APPWINDOW oParent:drawingArea

RETURN nil

* ------

#translate BUTTONMENU <m> => ;
  EVAL {|o|o:lbDown := {|a,b,o|oButton := o, ;
                               <m>:endMenu := {|a,b,o|Eval(oButton:killInputFocus,a,b,oButton)}, ;
                               <m>:PopUp( o:setParent(), o:currentPos(), 2, ;
                        XBPMENU_PU_DEFAULT + XBPMENU_PU_MOUSE_RBDOWN )}, ;
           o:keyboard := {|a,b,o|IIF(a==xbeK_ENTER,Eval(o:lbDown,a,b,o),nil)}, ;
           o:setInputFocus := {|a,b,o|PostAppEvent(xbeM_Enter,,,o)}, ;
           o:killInputFocus := {|a,b,o|PostAppEvent(xbeM_Leave,,,o)}}

FUNCTION ChildWindow2( oParent )

LOCAL GetList[0], oMenuBar, oSubMenu1, oSubMenu2, oStatTop, oButton

DCSTATUSBAR oStatTop HEIGHT 22 ALIGN DCGUI_ALIGN_TOP

@ 0,0 DCTOOLBAR oMenuBar SIZE 1000,22 PIXEL ;
      PARENT oStatTop BUTTONSIZE 100, 24 ;
      COLOR nil, GRA_CLR_PALEGRAY FONT '10.Arial Bold'

DCADDBUTTONXP CAPTION 'SubMenu 1' PARENT oMenuBar ;
   BUTTONMENU oSubMenu1 TABSTOP

  DCSUBMENU oSubMenu1 PROMPT 'SubMenu1' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu1 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu1 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu1 ACTION {||MsgBox('Item 3')}

DCADDBUTTONXP CAPTION 'SubMenu 2' PARENT oMenuBar ;
   BUTTONMENU oSubMenu2 TABSTOP

  DCSUBMENU oSubMenu2 PROMPT 'SubMenu2' PARENT oMenuBar

    DCMENUITEM 'Item 1' PARENT oSubMenu2 ACTION {||MsgBox('Item 1')}
    DCMENUITEM 'Item 2' PARENT oSubMenu2 ACTION {||MsgBox('Item 2')}
    DCMENUITEM 'Item 3' PARENT oSubMenu2 ACTION {||MsgBox('Item 3')}

DCREAD GUI TITLE 'Child Window' APPWINDOW oParent:drawingArea

RETURN nil

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 9:43 am
by rdonnay
1. The dcaddbuttonxp buttons do not stay highlighted (to look as if they have been selected) when the menu appears.
This is incorrect. My sample works fine. Which version of eXpress++ are you using?
2. Accelkeys cannot be assigned/used as the button does not have an Action codeblock.
You can use the & (ampersand). I will work on a solution for ACCELKEY.
3. You cannot move left and right to the previous / next menu item if the dropdown menu is displayed.
This is correct. The XbpMenuBar class handles left/right keyboard navigation. This solution eliminates the XbpMenuBar class to solve the other technical problem of only allowing 1 menubar in an application. The XbpMenu class handles up/down navigation, so that still works correctly. There are no key events that can be intercepted in the Windows menu system. It doesn't follows the rules of other classes. This has been a long-time frustration for me. DC_XbpMenu inherits from XbpMenu so I doubt that there is anything that can be done about this. I consider it a minor inconvenience in that this solves a bigger problem.

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 10:01 am
by reganc
rdonnay wrote:
1. The dcaddbuttonxp buttons do not stay highlighted (to look as if they have been selected) when the menu appears.
This is incorrect. My sample works fine. Which version of eXpress++ are you using?
2. Accelkeys cannot be assigned/used as the button does not have an Action codeblock.
You can use the & (ampersand). I will work on a solution for ACCELKEY.
3. You cannot move left and right to the previous / next menu item if the dropdown menu is displayed.
This is correct. The XbpMenuBar class handles left/right keyboard navigation. This solution eliminates the XbpMenuBar class to solve the other technical problem of only allowing 1 menubar in an application. The XbpMenu class handles up/down navigation, so that still works correctly. There are no key events that can be intercepted in the Windows menu system. It doesn't follows the rules of other classes. This has been a long-time frustration for me. DC_XbpMenu inherits from XbpMenu so I doubt that there is anything that can be done about this. I consider it a minor inconvenience in that this solves a bigger problem.
In answer to your first question, I am using 'eXPress++ (c) Version 2.0 Build 261'. Ok, I will qualify what I said a little. The 1st time you click on the dcaddbuttonxp it's fine. But with the menu still open, click on the dcaddbuttonxp again. On mine, the button then becomes unhighlighted and the menu is drawn again. Perhaps it just needs to not do the action if the menu is already open.

I don't mean to complain. I am hoping that this solution can be made to function identically to the real menubar while giving you (and us) the behavior you mention. Any difference in behavior will probably be picked up on by our customers immediately.

Re: Button Menu Sample

Posted: Tue Jun 30, 2015 10:12 am
by rdonnay
Any difference in behavior will probably be picked up on by our customers immediately.
Probably the best solution then would be to make sure that it doesn't look like a menu bar, but instead looks like a set of buttons.
This can be done with colors that are different than the background. A user would then expect a different behavior. I have been using this solution in a customer application for many years with 400+ users. The application has hundreds of child windows which are all based on a data-driven framework. Each child window has a menu across the top which are a set of buttons with pull-down menus (very similar to the sample).

There has never been a complaint that they cannot navigate horizontally when a menu is pulled down.

Re: Button Menu Sample

Posted: Wed Jul 01, 2015 12:45 am
by skiman
Hi Roger,
This sample was created to solve a technical problem, not necessarily a visual problem.
I wasn't aware of this problem. I never tried to add a menubar on a dialog. In that case your sample makes a lot of sense.