Office-style menus (full include) - 20Feb2013 [x86 / x64]

Share your advanced PureBasic knowledge/code with the community.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Office-style menus (full include) - 20Feb2013 [x86 / x64]

Post by Inf0Byt3 »

I have finally finished an old project of mine, an include for creating custom menus that look like the ones from Office. The idea is inspired by that of eesau that can be found here:

http://www.purebasic.fr/english/viewtopic.php?t=27233.

This one is a complete library, written from scratch. The system itself is modeled after PureBasic's menu lib to make it easy to implement, without having to modify too much code. Some features:
  • - Close resemblance to Office menus
    - You can add new styles (colors) and change them in real time
    - Own management system for Office Menu 'objects' (with IDs, etc.)
    - Should work on: Window$ 2000, XP, Vista, 7, 8 (32 / 64 bit, Unicode supported)
    - Support for keyboard navigation and mnemonics
    - Open source
The menus are also compatible with animations and draw correctly, the only downside being that they flicker a bit sometimes. Nothing that can't be fixed with some double buffering - if I knew how to implement it that is. But that's something for you to tackle with, as for me fiddling with owner drawn menus was like trying to count hairs while wearing boxing gloves, especially since the menu implementations are so inconsistent across Window$.

As for older operating systems, I did try to make this code compatible with them. The tests on Window$ 98 looked promising, except for a single thing that I would like to hear an explanation for: after you play with the menu in its current form and you enter sub-menus, next time you open them, the menu item states do not reset :shock:. So if one item was highlighted when you click somewhere to close the menu and you open it again, the items are drawn as highlighted even if the cursor does not hover over them. I even tried to reset their state by force upon #WM_INITMENUPOPUP, but to no avail. Inconsistent menu implementation is inconsistent, but if you have any idea why this happens, please let me know. On the other hand, in Win2K things went better, even if the slightest drawing mistake would break all other menus. I found this to be a good guide while implementing the drawing code because it reduced the risk of bugs slipping in.

And another cool one: on Window$ 8, the menus are automatically opened to the left. This makes things look ackward. Much to my amazement, system menus behave the same way, opening sub-menus to the left, even if the arrows are drawn on the right ( :lol: ) and there is enough space to the right edge of the screen (gotta love these 'great new features'). So after fiddling around for some time I found a way to show the menus the good ol' way from Control Panel, in Tablet PC -> Handedness. What on earth is happening @ M$?

Screenshots:

Image

Image

That being said, enjoy:

BE_OfficeMenu.zip, 16 KB
http://www.bytessence.com/download/snip ... ceMenu.zip

Changelog:
20 February 2013:
-Fixed a crash when showing menus from the systray
-Added double buffering (no more flickering)
-Added OfficeMenu_IsMenu procedure
-Switched all data types to integers to avoid potential problems on x64

4 November 2012:
-Added x64 support

16 October 2012:
-First release
Last edited by Inf0Byt3 on Wed Feb 20, 2013 8:22 pm, edited 2 times in total.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
eesau
Enthusiast
Enthusiast
Posts: 589
Joined: Fri Apr 27, 2007 12:38 pm
Location: Finland

Re: Office-style menus (full include) - 16Oct2012

Post by eesau »

Looks good!
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Office-style menus (full include) - 16Oct2012

Post by Inf0Byt3 »

Thank you, especially for breaking the ice with your code. Hopefully the lib will work as intended :).
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Re: Office-style menus (full include) - 16Oct2012

Post by yrreti »

Thanks very much Inf0Byt3

It looks very nice, and will make some menu's in some of my personal programs
look a lot nicer. :D :D :D

yrreti
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Office-style menus (full include) - 16Oct2012

Post by Kwai chang caine »

Waooouuuh !!! Splendid !! :shock:
Works great, perhaps you can give your candidacy to CROSOFT now :D
Thanks a lot for sharing this jewel 8)
ImageThe happiness is a road...
Not a destination
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Office-style menus (full include) - 16Oct2012

Post by Inf0Byt3 »

yrreti wrote:Thanks very much Inf0Byt3

It looks very nice, and will make some menu's in some of my personal programs
look a lot nicer. :D :D :D

yrreti
Sweet, let me know if you find any problem.
Kwaï chang caïne wrote:Waooouuuh !!! Splendid !! :shock:
Works great, perhaps you can give your candidacy to CROSOFT now :D
Thanks a lot for sharing this jewel 8)
Hehe they'll never get me alive :P.

