0

I have some code that behaves weirdly. In a main window, there is a green Border that contains a custom control MyControl that draws its edge(left:0, top:0, right:ActualWidth - 1, bottom:ActualHeight - 1) using red brush. However, when program runs, the left and top edge of MyControl overlap with the left and top edge of Border, and there is a one-pixel-width gap between right edge of MyControl and right edge of Border, there is also another one-pixel-width gap between bottom edge of MyControl and bottom edge of Border. It seems that (1,1) instead of (0,0) is treated as origin point so X=1 is left edge, Y=1 is top edge, X=ActualWidth is right edge, Y=ActualHeight is bottom. I'm confused. Is there any wrong with my code? Here is the code:

MyControl:

public class MyControl : Control
{
    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        Pen pen = new Pen(Brushes.Red, 1);
        drawingContext.DrawLine(pen, new Point(0, 0), new Point(ActualWidth - 1, 0));
        drawingContext.DrawLine(pen, new Point(0, 0), new Point(0, ActualHeight - 1));
        drawingContext.DrawLine(pen, new Point(ActualWidth - 1, 0), new Point(ActualWidth - 1, ActualHeight - 1));
        drawingContext.DrawLine(pen, new Point(0, ActualHeight - 1), new Point(ActualWidth - 1, ActualHeight - 1));
        Console.WriteLine($"{ActualWidth}, {ActualHeight}");
    }
}

MainWindow.xaml:

<Window x:Class="WpfPlayGround.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfPlayGround"
        mc:Ignorable="d"
        SnapsToDevicePixels="True"
        RenderOptions.EdgeMode="Aliased"
        Title="MainWindow" Height="450" Width="800">
    <Canvas>
        <Border Name="Border" BorderBrush="LightGreen" BorderThickness="1" Margin="36" ClipToBounds="True" >
            <local:MyControl x:Name="MyControl" Width="400" Height="300"></local:MyControl>
        </Border>
    </Canvas>
</Window>

enter image description here enter image description here

AlpacaMan
  • 465
  • 2
  • 7
  • 24
  • Be aware that view coordinates in WPF are double (i.e. floating point) values. Drawing a Line at y=0 with a thickness of 1 draws half of the line (the upper part) outside the view. To draw that line at the classical "pixels" you would have to use y=0.5 for the topmost pixel row. – Clemens Jan 26 '22 at 13:12
  • So you would have to write something like `drawingContext.DrawLine(pen, new Point(0.5, 0.5), new Point(ActualWidth - 0.5, 0.5));` – Clemens Jan 26 '22 at 13:16
  • @Clemens Can you explain the mechanism of offset 0.5?why using 0.5 can make code work as I expect? – AlpacaMan Jan 27 '22 at 01:17
  • 1
    Think of the pixel as small square areas in a raster. The upper left corner of the upper left pixel is at (0,0), while its center is at (0.5,0.5). If you want to draw from the center of pixel (x,y) to the center of pixel (u,v), you would draw a line from (x+0.5,y+0.5) to (u+0.5,v+0.5). – Clemens Jan 27 '22 at 07:26

0 Answers0