Merge branch 'per-monitor-dpi-aware-controls-2'

Improve Per-Monitor DPI awareness in more controls.

See https://github.com/wxWidgets/wxWidgets/pull/1572
This commit is contained in:
Vadim Zeitlin
2019-09-29 23:23:57 +02:00
40 changed files with 426 additions and 98 deletions

View File

@@ -895,9 +895,9 @@ public:
void SetDropEffect( wxDragResult effect ) { m_dropEffect = effect; }
wxDragResult GetDropEffect() const { return m_dropEffect; }
// for plaforms (currently only OSX) that support Drag/Drop insertion of items,
// this is the proposed child index for the insertion
void SetProposedDropIndex(int index) { m_proposedDropIndex = index; }
int GetProposedDropIndex() const { return m_proposedDropIndex;}
// this is the proposed child index for the insertion
void SetProposedDropIndex(int index) { m_proposedDropIndex = index; }
int GetProposedDropIndex() const { return m_proposedDropIndex;}
#endif // wxUSE_DRAG_AND_DROP
virtual wxEvent *Clone() const wxOVERRIDE { return new wxDataViewEvent(*this); }

View File

@@ -316,6 +316,8 @@ protected:
virtual void DoEnableSystemTheme(bool enable, wxWindow* window) wxOVERRIDE;
void OnDPIChanged(wxDPIChangedEvent& event);
public: // utility functions not part of the API
// returns the "best" width for the idx-th column

View File

@@ -206,6 +206,8 @@ protected:
void OnSize( wxSizeEvent& event );
void OnDPIChanged(wxDPIChangedEvent& event);
bool HasMenu() const
{
#if wxUSE_MENUS

View File

@@ -104,6 +104,7 @@ protected:
WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const wxOVERRIDE;
virtual bool MSWOnDraw(WXDRAWITEMSTRUCT *item) wxOVERRIDE;
virtual bool MSWOnMeasure(WXMEASUREITEMSTRUCT *item) wxOVERRIDE;
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// Event handlers
void OnSize(wxSizeEvent& event);

View File

@@ -81,6 +81,8 @@ protected:
ProcessCommand(event);
}
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
wxSize DoGetBestClientSize() const wxOVERRIDE;
wxDECLARE_EVENT_TABLE();

View File

@@ -181,6 +181,8 @@ protected:
return wxSize(w, h);
}
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// free memory (common part of Clear() and dtor)
void Free();

View File

@@ -394,6 +394,10 @@ protected:
virtual void DoSetToolTip(wxToolTip *tip) wxOVERRIDE;
#endif // wxUSE_TOOLTIPS
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
void OnDPIChanged(wxDPIChangedEvent& event);
wxSize MSWGetBestViewRect(int x, int y) const;
// Implement base class pure virtual methods.

View File

@@ -0,0 +1,77 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/private/dpiaware.h
// Purpose: AutoSystemDpiAware class
// Author: Maarten Bent
// Created: 2016-10-06
// Copyright: (c) Maarten Bent
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_MSW_DPI_AWARE_H_
#define _WX_MSW_DPI_AWARE_H_
#ifndef WX_PRECOMP
#include "wx/msw/missing.h"
#endif
#include "wx/dynlib.h"
#if wxUSE_DYNLIB_CLASS
namespace wxMSWImpl
{
// ----------------------------------------------------------------------------
// Temporarily change the DPI Awareness context to System
// ----------------------------------------------------------------------------
class AutoSystemDpiAware
{
#define WXDPI_AWARENESS_CONTEXT_UNAWARE ((WXDPI_AWARENESS_CONTEXT)-1)
#define WXDPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((WXDPI_AWARENESS_CONTEXT)-2)
typedef WXDPI_AWARENESS_CONTEXT
(WINAPI *SetThreadDpiAwarenessContext_t)(WXDPI_AWARENESS_CONTEXT);
public:
AutoSystemDpiAware()
: m_prevContext(WXDPI_AWARENESS_CONTEXT_UNAWARE),
m_pfnSetThreadDpiAwarenessContext((SetThreadDpiAwarenessContext_t)-1)
{
if ( m_pfnSetThreadDpiAwarenessContext == (SetThreadDpiAwarenessContext_t)-1)
{
wxLoadedDLL dllUser32("user32.dll");
wxDL_INIT_FUNC(m_pfn, SetThreadDpiAwarenessContext, dllUser32);
}
if ( m_pfnSetThreadDpiAwarenessContext )
{
m_prevContext = m_pfnSetThreadDpiAwarenessContext(
WXDPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
}
}
~AutoSystemDpiAware()
{
if ( m_pfnSetThreadDpiAwarenessContext )
{
m_pfnSetThreadDpiAwarenessContext(m_prevContext);
}
}
private:
WXDPI_AWARENESS_CONTEXT m_prevContext;
SetThreadDpiAwarenessContext_t m_pfnSetThreadDpiAwarenessContext;
};
#else // !wxUSE_DYNLIB_CLASS
// Just a stub to avoid littering the code with wxUSE_DYNLIB_CLASS checks.
class AutoSystemDpiAware { };
#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
} // namespace wxMSWImpl
#endif // _WX_MSW_DPI_AWARE_H_

View File

@@ -131,6 +131,7 @@ protected:
virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) wxOVERRIDE;
virtual bool MSWOnScroll(int orientation, WXWORD wParam,
WXWORD pos, WXHWND control) wxOVERRIDE;
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// handle processing of special keys
void OnChar(wxKeyEvent& event);

