将画布保存到bmp不会保存正确的坐标

时间:2017-03-13 18:23:48

标签: c# wpf canvas bmp

我想将MainCanvas的内容保存为BMP文件。

这是整个屏幕的图像。请注意,MainCanvas是白色区域,其中网格以树林图案显示:

enter image description here

这是将MainCanvas作为BMP保存到磁盘的代码:

private void SaveMapFileAs_click(object sender, RoutedEventArgs e)
    {

            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.DefaultExt = ".bmp"; // Default file extension
            dlg.Filter = "BMP files (.bmp)|*.bmp"; // Filter files by extension

            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                string filename = dlg.FileName;
                Rect rect = new Rect(MainCanvas.RenderSize);
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
                  (int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
                rtb.Render(MainCanvas);
                //endcode as BMP
                BitmapEncoder bmpEncoder = new BmpBitmapEncoder();
                bmpEncoder.Frames.Add(BitmapFrame.Create(rtb));

                //save to memory stream
                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                bmpEncoder.Save(ms);
                ms.Close();
                System.IO.File.WriteAllBytes(filename, ms.ToArray());

            }

    }

这是保存的结果:

enter image description here

正如您所看到的,它是MainCanvas的正确宽度和高度,但它不是从MainCanvas的0,0保存,而是整个屏幕的0,0。

最后,这是XAML:

