wxScrolledWindow not working as expected - wxwidgets

I have a problem with wxScrolledWindow.
I have a ScrolledWindow holding a wxListBox.
Behavior that works:
On adding items to the listbox the scrollbar will eventually appear.
Behavior that fails:
wxListBox has some items. When i reduce the size of the ScrolledWindow such that some items are occluded, the scrollbar fails to appear.
// split window into 2
wxBoxSizer *sizermain = new wxBoxSizer(wxVERTICAL);
wxSplitterWindow *splittermain = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE);
splittermain->SetSashGravity(0.5);
splittermain->SetMinimumPaneSize(20);
sizermain->Add(splittermain, 1,wxEXPAND,0);
this->SetSizer(sizermain);
// split left window into 2
wxSplitterWindow * splitterleft = new wxSplitterWindow(splittermain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE);
splitterleft->SetSashGravity(0.5);
splitterleft->SetMinimumPaneSize(20);
wxBoxSizer * sizerleft = new wxBoxSizer(wxHORIZONTAL);
sizerleft->Add(splitterleft, 1, wxEXPAND, 0);
// split right window into 2
wxSplitterWindow * splitteright = new wxSplitterWindow(splittermain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE);
splitteright->SetSashGravity(0.5);
splitteright->SetMinimumPaneSize(20);
wxBoxSizer * sizerright = new wxBoxSizer(wxHORIZONTAL);
sizerright->Add(splitteright, 1, wxEXPAND, 0);
wxScrolledWindow *tlpnl = new wxScrolledWindow(splitterleft, wxID_ANY);
wxListBox *tlcalls = new wxListBox(tlpnl, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_EXTENDED);
wxBoxSizer *tlsizer = new wxBoxSizer(wxVERTICAL);
tlsizer->Add(tlcalls, 1,wxEXPAND,0);
tlpnl->SetSizer(tlsizer);
wxScrolledWindow *blpnl = new wxScrolledWindow(splitterleft, wxID_ANY);
wxListBox *blcontacts = new wxListBox(blpnl, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_EXTENDED);
wxBoxSizer *blsizer = new wxBoxSizer(wxVERTICAL);
blsizer->Add(blcontacts, 1,wxEXPAND,0);
blpnl->SetSizer(blsizer);
wxScrolledWindow *trpnl = new wxScrolledWindow(splitteright, wxID_ANY);
inCall = new wxListBox(trpnl, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_EXTENDED);
wxBoxSizer *trsizer = new wxBoxSizer(wxVERTICAL);
trsizer->Add(inCall, 1,wxEXPAND,0);
trpnl->SetSizer(trsizer);
wxScrolledWindow *brpnl = new wxScrolledWindow(splitteright, wxID_ANY);
wxTextCtrl *brtext = new wxTextCtrl(brpnl, wxID_ANY);
wxBoxSizer *brsizer = new wxBoxSizer(wxVERTICAL);
brsizer->Add(brtext, 1,wxEXPAND,0);
brpnl->SetSizer(brsizer);
splittermain->SplitVertically(splitterleft, splitteright);
splitterleft->SplitHorizontally(tlpnl, blpnl);
splitteright->SplitHorizontally(trpnl, brpnl);

Your code doesn't seem to show the problem (as there are no items anywhere) but there is at least one thing wrong with it: you create sizerLeft and sizerRight sizers and add something to them but never use these sizers themselves. This might explain the layout problems... But if it doesn't, you really should show the code that actually shows the problem you're describing (and perhaps shorter than what you have, are both splitters actually needed?).

Related

WxWidgets SetContainingWindow exception