View File

@@ -240,6 +240,8 @@ protected:
virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const wxOVERRIDE;
#if wxUSE_RICHEDIT
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// Apply the character-related parts of wxTextAttr to the given selection
// or the entire control if start == end == -1.
//

View File

@@ -139,6 +139,9 @@ protected:
// set native toolbar padding
void MSWSetPadding(WXWORD padding);
void RealizeHelper();
void OnDPIChanged(wxDPIChangedEvent& event);
// the big bitmap containing all bitmaps of the toolbar buttons
WXHBITMAP m_hBitmap;

View File

@@ -261,6 +261,7 @@ protected:
// return true if the key was processed, false otherwise
bool MSWHandleSelectionKey(unsigned vkey);
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// data used only while editing the item label:
wxTextCtrl *m_textCtrl; // text control in which it is edited

View File

@@ -763,7 +763,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
wxDataViewTextRenderer *tr =
new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_INERT );
wxDataViewColumn *column0 =
new wxDataViewColumn( "title", tr, 0, 200, wxALIGN_LEFT,
new wxDataViewColumn( "title", tr, 0, FromDIP(200), wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE );
m_ctrl[Page_Music]->AppendColumn( column0 );
#if 0
@@ -776,10 +776,10 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
tr = new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_EDITABLE );
wxDataViewColumn *column1 =
new wxDataViewColumn( "artist", tr, 1, 150, wxALIGN_LEFT,
new wxDataViewColumn( "artist", tr, 1, FromDIP(150), wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE |
wxDATAVIEW_COL_RESIZABLE );
column1->SetMinWidth(150); // this column can't be resized to be smaller
column1->SetMinWidth(FromDIP(150)); // this column can't be resized to be smaller
m_ctrl[Page_Music]->AppendColumn( column1 );
// column 2 of the view control:
@@ -788,7 +788,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
new wxDataViewSpinRenderer( 0, 2010, wxDATAVIEW_CELL_EDITABLE,
wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
wxDataViewColumn *column2 =
new wxDataViewColumn( "year", sr, 2, 60, wxALIGN_LEFT,
new wxDataViewColumn( "year", sr, 2, FromDIP(60), wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE );
m_ctrl[Page_Music]->AppendColumn( column2 );
@@ -802,19 +802,19 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
new wxDataViewChoiceRenderer( choices, wxDATAVIEW_CELL_EDITABLE,
wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
wxDataViewColumn *column3 =
new wxDataViewColumn( "rating", c, 3, 100, wxALIGN_LEFT,
new wxDataViewColumn( "rating", c, 3, FromDIP(100), wxALIGN_LEFT,
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE );
m_ctrl[Page_Music]->AppendColumn( column3 );
// column 4 of the view control:
m_ctrl[Page_Music]->AppendProgressColumn( "popularity", 4, wxDATAVIEW_CELL_INERT, 80 );
m_ctrl[Page_Music]->AppendProgressColumn( "popularity", 4, wxDATAVIEW_CELL_INERT, FromDIP(80) );
// column 5 of the view control:
MyCustomRenderer *cr = new MyCustomRenderer(wxDATAVIEW_CELL_ACTIVATABLE);
wxDataViewColumn *column5 =
new wxDataViewColumn( "custom", cr, 5, -1, wxALIGN_LEFT,
new wxDataViewColumn( "custom", cr, 5, wxCOL_WIDTH_DEFAULT, wxALIGN_LEFT,
wxDATAVIEW_COL_RESIZABLE );
column5->SetBitmap(wxArtProvider::GetBitmap(wxART_INFORMATION, wxART_MENU));
m_ctrl[Page_Music]->AppendColumn( column5 );
@@ -900,7 +900,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
lc->AppendColumn(colRadio, "bool");
lc->AppendTextColumn( "Text" );
lc->AppendProgressColumn( "Progress" )->SetMinWidth(100);
lc->AppendProgressColumn( "Progress" )->SetMinWidth(FromDIP(100));
wxVector<wxVariant> data;
for (unsigned int i=0; i<10; i++)
@@ -957,17 +957,17 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
MultiLineCustomRenderer *tr =
new MultiLineCustomRenderer();
wxDataViewColumn *column0 =
new wxDataViewColumn("title", tr, 0, 200, wxALIGN_LEFT,
new wxDataViewColumn("title", tr, 0, FromDIP(200), wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
m_ctrl[Page_VarHeight]->AppendColumn(column0);
// column 1 of the view control:
tr = new MultiLineCustomRenderer();
wxDataViewColumn *column1 =
new wxDataViewColumn("artist", tr, 1, 150, wxALIGN_LEFT,
new wxDataViewColumn("artist", tr, 1, FromDIP(150), wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE |
wxDATAVIEW_COL_RESIZABLE);
column1->SetMinWidth(150); // this column can't be resized to be smaller
column1->SetMinWidth(FromDIP(150)); // this column can't be resized to be smaller
m_ctrl[Page_VarHeight]->AppendColumn(column1);
}
break;

View File

@@ -307,7 +307,7 @@ bool MyApp::OnInit()
// Create the main frame window
MyFrame* frame = new MyFrame((wxFrame *) NULL, wxID_ANY,
"wxToolBar Sample",
wxPoint(100, 100), wxSize(650, 350));
wxPoint(100, 100), wxDefaultSize);
frame->Show(true);
@@ -440,7 +440,7 @@ void MyFrame::PopulateToolbar(wxToolBarBase* toolBar)
// adding a combo to a vertical toolbar is not very smart
if ( !toolBar->IsVertical() )
{
wxComboBox *combo = new wxComboBox(toolBar, ID_COMBO, wxEmptyString, wxDefaultPosition, wxSize(100,-1) );
wxComboBox *combo = new wxComboBox(toolBar, ID_COMBO, wxEmptyString, wxDefaultPosition, FromDIP(wxSize(100,-1)) );
combo->Append("This");
combo->Append("is a");
combo->Append("combobox with extremely, extremely, extremely, extremely long label");
@@ -652,6 +652,8 @@ MyFrame::MyFrame(wxFrame* parent,
sizer->Add(m_extraToolBar, 0, wxEXPAND, 0);
#endif
sizer->Add(m_textWindow, 1, wxEXPAND, 0);
SetInitialSize(FromDIP(wxSize(650, 350)));
}
MyFrame::~MyFrame()
@@ -891,7 +893,7 @@ void MyFrame::OnToggleSearch(wxCommandEvent& WXUNUSED(event))
if ( !m_searchTool )
{
wxSearchCtrl * const srch = new wxSearchCtrl(tb, wxID_ANY, "needle");
srch->SetMinSize(wxSize(80, -1));
srch->SetMinSize(FromDIP(wxSize(80, -1)));
m_searchTool = tb->AddControl(srch);
}
else // tool already exists

View File

@@ -68,7 +68,8 @@ void wxBitmapComboBoxBase::Init()
void wxBitmapComboBoxBase::UpdateInternals()
{
m_fontHeight = GetControl()->GetCharHeight() + EXTRA_FONT_HEIGHT;
m_fontHeight = GetControl()->GetCharHeight()
+ GetControl()->FromDIP(EXTRA_FONT_HEIGHT);
while ( m_bitmaps.GetCount() < GetItemContainer()->GetCount() )
m_bitmaps.Add( new wxBitmap() );
@@ -159,7 +160,9 @@ int wxBitmapComboBoxBase::DetermineIndent()
if ( m_usedImgSize.x > 0 )
{
indent = m_usedImgSize.x + IMAGE_SPACING_LEFT + IMAGE_SPACING_RIGHT;
indent = m_usedImgSize.x
+ GetControl()->FromDIP(IMAGE_SPACING_LEFT)
+ GetControl()->FromDIP(IMAGE_SPACING_RIGHT);
m_imgAreaWidth = indent;
indent -= 3;
@@ -214,9 +217,12 @@ void wxBitmapComboBoxBase::DrawItem(wxDC& dc,
wxCoord w = bmp.GetWidth();
wxCoord h = bmp.GetHeight();
const wxWindow* win = const_cast<wxBitmapComboBoxBase*>(this)->GetControl();
const int imgSpacingLeft = win->FromDIP(IMAGE_SPACING_LEFT);
// Draw the image centered
dc.DrawBitmap(bmp,
rect.x + (m_usedImgSize.x-w)/2 + IMAGE_SPACING_LEFT,
rect.x + (m_usedImgSize.x-w)/2 + imgSpacingLeft,
rect.y + (rect.height-h)/2,
true);
}
@@ -235,7 +241,8 @@ wxCoord wxBitmapComboBoxBase::MeasureItem(size_t WXUNUSED(item)) const
return imgHeightArea > m_fontHeight ? imgHeightArea : m_fontHeight;
}
return wxBCB_DEFAULT_ITEM_HEIGHT;
const wxWindow* win = const_cast<wxBitmapComboBoxBase*>(this)->GetControl();
return win->FromDIP(wxBCB_DEFAULT_ITEM_HEIGHT);
}
#endif // wxBITMAPCOMBOBOX_OWNERDRAWN_BASED

View File

@@ -107,7 +107,7 @@ wxChoiceBase::~wxChoiceBase()
wxSize wxChoiceBase::DoGetBestSize() const
{
// a reasonable width for an empty choice list
wxSize best(80, -1);
wxSize best(FromDIP(80), -1);
const unsigned int nItems = GetCount();
if ( nItems > 0 )

View File

@@ -1374,7 +1374,7 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust
wxSize wxComboCtrlBase::DoGetBestSize() const
{
int width = m_text ? m_text->GetBestSize().x : 80;
int width = m_text ? m_text->GetBestSize().x : FromDIP(80);
return GetSizeFromTextSize(width);
}

View File

@@ -29,10 +29,9 @@
#include "wx/pen.h"
#include "wx/region.h"
#include "wx/log.h"
#include "wx/window.h"
#endif
#include "wx/display.h"
#ifdef __WXMSW__
#include "wx/msw/enhmeta.h"
#endif
@@ -624,7 +623,7 @@ void wxGraphicsContext::GetDPI( wxDouble* dpiX, wxDouble* dpiY)
{
if ( m_window )
{
const wxSize ppi = wxDisplay(m_window).GetPPI();
const wxSize ppi = m_window->GetDPI();
*dpiX = ppi.x;
*dpiY = ppi.y;
}

View File

@@ -327,7 +327,7 @@ wxSize wxAnimationCtrl::DoGetBestSize() const
if (m_animation.IsOk() && !this->HasFlag(wxAC_NO_AUTORESIZE))
return m_animation.GetSize();
return wxSize(100, 100);
return FromDIP(wxSize(100, 100));
}
void wxAnimationCtrl::SetAnimation(const wxAnimation& animation)

View File

@@ -193,7 +193,7 @@ int wxDataViewColumn::GetWidth() const
switch ( m_width )
{
case wxCOL_WIDTH_DEFAULT:
return wxDVC_DEFAULT_WIDTH;
return wxWindow::FromDIP(wxDVC_DEFAULT_WIDTH, m_owner);
case wxCOL_WIDTH_AUTOSIZE:
wxCHECK_MSG( m_owner, wxDVC_DEFAULT_WIDTH, "no owner control" );
@@ -709,8 +709,7 @@ public:
bool Cleared();
void Resort()
{
if ( m_rowHeightCache )
m_rowHeightCache->Clear();
ClearRowHeightCache();
if (!IsVirtualList())
{
@@ -718,6 +717,11 @@ public:
}
UpdateDisplay();
}
void ClearRowHeightCache()
{
if ( m_rowHeightCache )
m_rowHeightCache->Clear();
}
SortOrder GetSortOrder() const
{
@@ -1188,7 +1192,8 @@ wxSize wxDataViewTextRenderer::GetSize() const
return GetTextExtent(m_text);
}
else
return wxSize(wxDVC_DEFAULT_RENDERER_SIZE,wxDVC_DEFAULT_RENDERER_SIZE);
return GetView()->FromDIP(wxSize(wxDVC_DEFAULT_RENDERER_SIZE,
wxDVC_DEFAULT_RENDERER_SIZE));
}
// ---------------------------------------------------------
@@ -1251,7 +1256,8 @@ wxSize wxDataViewBitmapRenderer::GetSize() const
else if (m_icon.IsOk())
return wxSize( m_icon.GetWidth(), m_icon.GetHeight() );
return wxSize(wxDVC_DEFAULT_RENDERER_SIZE,wxDVC_DEFAULT_RENDERER_SIZE);
return GetView()->FromDIP(wxSize(wxDVC_DEFAULT_RENDERER_SIZE,
wxDVC_DEFAULT_RENDERER_SIZE));
}
// ---------------------------------------------------------
@@ -2770,11 +2776,8 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData
}
else
{
if ( m_rowHeightCache )
{
// specific position (row) is unclear, so clear whole height cache
m_rowHeightCache->Clear();
}
// specific position (row) is unclear, so clear whole height cache
ClearRowHeightCache();
wxDataViewTreeNode *parentNode = FindNode(parent);
@@ -3039,8 +3042,7 @@ bool wxDataViewMainWindow::Cleared()
m_selection.Clear();
m_currentRow = (unsigned)-1;
if ( m_rowHeightCache )
m_rowHeightCache->Clear();
ClearRowHeightCache();
if (GetModel())
{
@@ -5107,6 +5109,7 @@ void wxDataViewMainWindow::UpdateColumnSizes()
wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase);
wxBEGIN_EVENT_TABLE(wxDataViewCtrl, wxDataViewCtrlBase)
EVT_SIZE(wxDataViewCtrl::OnSize)
EVT_DPI_CHANGED(wxDataViewCtrl::OnDPIChanged)
wxEND_EVENT_TABLE()
wxDataViewCtrl::~wxDataViewCtrl()
@@ -5251,6 +5254,28 @@ void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
}
}
void wxDataViewCtrl::OnDPIChanged(wxDPIChangedEvent& event)
{
if ( m_clientArea )
{
m_clientArea->ClearRowHeightCache();
m_clientArea->SetRowHeight(m_clientArea->GetDefaultRowHeight());
}
for ( unsigned i = 0; i < m_cols.size(); ++i )
{
int minWidth = m_cols[i]->GetMinWidth();
if ( minWidth > 0 )
minWidth = minWidth * event.GetNewDPI().x / event.GetOldDPI().x;
m_cols[i]->SetMinWidth(minWidth);
int width = m_cols[i]->WXGetManuallySetWidth();
if ( width > 0 )
width = width * event.GetNewDPI().x / event.GetOldDPI().x;
m_cols[i]->SetWidth(width);
}
}
void wxDataViewCtrl::SetFocus()
{
if (m_clientArea)

View File

@@ -298,7 +298,14 @@ void wxSpinCtrlGenericBase::DoMoveWindow(int x, int y, int width, int height)
wxControl::DoMoveWindow(x, y, width, height);
// position the subcontrols inside the client area
wxSize sizeBtn = m_spinButton->GetSize();
// Use GetBestSize instead of GetSize to get the size of the spin control.
// This fixes a problem on wxMSW when the size is set after a DPI change.
// GetSize returns the old, invalid, size. GetBestSize will return the size
// that the control should be. Normally, GetBestSize and GetSize should
// always return the same value because the size of the spinButton never
// changes.
wxSize sizeBtn = m_spinButton->GetBestSize();
wxCoord wText = width - sizeBtn.x - MARGIN;
m_textCtrl->SetSize(0, 0, wText, height);

View File

@@ -248,6 +248,7 @@ wxEND_EVENT_TABLE()
wxBEGIN_EVENT_TABLE(wxSearchCtrl, wxSearchCtrlBase)
EVT_SEARCH_CANCEL(wxID_ANY, wxSearchCtrl::OnCancelButton)
EVT_SIZE(wxSearchCtrl::OnSize)
EVT_DPI_CHANGED(wxSearchCtrl::OnDPIChanged)
wxEND_EVENT_TABLE()
wxIMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl, wxSearchCtrlBase);
@@ -1234,6 +1235,11 @@ void wxSearchCtrl::OnSize( wxSizeEvent& WXUNUSED(event) )
LayoutControls();
}
void wxSearchCtrl::OnDPIChanged(wxDPIChangedEvent &WXUNUSED(event))
{
RecalcBitmaps();
}
#if wxUSE_MENUS
void wxSearchCtrl::PopupSearchMenu()

View File

@@ -431,7 +431,7 @@ wxSize wxMSWButton::IncreaseToStdSizeAndCache(wxControl *btn, const wxSize& size
//
// Note that we intentionally don't use GetDefaultSize() here, because
// it's inexact -- dialog units depend on this dialog's font.
const wxSize sizeDef = btn->ConvertDialogToPixels(wxSize(50, 14));
const wxSize sizeDef = btn->ConvertDialogToPixels(btn->FromDIP(wxSize(50, 14)));
sizeBtn.IncTo(sizeDef);
}

View File

@@ -39,8 +39,6 @@
#include "wx/odcombo.h"
#define IMAGE_SPACING_CTRL_VERTICAL 7 // Spacing used in control size calculation
// ============================================================================
// implementation
@@ -129,6 +127,7 @@ void wxBitmapComboBox::RecreateControl()
// mouse-wheel behaviour.
//
wxString value = GetValue();
int selection = GetSelection();
wxPoint pos = GetPosition();
wxSize size = GetSize();
size.y = GetBestSize().y;
@@ -212,6 +211,8 @@ void wxBitmapComboBox::RecreateControl()
// Revert the old string value
if ( !HasFlag(wxCB_READONLY) )
ChangeValue(value);
else if ( selection != wxNOT_FOUND )
SetSelection(selection);
// If disabled we'll have to disable it again after re-creating
if ( !IsEnabled() )
@@ -409,7 +410,7 @@ int wxBitmapComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
bool wxBitmapComboBox::OnAddBitmap(const wxBitmap& bitmap)
{
if ( wxBitmapComboBoxBase::OnAddBitmap(bitmap) )
if ( wxBitmapComboBoxBase::OnAddBitmap(bitmap) || !GetCount() )
{
// Need to recreate control for a new measureitem call?
int prevItemHeight = ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0);
@@ -532,4 +533,13 @@ bool wxBitmapComboBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
return true;
}
void wxBitmapComboBox::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxComboBox::MSWUpdateFontOnDPIChange(newDPI);
UpdateInternals();
RecreateControl();
}
#endif // wxUSE_BITMAPCOMBOBOX

View File

@@ -255,7 +255,20 @@ bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
}
return false;
}
}
void wxCheckListBox::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxCheckListBoxBase::MSWUpdateFontOnDPIChange(newDPI);
wxSize size = wxRendererNative::Get().GetCheckBoxSize(this);
size.x += 2 * CHECKMARK_EXTRA_SPACE + CHECKMARK_LABEL_SPACE;
for ( unsigned int i = 0; i < GetCount(); ++i )
{
GetItem(i)->SetMarginWidth(size.GetWidth());
}
}
// check items
// -----------

