В Windows 7 (Панель управления → Дисплей) установлена настройка. Он позволяет изменять размер текста и других элементов на экране. Мне нужно настроить этот параметр для включения/отключения некоторых функций в моем приложении С# на основе значения параметра. Возможно ли это?
Как получить настройки дисплея Windows?
Ответ 1
Этот параметр представляет собой экран DPI или точки на дюйм.
Прочитайте его так:
float dpiX, dpiY;
Graphics graphics = this.CreateGraphics();
dpiX = graphics.DpiX;
dpiY = graphics.DpiY;
Я не думаю, что на данный момент возможно, чтобы значения X и Y были разными. Значение 96 соответствует 100% масштабированию шрифта (меньше), 120 соответствует 125% масштабированию (средний), а 144 соответствует 150% масштабированию (больше). Однако пользователи могут устанавливать значения, отличные от этих стандартных.
Имейте в виду, что если ваше приложение не объявлено как DPI, то значения, которые вы наблюдаете, могут быть подвергнуты виртуализации DPI.
Ответ 2
Обе графики .DpiX и DeviceCap.LOGPIXELSX возвращают 96 на Surface Pro во всех уровнях масштабирования.
Вместо этого мне удалось вычислить масштабный коэффициент следующим образом:
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,
// http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
}
private float getScalingFactor()
{
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
return ScreenScalingFactor; // 1.25 = 125%
}
Ответ 3
Самый простой способ, по-моему, использовать функцию GetDeviceCaps
. Из pinvoke.net:
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
public enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90
// Other constants may be founded on pinvoke.net
}
И использование:
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
int Xdpi = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSX);
int Ydpi = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSY);
В этом подходе вам не нужно отмечать ваше приложение с учетом тренда.
Ответ 4
Вот как вы можете это сделать в WPF. Возвращаемое значение находится в логических единицах WPF, которые равны 1/96 дюйма дюйма. Поэтому, если ваш DPI для экрана установлен на 96, вы получите значение 1.
Matrix m =
PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice;
double dx = m.M11; // notice it divided by 96 already
double dy = m.M22; // notice it divided by 96 already
(источник)
Ответ 5
В случае WPF используйте следующий фрагмент,
PresentationSource source = PresentationSource.FromVisual(this);
double dpiX, dpiY;
if (source != null)
{
dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;
dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;
}
Ответ 6
Я использую этот способ в своем консольном приложении:
float dpiX, dpiY;
using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
{
dpiX = graphics.DpiX;
dpiY = graphics.DpiY;
}
Ответ 7
Использование ответа Farshid T в качестве базы работает в каждом масштабном коэффициенте, за исключением 125%. Я тестировал около 20 различных коэффициентов масштабирования, и DPI всегда возвращается как 96, за исключением случаев, когда установлено значение 125%, что возвращает DPI 120. 120/96 = 1,25. Не уверен, почему это так, но этот код работает для любых настроек масштаба.
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,
LOGPIXELSY = 90,
// http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
и использование:
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
int logpixelsy = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSY);
float screenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
float dpiScalingFactor = (float)logpixelsy / (float)96;
if (screenScalingFactor > 1 ||
dpiScalingFactor > 1)
{
// do something nice for people who can't see very well...
}
Ответ 8
Это очень старый вопрос, но с Windows 8.1 можно использовать различные другие функции, такие как GetDpiForWindow
В С#:
[DllImport("user32.dll")]
static extern int GetDpiForWindow(IntPtr hWnd);
public float GetDisplayScaleFactor(IntPtr windowHandle)
{
try
{
return GetDpiForWindow(windowHandle) / 96f;
}
catch
{
// Or fallback to GDI solutions above
return 1;
}
}
Для правильной работы с Windows 10 годовщина вам нужно добавить app.manifest
в свой проект С#:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- The combination of below two tags have the following effect :
1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
</windowsSettings>
</application>
</assembly>
Ответ 9
Вот решение, которое прекрасно работает в Windows 10. Там нет необходимости для DPI осведомленности или что-нибудь.
public static int GetWindowsScaling()
{
return (int)(100 * Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth);
}
Ответ 10
Я думаю, что это должно предоставить вам информацию, которую вы ищете:
http://www.pinvoke.net/default.aspx/user32.getsystemmetrics
http://pinvoke.net/default.aspx/Enums.SystemMetric
Изменить - о, жаль, похоже, что теперь есть более простой способ получить эту информацию без pinvoke,
http://msdn.microsoft.com/en-us/library/system.windows.forms.systeminformation.aspx