// Copyright 2016 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #include #include "DolphinWX/DolphinSlider.h" #ifdef __WXMSW__ #define WIN32_LEAN_AND_MEAN 1 // clang-format off #include #include // clang-format on #endif static constexpr int SLIDER_MIN_LENGTH = 100; DolphinSlider::DolphinSlider() = default; DolphinSlider::~DolphinSlider() = default; bool DolphinSlider::Create(wxWindow* parent, wxWindowID id, int value, int min_val, int max_val, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) { // Sanitize the style flags. // We don't want any label flags because those break DPI scaling on wxMSW, // wxWidgets will internally lock the height of the slider to 32 pixels. style &= ~wxSL_LABELS; return wxSlider::Create(parent, id, value, min_val, max_val, pos, size, style, validator, name); } wxSize DolphinSlider::DoGetBestClientSize() const { #ifdef __WXMSW__ int ticks = 0; int default_length = FromDIP(SLIDER_MIN_LENGTH); if (HasFlag(wxSL_TICKS)) { // NOTE: Ticks do not scale at all (on Win7) default_length += 4; ticks = 6; } int metric = 0; { // We need to determine the maximum thumb size because unfortunately the thumb size // is controlled by the theme so may have a varying maximum size limit. // NOTE: We can't use ourself because we're const so we can't change our size. // NOTE: This is less inefficient then it seems, DoGetBestSize() is only called once // per instance and cached until InvalidateBestSize() is called. wxSlider* helper = new wxSlider(GetParent(), wxID_ANY, GetValue(), GetMin(), GetMax(), wxDefaultPosition, FromDIP(wxSize(100, 100)), GetWindowStyle()); ::RECT r{}; ::SendMessageW(reinterpret_cast(helper->GetHWND()), TBM_GETTHUMBRECT, 0, reinterpret_cast(&r)); helper->Destroy(); // Breakdown metrics int computed_size; int scroll_size; if (HasFlag(wxSL_VERTICAL)) { // Trackbar thumb does not directly touch the edge, we add the padding // a second time to pad the other edge to make it symmetric. computed_size = static_cast(r.right + r.left); scroll_size = ::GetSystemMetrics(SM_CXVSCROLL); } else { computed_size = static_cast(r.bottom + r.top); scroll_size = ::GetSystemMetrics(SM_CYHSCROLL); } // This is based on how Microsoft calculates trackbar sizes in the .Net Framework // when using automatic sizing in WinForms. int max = scroll_size * 2; metric = wxClip(computed_size, scroll_size, max); } if (HasFlag(wxSL_VERTICAL)) return wxSize(metric + ticks, default_length); return wxSize(default_length, metric + ticks); #else wxSize base_size = wxSlider::DoGetBestClientSize(); // If the base class is not using DoGetBestClientSize(), fallback to DoGetBestSize() if (base_size == wxDefaultSize) return wxDefaultSize; return CorrectMinSize(base_size); #endif } wxSize DolphinSlider::DoGetBestSize() const { return CorrectMinSize(wxSlider::DoGetBestSize()); } wxSize DolphinSlider::CorrectMinSize(wxSize size) const { wxSize default_length = FromDIP(wxSize(SLIDER_MIN_LENGTH, SLIDER_MIN_LENGTH)); // GTK Styles sometimes don't return a default length. // NOTE: Vertical is the dominant flag if both are set. if (HasFlag(wxSL_VERTICAL)) { if (size.GetHeight() < default_length.GetHeight()) { size.SetHeight(default_length.GetHeight()); } } else if (size.GetWidth() < default_length.GetWidth()) { size.SetWidth(default_length.GetWidth()); } return size; } #ifdef __WXMSW__ WXLRESULT DolphinSlider::MSWWindowProc(WXUINT msg, WXWPARAM wp, WXLPARAM lp) { if (msg == WM_THEMECHANGED) InvalidateBestSize(); return wxSlider::MSWWindowProc(msg, wp, lp); } #endif