【发布时间】:2017-08-03 21:24:38
【问题描述】:
我想将 MainCanvas 的内容保存为 BMP 文件。
这是整个屏幕的图像。请注意,MainCanvas 是白色区域,网格以树林图案显示:
这是将 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());
}
}
这是保存的结果:
如您所见,它是 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 & 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 & 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 是怎么回事?它太狡猾了,这些天几乎不可能提出问题并得到答案。
【问题讨论】:
-
不是我的强项,但通常它在左边,顶部。你的代码似乎做对了,bot:RenderTargetBitmap((int)rect.Right, (int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default); rtb.Render(MainCanvas);
-
必须是右下角,否则会报错。该代码实际上来自 Stackoverflow 答案
-
什么错误等?对我来说,主要问题是你显然最终得到了一个位图,其中绘制的图像不在零左边
-
参数超出范围错误 (o,o)。 RengerTargetBitmap 的参数是 WIDTH 和 LENGTH 不是坐标。
-
恐怕我不知道,我更喜欢winforms,抱歉。话虽如此,结果与我对左侧不正确的drawimage所期望的结果完全相同。也许是 DPI 问题?