<Window x:Class="MapDesignModule.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MapDesignModule"

        WindowState="Maximized" UseLayoutRounding="True" 
        ResizeMode="CanMinimize" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" WindowStyle="SingleBorderWindow" Title="Map Design Module" MaxHeight="900" MaxWidth="1440" WindowStartupLocation="CenterScreen" FontFamily="Rudyard WF" FontSize="16">

    <StackPanel>
        <Menu VerticalAlignment="Top" HorizontalAlignment="Left" Grid.ColumnSpan="1" Width="1440" Margin="0,0,0,0" FontFamily="Ephinol WF" FontSize="16">
            <Menu.Background>
                <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                    <GradientStop Color="White" Offset="0.291" />
                    <GradientStop Color="#FF6F6454" Offset="0.924" />
                </LinearGradientBrush>
            </Menu.Background>
            <MenuItem Header="File">
                <MenuItem Header="_New Map" Name="NewMap" />
                <MenuItem Header="_Open Map File..." Name="OpenMapFile" />
                <MenuItem Header="_Save Map File" Name="SaveMapFile" />
                <MenuItem Header="_Save Map File As..." x:Name="SaveMapFileAs" Click="SaveMapFileAs_click" />
                <Separator/>
                <MenuItem Header="_Print Map..." Name="PrintMapMenu" Click="PrintMapMenu_click" />
                <Separator/>
                <MenuItem Header="_Quit to Main Menu"  />
                <MenuItem Header="_Quit to Desktop" Name="Quit"  Click= "Quit_click"/>
            </MenuItem>
            <MenuItem Header="Background">
                <MenuItem Header="_Show Background Paper" x:Name="ShowBackgroundPaperMenuItem" IsCheckable="true" IsChecked="True" Click="ShowBackgroundPaperMenuItem_Click"/>
                <MenuItem Header="_Select Background Paper..." x:Name="SelectBackgroundPaper"  Click="SelectBackgroundPaper_Click"/>
            </MenuItem>
            <MenuItem Header="Layers">
                <MenuItem Header="_Show Grid" x:Name="ShowGridMenuItem" IsCheckable="true" IsChecked="True" Click="ShowGrid_Click"/>
                <MenuItem Header="_Show Placenames" x:Name="ShowPlacenamesMenuItem" IsCheckable="true" IsChecked="True" Click="ShowPlacenames_Click"/>
                <MenuItem Header="_Show Coordinates" x:Name="ShowCoordinatesMenuItem" IsCheckable="true" IsChecked="False" Click="ShowCoordinatesMenuItem_Click"/>
            </MenuItem>
            <MenuItem Header="Help">
                <MenuItem Header="_About the General Staff Map Design Module" x:Name="AboutMenuItem" />

            </MenuItem>
        </Menu>

        <Grid  Height="872">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="284" />
                <ColumnDefinition Width="1167" />
            </Grid.ColumnDefinitions>
            <Canvas Grid.Column="0" HorizontalAlignment="Left" Height="817"  VerticalAlignment="Top" Width="273" Name="LeftCanvas">
                <Image  Width="271" Height="817" Stretch="Fill" Name="LeftPanelPaper"  />
                <Label Canvas.Left="6" Canvas.Top="30" Content="Select Drawing Tool:" Height="49" Name="label1" Width="261" FontFamily="Nestor WF" FontSize="26" HorizontalContentAlignment="Center" />
                <TextBlock Canvas.Left="46" Canvas.Top="163" Text="Ponds &amp; Lakes" Height="46" Name="PondsLabel" FontSize="40" MouseDown="Pond_MouseDown" MouseMove="Pond_MouseMove" MouseLeave="Pond_MouseLeave"  Foreground="Black" Width="202" TextWrapping="Wrap" />
                <Label Canvas.Left="6" Canvas.Top="156" Content="P" Height="57" Name="PondCheckMark" Width="58" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C"  />
                <TextBlock Canvas.Left="46" Canvas.Top="94" FontSize="40" Foreground="Black" Height="43" Name="WoodsLabel" Text="Woods " MouseDown="Woods_MouseDown"  MouseMove="Woods_MouseMove" MouseLeave="Woods_MouseLeave" />
                <Label Canvas.Left="3" Canvas.Top="87" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="42" Name="WoodsCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="233" FontSize="40" Foreground="Black" Height="46" Name="FortLabel" Text="Fortifications" TextWrapping="Wrap" Width="202" FontFamily="Rudyard WF" MouseDown="Fort_MouseDown"  MouseMove="Fort_MouseMove" MouseLeave="Fort_MouseLeave"/>
                <Label Canvas.Left="6" Canvas.Top="226" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="FortCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="299" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="SwampLabel" Text="Swamp" TextWrapping="Wrap" Width="202"  MouseDown="Swamp_MouseDown"  MouseMove="Swamp_MouseMove" MouseLeave="Swamp_MouseLeave"/>
                <Label Canvas.Left="6" Canvas.Top="291" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="SwampCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="368" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="HillLabel" Text="Hills &amp; Ridges" TextWrapping="Wrap" Width="202" MouseDown="Hill_MouseDown"  MouseMove="Hill_MouseMove" MouseLeave="Hill_MouseLeave"/>
                <Label Canvas.Left="6" Canvas.Top="360" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="HillCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="438" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="RoadLabel" Text="Roads" TextWrapping="Wrap" Width="202" MouseDown="Road_MouseDown"  MouseMove="Road_MouseMove" MouseLeave="Road_MouseLeave"/>
                <Label Canvas.Left="6" Canvas.Top="430" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="RoadsCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="512" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="RiverLabel" Text="Rivers" TextWrapping="Wrap" Width="202" MouseDown="River_MouseDown"  MouseMove="River_MouseMove" MouseLeave="River_MouseLeave"/>
                <Label Canvas.Left="3" Canvas.Top="506" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="RiverCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="585" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="CityLabel" Text="Cities" TextWrapping="Wrap" Width="202" MouseDown="City_MouseDown"  MouseMove="City_MouseMove" MouseLeave="City_MouseLeave"/>
                <TextBlock Canvas.Left="46" Canvas.Top="648" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="PlacenameLabel" Text="Placenames" TextWrapping="Wrap" Width="202" MouseDown="Placename_MouseDown"  MouseMove="Placename_MouseMove" MouseLeave="Placename_MouseLeave"/>
                <Label Canvas.Left="6" Canvas.Top="579" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="CityCheckMark" Width="58" />
                <Label Canvas.Left="6" Canvas.Top="641" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="PlacenamesCheckMark" Width="58" />
                <TextBlock Canvas.Left="46" Canvas.Top="714" FontFamily="Rudyard WF" FontSize="40" Foreground="Black" Height="46" Name="BridgeLabel" Text="Bridges" TextWrapping="Wrap" Width="202" MouseDown="Bridge_MouseDown"  MouseMove="Bridge_MouseMove" MouseLeave="Bridge_MouseLeave"/>
                <Label Canvas.Left="6" Canvas.Top="705" Content="P" FontFamily="Wingdings 2" FontSize="48" Foreground="#FFC44F1C" Height="57" Name="BridgeCheckMark" Width="58" />
            </Canvas>

            <Canvas HorizontalAlignment="Right" Height="817"  VerticalAlignment="Top" Width="1183" Name="MainCanvas" Grid.Column="1" MouseDown="Canvas_MouseDown_1" MouseUp="Canvas_MouseUp_1"  MouseMove="Canvas_MouseMove_1">
                <Image Width="1167" Height="817" Stretch="Fill" Name="PaperTextureSource" />
                <Image Width="1167" Height="817"  Name="MapBorderSource" Opacity="60" OpacityMask="{x:Null}" />
            </Canvas>
    </Grid>
    </StackPanel>
