Reputation: 89
I have been using wxWidgets 3.1.6
to create a C++
Windows 11
application, which I haven't been having a good experience with so far.
My application has been using absolute positioning for a long time, so I decided to switch to using wxSizers
instead.
With the help of wxSizers
, my widgets
are sized and laid out for me automatically.
I managed to use wxSizers
with my application without having to hardcode
any sizes.
However when checking to see what my program looks like on high dpi
, I see that my wxTextCtrl
isn't sized properly.
This is because even though I didn't hardcode any widgets, I did do something similar with my wxTextCtrl
.
Consider this code:
/* I am trying to set a wxTextCtrl's size based on the number of characters in it
/* In this case the number of characters is 162.
/* */
wxFont bigfont; // Creating font
bigfont.SetPointSize(11);
auto textctrl = new wxTextCtrl(panel, wxID_ANY, ""); // Creating textctrls
text->SetFont(bigfont);
std::string number_of_characters = std::string(162, ' ');
wxSize size = textctrl->GetSizeFromText(number_of_characters); // When checking the variable "size" in the debugger, it shows a different value for high and low dpi
textctrl->SetMinSize(size);
I am trying to set the wxTextCtrl's
size by making it display a given amount of characters, in this case, it's 162.
When checking the variable size
in the debugger :
On low dpi:
x = 499 , y = -1
On high dpi:
x = 644 , y = -1
Note: I don't care about the y axis since it will be calculated automatically by the sizers.
How Do I use wxControl::GetSizeFromText()
in such a way that I can make my wxTextCtrl
have the same size for high
and low dpi
??
If I can't do that ( I have realistic expectations )
then I need some other way to size the wxTextCtrl
.
Without sizing it myself, The widget would be sized differently which would be bad for UX reasons.
I've tried using FromDIP()
and ToDIP()
and dividing the size with wxWindow::GetDPIScaleFactor()
.
FromDIP()
returned a bigger size, when I needed to decrease the size:
x = 830 y = -1
ToDIP()
returned a smaller size :
x = 531 y = -1
Dividing my size with wxWindow::GetDPIScaleFactor()
returns the same size as ToDIP()
.
I checked the value of wxWindow::GetDPIScaleFactor()
:
It returned 1 for low dpi
It returned 1.25 for high dpi
Here is what the problem looks like :
As you can see the wxTextCtrl
on high dpi
is much longer then the wxTextCtrl
on low dpi
.
This is what is looks like without FromDIP()
and ToDIP()
.
Thank you.
Edit :
Here is my reproducible example , please test this on high
and low dpi
to see the difference:
This is only valid 7 days
from now...
Edit 2 :
Here is the source code:
wxFrame.cpp
#include "wxFrame.h"
MyFrame::MyFrame() : wxFrame(nullptr,
wxID_ANY,
"Sample",
wxDefaultPosition,
wxDefaultSize,
wxDEFAULT_FRAME_STYLE)
{
wxFont bigfont;
bigfont.SetPointSize(11);
wxFont smallfont;
smallfont.SetPointSize(10);
wxPanel* panel = new wxPanel(this, wxID_ANY);
wxBoxSizer* outerSizer = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer* fgs = new wxFlexGridSizer(3, 0, 3);
// row 1
int hello = 4;
auto text = new wxStaticText(panel, wxID_ANY, "Input File:");
auto textctrl = new wxTextCtrl(panel, wxID_ANY, "");
auto button = new wxButton(panel, wxID_ANY, " ... ", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
text->SetFont(bigfont);
// Getting textctrl size from text size
std::string spaces = std::string(162, ' ');
double dpi = wxWindow::GetDPIScaleFactor();
wxSize size__ = ToDIP(textctrl->GetSizeFromTextSize(
textctrl->GetTextExtent(spaces)));
// size__ /= dpi;
textctrl->SetMinSize(size__);
fgs->Add(text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 4);
fgs->Add(textctrl, 0, wxEXPAND | wxALL, 4);
fgs->Add(button, 0, wxALL, 4);
// row 2
auto text_ = new wxStaticText(panel, wxID_ANY, "Output Folder:");
auto textctrl_ = new wxTextCtrl(panel, wxID_ANY, "");
auto button_ = new wxButton(panel, wxID_ANY, " ... ", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
text_->SetFont(bigfont);
fgs->Add(text_, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 4);
fgs->Add(textctrl_, 0, wxEXPAND | wxALL, 4);
fgs->Add(button_, 0, wxALL, 4);
fgs->AddGrowableCol(1);
outerSizer->Add(fgs, 0, wxEXPAND | wxALL, 16); // <- border at all sides
panel->SetSizer(outerSizer);
outerSizer->SetSizeHints(this);
}
MyFrame::~MyFrame()
{
}
wxFrame.h
#include "wxIncludes.h"
///// Our Main Frame
/**/
class MyFrame : public wxFrame {
public :
// Sample Button
wxButton* sample = nullptr;
// Constructor
MyFrame();
// Destructor
~MyFrame();
};
wxApp.h
///// wxWidgets includes header
/**/
#include "wxIncludes.h"
#include "wxFrame.h"
class myApp : public wxApp {
public :
///// Startup function
/**/
myApp();
~myApp();
virtual bool OnInit();
};
wxApp.cpp
#include "wxApp.h"
///// Initalize the app
/**/
IMPLEMENT_APP(myApp);
// Constructor
myApp::myApp()
{}
// Destructor
myApp::~myApp()
{}
///// Startup function
/**/
bool myApp::OnInit()
{
// Creating our frame
MyFrame* myFrame = new MyFrame();
myFrame->Show();
// Continue to show window
return true;
}
wxIncludes.h
///// Winsock header
/**/
#include <winsock2.h>
///// Winsock header
/**/
#include <wx/wx.h>
#include <wx/zipstrm.h>
#include <wx/dir.h>
#include <wx/wfstream.h>
#include <wx/progdlg.h>
#include <wx/dirdlg.h>
#include <wx/statline.h>
Upvotes: 2
Views: 547
Reputation: 22753
The fact that GetSizeFromText()
doesn't return the same size in high DPI is not a problem at all -- actually it would be a problem if it did return the same size, as then the control would be twice smaller when using 200% scaling, for example.
What you seem to be complaining about it is that its result doesn't scale perfectly with the DPI scaling factor, i.e., if I understand you correctly, you'd expect it to return 1.25*500 == 625
instead of 644 you actually get when using 125% scaling. This is not totally unexpected neither because:
The difference of 19 pixels is a bit more than I'd expect, but, again, you can't count on it being exactly the same anyhow.
If you really must have the same size in any DPI (why?), you need to scale the desired size in DPI-Independent Pixels (called DIPs in wx API) using FromDIP()
, e.g. you could use FromDIP(wxSize(500, -1))
instead. It is not recommended to this, GetSizeFromText()
should be more precise, but if you want to have exactly the same size in all resolutions, you could do it like this.
Upvotes: 4