I am fairly new to WxWidgets. I wrote an app that was working fine in WxWidgets 3.1.5 but gives the following exceptions in 3.2.1. I looked at the sample code that comes with 3.2.1 and I don't see any issue with my code.
../src/common/sizer.cpp(887): assert "CheckExpectedParentIs(w, m_containingWindow)" failed in SetContainingWindow(): Windows managed by the sizer associated with the given window must have this window as parent, otherwise they will not be repositioned correctly.
Please use the window wxNotebook#0x7f9a5d9547d0 ("notebook") with which this sizer is associated, as the parent when creating the window wxStaticText#0x7f9a5d957e40 ("SMART log for /dev/nvme0n1") managed by it.
Collecting stack trace information, please wait...../src/common/sizer.cpp(887): assert "CheckExpectedParentIs(w, m_containingWindow)" failed in SetContainingWindow(): Windows managed by the sizer associated with the given window must have this window as parent, otherwise they will not be repositioned correctly.
Please use the window wxNotebook#0x7f9a5d9547d0 ("notebook") with which this sizer is associated, as the parent when creating the window wxButton#0x7f9a5d9564e0 ("Copy to clilpboard") managed by it.
Collecting stack trace information, please wait...../src/common/sizer.cpp(887): assert "CheckExpectedParentIs(w, m_containingWindow)" failed in SetContainingWindow(): Windows managed by the sizer associated with the given window must have this window as parent, otherwise they will not be repositioned correctly.
Please use the window wxNotebook#0x7f9a5d9547d0 ("notebook") with which this sizer is associated, as the parent when creating the window wxGrid#0x7f9a5c892a00 ("grid") managed by it.
Here is my source
int
DlgDisplayLogs::insertPage(wxString caption, wxString hostname, wxArrayString strArray)
{
wxPanel* panel = new wxPanel(notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize);
wxButton* btnClipboard = new wxButton(panel, wxID_ANY, "Copy to clilpboard");
wxStaticText* label = new wxStaticText(panel, wxID_ANY, caption, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
hbox->Add(label, 1, wxEXPAND | wxRIGHT | wxBOTTOM, 10);
hbox->Add(btnClipboard, 0, wxRIGHT | wxBOTTOM, 10);
wxGrid* grid;
int numEntries = strArray.GetCount();
grid = new wxGrid(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
if (!grid) {
return -1;
}
grid->CreateGrid(numEntries / 2, 2);
grid->EnableEditing(false);
grid->DisableCellEditControl();
grid->DisableDragGridSize();
grid->SetSelectionMode(wxGrid::wxGridSelectionModes::wxGridSelectRows);
grid->SetColLabelValue(0, "Description");
grid->SetColLabelValue(1, "Value");
grid->SetColMinimalWidth(0, 250);
grid->SetColMinimalWidth(1, 250);
grid->SetColSize(0, 250);
grid->SetColSize(1, 450);
grid->SetCellHighlightPenWidth(0);
grid->SetCellHighlightROPenWidth(0);
wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL);
// TODO hbox should be aligned to the right using wxALIGN_RIGHT
vbox->Add(hbox, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
vbox->Add(grid, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
notebook->SetSizerAndFit(vbox);
notebook->AddPage(panel, hostname, true);
notebook->Layout();
//notebook->Refresh();
for (int row = 0, i = 0; i < numEntries; row++, i += 2) {
grid->SetCellValue(row, 0, strArray[i]);
grid->SetCellValue(row, 1, strArray[i + 1]);
}
return 0;
}
All help greatly appreciated.
notebook->SetSizerAndFit(vbox)
Replace that with
panel->SetSizer(vbox)
The explanation there is quite extensive. Child windows with a particular parent, can be added to a sizer that must be set to the same parent.
In your code you used panel as parent, but set the sizer to notebook.

Embedding wxWidget controls ontop of each other

I have defined a wxPanel that contains a wxFlexGridSizer which contains 4 rows and 2 columns of controls (wxStaticText and wxTextCtrl).
For atheistic purposes, I want to over lay the content of this sizer with a wxRadioBox (with no radio buttons) as it shows a nice outline around the data I want the user to enter with a little description.
How would I go about achieving this?
Thank you!
Edit:
void MyFrame::Initialize_Project_Info() {
//wxStaticText* s = new wxStaticText(this, wxID_ANY, _T("")); //Random control assigned to the parent to overide wxEVT_SIZE (check wxFrame documentation)
//To try and implement Project Panel
int xx = 5, yy = 10;
int delta_x = 10, delta_y = 10;
wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
wxFlexGridSizer* fgs = new wxFlexGridSizer(4, 2, 10, 15);
wxPanel* Project_Panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(200, 200), wxTAB_TRAVERSAL, _T(""));
wxStaticBoxSizer* sbox = new wxStaticBoxSizer(wxVERTICAL, Project_Panel, _T("Project Information"));
//Project_Info_OverLay = new wxRadioBox(Project_Panel, wxID_ANY, _T("Project Information"), wxPoint(5, 0), wxSize(400, 250), 0, NULL, 1, wxRA_SPECIFY_COLS, wxDefaultValidator, _T(""));
//Note wsSize(width,height).
Project_Name = new wxStaticText(Project_Panel,wxID_ANY,_T("Project:"));
Engineer_Name = new wxStaticText(Project_Panel, wxID_ANY, _T("Engineer:"));
CrossSection_Name = new wxStaticText(Project_Panel, wxID_ANY, _T("Cross Section ID:"));
Additional_Notes = new wxStaticText(Project_Panel, wxID_ANY, _T("Additional Notes:"));
Enter_PN = new wxTextCtrl(Project_Panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB, wxDefaultValidator, _T(""));
Enter_EN = new wxTextCtrl(Project_Panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB, wxDefaultValidator, _T(""));
Enter_CSN = new wxTextCtrl(Project_Panel,wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB, wxDefaultValidator, _T(""));
Enter_AN = new wxTextCtrl(Project_Panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250,100), wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxTE_MULTILINE, wxDefaultValidator, _T(""));
fgs->Add(Project_Name);
fgs->Add(Enter_PN, 1, wxEXPAND);
fgs->Add(Engineer_Name);
fgs->Add(Enter_EN, 1, wxEXPAND);
fgs->Add(CrossSection_Name);
fgs->Add(Enter_CSN, 1, wxEXPAND);
fgs->Add(Additional_Notes);
fgs->Add(Enter_AN, 1, wxEXPAND);
sbox->Add(fgs);
Project_Panel->SetSizer(sbox);
You're almost there. Just change
Project_Panel->SetSizer(sbox);
to
hbox->Add(sbox, wxSizerFlags().Border(wxALL));
Project_Panel->SetSizer(hbox);
Although not part of you're question, I think a better option instead of specifying the horizontal and vertical gaps for the flex grid sizer would be to use sizer flags to define the gaps. This will help your forms be more flexible when dealing with high dpi screens.
To do this, define the sizer like this:
wxFlexGridSizer* fgs = new wxFlexGridSizer(4, 2, 0, 0);
And then add elements to it like this:
fgs->Add(Project_Name,
wxSizerFlags().Align(wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
.Border(wxTOP|wxBOTTOM|wxLEFT));
fgs->Add(Enter_PN,wxSizerFlags().Expand().Border(wxALL));
fgs->Add(Engineer_Name,
wxSizerFlags().Align(wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
.Border(wxBOTTOM|wxLEFT));
fgs->Add(Enter_EN, wxSizerFlags().Expand().Border(wxBOTTOM|wxLEFT|wxRIGHT));
fgs->Add(CrossSection_Name,
wxSizerFlags().Align(wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
.Border(wxBOTTOM|wxLEFT));
fgs->Add(Enter_CSN,
wxSizerFlags().Expand().Border(wxBOTTOM|wxLEFT|wxRIGHT));
fgs->Add(Additional_Notes,
wxSizerFlags().Align(wxALIGN_RIGHT).Border(wxBOTTOM|wxLEFT));
fgs->Add(Enter_AN, wxSizerFlags().Expand().Border(wxBOTTOM|wxLEFT|wxRIGHT));
This produces this layout:
(I've also aligned the static texts next to their text boxes. You can remove the Align(wxALIGN_RIGHT) parts if you don't like this.)
I realize, dealing with sizers can be tricky for newcomers to wxWidgets. There are some graphical gui builders such as wxFormbuilder or wxCrafter that you might find helpful.

How to make stamped image uneditable using iTextSharp?

My goal is stamp an image on a 3D PDF that behaves like a watermark (end-user cannot select, edit, resize, or delete the image).
I tried making an Annotation as shown below, but the image ("ClassificationBlock.png" in Resources) can be resized and deleted on the output PDF. Is that an inherent behavior of "PdfAnnotation" rectangles or is there a property I can define that will keep the image essentially read-only?
using (PdfStamper stamp = new PdfStamper(reader, fs))
.
.
.
Rectangle stampRect2 = null;
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.ClassificationBlock.GetHbitmap());
Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
Rectangle location2 = new Rectangle(0, 0, stampImage2.Width, stampImage2.Height);
PdfAnnotation pdfStamp2 = PdfAnnotation.CreateStamp(stamp.Writer, location2, null, "ImageText");
stampImage2.SetAbsolutePosition(0, 0);
PdfAppearance app2 = stamp.GetOverContent(1).CreateAppearance(stampImage2.Width, stampImage2.Height);
app2.AddImage(stampImage2);
pdfStamp2.SetAppearance(PdfName.N, app2);
pdfStamp2.SetPage();
stamp.AddAnnotation(pdfStamp2, 1);
stampRect2 = location2;
stamp.FormFlattening = true;
stamp.Close();
reader.Close();
fs.Close();
I've also tried it by mimicking another user's attempt at watermark text via pdfContentBytes, but I can't get the image to even display on the PDF.
stamp.FormFlattening = false;
iTextSharp.text.Rectangle pageRectangle = reader.GetPageSizeWithRotation(1);
PdfContentByte pdfData = stamp.GetOverContent(1);
pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 10);
PdfGState graphicsState = new PdfGState();
graphicsState.FillOpacity = 0.5F;
pdfData.SetGState(graphicsState);
pdfData.BeginText();
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.TEKLAPDF_InstructionBlock.GetHbitmap());
iTextSharp.text.Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
float width = pageRectangle.Width;
float height = pageRectangle.Height;
stampImage2.ScaleToFit(width, height);
stampImage2.SetAbsolutePosition(width / 2 - stampImage2.Width / 2, height / 2 - stampImage2.Height / 2);
stampImage2.SetAbsolutePosition(50, 50);
stampImage2.Rotation = 0;
pdfData.AddImage(stampImage2);
pdfData.EndText();
Any ideas on how best to accomplish this? This is driving me crazy.
EDIT*****************************
These are the current avenues I've pursued. Any ideas on how to "watermark" the 3D PDF?
//Stamp Image Method (works on 2D PDF and 3D PDF BUT results in EDITABLE stamp)
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.ClassificationBlock.GetHbitmap());
Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
Rectangle stampRect2 = null;
Rectangle location2 = new Rectangle(0, 0, stampImage2.Width, stampImage2.Height);
PdfAnnotation pdfStamp2 = PdfAnnotation.CreateStamp(stamp.Writer, location2, null, "ImageText");
stampImage2.SetAbsolutePosition(0, 0);
PdfAppearance app2 = stamp.GetUnderContent(1).CreateAppearance(stampImage2.Width, stampImage2.Height);
app2.AddImage(stampImage2);
pdfStamp2.SetAppearance(PdfName.N, app2);
pdfStamp2.SetPage();
stamp.AddAnnotation(pdfStamp2, 1);
stampRect2 = location2;
//Watermark Layering Method (works only on 2D PDF)
var layers = stamp.GetPdfLayers();
var imgLayer = new PdfLayer("StackoverflowImage", stamp.Writer);
PdfContentByte cb = stamp.GetUnderContent(1);
cb.BeginLayer(imgLayer);
stampImage2.ScalePercent(100f);
stampImage2.SetAbsolutePosition(pageWidth/2, pageHeight/2);
cb.AddImage(stampImage2);
cb.EndLayer();
//Jan's Watermark method (works only on 2D PDF)
PdfContentByte over = stamp.GetOverContent(1);
stampImage2.SetAbsolutePosition(pageWidth / 2, pageHeight / 2);
PdfLayer imgLayer = new PdfLayer("StackoverflowImage", stamp.Writer);
imgLayer.OnPanel = false;
over.BeginLayer(imgLayer);
over.AddImage(stampImage2);
over.EndLayer();
stamp.Close();
reader.Close();
First off: You most likely cannot prevent selection of the image.
Second: I do itext in Java, so you'll probably end up uppercasing first character of method names...
For the remainder or your question you could try to add this image to a layer:
PdfContentByte over = stamp.getOverContent(1)
Image img = ...//code to get your image;
img.setAbsolutePosition(x, y); //at your postion
PdfLayer imgLayer = new PdfLayer("StackoverflowImage", stamper.getWriter());
imgLayer.setOnPanel(false);
over.beginLayer(imgLayer);
over.addImage(img);
over.endLayer();
SOLVED! Using the "Stamp Image Method" as described above, I just needed to change the properties of the stamp itself (changing FLAGS to LOCKED and READ-ONLY). This results in a stamp that is above the 3D PDF layer AND cannot be resized, edited, or deleted. So the code is now:
//Stamp Image Method
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.ClassificationBlock.GetHbitmap());
Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
Rectangle stampRect2 = null;
Rectangle location2 = new Rectangle(0, 0, stampImage2.Width, stampImage2.Height);
PdfAnnotation pdfStamp2 = PdfAnnotation.CreateStamp(stamp.Writer, location2, null, "ImageText");
pdfStamp2.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_LOCKED;
pdfStamp2.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_READONLY;
stampImage2.SetAbsolutePosition(0, 0);
PdfAppearance app2 = stamp.GetUnderContent(1).CreateAppearance(stampImage2.Width, stampImage2.Height);
app2.AddImage(stampImage2);
pdfStamp2.SetAppearance(PdfName.N, app2);
pdfStamp2.SetPage();
stamp.AddAnnotation(pdfStamp2, 1);
stampRect2 = location2;