</Window>

有没有人知道为什么所有的MainCanvas都没有保存到磁盘上?

编辑: 这是解决方案(使用完整的方法):

  private void SaveMapFileAs_click(object sender, RoutedEventArgs e)
    {

        Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
        dlg.DefaultExt = ".bmp"; // Default file extension
        dlg.Filter = "BMP files (.bmp)|*.bmp"; // Filter files by extension

        // Show save file dialog box
        Nullable<bool> result = dlg.ShowDialog();

        // Process save file dialog box results
        if (result == true)
        {
            string filename = dlg.FileName;
            RenderTargetBitmap rtb = new RenderTargetBitmap((int)MainCanvas.RenderSize.Width,
                  (int)MainCanvas.RenderSize.Height, 96, 96, PixelFormats.Default);

            VisualBrush sourceBrush = new VisualBrush(MainCanvas);
            DrawingVisual drawingVisual = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();
            using (drawingContext)
            {
                drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0),
                       new Point(MainCanvas.RenderSize.Width, MainCanvas.RenderSize.Height)));
            }

            rtb.Render(drawingVisual);
            //endcode as BMP
            BitmapEncoder bmpEncoder = new BmpBitmapEncoder();
            bmpEncoder.Frames.Add(BitmapFrame.Create(rtb));

            //save to memory stream
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            bmpEncoder.Save(ms);
            ms.Close();
            System.IO.File.WriteAllBytes(filename, ms.ToArray());
        }

    }

就个人而言,我只想问一下,“Stackoverflow发生了什么事情?它太蠢了,这几天几乎不可能提出问题并得到答案。”

1 个答案:

答案 0 :(得分:0)

这是完整的方法,可以解决问题(原始代码来自Stackoverflow的原始帖子不正确):

 private void SaveMapFileAs_click(object sender, RoutedEventArgs e)
        {

            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.DefaultExt = ".bmp"; // Default file extension
            dlg.Filter = "BMP files (.bmp)|*.bmp"; // Filter files by extension

            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                string filename = dlg.FileName;
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)MainCanvas.RenderSize.Width,
                      (int)MainCanvas.RenderSize.Height, 96, 96, PixelFormats.Default);

                VisualBrush sourceBrush = new VisualBrush(MainCanvas);
                DrawingVisual drawingVisual = new DrawingVisual();
                DrawingContext drawingContext = drawingVisual.RenderOpen();
                using (drawingContext)
                {
                    drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0),
                           new Point(MainCanvas.RenderSize.Width, MainCanvas.RenderSize.Height)));
                }

                rtb.Render(drawingVisual);
                //endcode as BMP
                BitmapEncoder bmpEncoder = new BmpBitmapEncoder();
                bmpEncoder.Frames.Add(BitmapFrame.Create(rtb));

                //save to memory stream
                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                bmpEncoder.Save(ms);
                ms.Close();
                System.IO.File.WriteAllBytes(filename, ms.ToArray());
            }

        }