none
Как получить разрешение экрана в WPF? RRS feed

  • Общие обсуждения

  • Казалось бы все просто:

    double h = SystemParameters.PrimaryScreenHeight;

    double w = SystemParameters.PrimaryScreenWidth;

    У меня ноубук (Windows 8). При установленном в настройках разрешении экрана монитора 1920 на 1080 получаем h = 864.0, а w = 1536.0. То есть, в 1.25 раза меньше, чем ожидалось. Настольный ПК (WindowsXP) показывает h и w как в установленном разрешении. Возникает вопрос, как определить это отношение:  

    SystemParameters.PrimaryScreenHeight, SystemParameters.PrimaryScreenWidth и установленное в настройках разрешение экрана. Как точно узнать этот коэффициент (1.0 или 1.25).

    28 августа 2013 г. 13:54

Все ответы

  • Вопрос снимаю. Ответ, кажется, найден. Это - SystemParameters.CaretWidth (ширина в точках курсора в элементах управления – так написано в справке ).

    Установленное в настройках разрешение экрана равно

    SystemParameters.PrimaryScreenWidth/SystemParameters.CaretWidth по ширине и SystemParameters.PrimaryScreenHeight/SystemParameters.CaretWidth по высоте.

    У меня, по крайней мере, работает…

    29 августа 2013 г. 9:57
  • Все-таки мне нужен ответ. Может быть, ширина каретки в некоторых случаях подойдет, но все же, как программно определить установленное пользователем разрешение экрана?

    SystemParameters.PrimaryScreenWidth и SystemParameters.PrimaryScreenHeight показывают действительное (реальное) разрешение экрана. Например, пользователь на своем устройстве установил разрешение 1920 на 1080, а действительное разрешение устройства при этом будет 1536 на 864 (PrimaryScreenWidth и PrimaryScreenHeight). То есть, такое случается, если CaretWidth=0.8 на этом устройстве (экране). И 1920 * 0.8 = 1536, 1080 * 0.8 = 864. Все бы хорошо, но я не уверен, что ширина каретки (CaretWidth) всегда корректно покажет это соотношение. В приложении необходимо иногда перемещать один объект относительно другого, определяя координаты последнего с помощью метода Point PointToScreen(Point point) класса Visual. И не зная этой величины (0.8) на разных устройствах (настольный ПК, ноутбук, планшет) под Windows 8 не возможно корректно перемещать объекты по экрану. Прошу помочь мне решить эту проблему.

    11 сентября 2013 г. 7:43
  • Добрый день.

    Вот так:

    SystemParameters.WorkArea.Width 
    SystemParameters.WorkArea.Height 

    11 сентября 2013 г. 7:59
    Отвечающий
  • Хотя, может быть и:

    SystemParameters.VirtualScreenHeight

    Предыдущее вроде выкидывает таскбар...
    11 сентября 2013 г. 8:01
    Отвечающий
  • WorkArea...  явно не разрешение экрана, которое установил пользователь на своем устройстве. А вот второй вариант VirtualScreenHeight) -  похоже.  Сейчас нет под рукой ноутбука, где ширина каретки 0.8. Через час смогу практически проверить.

    11 сентября 2013 г. 13:50
  • Нет, не правильно. SystemParameters.VirtualScreenHeight и SystemParameters.VirtualScreenWidth показывают тоже самое, что и SystemParameters.PrimaryScreenHeight и SystemParameters.PrimaryScreenWidth. Может ли быть так, что ширина каретки всегда равна ширине точки экрана (например, у меня в ноутбуке 0.8 пикселя)? Уверенности нет. В MSDN ничего не нашел.


    • Изменено yura_ 11 сентября 2013 г. 15:34
    11 сентября 2013 г. 15:17
  • Решил все-таки продолжить тему. Так как не совсем уверен в найденном мной решении.

    У меня в приложении WPF имеется проблема при работе на устройствах, где физическое разрешение экрана в пикселях не соответствует установленному пользователем разрешению. Например, на новых ноутбуках Asys N550J рекомендованное производителем разрешение экрана 1920 на 1080 (FulHD) на самом деле (физически) означает разрешение 1536 на 864.  Соответственно и все остальные допустимые в настройках разрешения экрана физически в 0,8 раза меньше, чем указано в настройках. То есть точка разрешения экрана равна 0,8 пикселя?

    В приложении WPF можно определить только разрешение экрана действительное, в пикселях. То есть,  в моем случае, при установленном  разрешении экрана 1920 на 1080:

    SystemParameters.PrimaryScreenWidth = 1536

    SystemParameters.PrimaryScreenHeight = 864;

    Была большая надежда на VirtualScreenWidth и VirtualScreenHeight, но и эти свойства класса SystemParameters показывают то же самое.

    Иногда в приложении WPF приходиться устанавливать размер картинки. Например, если предполагается, что пользователь использует для работы с приложением разрешение экрана  1024 на 768 и установить размер картинки в XAML Width="1024" или в коде C#  Myimage.Width = 1024, то картинка не поместится на экране, так как этот размер устанавливается в пикселях. А приложение будет выведено в окне размером 819 пикселей на 614,4. Такие же проблемы появляются, если надо разместить в приложении одну картинку (или control) относительно другой в определенном месте.  Положение на экране первой картинки (или контрола) myImage, размещенного в контейнере (например, Grid) определяю  так:

     Point p = MyWindow.myImage.PointToScreen(pt).

    Точка p показывает смещение верхнего левого угла myimage в точках разрешения (на моем устройстве одна точка 0.8 пикселя). А когда вы хотите сместить в вычисленное положение другую картинку, myImage2.Left = p.X, то Left считается уже в пикселях. И на моем ноутбуке это выглядит совсем не так, как нужно.

    Может следует делать так:

    Сначала определить смещение картинки в текущих координатах (в точках разрешение экрана)

    Point pt = new Point();

    Point p = MyWindow.myimage.PointToScreen(pt);

    А затем определить это смещение относительно окна (экрана) в пикселях

    Point pf = app.acyWindow.PointFromScreen(p);

    myImage2.Left = pf.X;

    Не знаю. Но случайно я заметил, что свойство CaretWidth (ширина каретки) класса SystemParameters как раз равна размеру точки разрешения экрана в пикселях. В моем случает эта величина составляет 0,8. Это действительно «случайно» или и на других устройствах будет точно так же (и всегда в дальнейшем), мне не известно.

    Но, в связи с этим случаем, можно смещать картинку 2 так:

    Point p = MyWindow.myimage.PointToScreen(pt);

    myImage2.Left = p.X * SystemParameters.CaretWidth;

    Эти два способа не равнозначны и дают незначительную разницу в несколько пикселей. О причинах могу только догадываться…

    В то же время, приложения, написанные 5-10 лет назад в  Visual C++ 6.0 на Win32 работают отлично при любом разрешении экрана. Все масштабируется достаточно корректно и таких проблем не возникает.

    Может нужно тогда воспользоваться функциями win32?

    [DllImport("User32.dll")]

    [return: MarshalAs(UnmanagedType.Bool)]

    public static extern Boolean EnumDisplaySettings([param: MarshalAs(UnmanagedType.LPTStr)] string lpszDeviceName, [param: MarshalAs(UnmanagedType.U4)]int iModeNum,

                [In, Out]ref DEVMODE lpDevMode);

    DEVMODE mode = new DEVMODE();

    mode.dmSize = (ushort)Marshal.SizeOf(mode);

    EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref mode);

    И тогда уже размеры точки разрешения экрана:

    double widthPoint = SystemParameters.PrimaryScreenWidth / (double)mode.dmPelsWidth        

    double heighthPoint = SystemParameters.PrimaryScreenHeight/ (double)mode.dmPelsHeight;

    Не считаю себя достаточно компетентным, поэтому прошу совета. Неужели без старого доброго Win32 не обойтись?

    28 сентября 2013 г. 11:53
  • Я думаю Вы мудрите.

    В том смысле, что Microsoft разработчики с этой проблемой должны были быть знакомы и я почти уверен они уже написали код под капотом для коррекции всего этого.

    Только что проверил изменив разрешение.

    SystemParameters.PrimaryScreenWidth и SystemParameters.PrimaryScreenHeight выдают правильные значения.

    Несоответствия в вашем приложении могут быть связаны с понятиями ActualWidth & ActualHeight, которые дают реальные цифры в то время, как обычные Width & Height желаемые(установленные на этапе разработки) в которых сидят ещё значения заголовка окна и границ(Borders).

    Надеюсь помог. Удачи!

    16 июля 2018 г. 9:28