Size a button added to a wxRibbonButtonBar or size the ribbonPanel

I have a basic window (frame) (made with FormBuilder 3.5 actually) with a a vertical sizer and then a horizontal one(shown in code). In the H sizer I have a full ribbon with 1 (page, panel, buttonBar) and one button. I am adding a panel to the ribbon page and then adding a button to the panel. It is being sized so small that the button ends up in a drop-box(pane?) with the button in it. There should be no size constraint, it has plenty of space to be a button.
//late creation code
wxRibbonPage *ribbonPage = m_mainFrame->m_mainRibbonPage;//public pointer
if (nullptr != ribbonPage)
{
wxBoxSizer *a = new wxBoxSizer(wxHORIZONTAL);
wxRibbonPanel *panel = new wxRibbonPanel(ribbonPage, wxID_ANY, wxT("button group"), wxNullBitmap, wxDefaultPosition, wxSize(-1, -1), wxRIBBON_PANEL_DEFAULT_STYLE);
panel->SetSizer(a);
panel->SetSize(wxSize(300, -1));//looks same with/without
wxRibbonButtonBar *btnBar = new wxRibbonButtonBar(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
btnBar->AddToggleButton(wxID_ANY, wxT("play"), wxArtProvider::GetBitmap(wxART_MISSING_IMAGE, wxART_TOOLBAR), wxEmptyString);
}
m_mainFrame->m_ribbonBar2->Realize();
m_mainFrame->m_ribbonBar2->Layout();
m_mainFrame->Bind(wxEVT_MENU, &MyApp::OnSelectCard, this);//these easy
m_mainFrame->Show();
-Having a panel title or not doesn't seem to help.
-Calling wxButtonBar->Realize() doesn't seem to help.
-Calling wxRibbonBar->Layout() doesn't seem to help.
-Setting the minimum panel width to 300 appears to have NO affect.
-Creating a H box sizer and using newPanel->SetSizer(wxBoxSizer a) nope.
-Setting the panel size after setting the box sizer, nope.
and as an added benefit, the panel width goes to about 0 with the sizer.
//early object code derived from wxForm
wxBoxSizer* bSizer26;
bSizer26 = new wxBoxSizer( wxHORIZONTAL );
m_ribbonBar2 = new wxRibbonBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxRIBBON_BAR_DEFAULT_STYLE );
m_ribbonBar2->SetArtProvider(new wxRibbonDefaultArtProvider);
m_mainRibbonPage = new wxRibbonPage( m_ribbonBar2, ID_RIBBON_PAGE, wxEmptyString , wxNullBitmap , 0 );
m_ribbonBar2->SetActivePage( m_mainRibbonPage );
m_ribbonPanel2 = new wxRibbonPanel( m_mainRibbonPage, wxID_ANY, wxEmptyString , wxNullBitmap , wxDefaultPosition, wxDefaultSize, wxRIBBON_PANEL_DEFAULT_STYLE );
m_ribbonPanel2->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
m_ribbonButtonBar2 = new wxRibbonButtonBar( m_ribbonPanel2, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_ribbonButtonBar2->AddHybridButton( wxID_ANY, wxT("Card Select"), wxArtProvider::GetBitmap( wxART_MISSING_IMAGE, wxART_TOOLBAR ), wxEmptyString);
m_ribbonBar2->Realize();
bSizer26->Add( m_ribbonBar2, 1, wxALL, 0 );
I have been looking at wxwidgets.org.
I have been referencing the samples.
I have looked for similar questions.
If I get linked(in comments) to a resource that has an answer, I'll compose an answer if there isn't one.
The reason this happens is because the ribbon auto-sizes your button to a size that's smaller the auto size of the panel it's contained in. If you add at least two buttons to a panel then it looks fine.
But fear not, there is a way around this. I had to crack open the source code to figure it out, so it might be a bit of a hack. I am not sure if the developers plan on exposing the functionality or not.
The buttonbar.h header does not expose the members of wxRibbonButtonBarButtonSizeInfo or wxRibbonButtonBarButtonBase, so first you have to declare them in your source:
class wxRibbonButtonBarButtonSizeInfo
{
public:
bool is_supported;
wxSize size;
wxRect normal_region;
wxRect dropdown_region;
};
class wxRibbonButtonBarButtonBase
{
public:
wxRibbonButtonBarButtonInstance NewInstance();
wxRibbonButtonBarButtonState GetLargestSize();
bool GetSmallerSize(wxRibbonButtonBarButtonState* size, int n = 1);
wxString label;
wxString help_string;
wxBitmap bitmap_large;
wxBitmap bitmap_large_disabled;
wxBitmap bitmap_small;
wxBitmap bitmap_small_disabled;
wxRibbonButtonBarButtonSizeInfo sizes[3];
wxClientDataContainer client_data;
int id;
wxRibbonButtonKind kind;
long state;
};
Now that you have these members declared, you can simply change the "x" value of the "LARGE" size of the button that you added to the bar:
wxRibbonButtonBarButtonBase* newButton = buttonBar->AddButton( wxID_NEW,
"New", wxArtProvider::GetBitmap(wxART_NEW, wxART_TOOLBAR) );
newButton->sizes[wxRIBBON_BUTTONBAR_BUTTON_LARGE].size.x = 48;
And viola! Your single button, now having the correct width, will be displayed correctly on the panel. It seems that 48 pixels is the correct minimum size.
Also, you don't need a horizontal sizer to contain the ribbon. I typically just stack a ribbon and panel in a vertical sizer and then use the panel for the "main" part of the window.
wxFrame* frame = new wxFrame( NULL, wxID_ANY, "wxTestProject",
wxDefaultPosition, wxSize(640,480) );
wxRibbonBar* ribbon = new wxRibbonBar( frame, wxID_ANY );
wxPanel* panel = new wxPanel( frame );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
sizer->Add( ribbon, 0, wxGROW, 0 );
sizer->Add( panel, 1, wxGROW, 0 );
frame->SetSizer( sizer );

wxWidgets alignment problems

I want to create with wxWidgets window in which to top listbox, its size changed when you change the window size. Below are three buttons which size does not change when window size changed. Distance between the buttons and listbox constantly, and does not change when you resize the window.
You want a vertical wx.BoxSizer with proportion of 1 and wx.EXPAND flag. This sizer will have in it your listbox, added with proportion of 1 and wx.EXPAND flag. This sizer will also have in it a horizontal box sizer with the three buttons added. You want to do a window.SetSizer(<your vertical sizer>) to the "window" you mention (probably a wx.Frame).
void SizerTest::CreateControls()
{
////#begin SizerTest content construction
SizerTest* itemFrame1 = this;
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
itemFrame1->SetSizer(itemBoxSizer2);
wxArrayString itemListBox3Strings;
wxListBox* itemListBox3 = new wxListBox( itemFrame1, ID_LISTBOX2, wxDefaultPosition, wxDefaultSize, itemListBox3Strings, wxLB_SINGLE );
itemBoxSizer2->Add(itemListBox3, 1, wxGROW|wxLEFT|wxRIGHT|wxTOP, 5);
wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
itemBoxSizer2->Add(itemBoxSizer4, 0, wxALIGN_LEFT, 0);
wxButton* itemButton5 = new wxButton( itemFrame1, ID_BUTTON3, _("Button"), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer4->Add(itemButton5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxButton* itemButton6 = new wxButton( itemFrame1, ID_BUTTON4, _("Button"), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer4->Add(itemButton6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxButton* itemButton7 = new wxButton( itemFrame1, ID_BUTTON5, _("Button"), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer4->Add(itemButton7, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
////#end SizerTest content construction
}
Should look like this: http://screencast.com/t/ZonUBhPZ7
Resized: http://screencast.com/t/zRDpDix7Yr