If you look at wxRibbonButtonBar::AddButton, you will see that it uses four bitmaps, so if you have a large application, you can easily end up with task manager showing you are using 2000 GDI objects, most of which come from these bitmaps. And most of these bitmaps will never be used. Windows limits an application to 10000 bitmaps by default.
Does anyone have any suggestions for cutting this down?
One idea would be to implement a wxBitmapOnDemand which returns a size for the ribbon bar sizing but doesnt create the bitmap until needed. However, that does not work because the Width type methods are non virtual in the wxGDIImage base class. So I cant overload them.
Another idea, since wxBitmaps use references, is to, if the button is enabled, pass the same bitmaps for disabled, and if the button becomes disabled, set all four bitmaps to the enabled ones. Then you can at least cut the bitmaps down to half the count, maybe. The problem becomes how do you modify the original bitmaps and not the copy that gets made if you start to modify a bitmap?
The only feasible options seems to be to add the button with the disabled and normal buttons the same, so there are only two bitmaps and not four. And then if the enabled state of the button changes, remove the button via DeleteButton and add it back again via InsertButton, with the right set of bitmaps.
Any ideas on this?
Cutting down on ribbon bar bitmaps Topic is solved
Re: Cutting down on ribbon bar bitmaps
FWIW: The native WinAPI answer to GDI handle limits for bitmaps is ImageList, wrapped in wxWidgets as wxImageList. However, AFAIK the only wx controls using wxImageList are wxTreeCtrl and wxListCtrl. ImageList is used in native WinAPI by many other controls including toolbar and button, wxWidgets do not support image lists there either, not sure why. So it is not surprising that wxImageList was not used for wxRibbon either.
OTOH, the default limit of 10k GDI handles is still quite a lot, if you are really coming anywhere near to it, are you sure you are not leaking the handles somewhere?
OTOH, the default limit of 10k GDI handles is still quite a lot, if you are really coming anywhere near to it, are you sure you are not leaking the handles somewhere?
Last edited by PB on Mon Jan 27, 2020 7:49 pm, edited 1 time in total.
Re: Cutting down on ribbon bar bitmaps
Hi,
You should probably ask this on the wx-users ML.
Thank you.
You should probably ask this on the wx-users ML.
Thank you.
Re: Cutting down on ribbon bar bitmaps
We are not leaking GDI objects, I have been checking for that, trust me. It is just a bit odd that the application at startup is using nearly 2000 GDI images. Mind you, the number does not change much, and it is still far from the 10000, its just a bit surprising... But in general in very large complex applications I can see reaching that limit, which MS imposes to say "hey, if you are not leaking, find a better way of doing this".
I do see other people have the same issue, here for example:
viewtopic.php?t=44816
And the wxImageList indeed appears to be the solution... If only wxRibbonBar supported it! Let me look into that... THANKS!
I do see other people have the same issue, here for example:
viewtopic.php?t=44816
And the wxImageList indeed appears to be the solution... If only wxRibbonBar supported it! Let me look into that... THANKS!
Re: Cutting down on ribbon bar bitmaps
It looks like the ribbon bar code does not do much with the images other than hangs onto them and draws them really. So making wxRibbonbar support wxImageList should be easy, famous last words.
Re: Cutting down on ribbon bar bitmaps
Before coding anything, I would ask in the wx-users mailing list if such a change has any chance to be accepted.
Changes in the API aside, if one ribbon button requires 4 bitmaps, even if you ribbon has 250 buttons (I do not think even large applications have that many), it would still leave ~9k GDI handles to the rest of the application.
Changes in the API aside, if one ribbon button requires 4 bitmaps, even if you ribbon has 250 buttons (I do not think even large applications have that many), it would still leave ~9k GDI handles to the rest of the application.
Re: Cutting down on ribbon bar bitmaps
Thank you for all the help. I have also posed the information below as a new item viewtopic.php?f=1&t=46785 since it is really a separate question.
---------
I have been experimenting with using wxImageList in buttonbar.cpp, and it drastically reduces the number of GDI handles. NICE.
However, there is one problem, wxImageList::Add checks to see if the bitmap has an alpha (mine do, they are 32 bpp with a transparency layer), it converts it to a wxImage, it calls wxDIB::ConvertToImage which does something weird with the alpha layer.
So without using wxImageList the icons look like this:
and with wxImageList they look like this:
Now I am hoping someone more familiar with wxWidgets can perhaps suggest a remedy of some sort? What can I do to my wxImages before adding them the imagelist to prevent this? Some better handling of the transparency layer? These images originally come from Windows icons.
---------
I have been experimenting with using wxImageList in buttonbar.cpp, and it drastically reduces the number of GDI handles. NICE.
However, there is one problem, wxImageList::Add checks to see if the bitmap has an alpha (mine do, they are 32 bpp with a transparency layer), it converts it to a wxImage, it calls wxDIB::ConvertToImage which does something weird with the alpha layer.
So without using wxImageList the icons look like this:
and with wxImageList they look like this:
Now I am hoping someone more familiar with wxWidgets can perhaps suggest a remedy of some sort? What can I do to my wxImages before adding them the imagelist to prevent this? Some better handling of the transparency layer? These images originally come from Windows icons.
Re: Cutting down on ribbon bar bitmaps
I have implemented an enhancement around this, please see here https://trac.wxwidgets.org/ticket/18657