View File

@@ -40,6 +40,7 @@
#include "wx/scopeguard.h"
#include "wx/msw/private.h"
#include "wx/msw/private/dpiaware.h"
#include <stdlib.h>
#include <string.h>
@@ -216,6 +217,8 @@ int wxColourDialog::ShowModal()
gs_activeDialog = this;
wxON_BLOCK_EXIT_NULL(gs_activeDialog);
wxMSWImpl::AutoSystemDpiAware dpiAwareness;
// do show the modal dialog
if ( !::ChooseColor(&chooseColorStruct) )
{

View File

@@ -112,50 +112,37 @@ wxDateTime wxDateTimePickerCtrl::GetValue() const
wxSize wxDateTimePickerCtrl::DoGetBestSize() const
{
// Since Vista, the control can compute its best size itself, just ask it.
wxSize size;
if ( wxGetWinVersion() >= wxWinVersion_Vista )
{
SIZE idealSize;
// Do not use DateTime_GetIdealSize / DTM_GETIDEALSIZE. It returns
// incorrect sizes after the DPI of the window has changed. For every DPI
// change, the returned size is 4 pixels higher, even if the DPI is
// lowered.
// Work around https://bugs.winehq.org/show_bug.cgi?id=44680 by
// checking for the return value: even if all "real" MSW systems do
// support this message, Wine does not, even when it's configured to
// return Vista or later version to the application.
if ( ::SendMessage(m_hWnd, DTM_GETIDEALSIZE, 0, (LPARAM)&idealSize) )
{
size = wxSize(idealSize.cx, idealSize.cy);
}
}
wxClientDC dc(const_cast<wxDateTimePickerCtrl *>(this));
if ( !size.x || !size.y )
{
wxClientDC dc(const_cast<wxDateTimePickerCtrl *>(this));
// Use the same native format as the underlying native control.
// Use the same native format as the underlying native control.
#if wxUSE_INTL
wxString s = wxDateTime::Now().Format(wxLocale::GetOSInfo(MSWGetFormat()));
wxString s = wxDateTime::Now().Format(wxLocale::GetOSInfo(MSWGetFormat()));
#else // !wxUSE_INTL
wxString s("XXX-YYY-ZZZZ");
wxString s("XXX-YYY-ZZZZ");
#endif // wxUSE_INTL/!wxUSE_INTL
// the best size for the control is bigger than just the string
// representation of the current value because the control must accommodate
// any date and while the widths of all digits are usually about the same,
// the width of the month string varies a lot, so try to account for it
s += wxS("W");
// the best size for the control is bigger than just the string
// representation of the current value because the control must accommodate
// any date and while the widths of all digits are usually about the same,
// the width of the month string varies a lot, so try to account for it
s += wxS("W");
size = dc.GetTextExtent(s);
wxSize size = dc.GetTextExtent(s);
// account for the drop-down arrow or spin arrows
size.x += wxSystemSettings::GetMetric(wxSYS_HSCROLL_ARROW_X, m_parent);
}
// Account for the drop-down arrow or spin arrows.
size.x += wxSystemSettings::GetMetric(wxSYS_HSCROLL_ARROW_X, m_parent);
// We need to account for the checkbox, if we have one, ourselves as
// DTM_GETIDEALSIZE doesn't seem to take it into account, at least under
// Windows 7.
int scrollY = wxSystemSettings::GetMetric(wxSYS_HSCROLL_ARROW_Y, m_parent);
size.y = wxMax(size.y, scrollY);
// We need to account for the checkbox, if we have one.
if ( MSWAllowsNone() )
size.x += 3*GetCharWidth();
size.x += 3 * GetCharWidth();
// In any case, adjust the height to be the same as for the text controls.
size.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(size.y);

View File

@@ -47,6 +47,7 @@
#include "wx/scopeguard.h"
#include "wx/tokenzr.h"
#include "wx/modalhook.h"
#include "wx/msw/private/dpiaware.h"
// ----------------------------------------------------------------------------
// constants
@@ -375,6 +376,12 @@ void wxFileDialog::MSWOnTypeChange(WXHWND WXUNUSED(hDlg), int nFilterIndex)
// err is filled with the CDERR_XXX constant
static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err)
{
// Extra controls do not handle per-monitor DPI, fall back to system DPI
// so entire file-dialog is resized.
wxScopedPtr<wxMSWImpl::AutoSystemDpiAware> dpiAwareness;
if ( of->Flags & OFN_ENABLEHOOK )
dpiAwareness.reset(new wxMSWImpl::AutoSystemDpiAware());
if ( style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of) )
return true;

View File

@@ -37,6 +37,7 @@
#endif
#include "wx/fontutil.h"
#include "wx/msw/private/dpiaware.h"
#include <stdlib.h>
#include <string.h>
@@ -149,6 +150,8 @@ int wxFontDialog::ShowModal()
chooseFontStruct.Flags = flags;
wxMSWImpl::AutoSystemDpiAware dpiAwareness;
if ( ChooseFont(&chooseFontStruct) != 0 )
{
wxRGBToColour(m_fontData.m_fontColour, chooseFontStruct.rgbColors);

View File

@@ -122,9 +122,9 @@ wxSize wxGauge::DoGetBestSize() const
// the smaller one.
if (HasFlag(wxGA_VERTICAL))
return ConvertDialogToPixels(wxSize(8, 107));
return ConvertDialogToPixels(FromDIP(wxSize(8, 107)));
else
return ConvertDialogToPixels(wxSize(107, 8));
return ConvertDialogToPixels(FromDIP(wxSize(107, 8)));
}
// ----------------------------------------------------------------------------

View File

@@ -124,6 +124,7 @@ protected:
virtual void DoSetSize(int x, int y,
int width, int height,
int sizeFlags = wxSIZE_AUTO) wxOVERRIDE;
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
private:
// override MSW-specific methods needed for new control
@@ -324,6 +325,16 @@ wxSize wxMSWHeaderCtrl::DoGetBestSize() const
return wxSize(wxDefaultCoord, wpos.cy);
}
void wxMSWHeaderCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxControl::MSWUpdateFontOnDPIChange(newDPI);
if ( wxMSWHeaderCtrlCustomDraw * customDraw = GetCustomDraw() )
{
customDraw->m_attr.SetFont(m_font);
}
}
// ----------------------------------------------------------------------------
// wxMSWHeaderCtrl columns managements
// ----------------------------------------------------------------------------
@@ -701,7 +712,7 @@ bool wxMSWHeaderCtrl::SetFont(const wxFont& font)
if ( wxMSWHeaderCtrlCustomDraw* customDraw = GetCustomDraw() )
{
customDraw->m_attr.SetFont(font);
customDraw->m_attr.SetFont(m_font);
}
return true;

View File

@@ -190,6 +190,14 @@ WXDWORD wxListBox::MSWGetStyle(long style, WXDWORD *exstyle) const
return msStyle;
}
void wxListBox::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxListBoxBase::MSWUpdateFontOnDPIChange(newDPI);
if ( m_font.IsOk() )
SetFont(m_font);
}
void wxListBox::OnInternalIdle()
{
wxWindow::OnInternalIdle();
@@ -695,22 +703,22 @@ bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
bool wxListBox::SetFont(const wxFont &font)
{
wxListBoxBase::SetFont(font);
if ( HasFlag(wxLB_OWNERDRAW) )
{
const unsigned count = m_aItems.GetCount();
for ( unsigned i = 0; i < count; i++ )
m_aItems[i]->SetFont(font);
m_aItems[i]->SetFont(m_font);
// Non owner drawn list boxes update the item height on their own, but
// we need to do it manually in the owner drawn case.
wxClientDC dc(this);
dc.SetFont(font);
dc.SetFont(m_font);
SendMessage(GetHwnd(), LB_SETITEMHEIGHT, 0,
dc.GetCharHeight() + 2 * LISTBOX_EXTRA_SPACE);
}
wxListBoxBase::SetFont(font);
return true;
}

View File

@@ -265,6 +265,7 @@ private:
wxBEGIN_EVENT_TABLE(wxListCtrl, wxListCtrlBase)
EVT_PAINT(wxListCtrl::OnPaint)
EVT_CHAR_HOOK(wxListCtrl::OnCharHook)
EVT_DPI_CHANGED(wxListCtrl::OnDPIChanged)
wxEND_EVENT_TABLE()
// ============================================================================
@@ -319,6 +320,9 @@ bool wxListCtrl::Create(wxWindow *parent,
if ( InReportView() )
MSWSetExListStyles();
if ( HasFlag(wxLC_LIST) )
m_colCount = 1;
return true;
}
@@ -421,6 +425,47 @@ WXDWORD wxListCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
return wstyle;
}
void wxListCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxListCtrlBase::MSWUpdateFontOnDPIChange(newDPI);
for ( int i = 0; i < GetItemCount(); i++ )
{
wxMSWListItemData *data = MSWGetItemData(i);
if ( data && data->attr && data->attr->HasFont() )
{
wxFont f = data->attr->GetFont();
f.WXAdjustToPPI(newDPI);
SetItemFont(i, f);
}
}
if ( m_headerCustomDraw && m_headerCustomDraw->m_attr.HasFont() )
{
wxItemAttr item(m_headerCustomDraw->m_attr);
wxFont f = item.GetFont();
f.WXAdjustToPPI(newDPI);
item.SetFont(f);
// reset the item attribute first so wxListCtrl::SetHeaderAttr
// will detect the font change
SetHeaderAttr(wxItemAttr());
SetHeaderAttr(item);
}
}
void wxListCtrl::OnDPIChanged(wxDPIChangedEvent &event)
{
const int numCols = GetColumnCount();
for ( int i = 0; i < numCols; ++i )
{
int width = GetColumnWidth(i);
if ( width > 0 )
width = width * event.GetNewDPI().x / event.GetOldDPI().x;
SetColumnWidth(i, width);
}
}
#if WXWIN_COMPATIBILITY_3_0
// Deprecated
void wxListCtrl::UpdateStyle()
@@ -632,11 +677,16 @@ bool wxListCtrl::SetHeaderAttr(const wxItemAttr& attr)
// Don't just reset the font if no font is specified, as the header
// uses the same font as the listview control and not the ugly
// default GUI font by default.
const wxFont& font = attr.HasFont() ? attr.GetFont() : GetFont();
// We need to tell the header about its new font to let it compute
// its new height.
wxSetWindowFont(hwndHdr, font);
if ( attr.HasFont() )
{
wxSetWindowFont(hwndHdr, attr.GetFont());
}
else
{
// make sure m_font is valid before using its HFONT reference
SetFont(GetFont());
wxSetWindowFont(hwndHdr, m_font);
}
}
// Refreshing the listview makes it notice the change in height of its
@@ -953,6 +1003,13 @@ bool wxListCtrl::SetItem(wxListItem& info)
data->attr->AssignFrom(attrNew);
else
data->attr = new wxItemAttr(attrNew);
if ( data->attr->HasFont() )
{
wxFont f = data->attr->GetFont();
f.WXAdjustToPPI(GetDPI());
data->attr->SetFont(f);
}
}
}

