Creating application with DPI awareness

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
philm
Experienced Solver
Experienced Solver
Posts: 88
Joined: Fri Dec 18, 2015 4:46 am

Creating application with DPI awareness

Post by philm »

Hello everyone,

I am currently rewriting some code so that I can have my application better handle high DPI settings. I am currently developing on ubuntu 14.04 and I am using wxWidgets 3.1.0. I was wondering if there are any good methods on allowing your application to scale based on the DPI settings.

Here is a code snippet from one of my dialogs:

Code: Select all

    wxFont *font = new wxFont(8.5, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
    wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
    
	// This seciton will create a new panel and apply 2 buttons on the panel. 
	// The 2 buttons are associated with the panel and when the panel is destoryed, so are the buttons.
	initialStartPanel->Create(this, wxID_ANY, wxDefaultPosition);
	
	wxButton *buttonNewFile = new wxButton(initialStartPanel, buttonID::ID_buttonNew, "New", wxDefaultPosition);
    buttonNewFile->SetFont(*font);
    buttonNewFile->SetMinSize(initialStartPanel->FromDIP(wxSize(75, 23)));
 //   buttonNewFile->SetInitialSize(FromDIP(wxSize(75, 23), this));
 //   buttonNewFile->SetSize(buttonNewFile->GetBestFittingSize());
   // buttonNewFile->SetSize(wxSize(75, 23));
	wxButton *buttonOpenFile = new wxButton(initialStartPanel, buttonID::ID_buttonOpen, "Open");
    buttonOpenFile->SetFont(*font);
    buttonOpenFile->SetInitialSize(FromDIP(wxSize(75, 23)));
    
    buttonSizer->Add(buttonNewFile, 0, wxALL, 6);
    buttonSizer->Add(buttonOpenFile, 0, wxTOP | wxBOTTOM | wxRIGHT, 6);

    initialStartPanel->SetSizer(buttonSizer);
    
    SetSizerAndFit(buttonSizer);
    buttonSizer->Fit(initialStartPanel);
    
    this->SetSize(initialStartPanel->GetSize());
    this->SetMaxSize(this->GetSize());
 //   this->SetMinSize(initialStartPanel->GetSize());
 //   this->SetMaxSize(initialStartPanel->GetSize());
We already have the frame created and I am adding a panel with two buttons. Quite simple. However, I noticed that when I run the program and increase the dip settings in ubuntub, the font on the buttons gets cut off. I am looking to adjust the size of the buttons in order to prevent this from happening.

As you can see in my code, I have been trying some different methods. With 3.1.0, I have been trying to utilize the FromDIP function. My interpretation on this function is that it is able to take in a set wxSize() and return a scaled wxSize value based on the DPI settings. Please correct me if I am wrong.

I also have been looking at another post where the user would like to implement scaling based on DPI settings:

viewtopic.php?t=41603

However, when I implemented my method on using the wxDLG_unit, the button became too huge!

For those wondering, at a normal DPI setting, the size of the button needs to be wxSize(75, 23). If the DPI is increased, then the button should increase in proportion. If the DPI is decreased then there is no change in the size.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Creating application with DPI awareness

Post by doublemax »

I don't know anything about High DPI under Linux, but i think using absolute sizes, even with a correction for the DPI, is a bad idea. If you use wxDefaultSize you shouldn't get clipped text in buttons.

However, wxWidgets does not support changing DPI at runtime. You have to restart the application to see the changes. Or you would have to detect it yourself somehow and re-layout all controls.
Use the source, Luke!
philm
Experienced Solver
Experienced Solver
Posts: 88
Joined: Fri Dec 18, 2015 4:46 am

Re: Creating application with DPI awareness

Post by philm »

Yes, I am going to be assuming that the user is starting the application when they are in high DPI versus detecting during runtime. The latter might be a bit more complicated.

I would use wxDefaultSize but the size is bigger then what I am looking for. Could I get some clarification on what FromDIP does?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Creating application with DPI awareness

Post by doublemax »

Could I get some clarification on what FromDIP does?
A look into the source code is always the fastest and most reliable way to do that ;)

Code: Select all

/* static */
wxSize wxWindowBase::FromDIP(const wxSize& sz, const wxWindowBase* WXUNUSED(w))
{
    const wxSize dpi = wxScreenDC().GetPPI();

    // Take care to not scale -1 because it has a special meaning of
    // "unspecified" which should be preserved.
    return wxSize(sz.x == -1 ? -1 : wxMulDivInt32(sz.x, dpi.x, BASELINE_DPI),
                  sz.y == -1 ? -1 : wxMulDivInt32(sz.y, dpi.y, BASELINE_DPI));
}
As you can see, it does what you suspected.
Use the source, Luke!
Post Reply