我如何将此方法从Winforms转换为WPF?

Jer*_*ade 4 .net c# wpf

我有一个简单的程序,可以根据一系列数字创建一系列PNG图像,即; 我遍历每个数字,并以各种大小创建该数字的png图像.以下是我用来创建图像的空白.

private void CreatePNG(int number, string location, int width, int height)
        {
            string filename = number.ToString() + "-" + width.ToString() + "x" + height.ToString() + ".png";            
            Bitmap b = new Bitmap(width, height);

            Graphics g = Graphics.FromImage((System.Drawing.Image)b);
            g.FillRectangle(Brushes.White, 0f, 0f, width, height);

            StringFormat f = new StringFormat();
            f.Alignment = StringAlignment.Center;
            f.LineAlignment = StringAlignment.Center;
            g.DrawString(number.ToString(), new Font("Helvetica", 55), Brushes.Black, new RectangleF(0, 0, width, height), f);
            b.Save(location + "\\" + filename, ImageFormat.Png);    
        }
Run Code Online (Sandbox Code Playgroud)

我想要做的是将此void转换为与WPF一起使用.我目前对WPF没有经验,因此我的noobie问题.

目标框架是4.0

非常感谢帮助.

Ray*_*rns 9

System.Drawing是WinForms NOT WPF的一部分

首先,我想澄清一个误解.

System.Drawing基于Win32的GDI +,实际上是WinForms的一个组件.WPF不是基于它构建的,Silverlight和其他平台的WPF端口可能永远不会包含它,并且System.Drawing(WinForms)使用的约定与System.Windows.Media(WPF)使用的约定之间存在许多不兼容性. .例如,他们使用不同的度量单位(像素与固定的96dpi),不同的坐标类型(int vs double),不同的线条绘制规则,不同的旋转,不同的brushm,立即vs保留模式等.

WPF的System.Windows.Media库比WinForms System.Drawing(GDI +)库强大得多.WPF包含更多变换,更好的不透明度支持,3D和其他功能,允许System.Drawing(GDI +)非常困难的效果.

但是,问题中提出的代码是否可以与WPF一起使用?

是的,它会的.只要您在WPF上运行而不是像Silverlight这样的克隆,您仍然可以访问旧的WinForms库.所以你可以继续使用System.Drawing调用来绘制你的数字.但你无法获取生成的Bitmap并将其简单地插入到你的WPF应用程序中:位图是不兼容的,并且像往常一样WPF位图更强大.有一些方法可以将位图转换为WPF位图,或者可以将其保存为标准文件格式(如.png)并重新加载.

由于问题中提出的代码实际上确实将位图保存为.png文件,因此实际上可以不加改变地使用它.但是,如果在创建位图时需要任何新的WPF功能,或者如果要在不保存到文件的情况下使用位图,则需要特殊技术.

那你为什么不想按原样使用这段代码呢?

也许你会这样:如果你正在做一个快速的应用程序并且已经编写了代码,并且你确实想要将文件存储到磁盘,那么没有理由将代码转换为WPF.但是,如果您想使用新的WPF功能或使用数据绑定或其他动态技术将图像直接合并到WPF用户界面,您可能希望将程序转换为使用WPF的库而不是使用WinForms.这是根据您的需求进行的判断.

您的问题询问了使用此代码"使用WPF"所需的条件.答案是:没什么.您的代码编写普通的.png文件,WPF读取普通的.png文件.所以它会奏效.

如果您的代码是使用COBOL或Java或任何其他原始语言从90年代调用基于Unix的绘图库,则可以说同样的事情.只要代码最终编写标准.png文件(或.gif或.jpg或...),其输出将与WPF一起使用.正如有令人信服的理由不将代码保留在COBOL或Java中一样,有理由不使用System.Drawing保留代码:

  1. 依赖于System.Drawing随着时间的推移可能会或可能不会出现WPF可以使用.
  2. 你可以画的限制
  3. 与其他WPF代码不同的绘图模型

那么我如何使用WPF来代替WinForms呢?

您可以使用三个简单步骤从WPF中显示的任何内容中制作位图:

  1. 使用XAML或代码构建WPF Visual.
  2. 在代码中,构造一个所需大小的RenderTargetBitmap然后调用.Render(visual)
  3. 在应用程序的其他位置使用生成的位图,或使用PngBitmapEncoder或类似方法保存它.

对于您的特定示例,我可能会使用如下的DataTemplate:

<DataTempate x:Key="NumberTemplate">
  <TextBlock
    Background="White"
    HorizontalAlignment="Center" VerticalAlignment="Center"
    FontFamily="Helvetica" FontSize="55"
    Text="{Binding}"
  />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

那么你写出文件的实际代码是:

void CreatePng(int number, string location, int width, int height)
{
  WritePng(location + "/" + number + "-" + width + "x" + height + ".png",
           new ContentPresenter  // Invokes a DataTemplate on its content
           {
             Content = number.ToString(),
             Template = NumberTemplate,
             Width = width, Height = height
           });
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以省略模板,只需在代码中构造TextBlock来代替ContentPresenter.但是模板可以很容易地快速改变你的外观并添加不透明度,渐变画笔,位图效果等花哨的东西,所以我建议使用模板,除非你绝对确定你的外观永远不会改变.

WritePng()方法是一个通用的单帧.png文件编写器,它在一个简单的界面中封装了WPF的高级功能.它的编码如下:

void WritePng(string path, UIElement element)
{
  // Create the bitmep specifying the size, pixel format and DPI
  var bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
                                      96, 96, PixelFormats.Pbgra32);
  bitmap.Render(element); // At this point the bitmap is usable within WPF

  // Write to a file:  WPF can write multiple frames but we need only one
  var encoder = new PngBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bitmap));
  using(Stream stream = File.Create(path))
    encoder.Save(stream);  // Could be any stream, not just a file
}
Run Code Online (Sandbox Code Playgroud)

  • "System.Drawing是WinForms的一部分...... GDI +实际上是WinForms的一个组件." 不,GDI +是一个通用的绘图库,独立于WinForms; 它不是.NET中任何其他东西的"组件".是的,WinForms使用GDI +但反之亦然.事实上,GDI +可以从优秀的旧版Win32中使用!也就是说,你使用GDI +在你的代码库中留下两个不同的绘图模型的观点是公平的,RenderTargetBitmap在WPF环境中肯定更加惯用,所以这真是一个技术挑剔 - 很好的答案. (2认同)