преобразовательные известного размера для устройства пикселей
Если ваш визуальный элемент уже подключен к PresentationSource (например, это часть окна, которая видна на экране), то преобразование нашел этот путь :
var source = PresentationSource.FromVisual(element);
Matrix transformToDevice = source.CompositionTarget.TransformToDevice;
Если нет, используйте HwndSource для создания временного HWND:
Matrix transformToDevice;
using(var source = new HwndSource(new HwndSourceParameters()))
transformToDevice = source.TransformToDevice;
не e, что это менее эффективно, чем создание с использованием hWnd IntPtr.Zero, но я считаю его более надежным, поскольку hWnd, созданный HwndSource, будет прикреплен к тому же дисплею, что и фактическое вновь созданное Окно. Таким образом, если разные устройства отображения имеют разные DPI, вы обязательно получите правильное значение DPI.
После преобразования, вы можете конвертировать любой размер от размера WPF до размера пикселя:
var pixelSize = (Size)transformToDevice.Transform((Vector)wpfSize);
Преобразования размера пикселя в целых
Если вы хотите, чтобы преобразовать пиксел размер для целых чисел, вы можете просто сделать:
int pixelWidth = (int)pixelSize.Width;
int pixelHeight = (int)pixelSize.Height;
, но более надежным решением будет один используемый ElementHost:
int pixelWidth = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, pixelSize.Width));
int pixelHeight = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, pixelSize.Height));
Получение желаемого размера UIElement
Чтобы получить нужный размер UIElement вам нужно убедиться, что она измеряется. В некоторых случаях это уже будет измеряться, либо потому, что:
- Вы измерили уже
- вы измерили один из его предков, или
- Это является частью PresentationSource (например, он находится в видимом окне), и вы выполняете ниже DispatcherPriority.Render, чтобы вы знали, что измерение уже произошло автоматически.
Если визуальный элемент не был еще измерить, вы должны вызвать Measure по контролю или одного из его предков по мере необходимости, переходящий в имеющемся размере (или new Size(double.PositivieInfinity, double.PositiveInfinity)
, если вы хотите, чтобы размер для содержания:
element.Measure(availableSize);
После измерения будет сделано, все, что необходимо, чтобы использовать матрицу для преобразования DesiredSize:
var pixelSize = (Size)transformToDevice.Transform((Vector)element.DesiredSize);
Собираем все вместе
Вот простой метод, который показывает, как получить размер пикселя элемента:
public Size GetElementPixelSize(UIElement element)
{
Matrix transformToDevice;
var source = PresentationSource.FromVisual(element);
if(source!=null)
transformToDevice = source.CompositionTarget.TransformToDevice;
else
using(var source = new HwndSource(new HwndSourceParameters()))
transformToDevice = source.CompositionTarget.TransformToDevice;
if(element.DesiredSize == new Size())
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
return (Size)transformToDevice.Transform((Vector)element.DesiredSize);
}
Обратите внимание, что в этом коде я называю Измерить только если нет DesiredSize нет. Это обеспечивает удобный способ, чтобы сделать все, но имеет ряд недостатков:
- Это может быть, что родитель элемента прошел бы в меньшей availableSize
- Это неэффективно, если фактическая DesiredSize равна нулю (это переоценивается неоднократно)
- Это может замаскировать ошибки таким образом, что вызывает приложение к сбою из-за неожиданное время (например. код вызывается на уровне или выше DispatchPriority.Render)
из-за эти причины, я был бы склонен опустить вызов Measure в Get ElementPixelSize и просто позвольте клиенту сделать это.
Вы хотите что-то ищите? http://books.google.com/books?id=xEDKq_QlZ18C&lpg=PA7&ots=lxNG6ADXPa&dq=WPF%20pixels%20to%20real%20screen%20pixels&pg=PA7#v=onepage&q=WPF%20pixels%20to%20real%20screen% 20pixels & f = false – Ragepotato
@Ragepotato, это всего лишь концептуальный обзор - он не дает код для преобразования из WPF в пиксели, и он не объясняет, как обрабатывать граничные условия. –