wxStatusBar - How to position a bitmap in the status bar correctly?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

wxStatusBar - How to position a bitmap in the status bar correctly?

Post by apoorv569 »

I'm trying to put a bitmap image on the statusbar, that has 3 sections. I created the statusbar with the CreateStatusBar(3). I want to display the bitmap in the last section before the text I am displaying. But I'm not sure how to position it properly. Here is a example image, for where I want to draw,
Image

The red is what I want to draw, and the green is where I want to draw.

Here is how I create the statusbar,

Code: Select all

    m_StatusBar = CreateStatusBar(3);

    int status_width[3] = { -2, -6, -1 };
    m_StatusBar->SetStatusWidths(3, status_width);
I can set a position manually but it won't be dynamic, different resolution/window size can put it some different position. Here is how I am drawing bitmap on the statusbar,

Code: Select all

    wxRect rect;
    m_StatusBar->GetFieldRect(2, rect);
    wxStaticBitmap* bm = new wxStaticBitmap(m_StatusBar, wxID_ANY, wxBitmap(ICON_APP), wxPoint(rect.x, rect.y));
Here is a screenshot of where it draws using the above code,
Image
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by doublemax »

Check the "statbar" sample that comes with wxWidgets, its shows how to do it. Basically, you need to catch the EVT_SIZE size event and recalculate the position of the bitmap each time.
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by apoorv569 »

doublemax wrote: Thu Jul 08, 2021 11:27 pm Check the "statbar" sample that comes with wxWidgets, its shows how to do it. Basically, you need to catch the EVT_SIZE size event and recalculate the position of the bitmap each time.
I draw the bitmap initially like this,

Code: Select all

