Improvements of High DPI scaling on Windows.

This commit is contained in:
bubnikv 2019-05-06 18:28:23 +02:00
parent 045879f68a
commit c9cd4818c7
9 changed files with 48 additions and 30 deletions

View File

@ -340,15 +340,19 @@ void GUI_App::init_fonts()
#endif /*__WXMAC__*/
}
void GUI_App::update_fonts()
void GUI_App::update_fonts(const MainFrame *main_frame)
{
/* Only normal and bold fonts are used for an application rescale,
* because of under MSW small and normal fonts are the same.
* To avoid same rescaling twice, just fill this values
* from rescaled MainFrame
*/
m_normal_font = mainframe->normal_font();
m_bold_font = mainframe->normal_font().Bold();
if (main_frame == nullptr)
main_frame = this->mainframe;
m_normal_font = main_frame->normal_font();
m_small_font = m_normal_font;
m_bold_font = main_frame->normal_font().Bold();
m_em_unit = main_frame->em_unit();
}
void GUI_App::set_label_clr_modified(const wxColour& clr) {
@ -773,14 +777,14 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
// to notify the user whether he is aware that some preset changes will be lost.
bool GUI_App::check_unsaved_changes()
{
std::string dirty;
wxString dirty;
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
for (Tab *tab : tabs_list)
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
if (dirty.empty())
dirty = tab->name();
dirty = _(tab->name());
else
dirty += std::string(", ") + tab->name();
dirty += wxString(", ") + _(tab->name());
if (dirty.empty())
// No changes, the application may close or reload presets.
return true;

View File

@ -100,7 +100,7 @@ public:
void init_label_colours();
void update_label_colours_from_appconfig();
void init_fonts();
void update_fonts();
void update_fonts(const MainFrame *main_frame = nullptr);
void set_label_clr_modified(const wxColour& clr);
void set_label_clr_sys(const wxColour& clr);

View File

@ -64,6 +64,7 @@ template<class F> typename F::FN winapi_get_function(const wchar_t *dll, const c
}
#endif
// If called with nullptr, a DPI for the primary monitor is returned.
int get_dpi_for_window(wxWindow *window)
{
#ifdef _WIN32
@ -82,7 +83,8 @@ int get_dpi_for_window(wxWindow *window)
static auto GetDpiForWindow_fn = winapi_get_function<GetDpiForWindow_t>(L"User32.dll", "GetDpiForWindow");
static auto GetDpiForMonitor_fn = winapi_get_function<GetDpiForMonitor_t>(L"Shcore.dll", "GetDpiForMonitor");
const HWND hwnd = window->GetHandle();
// Desktop Window is the window of the primary monitor.
const HWND hwnd = (window == nullptr) ? ::GetDesktopWindow() : window->GetHandle();
if (GetDpiForWindow_fn != nullptr) {
// We're on Windows 10, we have per-screen DPI settings

View File

@ -59,13 +59,16 @@ public:
: P(parent, id, title, pos, size, style, name)
{
m_scale_factor = (float)get_dpi_for_window(this) / (float)DPI_DEFAULT;
m_normal_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
m_prev_scale_factor = m_scale_factor;
float scale_primary_display = (float)get_dpi_for_window(nullptr) / (float)DPI_DEFAULT;
m_normal_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
if (std::abs(m_scale_factor - scale_primary_display) > 1e-6)
m_normal_font = m_normal_font.Scale(m_scale_factor / scale_primary_display);
// An analog of em_unit value from GUI_App.
m_em_unit = std::max<size_t>(10, 10 * m_scale_factor);
m_prev_scale_factor = m_scale_factor;
recalc_font();
// recalc_font();
this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) {
m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;
@ -107,7 +110,7 @@ public:
float prev_scale_factor() const { return m_prev_scale_factor; }
int em_unit() const { return m_em_unit; }
int font_size() const { return m_font_size; }
// int font_size() const { return m_font_size; }
const wxFont& normal_font() const { return m_normal_font; }
protected:
@ -116,19 +119,19 @@ protected:
private:
float m_scale_factor;
int m_em_unit;
int m_font_size;
// int m_font_size;
wxFont m_normal_font;
float m_prev_scale_factor;
bool m_can_rescale{ true };
void recalc_font()
{
wxClientDC dc(this);
const auto metrics = dc.GetFontMetrics();
m_font_size = metrics.height;
// void recalc_font()
// {
// wxClientDC dc(this);
// const auto metrics = dc.GetFontMetrics();
// m_font_size = metrics.height;
// m_em_unit = metrics.averageWidth;
}
// }
// check if new scale is differ from previous
bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }

View File

@ -36,6 +36,12 @@ MainFrame::MainFrame() :
DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
{
// Fonts were created by the DPIFrame constructor for the monitor, on which the window opened.
wxGetApp().update_fonts(this);
this->SetFont(this->normal_font());
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
wxGetApp().set_em_unit(std::max<size_t>(10, GetTextExtent("m").x - 1));
// Load the icon either from the exe, or from the ico file.
#if _WIN32
{
@ -54,11 +60,6 @@ DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAU
SLIC3R_VERSION +
_(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")));
// initialize default width_unit according to the width of the one symbol ("x") of the current system font
const wxSize size = GetTextExtent("m");
wxGetApp().set_em_unit(std::max<size_t>(10, size.x - 1));
/* Load default preset bitmaps before a tabpanel initialization,
* but after filling of an em_unit value
*/
@ -141,6 +142,7 @@ void MainFrame::init_tabpanel()
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10
// with multiple high resolution displays connected.
m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font());
m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxEvent&) {
auto panel = m_tabpanel->GetCurrentPage();
@ -278,10 +280,9 @@ bool MainFrame::can_delete_all() const
void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
{
wxGetApp().update_fonts();
// _strange_ workaround for correct em_unit calculation
const int new_em_unit = scale_factor() * 10;
wxGetApp().set_em_unit(std::max<size_t>(10, new_em_unit));
this->SetFont(this->normal_font());
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
wxGetApp().set_em_unit(std::max<size_t>(10, GetTextExtent("m").x - 1));
/* Load default preset bitmaps before a tabpanel initialization,
* but after filling of an em_unit value

View File

@ -1377,6 +1377,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
, view_toolbar(GLToolbar::Radio)
#endif // ENABLE_SVG_ICONS
{
this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font());
arranging = false;
rotoptimizing = false;
background_process.set_fff_print(&fff_print);

View File

@ -32,6 +32,7 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id):
m_prog->Hide();
m_cancelbutton->Hide();
self->SetFont(GUI::wxGetApp().normal_font());
self->SetFieldsCount(3);
int w[] = {-1, 150, 155};
self->SetStatusWidths(3, w);

View File

@ -42,6 +42,7 @@ Tab::Tab(wxNotebook* parent, const wxString& title, const char* name) :
m_parent(parent), m_title(title), m_name(name)
{
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name);
this->SetFont(Slic3r::GUI::wxGetApp().normal_font());
set_type();
m_compatible_printers.type = Preset::TYPE_PRINTER;

View File

@ -299,9 +299,13 @@ int em_unit(wxWindow* win)
{
if (win)
{
Slic3r::GUI::DPIDialog* dlg = dynamic_cast<Slic3r::GUI::DPIDialog*>(Slic3r::GUI::find_toplevel_parent(win));
wxTopLevelWindow *toplevel = Slic3r::GUI::find_toplevel_parent(win);
Slic3r::GUI::DPIDialog* dlg = dynamic_cast<Slic3r::GUI::DPIDialog*>(toplevel);
if (dlg)
return dlg->em_unit();
Slic3r::GUI::DPIFrame* frame = dynamic_cast<Slic3r::GUI::DPIFrame*>(toplevel);
if (frame)
return frame->em_unit();
}
return Slic3r::GUI::wxGetApp().em_unit();