transformación de un tamaño conocido a píxeles dispositivo
Si su elemento visual ya está unido a un PresentationSource (por ejemplo, es parte de una ventana que es visible en la pantalla), la transformada se encuentra de esta manera :
var source = PresentationSource.FromVisual(element);
Matrix transformToDevice = source.CompositionTarget.TransformToDevice;
Si no es así, utilice HwndSource para crear un CVent temporal:
Matrix transformToDevice;
using(var source = new HwndSource(new HwndSourceParameters()))
transformToDevice = source.TransformToDevice;
no
e que esto es menos eficiente que construir utilizando un hWnd de IntPtr.Zero, pero lo considero más confiable porque el hWnd creado por HwndSource se conectará al mismo dispositivo de visualización como lo haría una Ventana recién creada. De esta forma, si los diferentes dispositivos de visualización tienen diferentes DPI, está seguro de obtener el valor correcto de DPI.
Una vez que haya la transformación, puede convertir cualquier tamaño, desde un tamaño de WPF a un tamaño de píxel:
var pixelSize = (Size)transformToDevice.Transform((Vector)wpfSize);
Conversión del tamaño de píxel de números enteros
Si desea convertir el píxel el tamaño de los números enteros, sólo tiene que hacer:
int pixelWidth = (int)pixelSize.Width;
int pixelHeight = (int)pixelSize.Height;
pero una solución más robusta sería el utilizado por 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));
conseguir el tamaño deseado de UIElement
Para obtener el tamaño deseado de un UIElement que necesita para asegurarse de que se mide. En algunas circunstancias que ya se medirá, ya sea porque:
- que se ha medido ya
- que se ha medido una de sus antepasados, o
- Es parte de un PresentationSource (por ejemplo, se encuentra en una ventana visible) y se está ejecutando debajo de DispatcherPriority.Render para que sepa que la medición ya ha ocurrido automáticamente.
Si el elemento visual no se ha medido sin embargo, debe llamar a la medida en el control o uno de sus antepasados, según corresponda, que pasa en el tamaño disponible (o new Size(double.PositivieInfinity, double.PositiveInfinity)
si quiere clasificar al contenido:
element.Measure(availableSize);
Una vez que la medición se hace, todo lo que es necesario es utilizar la matriz para transformar el DesiredSize:
var pixelSize = (Size)transformToDevice.Transform((Vector)element.DesiredSize);
Poniendo todo junto
Aquí es un método simple que muestra cómo obtener el tamaño de píxel de un elemento:
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);
}
Tenga en cuenta que en este código que llamo Medida sólo si no hay DesiredSize está presente. Esto proporciona un método conveniente de hacerlo todo pero tiene varias deficiencias:
- Puede ser que los padres del elemento habría pasado en un pequeño availableSize
- Es ineficiente si el DesiredSize real es cero (que se vuelve a medir repetidamente)
- puede enmascarar errores de una manera que hace que la aplicación a fallar debido a la sincronización inesperado (por ejemplo. el código que está siendo llamado en o por encima DispatchPriority.Render)
debido a estas razones, estaría inclinado omitir la llamada Medir en Obtener ElementPixelSize y simplemente deja que el cliente lo haga.
¿Es esto lo que estás buscando? 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% 20 píxeles & f = falso – Ragepotato
@Ragepotato, eso es solo una descripción conceptual: no da el código para convertir de WPF a píxeles, y no explica cómo manejar las condiciones de contorno. –