Search code examples
c#wpfwindowsize

Why window smaller than actualwidth?


I want capture window but The actual window size seems to be smaller than the figure.

this is code

<Window x:Class="FileRead.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Width="620" Height="340" >
<Grid>

    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <Button x:Name="ReadImageButton" Width="100" Height="30" Margin="10" Click="ReadImage_Click">
                LoadImage
            </Button>

            <Button x:Name="ReadTextButton" Width="100" Height="30" Margin="10" Click="ReadText_Click">
                LoadText
            </Button>

            <Button x:Name="CaptueScreenButton" Width="80" Height="30" Margin="10" Click="CaptueScreenButton_Click">
                ScreenCapture
            </Button>

            <Button x:Name="CaptuerWindowButton" Width="80" Height="30" Margin="10" Click="CaptuerWindowButton_Click">
                WindowCapture
            </Button>

I couldn't find a problem.

private void CaptuerWindowButton_Click(object sender, RoutedEventArgs e)
{
    int width = (int)this.ActualWidth;
    int height = (int)this.ActualHeight;

    Point point = this.PointToScreen(new Point(0, 0)); 

    CheckLable.Content = string.Format("{0} / {1}", this.Width, this.ActualWidth);

    using (Bitmap bmp = new Bitmap(width, height))
    {
        using (Graphics gr = Graphics.FromImage(bmp))
        {
            gr.CopyFromScreen( (int)point.X, (int)this.Top, 0, 0, bmp.Size);

        }


        bmp.Save(ImagePath + "/WindowCapture.png", ImageFormat.Png);
    }
}

result image result image

There is always a difference of about 15 points.: https://i.sstatic.net/1YTvy.png

help me please.

enter image description here


Solution

  • The cause of your problem is that size of a window include the area that draw by OS, which was called "non-client area", usually include frame, border, drop show effect. And your calculation didn't consider that. The right code will like

        var clientTopLeft = this.PointToScreen(new System.Windows.Point(0, 0));
        // calculate the drop show effect offset. 
        var shadowOffset = SystemParameters.DropShadow ? clientTopLeft.X - Left - 
            ((WindowStyle == WindowStyle.None && ResizeMode < ResizeMode.CanResize) ? 0 : SystemParameters.BorderWidth) : 0;
    
        // exclude left and right drop shadow area
        int width = (int)(Width - 2 * shadowOffset);
        // exclude bottom drop shadow area
        int height = (int)(Height - shadowOffset);
    
        using (Bitmap bmp = new Bitmap(width, height))
        {
            using (Graphics gr = Graphics.FromImage(bmp))
            {
                gr.CopyFromScreen((int)(Left + shadowOffset),
                    (int)Top, 0, 0, bmp.Size);
            }
    
            bmp.Save("WindowCapture.png");
        }