Resize a window full width Topic is solved

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
gmapp
Earned a small fee
Earned a small fee
Posts: 19
Joined: Wed Jan 24, 2018 4:39 pm

Resize a window full width

Post by gmapp »

Hi,

Simplifying what I need with an example:
I'm trying to implement a button that changes the position and the size of the window.
In the end, the windows should have a size s=(full-width, 250 pixels) and be positioned on the top of my display.
The following code works... but the window is some pixels too small (8 pixels left, 8 right, 8 on bottom).
Is there a bug in my code? In the library?

Code: Select all

void wxTestFrame::OnButton1Click(wxCommandEvent& event){
    int height_main_frame = 250;

    // Get display size
    wxDisplay display(wxDisplay::GetFromWindow(this));
    //wxRect screen = display.GetGeometry();
    //std::cout << screen.width << "x" << screen.height << std::endl;
    wxRect screen = display.GetClientArea();
    std::cout << screen.width << "x" << screen.height << std::endl;

    // Set new size and position for the main window
    this->SetSize(0, 0, screen.width, screen.height);
    
    // Correct size on my enviroment (full screen for testing purpose)
    //this->SetSize(-8, 0, screen.width+16, screen.height+8);
}
OS: Win10
IDE: VS
wx: 3.1.3

Thanks
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Resize a window full width

Post by doublemax »

The code looks ok and does work for me. Does display.GetClientArea() return the expected values? Do you have an code that could restrict the size of the window? Try the code in the "minimal" sample that comes with wxWidgets.
Use the source, Luke!
gmapp
Earned a small fee
Earned a small fee
Posts: 19
Joined: Wed Jan 24, 2018 4:39 pm

Re: Resize a window full width

Post by gmapp »

Yes, display.GetClientArea() returns the expected values (1920x1040)
I tested the code in the minimal sample and I got the same problem...

Code: Select all

 I pasted the code into MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
Unfortunately, I removed an old version of wx library (useful to test) but at this point, it looks like a bug... isn't it?
Have I to run layout() after SetSize()?

Thanks for your help
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Resize a window full width

Post by ONEEYEMAN »

Hi,
You can try and see if it helps.

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Resize a window full width

Post by doublemax »

I removed an old version of wx library (useful to test) but at this point, it looks like a bug... isn't it?
Very unlikely. Try tracing through the SetSize() call and see what it does.
Have I to run layout() after SetSize()?
No. Layout() is for the sizer algorithm, it has nothing to do with the outer size of a toplevel window.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Resize a window full width

Post by PB »

FWIW, I vaguely remember recently using SetSize() on a wxFrame and the resulting size being a couple of pixels off the requested at least in one dimension (Win10).
gmapp
Earned a small fee
Earned a small fee
Posts: 19
Joined: Wed Jan 24, 2018 4:39 pm

Re: Resize a window full width

Post by gmapp »

I ran some tests:
1) On windows wx version 3.1.3 the code doesn't work as aspected
2) On windows wx version 3.0.4 it doesn't work as aspected
3) On Linux wx version 3.1.1 it WORKS :D ! (It was just a test, I need a windows software, unfortunately)

On Windows in debugging mode, I followed step by step the function SetSize(). I arrived at line 1960 of the window.cpp file[1]:

Code: Select all

if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
The values of the parameters were correct (hwnd, 0, 0, 1920, 250, true).
But I was not able to step into the MoveWindow function with the VS debugger. I'm not a debugging expert, if anyone has suggestions, I'm happy to continue.

Thanks

[1] windows wxWidgets 3.0.4 source
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Resize a window full width

Post by doublemax »

I tried under Windows 10 and see it too. I'm almost certain it's done by Windows 10 on purpose, although i can't find any documentation for it. In any case, i don't know what you can do about it.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Resize a window full width

Post by PB »

Is not the issue the invisible border around the window, making it seem smaller than it really is, e.g.
https://stackoverflow.com/questions/319 ... ing-border
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Resize a window full width

Post by doublemax »

PB wrote: Fri Mar 27, 2020 5:08 pm Is not the issue the invisible border around the window, making it seem smaller than it really is, e.g.
https://stackoverflow.com/questions/319 ... ing-border
Nice, i guess "invisible borders" was the right keyword for Google to find it ;)
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Resize a window full width

Post by PB »

This post may better explain "invisible borders" in Win10
https://stackoverflow.com/a/34143777/7267315

Not sure if it is of any help to the OP...
gmapp
Earned a small fee
Earned a small fee
Posts: 19
Joined: Wed Jan 24, 2018 4:39 pm

Re: Resize a window full width

Post by gmapp »

Thank you all for your support. As suggested I have solved the problem by increasing, on windows, by 8 pixels to the right, left and bottom.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Resize a window full width

Post by PB »

Perhaps instead of hard-coding the values, you could use the way described in the second post I linked. Possibility of these values changing in future Windows versions aside, I would not be surprised if these values were noticeably different when using large DPI scaling such as 200%.

EDIT
Just for the future reference, this seems to work fine

Code: Select all

#include <wx/wx.h>
#include <wx/display.h>

#ifdef __WXMSW__
    #include <dwmapi.h> // needs also to link with dwmapi.lib
#endif // __WXMSW__

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, _("Test"))
    {
        wxPanel* mainPanel = new wxPanel(this);
        wxBoxSizer* mainPanelSizer = new wxBoxSizer(wxVERTICAL);
        
        wxButton* button = new wxButton(mainPanel, wxID_ANY, "Fit to Screen");        
        button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::FitToScreen, this);
        mainPanelSizer->Add(button, wxSizerFlags().Border().CenterHorizontal());

        wxTextCtrl* logCtrl = new wxTextCtrl(mainPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
            wxTE_MULTILINE | wxTE_RICH2 | wxTE_READONLY);
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));
        wxLog::DisableTimestamp();
        mainPanelSizer->Add(logCtrl, wxSizerFlags().Proportion(1).Expand().Border());

        mainPanel->SetSizer(mainPanelSizer);
    }	
private:    
    static wxString wxRectTowxString(const wxRect& r)
    {
        return wxString::Format(_("(left, top; right, bottom): %d, %d; %d, %d"),
            r.GetLeft(), r.GetTop(), r.GetRight(), r.GetBottom());
    }
    
    void FitToScreen(wxCommandEvent&)
    {        
        const wxDisplay display(wxDisplay::GetFromWindow(this));    

        if ( !display.IsOk() )
        {
            wxLogError("Could not create wxDisplay from this window.");
            return;
        }

        const wxRect displayClientRect(display.GetClientArea());
        wxRect windowRect(displayClientRect);        

        wxLogMessage("%s (%dx%d DPI) client rect %s", display.GetName(), 
            display.GetPPI().GetWidth(), display.GetPPI().GetHeight(),
            wxRectTowxString(displayClientRect));        

#ifdef __WXMSW__
        // based on the code from https://stackoverflow.com/a/34143777/7267315
        RECT dwmRect;
        
        if ( SUCCEEDED(::DwmGetWindowAttribute(GetHWND(), DWMWA_EXTENDED_FRAME_BOUNDS,
                       &dwmRect, sizeof(dwmRect))) )
        {
            wxRect borders;
            wxRect windowRectAdjusted(GetRect());

            borders.SetLeft(dwmRect.left - windowRectAdjusted.GetLeft());
            borders.SetTop(dwmRect.top - windowRectAdjusted.GetTop());
            borders.SetRight(windowRectAdjusted.GetRight() - dwmRect.right);
            borders.SetBottom(windowRectAdjusted.GetBottom() - dwmRect.bottom);
            wxLogMessage("Window invisible borders %s", wxRectTowxString(borders));

            windowRectAdjusted = windowRect;
            windowRectAdjusted.Offset(-borders.GetLeft(), -borders.GetTop());
            windowRectAdjusted.SetWidth(windowRect.GetWidth() + borders.GetLeft() + borders.GetRight());
            windowRectAdjusted.SetHeight(windowRect.GetHeight() + borders.GetTop() + borders.GetBottom());            
            wxLogMessage("Adjusted fit-to-screen window rect %s", wxRectTowxString(windowRectAdjusted));

            windowRect = windowRectAdjusted;
        }
#endif // __WXMSW__
        
        SetSize(windowRect);
    }
};


class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        (new MyFrame())->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);;
Regarding the difference with DPI scaling:

Code: Select all

\\.\DISPLAY1 (120x120 DPI) client rect (left, top; right, bottom): 0, 0; 2559, 1338
Window invisible borders (left, top; right, bottom): 8, 0; 7, 7
Adjusted fit-to-screen window rect (left, top; right, bottom): -8, 0; 2566, 1345
\\.\DISPLAY2 (96x96 DPI) client rect (left, top; right, bottom): -1680, 195; -1, 1204
Window invisible borders (left, top; right, bottom): 7, 0; 6, 6
Adjusted fit-to-screen window rect (left, top; right, bottom): -1687, 195; 5, 1210

so the difference could be noticeable with higher differences in DPI scalings when hard-coded borders are used...

You can also see (for \\.\DISPLAY2) that for the display client rect neither top nor left are always 0, if one has multiple displays (which is nowadays very common).
Post Reply