BTW, has anyone compiled it on x64 yet? I'm curious if it even runs.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
User avatar
leonhardt
Enthusiast
Enthusiast
Posts: 220
Joined: Wed Dec 23, 2009 3:26 pm

Re: Office-style menus (full include) - 16Oct2012

Post by leonhardt »

:P useful,thanks
poor English...

PureBasic & Delphi & VBA
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

Re: Office-style menus (full include) - 16Oct2012

Post by NoahPhense »

Very nice IB!
rudz
User
User
Posts: 35
Joined: Sun Mar 21, 2010 6:59 am
Location: Denmark
Contact:

Re: Office-style menus (full include) - 16Oct2012

Post by rudz »

I compiled it using PB 5.0 B5 x64, the menu is not showing.
However, works like a charm in the x86 version.
AMD FX-8350 @ ~4.8GHz | 8GB Corsair DDR3-SDRAM @ 1800Mhz | 7even Ult & Manjaro 0.8.7.1 | PB 5.3
Web: rudz.dk
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Office-style menus (full include) - 16Oct2012

Post by Inf0Byt3 »

NoahPhense wrote:Very nice IB!
Thanks!
rudz wrote:I compiled it using PB 5.0 B5 x64, the menu is not showing.
However, works like a charm in the x86 version.
Thanks for testing. I will try to add x64 support for the next version.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Office-style menus (full include) - 16Oct2012

Post by Inf0Byt3 »

mevedia.de wrote: The only Problem here (again) is the gray Line between MenuBar and the client Area. (Line has #COLOR_3DFACE) :?
Ahh yes, that line is a total pain. I was quite annoyed by it too, but the thing is that it doesn't seem to be part of the menu itself, so trying to draw over it from the menu callback led nowhere. It could be a part of the main window client area. In other implementations, like the Internet Explorer menu, the "titles" are not actually menus, but toolbar items made to look like menus. The toolbar is then snapped onto a rebar, that's why it doesn't have a line under it. Maybe some API guru on the forum knows a way to eliminate it?
mevedia.de wrote: Small suggestion: Would be great, if you create a full featured MenuBar + ToolBar. (automaticly creating the ToolBar from MenuBar) and possibility to show/hide Menu Groups. :)
Initially this include should have been a complete menu, rebar and toolbar library, but due to the lack of examples regarding on how to owner-draw a rebar or even a toolbar, only the menu made it. Most examples were on buttons, combo-boxes or menus. It is possible to create a toolbar from scratch to avoid fiddling with API, I had started some code a few years back but never finished it. Maybe it's time to dig it up :mrgreen:.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: Office-style menus (full include) - 16Oct2012

Post by RASHAD »

Workaround
But it needs more work to do

Code: Select all


;- DEMO for BE_OfficeMenus

;{ Includes
XIncludeFile "BE_OfficeMenu.pbi"
;}

;{ Variables
Define AddIcons, Image, WindowHandle, Event, PopupEvent
;}

;{ Create an array and put some icons into it
Dim Icons(9)
For AddIcons = 0 To 9
  Icons(AddIcons) = ExtractIcon_(GetModuleHandle_(0), "Shell32.dll", 15 + AddIcons)
Next
;}