MainFrame::MainFrame()
    : wxFrame(NULL, wxID_ANY, "Sample Hive", wxDefaultPosition),
      m_ConfigFilepath("config.yaml"), m_DatabaseFilepath("sample.hive")
{
    m_StatusBar = CreateStatusBar(3);

    int status_width[3] = { -2, -6, -1 };
    m_StatusBar->SetStatusWidths(3, status_width);

    int status_style[3] = { wxSB_NORMAL, wxSB_RAISED, wxSB_SUNKEN };
    m_StatusBar->SetStatusStyles(3, status_style);

    bm = new wxStaticBitmap(m_StatusBar, wxID_ANY, wxBitmap(ICON_APP));
But when I Bind the event for EVT_SIZE, the application looks weird, all the layout seems messed up,
Image

Code: Select all

    Bind(wxEVT_SIZE, &MainFrame::OnResizeStatusBar, this);
If I try to resize the window, nothing happens, but if I resize the splitter window, then this happens,
Image

If I comment out the Bind() for EVT_SIZE, then this issue gets fixed.

Here is the OnResizeStatusBar()

Code: Select all

void MainFrame::OnResizeStatusBar(wxSizeEvent& event)
{
    wxRect rect;
    m_StatusBar->GetFieldRect(1, rect);

    wxSize bmsize = bm->GetSize();

    bm->Move(rect.x + (rect.width - bmsize.x) / 2,
             rect.y + (rect.height - bmsize.y) / 2);
}
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by doublemax »

Catch the size event of the status bar, not the frame. And, in 99.9% of all cases when you have an wxEVT_SIZE event handler, you need to call event.Skip in it.
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by apoorv569 »

doublemax wrote: Fri Jul 09, 2021 3:12 pm Catch the size event of the status bar, not the frame. And, in 99.9% of all cases when you have an wxEVT_SIZE event handler, you need to call event.Skip in it.
I see. I tried catching the event for status bar, looks like its working now, I did ran the app at first without the event.Skip() it crashed immediately.

Code: Select all

MainFrame::MainFrame()
    : wxFrame(NULL, wxID_ANY, "Sample Hive", wxDefaultPosition),
      m_ConfigFilepath("config.yaml"), m_DatabaseFilepath("sample.hive")
{
    m_StatusBar = CreateStatusBar(3);

    int status_width[3] = { -2, -6, -1 };
    m_StatusBar->SetStatusWidths(3, status_width);

    bm = new wxStaticBitmap(m_StatusBar, wxID_ANY, wxBitmap(ICON_APP));
Then I connected the status bar to the event,

Code: Select all

    m_StatusBar->Connect(wxEVT_SIZE, wxSizeEventHandler(MainFrame::OnResizeStatusBar), NULL, this);
Here is the event handler,

Code: Select all

void MainFrame::OnResizeStatusBar(wxSizeEvent& event)
{
    wxLogDebug("RESIZING..");

    wxRect rect;
    m_StatusBar->GetFieldRect(2, rect);

    wxSize bmsize = bm->GetSize();

    bm->Move(rect.x + (rect.width - bmsize.x),
             rect.y + (rect.height - bmsize.y));

    event.Skip();
}
There is one problem however, initially it draws the bitmap in the bottom left, beginning of the statusbar.
Image

But when I resize the window, then it moves to the right position,
Image

Also when I resize the window a bit too small, the bitmap starts overlapping the text and the second section of the statusbar, moves a little too much backwards then I would like, I want it to always be under the wxDVLC, just starting from the below the sash line of wxDirCtrl. Can sizers be places in the statusbar to properly layout widgets?
Image

Maybe I should start with setting the minimum size of the window, and it should not be resizable below that. But what about the statusbar section widths? Do I set it to something like m_BottomSplitter->GetMinWidth() ?
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by doublemax »

Usually there is not such a tight coupling between the layout of the status bar and the layout of the main content. Maybe it would be easier if you just added another panel at the bottom instead of the status bar?
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by apoorv569 »

doublemax wrote: Fri Jul 09, 2021 10:48 pm Usually there is not such a tight coupling between the layout of the status bar and the layout of the main content. Maybe it would be easier if you just added another panel at the bottom instead of the status bar?
I see, I guess I'll stick with the statusbar for now. Maybe some other time I change it.

BTW how do I set its initial position to also be the same as when resized, if I just do this,

Code: Select all

MainFrame::MainFrame()
    : wxFrame(NULL, wxID_ANY, "Sample Hive", wxDefaultPosition),
      m_ConfigFilepath("config.yaml"), m_DatabaseFilepath("sample.hive")
{
    m_StatusBar = CreateStatusBar(3);

    int status_width[3] = { -2, -6, -1 };
    m_StatusBar->SetStatusWidths(3, status_width);

    bm = new wxStaticBitmap(m_StatusBar, wxID_ANY, wxBitmap(ICON_APP));

    wxRect rect;
    m_StatusBar->GetFieldRect(2, rect);

    wxSize bmsize = bm->GetSize();

    bm->SetPosition(wxPoint(rect.x + (rect.width - bmsize.x), rect.y + (rect.height - bmsize.y)));
It draws here, in the middle of the statusbar,
Image

After resizing the window it fixes it self,
Image
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by doublemax »

I would have expected the size event handler to be enough. The statbar sample also doesn't contain any additional code for positioning the bitmap. Does it work correctly for you?

Code: Select all

m_StatusBar->GetFieldRect(2, rect);
Print out the values you get for the rect here and check if they are what you expect.
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by apoorv569 »

doublemax wrote: Sat Jul 10, 2021 8:20 am I would have expected the size event handler to be enough. The statbar sample also doesn't contain any additional code for positioning the bitmap. Does it work correctly for you?

Code: Select all

m_StatusBar->GetFieldRect(2, rect);
Print out the values you get for the rect here and check if they are what you expect.
I fixed it, it was not a problem with wx, it was my window manger acting weird.

But I also noticed that the OnResizeStatusBar() gets called 3 times, I have wxLogDebug statement inside the method, and it gets printed 3 times. Is this behavior normal/expected?

Also using different system theme and different window sizes, it doesn't look very consistent. I think I'll remove the bitmap from the statusbar. And stick with just the text.
Image
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by apoorv569 »

doublemax wrote: Sat Jul 10, 2021 8:20 am I would have expected the size event handler to be enough. The statbar sample also doesn't contain any additional code for positioning the bitmap. Does it work correctly for you?

Code: Select all

m_StatusBar->GetFieldRect(2, rect);
Print out the values you get for the rect here and check if they are what you expect.
Okay after playing with it for a while, I think I got it how I want it to be. I set the minimum size that the window can be resized to, and I also the width for the first and last section to hard coded value, so the icon stays where it should be and cannot overlap the text before it, and resizing the window will always keep it after the text,

Code: Select all

MainFrame::MainFrame()
    : wxFrame(NULL, wxID_ANY, "Sample Hive", wxDefaultPosition),
      m_ConfigFilepath("config.yaml"), m_DatabaseFilepath("sample.hive")
{
    m_StatusBar = CreateStatusBar(3);

    int status_width[3] = { 300, -1, 135 };
    m_StatusBar->SetStatusWidths(3, status_width);
.
.
.
    this->SetMinSize(wxSize(width, height));
300 is the minimum size of the left splitter window, and for the last section, I just messed around and found a sweet spot for it.

Image

Hope this will be good enough.
itachiboi999
Knows some wx things
Knows some wx things
Posts: 33
Joined: Mon Nov 15, 2021 7:06 pm

Re: wxStatusBar - How to position a bitmap in the status bar correctly?

Post by itachiboi999 »

apoorv569 wrote: Sat Jul 10, 2021 9:55 pm
doublemax wrote: Sat Jul 10, 2021 8:20 am I would have expected the size event handler to be enough. The statbar sample also doesn't contain any additional code for positioning the bitmap. Does it work correctly for you?

Code: Select all

m_StatusBar->GetFieldRect(2, rect);
Print out the values you get for the rect here and check if they are what you expect.
Okay after playing with it for a while, I think I got it how I want it to be. I set the minimum size that the window can be resized to, and I also the width for the first and last section to hard coded value, so the icon stays where it should be and cannot overlap the text before it, and resizing the window will always keep it after the text,

Code: Select all

MainFrame::MainFrame()
    : wxFrame(NULL, wxID_ANY, "Sample Hive", wxDefaultPosition),
      m_ConfigFilepath("config.yaml"), m_DatabaseFilepath("sample.hive")
{
    m_StatusBar = CreateStatusBar(3);

    int status_width[3] = { 300, -1, 135 };
    m_StatusBar->SetStatusWidths(3, status_width);
.
.
.
    this->SetMinSize(wxSize(width, height));
300 is the minimum size of the left splitter window, and for the last section, I just messed around and found a sweet spot for it.

Image

Hope this will be good enough.
Hey! i am trying to do the same thing for my application and I was wondering both what your width and height values are to allow it to fit and stay in the bottom right-hand corner and was also wondering how you got the main wxFrame to be dark gray/night mode looking??l!!
Because I know if you make the frame a variable you can use SetBackgroundColour(), but what if you declare it this way:

Code: Select all

cppMain::cppMain() : wxFrame(nullptr, wxID_ANY, "Example Frame", wxPoint(30, 30), wxSize(1300,700)
{
.
.
.

})
how could i have the wxFrame adopt the darker color properties?? and is this color aspect adjustable dynamically?


Any and all help is extremely appreciated!
Thank you in advance !
Post Reply