WPF 應用程式的像素快照
更新:2007 年 11 月
WPF 圖形系統使用與裝置無關的單位以獲得解析度和裝置的獨立性。每個與裝置無關的像素都會隨系統的 Dots Per Inch (DPI) 設定自動縮放。這可以讓 WPF 應用程式在不同的 DPI 設定下適當縮放,使應用程式自動成為 DPI 感知。
不過,這個不受 DPI 影響的特性可能由於消除鋸齒而建立不規則的邊緣。這些疊影多為模糊或半透明邊緣,當邊緣的位置落在裝置像素中 (而非裝置像素之間的交界) 時出現。為解決這個問題,WPF 可以透過像素格線編排的方式,將視覺化樹狀結構中的物件邊緣對齊至 (或固定至) 裝置像素,以去除消除鋸齒功能產生的半透明邊緣。
像素格線編排是一種消除這些視覺疊影的方法,其原理是對視覺物件的幾何套用少量的位移 (Offset),以使幾何對齊至裝置像素。
這個主題包含下列章節。
- 用於消除鋸齒功能的像素格線編排
- 方針
- 點陣圖影像
- 相關主題
用於消除鋸齒功能的像素格線編排
銳利線條
如果未使用像素格線編排,而且邊緣未落在裝置像素之間,則消除鋸齒的線條可能是半透明的。下圖顯示單一像素寬度的線條落在裝置像素的中央 (左側) 和落在裝置像素之間 (右側) 時,在消除鋸齒的輸出。
消除鋸齒的線條。
使用像素格線編排時,消除鋸齒的線條會對齊至 (或固定至) 裝置像素並且呈現為銳利線條,而不是半透明線條。下列範例示範 SnapsToDevicePixels 屬性對單一像素線條的影響。緩慢調整視窗大小時會發現,隨著位置的變更,未對齊的線條 (左側) 上會有視覺疊影,而對齊的線條 (右側) 仍保持固定大小。
<Page x:Class="PixelSnapping.Lines"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Title="Lines" Name="linesPage"
>
<StackPanel Width="150" Margin="7" Orientation="Horizontal">
<!-- Single pixel line with pixel snapping turned OFF.-->
<Rectangle SnapsToDevicePixels="False"
Width="45.5" Margin="10" Height="1" Fill="Red"/>
<!-- Single pixel line with pixel snapping turned ON.-->
<Rectangle SnapsToDevicePixels="True"
Width="45.5" Margin="10" Height="1" Fill="Red"/>
</StackPanel>
<!-- Background Grid -->
<Page.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Page.Background>
</Page>
![]() |
---|
SnapsToDevicePixels 只會影響透過配置階段執行的項目。您可以使用 DrawingGroup 物件的 GuidelineSet 屬性在 Drawing 上設定方針。若要手動設定 Visual 的方針,請使用 VisualYSnappingGuidelines 和 VisualXSnappingGuidelines 屬性建立新方針。 |
像素格線編排只會將水平和垂直的線條銳利化,不會影響斜線。
相鄰物件
在物件的邊緣相接,而且相接邊緣未準確對齊裝置像素之列或欄間的交界時,消除鋸齒也會造成視覺疊影。消除鋸齒的場景可能會使用基礎背景色彩柔化邊緣,而產生錯位效果 (即每個物件之間的邊緣呈現透明色彩)。下圖示範這個錯位效果。
具有錯位效果的相接物件。
啟用像素格線編排時,相接邊緣會對齊至裝置像素以消除錯位效果。下列範例示範 SnapsToDevicePixels 屬性對相接物件的影響。緩慢調整視窗大小時會發現,未對齊的矩形 (左側) 有錯位問題,而對齊的矩形 (右側) 仍很清楚,沒有視覺上的變化。
<Page x:Class="PixelSnapping.Seeping"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Title="Seeping"
>
<StackPanel Orientation="Horizontal" Height="100">
<Border
SnapsToDevicePixels="False"
Margin="10" BorderThickness="1" BorderBrush="Black" Height="80" Background="White">
<StackPanel Height="100.0">
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
</StackPanel>
</Border>
<Border
SnapsToDevicePixels="True"
Margin="10" BorderThickness="1" BorderBrush="Black" Height="80" Background="White">
<StackPanel Height="100.0">
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
</StackPanel>
</Border>
</StackPanel>
<!-- Background Grid -->
<Page.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Page.Background>
</Page>
請注意,對齊的矩形中並沒有明確設定 SnapsToDevicePixels 屬性的值。只需要將根項目的這個屬性設為 true,就可以在所有子項目上啟用這個行為。
文字
Windows Presentation Foundation (WPF) 一律會產生消除鋸齒的文字,如果文字是靜態的,就會進行像素對齊。這有助於讓消除鋸齒的文字看起來更清晰,其原理是將圖像 (Glyph) 直接置於像素格線上,因而提供更清楚的文字。不過,當 Windows Presentation Foundation (WPF) 偵測到任何類似動畫的移動時,例如捲動、縮放或平移動畫,就會關閉像素格線編排,直到移動完成為止。等到動畫或捲動等移動完成後,像素格線編排就會慢慢以動畫方式復原。
方針
像素格線編排的核心作業是由方針控制。方針會協助將幾何調整成對齊裝置像素格線。大多數的情況下,使用 SnapsToDevicePixels 屬性進行像素格線編排可以達到想要的結果。不過,這個屬性不是永遠都可以使用,特別是在使用 Drawing 物件或直接處理 DrawingContext 時,因此您必須設定方針以達到想要讓像素格線編排提供的清晰度。
若要在 Drawing 和 DrawingContext 物件上設定方針,您會使用 GuidelineSet 類別。這個類別讓您可以建立水平和垂直的方針,供套用至 DrawingGroup 或推入至 DrawingContext 以用於後續的繪圖命令。方針會指示繪圖哪條線應該對齊至裝置像素。如需 GuidelineSet 的詳細用法範例,請參閱 HOW TO:對圖形套用 GuidelineSet。
方針也可以在 Visual 層級上設定,方法是變更水平和垂直方針集合。這些都是可以透過 VisualYSnappingGuidelines 和 VisualXSnappingGuidelines 屬性存取的。
點陣圖影像
因為 WPF 具有與 DPI 無關的本質,點陣圖架構的 UI 的效果可能會不佳。在消除鋸齒的場景中,影像可能因為未對齊至完整像素的問題而變得模糊。對於具有高度變化的影像更是如此,這些變化包括單一像素的線條旁有對比項目 (例如黑線和白線交替)。下圖示範對齊影像 (左側) 和未與裝置像素對齊之影像 (右側) 的影像品質差異。
裝置像素的影像對齊。
UI 中影像的常見案例是將代表圖示的影像在其他物件內置中。因為圖示通常是具有高度變化的小型影像,所以可能需要調整應用程式的配置,以避免消除鋸齒功能產生的視覺疊影。
為正確地將影像置中,如果影像的像素寬度、長度為偶數,容器 (Container) 的寬度、長度也應該為偶數。如果影像的像素寬度、長度為奇數,容器項目的寬度、長度也應該為奇數。
下列範例會建立兩個內含 Image 的 Border 物件。上框線的寬度和長度為偶數,以符合影像的寬度和長度。下框線的寬度和長度則為奇數。
下圖顯示這個範例的輸出,以及容器大小對影像的影響。
<Page x:Class="PixelSnapping.Images"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Title="Images"
>
<StackPanel>
<!-- Image has a pixel dimension of 144x96. -->
<!-- Because the image has a even width and height,
an even border width and height allows the image to proper center.
-->
<Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="100">
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="sharpness.png" Stretch="None"/>
</Border>
<!-- Image has a pixel dimension of 144x96. -->
<!-- Because the image has a even width and height,
an odd border width and height causes the image to soften.
-->
<Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="201" Height="101">
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="sharpness.png" Stretch="None"/>
</Border>
</StackPanel>
<!-- Grid Background -->
<Page.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Page.Background>
</Page>
可惜的是,只調整容器物件的大小並不保證能與裝置像素對齊。應用程式的整個配置會影響影像的對齊。顯示器的 Dots Per Inch (DPI) 也會影響影像對齊。在上述範例中,影像對齊只會在顯示器設為 96 Dots Per Inch (DPI) 時有作用。如果是其他設定值,就需要調整配置以符合顯示器設定。Windows Presentation Foundation (WPF) 應用程式中應盡可能避免高度變化的影像。