wxWidgets Question

I am sorry to ask this question here, but I know that you use wxWidgets to develop the application and I wonder how you implemented the “File” menu as part of the wxRibbon?

I am trying to do something similar for my application. Thanks for any help!

Hi,

When I received your private message, I remember that you had posted a message about the ribbon a long time ago, sorry for not having answered. :blush:
I paste here my answer to your private message so that everyone can enjoy it :smiley:

The button is a wxStaticBitmap. I’ve added events to popup a menu when the bitmap is clicked and another event to change the bitmap when it is hovered.
The most tricky part is to generate the hovered and non hovered bitmap. To do this, I create a fake wxRibbonBar with the same wxRibbonArtProvider as the original ribbon, I add a tab called “File”, and I ask the art provider to draw the tab in a wxMemoryDC. Finally, when the bitmap is rendered, I just put it on the wxStaticBitmap, which is put over the ribbon. Here is the complete code used to do this :

[code]
//In this code, the ribbon is a member of MainFrame called ribbon.
//Rendered bitmap are also members of MainFrame, and are called ribbonFileNormalBitmap and ribbonFileHoveredBitmap
//Finally, the wxStaticBitmap is called ribbonFileBt.
void MainFrame::RealizeRibbonCustomButtons()
{
wxRibbonArtProvider * artProvider = ribbon->GetArtProvider();
if ( artProvider == NULL ) return;

wxColor buttonColor;
if ( !wxConfigBase::Get()->Read( _T( "/Skin/FileButtonColor" ), &buttonColor ) )
    buttonColor = wxColour(200, 200, 255);

//Create a temporary fake ribbon used to render the button with a custom color
wxRibbonBar * fakeRibbon = new wxRibbonBar(this);
fakeRibbon->SetArtProvider(artProvider->Clone());
fakeRibbon->GetArtProvider()->SetColourScheme(buttonColor, buttonColor, buttonColor);

//The device context used to render the button in memory
wxMemoryDC dc;

//Compute width of the bitmap button
int width; artProvider->GetBarTabWidth(dc, fakeRibbon, _("File"), wxNullBitmap, &width, NULL, NULL, NULL);

//Create a fake ribbon page...
wxRibbonPage *page = new wxRibbonPage(fakeRibbon, wxID_ANY, _("File"));
//...and the associated wxRibbonPageTabInfo
wxRibbonPageTabInfo tabInfo;
tabInfo.rect = wxRect(0,0, width, 16 /*Will be changed later*/);
tabInfo.ideal_width = width;
tabInfo.small_begin_need_separator_width = width;
tabInfo.small_must_have_separator_width = width;
tabInfo.minimum_width = width;
tabInfo.page = page;
tabInfo.active = true;
tabInfo.hovered = false;
wxRibbonPageTabInfoArray pages;
pages.Add(tabInfo);
pages.Add(tabInfo); //Add page twice to ensure that tab have a correct height

//Compute height of the bitmap button and create bitmap
int height = artProvider->GetTabCtrlHeight(dc, ribbon, pages);
wxBitmap bitmapLabel(width+2, height);
dc.SelectObject(bitmapLabel);

tabInfo.rect = wxRect(0,0, width, height+2); //We've got the correct height now.

//Render the file button. Use the background of the real ribbon.
artProvider->DrawTabCtrlBackground(dc, fakeRibbon, bitmapLabel.GetSize());
fakeRibbon->GetArtProvider()->DrawTab(dc, fakeRibbon, tabInfo);
ribbonFileNormalBitmap = wxBitmap(bitmapLabel);

//Render the hovered file button
wxBitmap bitmapHoveredLabel(ribbonFileNormalBitmap.ConvertToImage());
dc.SelectObject(bitmapHoveredLabel);

tabInfo.active = false;
tabInfo.hovered = true;
artProvider->DrawTabCtrlBackground(dc, fakeRibbon, bitmapHoveredLabel.GetSize());
wxColour backgroundColour = wxColor(bitmapHoveredLabel.ConvertToImage().GetRed(0,0), bitmapHoveredLabel.ConvertToImage().GetGreen(0,0), bitmapHoveredLabel.ConvertToImage().GetBlue(0,0)); //For later use...
fakeRibbon->GetArtProvider()->DrawTab(dc, fakeRibbon, tabInfo);
ribbonFileHoveredBitmap = bitmapHoveredLabel;

//Cut a bit the bottom of the bitmaps
if ( ribbonFileNormalBitmap.GetSize().GetHeight() > 3 )
    ribbonFileNormalBitmap.SetHeight(ribbonFileNormalBitmap.GetSize().GetHeight()-2);

if ( ribbonFileHoveredBitmap.GetSize().GetHeight() > 3 )
    ribbonFileHoveredBitmap.SetHeight(ribbonFileHoveredBitmap.GetSize().GetHeight()-2);

fakeRibbon->Destroy();

//Finally create our bitmaps and make sure the ribbon is ready.
ribbonFileBt->SetPosition(wxPoint(3,1));
ribbonFileBt->SetBitmap(ribbonFileNormalBitmap);
ribbon->SetTabCtrlMargins(bitmapLabel.GetSize().GetWidth()+3+3, 0);

}[/code]

You should be able to adapt it to any code base by renaming MainFrame and its members variables. If there is any problem, you can test if the bitmap generation is made correctly by saving the bitmaps to file ( wxBitmap::SaveFile ). :slight_smile:

:smiley: Thanks and sorry for my slow response, I didn’t realise that this post was here!

Do you mind if I put this on the wxWidgets forum - maybe someone will find it useful there.

p.s. the new forum is very nice!!

You can of course share it on other forums. Just be sure to include a link to this topic with your message :slight_smile: ( You may also include a screenshot of the File button to show how nice is the result :smiley: )

Thanks :slight_smile: