Use DPI Aware wxGetSystemMetrics
If no wxWindow is known, use wxTheApp->GetTopWindow(). Also use a wxWindow for all wxSystemSettings::GetMetric calls.
This commit is contained in:
@@ -1290,8 +1290,8 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
|
int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X, this);
|
||||||
int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
|
int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y, this);
|
||||||
|
|
||||||
if (abs(pos.x - m_clickPt.x) > drag_x_threshold ||
|
if (abs(pos.x - m_clickPt.x) > drag_x_threshold ||
|
||||||
abs(pos.y - m_clickPt.y) > drag_y_threshold)
|
abs(pos.y - m_clickPt.y) > drag_y_threshold)
|
||||||
|
@@ -4589,8 +4589,8 @@ void wxAuiManager::OnMotion(wxMouseEvent& event)
|
|||||||
}
|
}
|
||||||
else if (m_action == actionClickCaption)
|
else if (m_action == actionClickCaption)
|
||||||
{
|
{
|
||||||
int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
|
int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X, m_frame);
|
||||||
int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
|
int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y, m_frame);
|
||||||
|
|
||||||
// caption has been clicked. we need to check if the mouse
|
// caption has been clicked. we need to check if the mouse
|
||||||
// is now being dragged. if it is, we need to change the
|
// is now being dragged. if it is, we need to change the
|
||||||
|
@@ -611,8 +611,8 @@ void wxAuiMDIChildFrame::SetIcons(const wxIconBundle& icons)
|
|||||||
wxAuiMDIParentFrame* pParentFrame = GetMDIParentFrame();
|
wxAuiMDIParentFrame* pParentFrame = GetMDIParentFrame();
|
||||||
wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
|
wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
|
||||||
|
|
||||||
const wxSize sizeIcon(wxSystemSettings::GetMetric(wxSYS_SMALLICON_X),
|
const wxSize sizeIcon(wxSystemSettings::GetMetric(wxSYS_SMALLICON_X, this),
|
||||||
wxSystemSettings::GetMetric(wxSYS_SMALLICON_Y));
|
wxSystemSettings::GetMetric(wxSYS_SMALLICON_Y, this));
|
||||||
wxBitmap bmp;
|
wxBitmap bmp;
|
||||||
bmp.CopyFromIcon(icons.GetIcon(sizeIcon));
|
bmp.CopyFromIcon(icons.GetIcon(sizeIcon));
|
||||||
|
|
||||||
|
@@ -2276,7 +2276,7 @@ void wxComboCtrlBase::ShowPopup()
|
|||||||
int maxHeightPopup;
|
int maxHeightPopup;
|
||||||
wxSize ctrlSz = GetSize();
|
wxSize ctrlSz = GetSize();
|
||||||
|
|
||||||
screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
|
screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y, this );
|
||||||
scrPos = GetScreenPosition();
|
scrPos = GetScreenPosition();
|
||||||
|
|
||||||
spaceAbove = scrPos.y;
|
spaceAbove = scrPos.y;
|
||||||
@@ -2354,7 +2354,7 @@ void wxComboCtrlBase::ShowPopup()
|
|||||||
if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
|
if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
|
||||||
leftX -= ctrlSz.x;
|
leftX -= ctrlSz.x;
|
||||||
|
|
||||||
int screenWidth = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
|
int screenWidth = wxSystemSettings::GetMetric( wxSYS_SCREEN_X, this );
|
||||||
|
|
||||||
// If there is not enough horizontal space, anchor on the other side.
|
// If there is not enough horizontal space, anchor on the other side.
|
||||||
// If there is no space even then, place the popup at x 0.
|
// If there is no space even then, place the popup at x 0.
|
||||||
|
@@ -1743,7 +1743,7 @@ wxSize wxDataViewSpinRenderer::GetSize() const
|
|||||||
// Allow some space for the spin buttons, which is approximately the size
|
// Allow some space for the spin buttons, which is approximately the size
|
||||||
// of a scrollbar (and getting pixel-exact value would be complicated).
|
// of a scrollbar (and getting pixel-exact value would be complicated).
|
||||||
// Also add some whitespace between the text and the button:
|
// Also add some whitespace between the text and the button:
|
||||||
sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, m_editorCtrl);
|
||||||
sz.x += GetTextExtent("M").x;
|
sz.x += GetTextExtent("M").x;
|
||||||
|
|
||||||
return sz;
|
return sz;
|
||||||
@@ -1821,7 +1821,7 @@ wxSize wxDataViewChoiceRenderer::GetSize() const
|
|||||||
// Allow some space for the right-side button, which is approximately the
|
// Allow some space for the right-side button, which is approximately the
|
||||||
// size of a scrollbar (and getting pixel-exact value would be complicated).
|
// size of a scrollbar (and getting pixel-exact value would be complicated).
|
||||||
// Also add some whitespace between the text and the button:
|
// Also add some whitespace between the text and the button:
|
||||||
sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, m_editorCtrl);
|
||||||
sz.x += GetTextExtent("M").x;
|
sz.x += GetTextExtent("M").x;
|
||||||
|
|
||||||
return sz;
|
return sz;
|
||||||
|
@@ -210,7 +210,7 @@ wxSizer *wxDialogBase::CreateTextSizer(const wxString& message,
|
|||||||
const bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
|
const bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
|
||||||
if (is_pda)
|
if (is_pda)
|
||||||
{
|
{
|
||||||
widthMax = wxSystemSettings::GetMetric( wxSYS_SCREEN_X ) - 25;
|
widthMax = wxSystemSettings::GetMetric( wxSYS_SCREEN_X, this ) - 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper.CreateSizer(message, widthMax);
|
return wrapper.CreateSizer(message, widthMax);
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
#include "wx/msw/wrapwin.h"
|
#include "wx/msw/wrapwin.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "wx/app.h"
|
||||||
#include "wx/settings.h"
|
#include "wx/settings.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#include "wx/intl.h"
|
#include "wx/intl.h"
|
||||||
@@ -266,8 +267,9 @@ wxIcon wxIconBundle::GetIcon(const wxSize& size, int flags) const
|
|||||||
sysY = 0;
|
sysY = 0;
|
||||||
if ( flags & FALLBACK_SYSTEM )
|
if ( flags & FALLBACK_SYSTEM )
|
||||||
{
|
{
|
||||||
sysX = wxSystemSettings::GetMetric(wxSYS_ICON_X);
|
wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
sysY = wxSystemSettings::GetMetric(wxSYS_ICON_Y);
|
sysX = wxSystemSettings::GetMetric(wxSYS_ICON_X, win);
|
||||||
|
sysY = wxSystemSettings::GetMetric(wxSYS_ICON_Y, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If size == wxDefaultSize, we use system default icon size by convention.
|
// If size == wxDefaultSize, we use system default icon size by convention.
|
||||||
|
@@ -155,9 +155,9 @@ void wxMouseEventsManager::OnMove(wxMouseEvent& event)
|
|||||||
// assumption that they don't change -- which is wrong, of
|
// assumption that they don't change -- which is wrong, of
|
||||||
// course, the user can change them but it doesn't happen often
|
// course, the user can change them but it doesn't happen often
|
||||||
static const int
|
static const int
|
||||||
dragMinX = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
|
dragMinX = wxSystemSettings::GetMetric(wxSYS_DRAG_X, m_win);
|
||||||
static const int
|
static const int
|
||||||
dragMinY = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
|
dragMinY = wxSystemSettings::GetMetric(wxSYS_DRAG_Y, m_win);
|
||||||
|
|
||||||
const wxPoint& pos = event.GetPosition();
|
const wxPoint& pos = event.GetPosition();
|
||||||
const wxPoint ofs = pos - m_posLast;
|
const wxPoint ofs = pos - m_posLast;
|
||||||
|
@@ -58,9 +58,9 @@ public:
|
|||||||
{
|
{
|
||||||
int w = GetSize().x;
|
int w = GetSize().x;
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
w -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X) + 6;
|
w -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, this) + 6;
|
||||||
#else
|
#else
|
||||||
w -= 2*wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
w -= 2*wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, this);
|
||||||
#endif
|
#endif
|
||||||
if (w < 0) w = 0;
|
if (w < 0) w = 0;
|
||||||
SetColumnWidth(0, w);
|
SetColumnWidth(0, w);
|
||||||
|
@@ -830,7 +830,7 @@ wxSize wxVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int
|
|||||||
CalcWidths();
|
CalcWidths();
|
||||||
|
|
||||||
// Take scrollbar into account in width calculations
|
// Take scrollbar into account in width calculations
|
||||||
int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, this);
|
||||||
return wxSize(minWidth > widestWidth ? minWidth : widestWidth,
|
return wxSize(minWidth > widestWidth ? minWidth : widestWidth,
|
||||||
height+2);
|
height+2);
|
||||||
}
|
}
|
||||||
|
@@ -1553,11 +1553,12 @@ wxSize wxScrolledT_Helper::FilterBestSize(const wxWindow *win,
|
|||||||
|
|
||||||
wxSize minSize = win->GetMinSize();
|
wxSize minSize = win->GetMinSize();
|
||||||
|
|
||||||
|
wxWindow* window = const_cast<wxWindow*>(win);
|
||||||
if ( ppuX > 0 )
|
if ( ppuX > 0 )
|
||||||
best.x = minSize.x + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
best.x = minSize.x + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, window);
|
||||||
|
|
||||||
if ( ppuY > 0 )
|
if ( ppuY > 0 )
|
||||||
best.y = minSize.y + wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
|
best.y = minSize.y + wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
return best;
|
return best;
|
||||||
|
@@ -146,7 +146,7 @@ wxTipWindow::wxTipWindow(wxWindow *parent,
|
|||||||
// NB: the reason we use "/ 2" here is that we don't know where the current
|
// NB: the reason we use "/ 2" here is that we don't know where the current
|
||||||
// cursors hot spot is... it would be nice if we could find this out
|
// cursors hot spot is... it would be nice if we could find this out
|
||||||
// though
|
// though
|
||||||
y += wxSystemSettings::GetMetric(wxSYS_CURSOR_Y) / 2;
|
y += wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, this) / 2;
|
||||||
|
|
||||||
#if wxUSE_POPUPWIN
|
#if wxUSE_POPUPWIN
|
||||||
Position(wxPoint(x, y), wxSize(0,0));
|
Position(wxPoint(x, y), wxSize(0,0));
|
||||||
|
@@ -714,8 +714,8 @@ wxSize wxWizard::GetPageSize() const
|
|||||||
if ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA )
|
if ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA )
|
||||||
{
|
{
|
||||||
// Make the default page size small enough to fit on screen
|
// Make the default page size small enough to fit on screen
|
||||||
DEFAULT_PAGE_WIDTH = wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2;
|
DEFAULT_PAGE_WIDTH = wxSystemSettings::GetMetric(wxSYS_SCREEN_X, m_parent) / 2;
|
||||||
DEFAULT_PAGE_HEIGHT = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2;
|
DEFAULT_PAGE_HEIGHT = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y, m_parent) / 2;
|
||||||
}
|
}
|
||||||
else // !PDA
|
else // !PDA
|
||||||
{
|
{
|
||||||
|
@@ -404,7 +404,7 @@ wxSize wxMSWButton::GetFittingSize(wxWindow *win,
|
|||||||
|
|
||||||
// account for the shield UAC icon if we have it
|
// account for the shield UAC icon if we have it
|
||||||
if ( flags & Size_AuthNeeded )
|
if ( flags & Size_AuthNeeded )
|
||||||
sizeBtn.x += wxSystemSettings::GetMetric(wxSYS_SMALLICON_X);
|
sizeBtn.x += wxSystemSettings::GetMetric(wxSYS_SMALLICON_X, win);
|
||||||
|
|
||||||
return sizeBtn;
|
return sizeBtn;
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/artprov.h"
|
#include "wx/artprov.h"
|
||||||
|
|
||||||
|
#ifndef WX_PRECOMP
|
||||||
|
#include "wx/app.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "wx/image.h"
|
#include "wx/image.h"
|
||||||
#include "wx/dynlib.h"
|
#include "wx/dynlib.h"
|
||||||
#include "wx/volume.h"
|
#include "wx/volume.h"
|
||||||
@@ -324,32 +329,33 @@ wxBitmap wxWindowsArtProvider::CreateBitmap(const wxArtID& id,
|
|||||||
/*static*/
|
/*static*/
|
||||||
wxSize wxArtProvider::GetNativeSizeHint(const wxArtClient& client)
|
wxSize wxArtProvider::GetNativeSizeHint(const wxArtClient& client)
|
||||||
{
|
{
|
||||||
|
const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
if ( client == wxART_TOOLBAR )
|
if ( client == wxART_TOOLBAR )
|
||||||
{
|
{
|
||||||
return wxWindow::FromDIP(wxSize(24, 24), NULL);
|
return wxWindow::FromDIP(wxSize(24, 24), win);
|
||||||
}
|
}
|
||||||
else if ( client == wxART_MENU )
|
else if ( client == wxART_MENU )
|
||||||
{
|
{
|
||||||
return wxWindow::FromDIP(wxSize(16, 16), NULL);
|
return wxWindow::FromDIP(wxSize(16, 16), win);
|
||||||
}
|
}
|
||||||
else if ( client == wxART_FRAME_ICON )
|
else if ( client == wxART_FRAME_ICON )
|
||||||
{
|
{
|
||||||
return wxSize(::GetSystemMetrics(SM_CXSMICON),
|
return wxSize(wxGetSystemMetrics(SM_CXSMICON, win),
|
||||||
::GetSystemMetrics(SM_CYSMICON));
|
wxGetSystemMetrics(SM_CYSMICON, win));
|
||||||
}
|
}
|
||||||
else if ( client == wxART_CMN_DIALOG ||
|
else if ( client == wxART_CMN_DIALOG ||
|
||||||
client == wxART_MESSAGE_BOX )
|
client == wxART_MESSAGE_BOX )
|
||||||
{
|
{
|
||||||
return wxSize(::GetSystemMetrics(SM_CXICON),
|
return wxSize(wxGetSystemMetrics(SM_CXICON, win),
|
||||||
::GetSystemMetrics(SM_CYICON));
|
wxGetSystemMetrics(SM_CYICON, win));
|
||||||
}
|
}
|
||||||
else if (client == wxART_BUTTON)
|
else if (client == wxART_BUTTON)
|
||||||
{
|
{
|
||||||
return wxWindow::FromDIP(wxSize(16, 16), NULL);
|
return wxWindow::FromDIP(wxSize(16, 16), win);
|
||||||
}
|
}
|
||||||
else if (client == wxART_LIST)
|
else if (client == wxART_LIST)
|
||||||
{
|
{
|
||||||
return wxWindow::FromDIP(wxSize(16, 16), NULL);
|
return wxWindow::FromDIP(wxSize(16, 16), win);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxDefaultSize;
|
return wxDefaultSize;
|
||||||
|
@@ -523,7 +523,7 @@ bool wxMSWOwnerDrawnButtonBase::MSWDrawButton(WXDRAWITEMSTRUCT *item)
|
|||||||
// choose the values consistent with those used for native, non
|
// choose the values consistent with those used for native, non
|
||||||
// owner-drawn, buttons
|
// owner-drawn, buttons
|
||||||
static const int MARGIN = 3;
|
static const int MARGIN = 3;
|
||||||
int CXMENUCHECK = ::GetSystemMetrics(SM_CXMENUCHECK) + 1;
|
int CXMENUCHECK = wxGetSystemMetrics(SM_CXMENUCHECK, m_win) + 1;
|
||||||
|
|
||||||
// the buttons were even bigger under Windows XP
|
// the buttons were even bigger under Windows XP
|
||||||
if ( wxGetWinVersion() < wxWinVersion_6 )
|
if ( wxGetWinVersion() < wxWinVersion_6 )
|
||||||
|
@@ -115,7 +115,10 @@ wxSize wxCursorRefData::ms_sizeStd;
|
|||||||
wxCoord wxCursorRefData::GetStandardWidth()
|
wxCoord wxCursorRefData::GetStandardWidth()
|
||||||
{
|
{
|
||||||
if ( !ms_sizeStd.x )
|
if ( !ms_sizeStd.x )
|
||||||
ms_sizeStd.x = wxSystemSettings::GetMetric(wxSYS_CURSOR_X);
|
{
|
||||||
|
wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
|
ms_sizeStd.x = wxSystemSettings::GetMetric(wxSYS_CURSOR_X, win);
|
||||||
|
}
|
||||||
|
|
||||||
return ms_sizeStd.x;
|
return ms_sizeStd.x;
|
||||||
}
|
}
|
||||||
@@ -123,7 +126,10 @@ wxCoord wxCursorRefData::GetStandardWidth()
|
|||||||
wxCoord wxCursorRefData::GetStandardHeight()
|
wxCoord wxCursorRefData::GetStandardHeight()
|
||||||
{
|
{
|
||||||
if ( !ms_sizeStd.y )
|
if ( !ms_sizeStd.y )
|
||||||
ms_sizeStd.y = wxSystemSettings::GetMetric(wxSYS_CURSOR_Y);
|
{
|
||||||
|
wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
|
ms_sizeStd.y = wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, win);
|
||||||
|
}
|
||||||
|
|
||||||
return ms_sizeStd.y;
|
return ms_sizeStd.y;
|
||||||
}
|
}
|
||||||
|
@@ -148,7 +148,7 @@ wxSize wxDateTimePickerCtrl::DoGetBestSize() const
|
|||||||
size = dc.GetTextExtent(s);
|
size = dc.GetTextExtent(s);
|
||||||
|
|
||||||
// account for the drop-down arrow or spin arrows
|
// account for the drop-down arrow or spin arrows
|
||||||
size.x += wxSystemSettings::GetMetric(wxSYS_HSCROLL_ARROW_X);
|
size.x += wxSystemSettings::GetMetric(wxSYS_HSCROLL_ARROW_X, m_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to account for the checkbox, if we have one, ourselves as
|
// We need to account for the checkbox, if we have one, ourselves as
|
||||||
|
@@ -334,8 +334,8 @@ bool wxDragImage::BeginDrag(const wxPoint& hotspot, wxWindow* window, bool fullS
|
|||||||
#else
|
#else
|
||||||
if (!m_hCursorImageList)
|
if (!m_hCursorImageList)
|
||||||
{
|
{
|
||||||
int cxCursor = ::GetSystemMetrics(SM_CXCURSOR);
|
int cxCursor = wxGetSystemMetrics(SM_CXCURSOR, window);
|
||||||
int cyCursor = ::GetSystemMetrics(SM_CYCURSOR);
|
int cyCursor = wxGetSystemMetrics(SM_CYCURSOR, window);
|
||||||
m_hCursorImageList = (WXHIMAGELIST) ImageList_Create(cxCursor, cyCursor, ILC_MASK, 1, 1);
|
m_hCursorImageList = (WXHIMAGELIST) ImageList_Create(cxCursor, cyCursor, ILC_MASK, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -473,9 +473,10 @@ bool wxICOFileHandler::LoadIcon(wxIcon *icon,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
// were we asked for a large icon?
|
// were we asked for a large icon?
|
||||||
if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
|
const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
desiredHeight == ::GetSystemMetrics(SM_CYICON) )
|
if ( desiredWidth == wxGetSystemMetrics(SM_CXICON, win) &&
|
||||||
|
desiredHeight == wxGetSystemMetrics(SM_CYICON, win) )
|
||||||
{
|
{
|
||||||
// get the specified large icon from file
|
// get the specified large icon from file
|
||||||
if ( !::ExtractIconEx(nameReal.t_str(), iconIndex, &hicon, NULL, 1) )
|
if ( !::ExtractIconEx(nameReal.t_str(), iconIndex, &hicon, NULL, 1) )
|
||||||
@@ -487,8 +488,8 @@ bool wxICOFileHandler::LoadIcon(wxIcon *icon,
|
|||||||
name.c_str());
|
name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
|
else if ( desiredWidth == wxGetSystemMetrics(SM_CXSMICON, win) &&
|
||||||
desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
|
desiredHeight == wxGetSystemMetrics(SM_CYSMICON, win) )
|
||||||
{
|
{
|
||||||
// get the specified small icon from file
|
// get the specified small icon from file
|
||||||
if ( !::ExtractIconEx(nameReal.t_str(), iconIndex, NULL, &hicon, 1) )
|
if ( !::ExtractIconEx(nameReal.t_str(), iconIndex, NULL, &hicon, 1) )
|
||||||
@@ -668,8 +669,9 @@ wxSize wxGetHiconSize(HICON hicon)
|
|||||||
if ( !size.x )
|
if ( !size.x )
|
||||||
{
|
{
|
||||||
// use default icon size on this hardware
|
// use default icon size on this hardware
|
||||||
size.x = ::GetSystemMetrics(SM_CXICON);
|
const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
size.y = ::GetSystemMetrics(SM_CYICON);
|
size.x = wxGetSystemMetrics(SM_CXICON, win);
|
||||||
|
size.y = wxGetSystemMetrics(SM_CYICON, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
@@ -124,7 +124,7 @@ bool wxHeaderCtrl::Create(wxWindow *parent,
|
|||||||
// use 0 here but this starts to look ugly)
|
// use 0 here but this starts to look ugly)
|
||||||
if ( wxApp::GetComCtl32Version() >= 600 )
|
if ( wxApp::GetComCtl32Version() >= 600 )
|
||||||
{
|
{
|
||||||
(void)Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE));
|
(void)Header_SetBitmapMargin(GetHwnd(), wxGetSystemMetrics(SM_CXEDGE, parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -625,7 +625,7 @@ wxSize wxListBox::DoGetBestClientSize() const
|
|||||||
wListbox += 3*GetCharWidth();
|
wListbox += 3*GetCharWidth();
|
||||||
|
|
||||||
// add room for the scrollbar
|
// add room for the scrollbar
|
||||||
wListbox += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
wListbox += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, m_parent);
|
||||||
|
|
||||||
// don't make the listbox too tall (limit height to 10 items) but don't
|
// don't make the listbox too tall (limit height to 10 items) but don't
|
||||||
// make it too small neither
|
// make it too small neither
|
||||||
|
@@ -1486,9 +1486,9 @@ wxSize wxListCtrl::MSWGetBestViewRect(int x, int y) const
|
|||||||
const DWORD mswStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE);
|
const DWORD mswStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE);
|
||||||
|
|
||||||
if ( mswStyle & WS_HSCROLL )
|
if ( mswStyle & WS_HSCROLL )
|
||||||
size.y += wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
|
size.y += wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y, m_parent);
|
||||||
if ( mswStyle & WS_VSCROLL )
|
if ( mswStyle & WS_VSCROLL )
|
||||||
size.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
size.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, m_parent);
|
||||||
|
|
||||||
// OTOH we have to subtract the size of our borders because the base class
|
// OTOH we have to subtract the size of our borders because the base class
|
||||||
// public method already adds them, but ListView_ApproximateViewRect()
|
// public method already adds them, but ListView_ApproximateViewRect()
|
||||||
|
@@ -126,10 +126,10 @@ private:
|
|||||||
int m_modeOld;
|
int m_modeOld;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool IsGreaterThanStdSize(const wxBitmap& bmp)
|
inline bool IsGreaterThanStdSize(const wxBitmap& bmp, const wxWindow* win)
|
||||||
{
|
{
|
||||||
return bmp.GetWidth() > ::GetSystemMetrics(SM_CXMENUCHECK) ||
|
return bmp.GetWidth() > wxGetSystemMetrics(SM_CXMENUCHECK, win) ||
|
||||||
bmp.GetHeight() > ::GetSystemMetrics(SM_CYMENUCHECK);
|
bmp.GetHeight() > wxGetSystemMetrics(SM_CYMENUCHECK, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
@@ -306,9 +306,9 @@ MenuDrawData* MenuDrawData::ms_instance = NULL;
|
|||||||
void MenuDrawData::Init()
|
void MenuDrawData::Init()
|
||||||
{
|
{
|
||||||
#if wxUSE_UXTHEME
|
#if wxUSE_UXTHEME
|
||||||
|
const wxWindow* window = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
|
||||||
if ( IsUxThemeActive() )
|
if ( IsUxThemeActive() )
|
||||||
{
|
{
|
||||||
wxWindow* window = static_cast<wxApp*>(wxApp::GetInstance())->GetTopWindow();
|
|
||||||
wxUxThemeHandle hTheme(window, L"MENU");
|
wxUxThemeHandle hTheme(window, L"MENU");
|
||||||
|
|
||||||
::GetThemeMargins(hTheme, NULL, MENU_POPUPITEM, 0,
|
::GetThemeMargins(hTheme, NULL, MENU_POPUPITEM, 0,
|
||||||
@@ -366,12 +366,12 @@ void MenuDrawData::Init()
|
|||||||
const NONCLIENTMETRICS& metrics = wxMSWImpl::GetNonClientMetrics();
|
const NONCLIENTMETRICS& metrics = wxMSWImpl::GetNonClientMetrics();
|
||||||
|
|
||||||
CheckMargin.cxLeftWidth =
|
CheckMargin.cxLeftWidth =
|
||||||
CheckMargin.cxRightWidth = ::GetSystemMetrics(SM_CXEDGE);
|
CheckMargin.cxRightWidth = wxGetSystemMetrics(SM_CXEDGE, window);
|
||||||
CheckMargin.cyTopHeight =
|
CheckMargin.cyTopHeight =
|
||||||
CheckMargin.cyBottomHeight = ::GetSystemMetrics(SM_CYEDGE);
|
CheckMargin.cyBottomHeight = wxGetSystemMetrics(SM_CYEDGE, window);
|
||||||
|
|
||||||
CheckSize.cx = ::GetSystemMetrics(SM_CXMENUCHECK);
|
CheckSize.cx = wxGetSystemMetrics(SM_CXMENUCHECK, window);
|
||||||
CheckSize.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
|
CheckSize.cy = wxGetSystemMetrics(SM_CYMENUCHECK, window);
|
||||||
|
|
||||||
ArrowSize = CheckSize;
|
ArrowSize = CheckSize;
|
||||||
|
|
||||||
@@ -1293,8 +1293,9 @@ bool wxMenuItem::MSWMustUseOwnerDrawn()
|
|||||||
const wxBitmap& bmpUnchecked = GetBitmap(false),
|
const wxBitmap& bmpUnchecked = GetBitmap(false),
|
||||||
bmpChecked = GetBitmap(true);
|
bmpChecked = GetBitmap(true);
|
||||||
|
|
||||||
if ( (bmpUnchecked.IsOk() && IsGreaterThanStdSize(bmpUnchecked)) ||
|
const wxWindow* win = m_parentMenu ? m_parentMenu->GetWindow() : NULL;
|
||||||
(bmpChecked.IsOk() && IsGreaterThanStdSize(bmpChecked)) ||
|
if ( (bmpUnchecked.IsOk() && IsGreaterThanStdSize(bmpUnchecked, win)) ||
|
||||||
|
(bmpChecked.IsOk() && IsGreaterThanStdSize(bmpChecked, win)) ||
|
||||||
(bmpChecked.IsOk() && IsCheckable()) )
|
(bmpChecked.IsOk() && IsCheckable()) )
|
||||||
{
|
{
|
||||||
mustUseOwnerDrawn = true;
|
mustUseOwnerDrawn = true;
|
||||||
|
@@ -193,8 +193,8 @@ void wxMessageDialog::ReplaceStaticWithEdit()
|
|||||||
// some space above and below it
|
// some space above and below it
|
||||||
const int hText = (7*rectDisplay.height)/8 -
|
const int hText = (7*rectDisplay.height)/8 -
|
||||||
(
|
(
|
||||||
2*::GetSystemMetrics(SM_CYFIXEDFRAME) +
|
2*wxGetSystemMetrics(SM_CYFIXEDFRAME, this) +
|
||||||
::GetSystemMetrics(SM_CYCAPTION) +
|
wxGetSystemMetrics(SM_CYCAPTION, this) +
|
||||||
5*GetCharHeight() // buttons + margins
|
5*GetCharHeight() // buttons + margins
|
||||||
);
|
);
|
||||||
const int dh = (rc.bottom - rc.top) - hText; // vertical space we save
|
const int dh = (rc.bottom - rc.top) - hText; // vertical space we save
|
||||||
@@ -207,8 +207,8 @@ void wxMessageDialog::ReplaceStaticWithEdit()
|
|||||||
// NB: you would have thought that 2*SM_CXEDGE would be enough but it
|
// NB: you would have thought that 2*SM_CXEDGE would be enough but it
|
||||||
// isn't, somehow, and the text control breaks lines differently from
|
// isn't, somehow, and the text control breaks lines differently from
|
||||||
// the static one so fudge by adding some extra space
|
// the static one so fudge by adding some extra space
|
||||||
const int dw = ::GetSystemMetrics(SM_CXVSCROLL) +
|
const int dw = wxGetSystemMetrics(SM_CXVSCROLL, this) +
|
||||||
4*::GetSystemMetrics(SM_CXEDGE);
|
4*wxGetSystemMetrics(SM_CXEDGE, this);
|
||||||
rc.right += dw;
|
rc.right += dw;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -802,10 +802,10 @@ void wxProgressDialog::SetIcons(const wxIconBundle& icons)
|
|||||||
wxIcon iconBig;
|
wxIcon iconBig;
|
||||||
if (!icons.IsEmpty())
|
if (!icons.IsEmpty())
|
||||||
{
|
{
|
||||||
const wxSize sizeSmall(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
|
const wxSize sizeSmall(wxGetSystemMetrics(SM_CXSMICON, this), wxGetSystemMetrics(SM_CYSMICON, this));
|
||||||
iconSmall = icons.GetIcon(sizeSmall, wxIconBundle::FALLBACK_NEAREST_LARGER);
|
iconSmall = icons.GetIcon(sizeSmall, wxIconBundle::FALLBACK_NEAREST_LARGER);
|
||||||
|
|
||||||
const wxSize sizeBig(::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
|
const wxSize sizeBig(wxGetSystemMetrics(SM_CXICON, this), wxGetSystemMetrics(SM_CYICON, this));
|
||||||
iconBig = icons.GetIcon(sizeBig, wxIconBundle::FALLBACK_NEAREST_LARGER);
|
iconBig = icons.GetIcon(sizeBig, wxIconBundle::FALLBACK_NEAREST_LARGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -527,8 +527,8 @@ wxSize wxRendererMSW::GetCheckBoxSize(wxWindow* win)
|
|||||||
// that it's valid to avoid surprises when using themes.
|
// that it's valid to avoid surprises when using themes.
|
||||||
wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" );
|
wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" );
|
||||||
|
|
||||||
return wxSize(::GetSystemMetrics(SM_CXMENUCHECK),
|
return wxSize(wxGetSystemMetrics(SM_CXMENUCHECK, win),
|
||||||
::GetSystemMetrics(SM_CYMENUCHECK));
|
wxGetSystemMetrics(SM_CYMENUCHECK, win));
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxRendererMSW::GetHeaderButtonHeight(wxWindow * win)
|
int wxRendererMSW::GetHeaderButtonHeight(wxWindow * win)
|
||||||
|
@@ -208,11 +208,11 @@ wxSize wxScrollBar::DoGetBestSize() const
|
|||||||
|
|
||||||
if ( IsVertical() )
|
if ( IsVertical() )
|
||||||
{
|
{
|
||||||
w = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
w = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, m_parent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
h = wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
|
h = wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y, m_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxSize(w, h);
|
return wxSize(w, h);
|
||||||
|
@@ -260,7 +260,7 @@ static const int gs_metricsMap[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get a system metric, e.g. scrollbar size
|
// Get a system metric, e.g. scrollbar size
|
||||||
int wxSystemSettingsNative::GetMetric(wxSystemMetric index, wxWindow* WXUNUSED(win))
|
int wxSystemSettingsNative::GetMetric(wxSystemMetric index, wxWindow* win)
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( index > 0 && (size_t)index < WXSIZEOF(gs_metricsMap), 0,
|
wxCHECK_MSG( index > 0 && (size_t)index < WXSIZEOF(gs_metricsMap), 0,
|
||||||
wxT("invalid metric") );
|
wxT("invalid metric") );
|
||||||
@@ -297,7 +297,7 @@ int wxSystemSettingsNative::GetMetric(wxSystemMetric index, wxWindow* WXUNUSED(w
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = ::GetSystemMetrics(indexMSW);
|
int rc = wxGetSystemMetrics(indexMSW, win);
|
||||||
if ( index == wxSYS_NETWORK_PRESENT )
|
if ( index == wxSYS_NETWORK_PRESENT )
|
||||||
{
|
{
|
||||||
// only the last bit is significant according to the MSDN
|
// only the last bit is significant according to the MSDN
|
||||||
|
@@ -150,8 +150,8 @@ wxSize wxSpinButton::DoGetBestSize() const
|
|||||||
{
|
{
|
||||||
const bool vert = HasFlag(wxSP_VERTICAL);
|
const bool vert = HasFlag(wxSP_VERTICAL);
|
||||||
|
|
||||||
wxSize bestSize(::GetSystemMetrics(vert ? SM_CXVSCROLL : SM_CXHSCROLL),
|
wxSize bestSize(wxGetSystemMetrics(vert ? SM_CXVSCROLL : SM_CXHSCROLL, m_parent),
|
||||||
::GetSystemMetrics(vert ? SM_CYVSCROLL : SM_CYHSCROLL));
|
wxGetSystemMetrics(vert ? SM_CYVSCROLL : SM_CYHSCROLL, m_parent));
|
||||||
|
|
||||||
if ( vert )
|
if ( vert )
|
||||||
bestSize.y *= 2;
|
bestSize.y *= 2;
|
||||||
|
@@ -2442,14 +2442,14 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
|
|||||||
{
|
{
|
||||||
// add space for vertical scrollbar
|
// add space for vertical scrollbar
|
||||||
if ( !(m_windowStyle & wxTE_NO_VSCROLL) )
|
if ( !(m_windowStyle & wxTE_NO_VSCROLL) )
|
||||||
wText += ::GetSystemMetrics(SM_CXVSCROLL);
|
wText += wxGetSystemMetrics(SM_CXVSCROLL, m_parent);
|
||||||
|
|
||||||
if ( ylen <= 0 )
|
if ( ylen <= 0 )
|
||||||
{
|
{
|
||||||
hText *= wxMax(wxMin(GetNumberOfLines(), 10), 2);
|
hText *= wxMax(wxMin(GetNumberOfLines(), 10), 2);
|
||||||
// add space for horizontal scrollbar
|
// add space for horizontal scrollbar
|
||||||
if ( m_windowStyle & wxHSCROLL )
|
if ( m_windowStyle & wxHSCROLL )
|
||||||
hText += ::GetSystemMetrics(SM_CYHSCROLL);
|
hText += wxGetSystemMetrics(SM_CYHSCROLL, m_parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for single line control cy (height + external leading) is ok
|
// for single line control cy (height + external leading) is ok
|
||||||
|
@@ -581,11 +581,11 @@ wxSize wxToolBar::DoGetBestSize() const
|
|||||||
wxSize sizeBest;
|
wxSize sizeBest;
|
||||||
if ( IsVertical() )
|
if ( IsVertical() )
|
||||||
{
|
{
|
||||||
sizeBest.x = sizeTool.x + 2 * ::GetSystemMetrics(SM_CXBORDER);
|
sizeBest.x = sizeTool.x + 2 * wxGetSystemMetrics(SM_CXBORDER, this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sizeBest.y = sizeTool.y + 2 * ::GetSystemMetrics(SM_CYBORDER);
|
sizeBest.y = sizeTool.y + 2 * wxGetSystemMetrics(SM_CYBORDER, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxToolBarToolsList::compatibility_iterator node;
|
wxToolBarToolsList::compatibility_iterator node;
|
||||||
@@ -634,11 +634,11 @@ wxSize wxToolBar::DoGetBestSize() const
|
|||||||
{
|
{
|
||||||
if ( IsVertical() )
|
if ( IsVertical() )
|
||||||
{
|
{
|
||||||
sizeBest.x += 2 * ::GetSystemMetrics(SM_CXBORDER);
|
sizeBest.x += 2 * wxGetSystemMetrics(SM_CXBORDER, this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sizeBest.y += 2 * ::GetSystemMetrics(SM_CYBORDER);
|
sizeBest.y += 2 * wxGetSystemMetrics(SM_CYBORDER, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,7 +1247,7 @@ bool wxToolBar::Realize()
|
|||||||
{
|
{
|
||||||
// We want just the usable height, so remove the space taken by the
|
// We want just the usable height, so remove the space taken by the
|
||||||
// border/divider.
|
// border/divider.
|
||||||
height -= 2 * ::GetSystemMetrics(SM_CYBORDER);
|
height -= 2 * wxGetSystemMetrics(SM_CYBORDER, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust the controls size to fit nicely in the toolbar and compute its
|
// adjust the controls size to fit nicely in the toolbar and compute its
|
||||||
|
@@ -984,7 +984,7 @@ bool wxTopLevelWindowMSW::DoSelectAndSetIcon(const wxIconBundle& icons,
|
|||||||
int smY,
|
int smY,
|
||||||
int i)
|
int i)
|
||||||
{
|
{
|
||||||
const wxSize size(::GetSystemMetrics(smX), ::GetSystemMetrics(smY));
|
const wxSize size(wxGetSystemMetrics(smX, this), wxGetSystemMetrics(smY, this));
|
||||||
|
|
||||||
wxIcon icon = icons.GetIcon(size, wxIconBundle::FALLBACK_NEAREST_LARGER);
|
wxIcon icon = icons.GetIcon(size, wxIconBundle::FALLBACK_NEAREST_LARGER);
|
||||||
|
|
||||||
|
@@ -3018,8 +3018,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
int cx = abs(m_ptClick.x - x);
|
int cx = abs(m_ptClick.x - x);
|
||||||
int cy = abs(m_ptClick.y - y);
|
int cy = abs(m_ptClick.y - y);
|
||||||
|
|
||||||
if ( cx > ::GetSystemMetrics(SM_CXDRAG) ||
|
if ( cx > wxGetSystemMetrics(SM_CXDRAG, this) ||
|
||||||
cy > ::GetSystemMetrics(SM_CYDRAG) )
|
cy > wxGetSystemMetrics(SM_CYDRAG, this) )
|
||||||
{
|
{
|
||||||
NM_TREEVIEW tv;
|
NM_TREEVIEW tv;
|
||||||
wxZeroMemory(tv);
|
wxZeroMemory(tv);
|
||||||
|
@@ -647,7 +647,7 @@ void wxPropertyGridManager::SetId( wxWindowID winid )
|
|||||||
wxSize wxPropertyGridManager::DoGetBestSize() const
|
wxSize wxPropertyGridManager::DoGetBestSize() const
|
||||||
{
|
{
|
||||||
// Width: margin=15 + columns=2*40 + scroll bar
|
// Width: margin=15 + columns=2*40 + scroll bar
|
||||||
return wxSize(15+2*40+wxSystemSettings::GetMetric(wxSYS_VSCROLL_X), 150);
|
return wxSize(15+2*40+wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, m_pPropGrid), 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
@@ -1711,8 +1711,8 @@ wxPoint wxPropertyGrid::GetGoodEditorDialogPosition( wxPGProperty* p,
|
|||||||
|
|
||||||
ImprovedClientToScreen( &x, &y );
|
ImprovedClientToScreen( &x, &y );
|
||||||
|
|
||||||
int sw = wxSystemSettings::GetMetric( ::wxSYS_SCREEN_X );
|
int sw = wxSystemSettings::GetMetric( ::wxSYS_SCREEN_X, this );
|
||||||
int sh = wxSystemSettings::GetMetric( ::wxSYS_SCREEN_Y );
|
int sh = wxSystemSettings::GetMetric( ::wxSYS_SCREEN_Y, this );
|
||||||
|
|
||||||
int new_x;
|
int new_x;
|
||||||
int new_y;
|
int new_y;
|
||||||
|
@@ -2718,7 +2718,8 @@ PRectangle wxSTCListBox::GetDesiredRect() const
|
|||||||
|
|
||||||
// Add space for a scrollbar if needed.
|
// Add space for a scrollbar if needed.
|
||||||
if ( count > desiredVisibleRows )
|
if ( count > desiredVisibleRows )
|
||||||
maxw += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
|
maxw += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X,
|
||||||
|
const_cast<wxWindow*>(wxDynamicCast(this, wxWindow)));
|
||||||
|
|
||||||
// Add borders.
|
// Add borders.
|
||||||
maxw += 2 * m_borderSize;
|
maxw += 2 * m_borderSize;
|
||||||
|
Reference in New Issue
Block a user