;{ Create an image here
Image = CreateImage(#PB_Any, 200, 20)
If IsImage(Image)
  StartDrawing(ImageOutput(Image))
  Box(0, 0, 200, 20, RGB(0, 128, 255))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawText(6, 2, "Image gadget (right click me)", 0)
  DrawText(7, 3, "Image gadget (right click me)", RGB(255, 255, 255))
  StopDrawing()
EndIf
;}

If OpenWindow(0, 0, 0, 400, 280, "OfficeMenu Test", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_Invisible | #PB_Window_SizeGadget)
   OpenWindow(1, 0, 0, 400, 19, "OfficeMenu Test", #WS_POPUP|#PB_Window_BorderLess,WindowID(0))
   SetParent_(WindowID(1),WindowID(0))
  ;{ Init
  SetWindowColor(0, RGB(128,128,128))
  OfficeMenu_Init(WindowID(1)) ;This will hook the main window, must be called before adding OfficeMenus!
  ;}

  ;{ Gadgets
  UseGadgetList(WindowID(0))
  ButtonGadget(0, 100, 40, 200, 20, "Change menu theme")
  ImageGadget(1, 100, 90, 200, 20, ImageID(Image))
  StringGadget(2, 100, 140, 200, 20, "My context menu is left alone :P")
  ButtonGadget(3, 100, 190, 200, 20, "Change items")
  ButtonGadget(4, 100, 240, 200, 20, "Change titles")
  ;}

  ;{ Create menus
  WindowHandle = WindowID(1)
  If OfficeMenu_CreateMenu(0, WindowHandle, #OfficeMenu_Style_Blue) <> 0
    OfficeMenu_Title(0, "&File")
    OfficeMenu_Item(0, 0, "New" + Chr(9) + "Ctrl N")
    OfficeMenu_Item(0, 1, "&Open..." + Chr(9 ) + "Ctrl O")
    OfficeMenu_Item(0, 2, "Save" + Chr(9) + "Ctrl S", Icons(1))
    OfficeMenu_Item(0, 3, "Save As...", Icons(2))
    OfficeMenu_Item(0, 4, "Save All")
    OfficeMenu_Item(0, 5, "&Close" + Chr(9) + "Ctrl W", Icons(3))
    OfficeMenu_Item(0, 6, "Close All")
    OfficeMenu_Bar(0)
    OfficeMenu_Item(0, 7, "Sort &Sources...", Icons(4))
    OfficeMenu_Bar(0)
    OfficeMenu_Item(0, 8, "Preferences...", Icons(5))
    OfficeMenu_Bar(0)
    If OfficeMenu_OpenSubMenu(0, "Recent Files", Icons(8))
      OfficeMenu_Item(0, 9, "file1.pb")
      OfficeMenu_Item(0, 10, "file2.pb")
      OfficeMenu_Item(0, 11, "file3.pb", Icons(6))
      OfficeMenu_Bar(0)
      If OfficeMenu_OpenSubMenu(0, "More Files", Icons(1))
        OfficeMenu_Item(0, 12, "file4.pb")
        OfficeMenu_Item(0, 13, "file5.pb", Icons(7))
        OfficeMenu_Item(0, 14, "file6.pb")
        OfficeMenu_Item(0, 15, "file7.pb", Icons(8))
        OfficeMenu_Item(0, 16, "file8.pb")
        OfficeMenu_CloseSubMenu(0)
      EndIf
      OfficeMenu_Bar(0)
      OfficeMenu_Item(0, 17, "&Another item!", Icons(9))
      OfficeMenu_CloseSubMenu(0)
    EndIf
    OfficeMenu_Bar(0)
    OfficeMenu_Item(0, 18, "Exit" + Chr(9) + "Alt + F4")
    OfficeMenu_Title(0, "&Edit")
    OfficeMenu_Item(0, 19, "&Undo" + Chr(9)+ "Ctrl + Z", Icons(2))
    OfficeMenu_Item(0, 20, "&Redo" + Chr(9)+ "Ctrl + Y")
    OfficeMenu_Bar(0)
    OfficeMenu_Item(0, 21, "&Cut" + Chr(9)+ "Ctrl + X")
    OfficeMenu_Item(0, 22, "Co&py" + Chr(9)+ "Ctrl + C", Icons(5))
    OfficeMenu_Item(0, 23, "Pas&te" + Chr(9)+ "Ctrl + V", Icons(6))
    OfficeMenu_Bar(0)
    OfficeMenu_Item(0, 24, "Select &All" + Chr(9)+ "Ctrl + A")
    OfficeMenu_Bar(0)
    OfficeMenu_Item(0, 25, "&Find" + Chr(9)+ "Ctrl + F", Icons(8))
    OfficeMenu_Title(0, "&Help")
    If OfficeMenu_OpenSubMenu(0, "I want", Icons(4))
      OfficeMenu_Item(0, 26, "some")
      If OfficeMenu_OpenSubMenu(0, "help", Icons(7))
        OfficeMenu_Item(0, 27, "please!" + Chr(9)+ "F1", Icons(3))
        OfficeMenu_CloseSubMenu(0)
      EndIf
      OfficeMenu_CloseSubMenu(0)
    EndIf
  Else
    Debug "Error creating main menu"
  EndIf
  If OfficeMenu_CreatePopupMenu(1, #OfficeMenu_Style_Standard) <> 0
    OfficeMenu_Item(1, 1000, "&This is", Icons(1))
    OfficeMenu_Item(1, 1001, "A &cool")
    OfficeMenu_Item(1, 1002, "Popup &menu!")
    OfficeMenu_Bar(1)
    If OfficeMenu_OpenSubMenu(1, "&Submenu", Icons(5))
      OfficeMenu_Item(1, 1003, "&Here")
      OfficeMenu_Bar(1)
      If OfficeMenu_OpenSubMenu(1, "And &another", Icons(2))
        OfficeMenu_Item(1, 1004, "&Here!")
        OfficeMenu_CloseSubMenu(1)
      EndIf
      OfficeMenu_CloseSubMenu(1)
    EndIf
    OfficeMenu_Bar(1)
    OfficeMenu_Item(1, 1005, "Co&nfiguration")
  Else
    Debug "Error creating popup menu"
  EndIf
  ;}

  ;{ Configure the menu
  OfficeMenu_SetItemState(0, 0, #MFS_CHECKED)
  OfficeMenu_SetItemState(0, 1, #MFS_CHECKED | #MFS_DISABLED)
  OfficeMenu_SetItemState(0, 10, #MFS_CHECKED)
  OfficeMenu_SetItemState(1, 1002, #MFS_CHECKED)
  OfficeMenu_SetItemState(1, 1004, #MFS_CHECKED)
  ;}

  ;{ Show the window
  HideWindow(0, 0)
  ;}

EndIf
SetActiveWindow(1)
Repeat
  Event = WaitWindowEvent()
  Select Event

    Case #PB_Event_Gadget ;{
      Select EventGadget()

        Case 0 ;{ Change theme
          If OfficeMenu_GetStyle(0) = #OfficeMenu_Style_Standard
            OfficeMenu_SetStyle(0, #OfficeMenu_Style_Blue)
            OfficeMenu_SetStyle(1, #OfficeMenu_Style_Standard)
          Else
            OfficeMenu_SetStyle(0, #OfficeMenu_Style_Standard)
            OfficeMenu_SetStyle(1, #OfficeMenu_Style_Blue)
          EndIf
          ;}

        Case 1 ;{ Image gadget
          If EventType() = #PB_EventType_RightClick
            PopupEvent = OfficeMenu_DisplayPopupMenu(1, WindowID(0), 0, 0, 1) ;Also return the selected item
            If PopupEvent <> 0
              MessageRequester("Menu event!","Popup event menu: "+Str(PopupEvent))
            EndIf
          EndIf
          ;}

        Case 3 ;{ Change items
          OfficeMenu_SetItemText(0, 6, "Looooooooooooooooooooooooooooooooong STRING :P "+Str(Random(1024)))
          Debug "New text for item 6: "+OfficeMenu_GetItemText(0, 6)
          OfficeMenu_SetItemIcon(0, 7, Icons(Random(9)))
          OfficeMenu_SetItemIcon(0, 8, Icons(Random(9)))
          OfficeMenu_SetItemIcon(1, 1000, Icons(Random(9)))
          OfficeMenu_SetItemIcon(1, 1003, Icons(Random(9)))
          ;}

        Case 4 ;{ Change titles
          OfficeMenu_SetTitleText(0, 0, "&What File !?")
          OfficeMenu_SetTitleText(0, 1, "&Tools are cool")
          Debug "New text for title 0: "+OfficeMenu_GetTitleText(0, 0)
          Debug "New text for title 1: "+OfficeMenu_GetTitleText(0, 1)
          If OfficeMenu_GetTitleState(0, 1) & #MFS_GRAYED
            OfficeMenu_SetTitleState(0, 1, #MFS_ENABLED)
          Else
            OfficeMenu_SetTitleState(0, 1, #MFS_GRAYED)
          EndIf
          ;}

      EndSelect
      ;}

    Case #PB_Event_Menu ;{
      MessageRequester("Menu event!","Event menu: "+Str(EventMenu()))
      ;}

  EndSelect
Until Event = #PB_Event_CloseWindow
;Manually free the menus!
OfficeMenu_FreeMenu(0)
OfficeMenu_FreeMenu(1)
;And uninit from the window
OfficeMenu_UnInit(WindowID(0))

Edit : Updated
Last edited by RASHAD on Sat Oct 27, 2012 11:51 pm, edited 1 time in total.
Egypt my love
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Office-style menus (full include) - 16Oct2012

Post by Inf0Byt3 »

Thanks RASHAD, that seems to eliminate the line. The downside is that it makes the main window lose focus :).
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: Office-style menus (full include) - 16Oct2012

Post by RASHAD »

Yes,but you can handle that a fake through a CallBack() with Moving and Resizing........
Egypt my love
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Office-style menus (full include) - 16Oct2012

Post by Inf0Byt3 »

Indeed, it's worth a try :).
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Post Reply