TRibbonBar

Office-style ribbon bar with tabs, groups, and buttons

Source: source/classes/tribbon.prg  |  Parent: TControl  |  Header: include/ribbon.ch

Overview

TRibbonBar implements a Microsoft Office-style ribbon interface. The ribbon docks to the top of a window and organizes commands into tabs, each containing groups of buttons. It supports multiple visual styles (2010, 2013, 2015, 2016), a Quick Access toolbar, keyboard accelerators, backstage view, and fully owner-drawn rendering with gradients.

Architecture

graph TD WINDOW["TWindow
(Main Window)"] --> RIBBON["TRibbonBar"] RIBBON --> QUICK["Quick Access
Toolbar"] RIBBON --> TAB1["Tab: Home"] RIBBON --> TAB2["Tab: Insert"] RIBBON --> TAB3["Tab: View"] RIBBON --> BACK["BackStage
Panel"] TAB1 --> G1["TRBGroup
Clipboard"] TAB1 --> G2["TRBGroup
Font"] TAB1 --> G3["TRBGroup
Paragraph"] G1 --> B1["TRBButton
Paste"] G1 --> B2["TRBButton
Cut"] G1 --> B3["TRBButton
Copy"] G2 --> B4["TRBButton
Bold"] G2 --> B5["TRBButton
Italic"] style RIBBON fill:#1c2129,stroke:#58a6ff,stroke-width:2px,color:#e6edf3 style G1 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3 style G2 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3 style G3 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3

Component Hierarchy

graph LR RB["TRibbonBar"] --> RBG["TRBGroup"] RBG --> RBB["TRBButton"] RBG --> SEP["Separator"] RBB --> POPUP["Popup Menu"] subgraph "Button Types" NORMAL["NORMAL
Standard button"] POPUPB["POPUP
Menu dropdown"] SPLIT["SPLITPOPUP
Button + dropdown"] SAYB["SAYBUTTON
Label button"] end RBB --> NORMAL RBB --> POPUPB RBB --> SPLIT RBB --> SAYB

TRibbonBar Properties

PropertyTypeDescription
aPromptsArrayArray of tab label strings
aDialogsArrayArray of dialog objects (one per tab, holding groups)
nOptionNumericCurrently selected tab index (1-based)
nOldOptionNumericPreviously selected tab (for change detection)
bActionBlockCode block fired on tab change: { |nOption, nOldOption| ... }
aEnableArrayPer-tab enable state
aVisibleArrayPer-tab visibility state
nTopMarginNumericHeight of the tab strip area (default 25)
nGroupSeparationNumericPixel gap between groups (default 3)
nLeftMarginNumericLeft margin for the first group
nRightMarginNumericRight margin
nRoundBoxNumericCorner radius for tab boxes (default 7)
nClrPaneRBNumericRibbon background color
nClrBoxOut / nClrBoxInNumericTab box outer/inner colors
nClrBoxSelOut / nClrBoxSelInNumericSelected tab box outer/inner colors
aGradArrayBackground gradient
aGradFldArrayTab content area gradient
aGradHighArrayTab highlight gradient (mouse-over)
aGradOverArrayTab hover gradient
l2010 / l2013 / l2015 / l2016LogicalVisual style flags (only one should be .T.)
oBackStageObjectPanel used as the backstage view (File tab)
lUseAccLogicalEnable keyboard accelerator hints
aQuickBmpArrayQuick Access toolbar bitmaps
nStartNumericStarting button offset for Quick Access

Key Methods

MethodDescription
New( oWnd, aPrompts, bAction, nOption, nWidth, nHeight, nTopMargin, nClrPaneRB, nClrBoxOut, nClrBoxIn, nClrBoxSelOut, nClrBoxSelIn, aGrad, aGradFld, aGradHigh, aGradOver, l2010, nStart, l2013, l2015, l2016 )Constructor. Creates the ribbon bar at the top of the window.
AddTab( cPrompt, nPos, lDefault, bClrTxt )Add a new tab at runtime
DeleteTab( nTab )Remove a tab
AddGroup( nWidth, cCaption, nDialogs, bAction, cBitmap, aGrad )Add a group to a tab. Returns the group object.
SetOption( nOption )Programmatically switch to a tab
GoLeft() / GoRight()Navigate to previous/next tab
Enable( nPos, lOnOff )Enable or disable a specific tab
Show( nPos ) / Hide( nPos )Show or hide a specific tab
QuickAccess( nLeft, lQuickGrad )Set up the Quick Access toolbar area
QuickRoundBtn( cBitmap, cBmp, cBmpOver, cBmpPush, bAction, lQuickGrad, bLDblClick )Add a Quick Access round button (e.g. the "File" orb)
SetBackStage( oBackStage )Assign a backstage panel
BackStage()Show the backstage view
SetStyles( l2010, l2013, l2015, nTopMargin, ... )Change visual style at runtime
KeybMode()Enter keyboard accelerator mode (Alt key)

TRBGroup Methods

Groups are created by TRibbonBar:AddGroup() or the ADD GROUP command. Each group can contain buttons, separators, and other controls.

MethodDescription
AddButton( nRow, nCol, nHeight, nWidth, cCaption, bAction, cType, bWhen, cBitmap, lBorder, lRound, cLayout, oPopup, ... )Add a button to this group
AddSeparator( nCol )Add a vertical separator line

Command Syntax

#include "ribbon.ch"

// Create the ribbon bar
DEFINE RIBBONBAR [ oRBar ] ;
   [ OF oWnd ] ;
   [ PROMPTS cTab1, cTab2, cTab3 ] ;
   [ ACTION bAction ] ;
   [ OPTION nOption ] ;
   [ HEIGHT nHeight ] ;
   [ TOPMARGIN nTopMargin ] ;
   [ COLOR nClrPane ] ;
   [ COLORBOX nClrBoxOut, nClrBoxIn ] ;
   [ COLORSEL nClrBoxSelOut, nClrBoxSelIn ] ;
   [ 2010 | 2013 | 2015 | 2016 ] ;
   [ STARTBTN nStart ]

// Add a group to a tab
ADD GROUP [ oGr ] ;
   RIBBON oRBar ;
   TO nTabIndex ;
   [ PROMPT cCaption ] ;
   [ WIDTH nWidth ] ;
   [ ACTION bAction ] ;
   [ BITMAP cBitmap ]

// Add buttons to a group (using @ row, col notation)
@ nRow, nCol ADD BUTTON [ oBtn ] ;
   [ PROMPT cCaption ] ;
   [ SIZE nWidth, nHeight ] ;
   [ BITMAP cBitmap ] ;
   [ ACTION bAction ] ;
   [ OF oGroup ] ;
   [ WHEN bWhen ] ;
   [ BORDER ] ;
   [ ROUND ] ;
   [ TOP | LEFT | BOTTOM | RIGHT | CENTER ] ;
   [ NORMAL | POPUP | SPLITPOPUP | SAYBUTTON ] ;
   [ MENU oPopup ] ;
   [ TOOLTIP cToolTip ]

// Add a separator
ADD SEPARATOR TO GROUP oGr [ COL nCol ]

Ribbon Lifecycle

sequenceDiagram participant App participant RB as TRibbonBar participant GR as TRBGroup participant BT as TRBButton App->>RB: DEFINE RIBBONBAR PROMPTS "Home","Insert","View" RB-->>App: Creates ribbon with 3 tab dialogs App->>RB: ADD GROUP RIBBON oRBar TO 1 PROMPT "Clipboard" WIDTH 120 RB->>GR: Creates group on tab 1 RB-->>App: Returns oGrClip App->>GR: @ 2,2 ADD BUTTON PROMPT "Paste" BITMAP "paste.bmp" ACTION ... GR->>BT: Creates button inside group GR-->>App: Returns oBtn App->>RB: ACTIVATE WINDOW oWnd Note over RB: Tab 1 visible, groups painted RB-->>App: User clicks "Insert" tab RB->>RB: SetOption(2) RB-->>App: Eval(bAction, 2, 1) Note over RB: Tab 2 groups now visible

Code Examples

Example 1: Basic Ribbon with Groups and Buttons

#include "FiveWin.ch"
#include "Ribbon.ch"

FUNCTION Main()
   LOCAL oWnd, oRBar
   LOCAL oGrFile, oGrEdit, oGrView

   DEFINE WINDOW oWnd TITLE "Ribbon Demo"

   DEFINE RIBBONBAR oRBar OF oWnd ;
      PROMPTS "Home", "Insert", "View" ;
      HEIGHT 160 2015

   // ----- HOME TAB (option 1) -----

   ADD GROUP oGrFile RIBBON oRBar TO 1 ;
      PROMPT "File" WIDTH 140

   @ 2, 5 ADD BUTTON PROMPT "New" ;
      SIZE 36, 60 BITMAP "new32.bmp" ;
      ACTION NewDocument() ;
      OF oGrFile TOP

   @ 2, 45 ADD BUTTON PROMPT "Open" ;
      SIZE 36, 60 BITMAP "open32.bmp" ;
      ACTION OpenDocument() ;
      OF oGrFile TOP

   @ 2, 85 ADD BUTTON PROMPT "Save" ;
      SIZE 36, 60 BITMAP "save32.bmp" ;
      ACTION SaveDocument() ;
      OF oGrFile TOP

   ADD GROUP oGrEdit RIBBON oRBar TO 1 ;
      PROMPT "Editing" WIDTH 180

   @ 2, 5 ADD BUTTON PROMPT "Cut" ;
      SIZE 50, 22 BITMAP "cut16.bmp" ;
      ACTION Cut() OF oGrEdit

   @ 26, 5 ADD BUTTON PROMPT "Copy" ;
      SIZE 50, 22 BITMAP "copy16.bmp" ;
      ACTION Copy() OF oGrEdit

   @ 50, 5 ADD BUTTON PROMPT "Paste" ;
      SIZE 50, 22 BITMAP "paste16.bmp" ;
      ACTION Paste() OF oGrEdit

   ADD SEPARATOR TO GROUP oGrEdit COL 65

   @ 2, 70 ADD BUTTON PROMPT "Find" ;
      SIZE 50, 22 BITMAP "find16.bmp" ;
      ACTION FindText() OF oGrEdit

   @ 26, 70 ADD BUTTON PROMPT "Replace" ;
      SIZE 60, 22 BITMAP "replace16.bmp" ;
      ACTION ReplaceText() OF oGrEdit

   // ----- INSERT TAB (option 2) -----

   ADD GROUP oGrView RIBBON oRBar TO 2 ;
      PROMPT "Objects" WIDTH 200

   @ 2, 5 ADD BUTTON PROMPT "Table" ;
      SIZE 36, 60 BITMAP "table32.bmp" ;
      ACTION InsertTable() OF oGrView TOP

   @ 2, 50 ADD BUTTON PROMPT "Image" ;
      SIZE 36, 60 BITMAP "image32.bmp" ;
      ACTION InsertImage() OF oGrView TOP

   @ 2, 95 ADD BUTTON PROMPT "Chart" ;
      SIZE 36, 60 BITMAP "chart32.bmp" ;
      ACTION InsertChart() OF oGrView TOP

   SET MESSAGE OF oWnd TO "Ready" CENTERED

   ACTIVATE WINDOW oWnd
RETURN NIL

Example 2: Ribbon with Quick Access and Backstage

#include "FiveWin.ch"
#include "Ribbon.ch"

FUNCTION RibbonAdvanced()
   LOCAL oWnd, oRBar, oBackStage

   DEFINE WINDOW oWnd TITLE "Advanced Ribbon"

   DEFINE RIBBONBAR oRBar OF oWnd ;
      PROMPTS "Home", "Data", "Reports" ;
      HEIGHT 160 2016 ;
      STARTBTN 1

   // Quick Access round button (File orb)
   oRBar:QuickRoundBtn( "orb.bmp",, , , ;
      { || oRBar:BackStage() } )

   // Backstage panel (shown when orb is clicked)
   oBackStage := TPanel():New( 0, 0, 600, 300, oWnd )
   @ 2, 2 SAY "New"   OF oBackStage
   @ 4, 2 SAY "Open"  OF oBackStage
   @ 6, 2 SAY "Save"  OF oBackStage
   @ 8, 2 SAY "Print" OF oBackStage
   oBackStage:Hide()
   oRBar:SetBackStage( oBackStage )

   // Tab change handling
   oRBar:bAction := { |nTab, nOld| ;
      MsgInfo( "Switched from tab " + Str(nOld) + ;
               " to tab " + Str(nTab) ) }

   // Disable a tab at runtime
   // oRBar:Enable( 3, .F. )

   // Hide a tab at runtime
   // oRBar:Hide( 2 )

   ACTIVATE WINDOW oWnd
RETURN NIL

Example 3: Popup Buttons and Split Buttons

// Button with a dropdown popup menu
LOCAL oPopup

MENU oPopup POPUP
   MENUITEM "Option A" ACTION DoA()
   MENUITEM "Option B" ACTION DoB()
   SEPARATOR
   MENUITEM "More..."  ACTION DoMore()
ENDMENU

@ 2, 5 ADD BUTTON PROMPT "Dropdown" ;
   SIZE 80, 60 BITMAP "menu32.bmp" ;
   ACTION NIL ;
   OF oGroup ;
   POPUP ;
   MENU oPopup TOP

// Split button: click fires action, arrow opens menu
@ 2, 90 ADD BUTTON PROMPT "Print" ;
   SIZE 70, 60 BITMAP "print32.bmp" ;
   ACTION QuickPrint() ;
   OF oGroup ;
   SPLITPOPUP ;
   MENU oPopup TOP

Visual Styles

StyleDescription
2010Office 2010 style with gradient tabs and rounded orb button. Left margin = 10.
2013Office 2013 flat style with minimal borders
2015Office 2015/2016 style with colored tab strip
2016Office 2016/365 modern flat style
(default)Classic ribbon style with full gradients and 3D boxes

You can change the style at runtime using SetStyles():

// Switch to 2016 style
oRBar:SetStyles( .F., .F., .F., 25, , , , , , , , , , .T. )

Tips

See Also