View File

@@ -550,8 +550,8 @@ wxRendererMSW::DrawTitleBarBitmap(wxWindow *win,
wxSize wxRendererMSW::GetCheckBoxSize(wxWindow* win)
{
// Even though we don't use the window in this implementation, still check
// that it's valid to avoid surprises when using themes.
// We must have a valid window in order to return the size which is correct
// for the display this window is on.
wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" );
return wxSize(wxGetSystemMetrics(SM_CXMENUCHECK, win),

View File

@@ -223,6 +223,14 @@ void wxSpinCtrl::OnKillFocus(wxFocusEvent& event)
event.Skip();
}
void wxSpinCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxSpinButton::MSWUpdateFontOnDPIChange(newDPI);
if ( m_font.IsOk() )
wxSetWindowFont(GetBuddyHwnd(), m_font);
}
void wxSpinCtrl::OnSetFocus(wxFocusEvent& event)
{
// when we get focus, give it to our buddy window as it needs it more than
@@ -577,7 +585,8 @@ bool wxSpinCtrl::SetFont(const wxFont& font)
return false;
}
wxSetWindowFont(GetBuddyHwnd(), GetFont());
if ( m_font.IsOk() )
wxSetWindowFont(GetBuddyHwnd(), m_font);
return true;
}

View File

@@ -2633,6 +2633,16 @@ wxMenu *wxTextCtrl::MSWCreateContextMenu()
return m;
}
void wxTextCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
// Don't do anything for the rich edit controls, they (somehow?) update
// their appearance on their own and changing their HFONT, as the base
// class version does, would reset all the styles used by them when the DPI
// changes, which is unwanted.
if ( !IsRich() )
wxTextCtrlBase::MSWUpdateFontOnDPIChange(newDPI);
}
// ----------------------------------------------------------------------------
// EN_LINK processing
// ----------------------------------------------------------------------------

View File

@@ -38,6 +38,8 @@
#include "wx/region.h"
#include "wx/dcmemory.h"
#include "wx/control.h"
#include "wx/choice.h"
#include "wx/combobox.h"
#include "wx/app.h" // for GetComCtl32Version
#include "wx/image.h"
#include "wx/stattext.h"
@@ -127,6 +129,7 @@ wxBEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged)
EVT_ERASE_BACKGROUND(wxToolBar::OnEraseBackground)
EVT_DPI_CHANGED(wxToolBar::OnDPIChanged)
wxEND_EVENT_TABLE()
// ----------------------------------------------------------------------------
@@ -1001,7 +1004,7 @@ bool wxToolBar::Realize()
// Strangely, toolbar expects bitmaps with transparency to not
// be premultiplied, unlike most of the rest of win32. Without this
// conversion, e.g. antialiased lines would be subtly, but
// noticeably misrendered.
// noticeably misrendered.
hBitmap = wxDIB(bitmap.ConvertToImage(),
wxDIB::PixelFormat_NotPreMultiplied).Detach();
}
@@ -1895,6 +1898,57 @@ void wxToolBar::OnEraseBackground(wxEraseEvent& event)
#endif // wxHAS_MSW_BACKGROUND_ERASE_HOOK
}
void wxToolBar::RealizeHelper()
{
Realize();
}
void wxToolBar::OnDPIChanged(wxDPIChangedEvent& event)
{
// Manually scale the size of the controls. Even though the font has been
// updated, the internal size of the controls does not.
const float scaleFactor = (float)event.GetNewDPI().y / event.GetOldDPI().y;
wxToolBarToolsList::compatibility_iterator node;
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
{
wxToolBarTool* const tool = static_cast<wxToolBarTool*>(node->GetData());
if ( !tool->IsControl() )
continue;
if ( wxControl* const control = tool->GetControl() )
{
const wxSize oldSize = control->GetSize();
wxSize newSize = oldSize * scaleFactor;
// Use the best height for choice-based controls.
// Scaling the current size does not work, because the control
// automatically increases size when the font-size increases.
if ( wxDynamicCast(control, wxComboBox) ||
wxDynamicCast(control, wxChoice) )
{
const wxSize bestSize = control->GetBestSize();
newSize.y = bestSize.y;
}
control->SetSize(newSize);
}
if ( wxStaticText* const staticText = tool->GetStaticText() )
{
// Use the best size for the label
staticText->SetSize(staticText->GetBestSize());
}
}
// Use CallAfter because creating the toolbar directly sometimes doesn't
// work. E.g. when switching from 125% to 150%. All the sizes are set
// correctly, but after all dpi events are handled, 5px of the toolbar are
// gone and a dark-gray bar appears. After resizing the window, the gray
// bar disapears as well.
CallAfter(&wxToolBar::RealizeHelper);
}
bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM WXUNUSED(lParam))
{
// wait until we have some tools

View File

@@ -1253,7 +1253,9 @@ void wxTreeCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font)
attr = it->second;
}
attr->SetFont(font);
wxFont f = font;
f.WXAdjustToPPI(GetDPI());
attr->SetFont(f);
// Reset the item's text to ensure that the bounding rect will be adjusted
// for the new font.
@@ -2270,6 +2272,17 @@ bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id_)
return true;
}
void wxTreeCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxTreeCtrlBase::MSWUpdateFontOnDPIChange(newDPI);
for ( wxMapTreeAttr::const_iterator it = m_attrs.begin(); it != m_attrs.end(); ++it )
{
if ( it->second->HasFont() )
SetItemFont(it->first, it->second->GetFont());
}
}
bool wxTreeCtrl::MSWIsOnItem(unsigned flags) const
{
unsigned mask = TVHT_ONITEM;

View File

@@ -4830,7 +4830,7 @@ wxSize wxWindowMSW::GetDPI() const
if ( !dpi.x || !dpi.y )
{
WindowHDC hdc(GetHwnd());
WindowHDC hdc(hwnd);
dpi.x = ::GetDeviceCaps(hdc, LOGPIXELSX);
dpi.y = ::GetDeviceCaps(hdc, LOGPIXELSY);
}

View File

@@ -3808,7 +3808,7 @@ void wxRichTextCtrl::OnDropFiles(wxDropFilesEvent& event)
wxSize wxRichTextCtrl::DoGetBestSize() const
{
return wxSize(10, 10);
return FromDIP(wxSize(10, 10));
}
// ----------------------------------------------------------------------------