You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求WPF中WinForm Graphics类替代方案及代码转换帮助

嘿,我太懂你把WinForm代码转WPF时的那种挫败感了——尤其是找不到Graphics类的替代方案,完全摸不着头绪对吧?别慌,我来给你梳理清楚WPF里的对应思路,毕竟WPF的渲染逻辑和WinForm的GDI+完全不是一回事,得换个路子来搞~

WinForm转WPF:Graphics类的替代方案及条码绘制示例

首先得明确:WPF没有直接对应WinForm中Graphics的类,因为两者的渲染机制天差地别——WinForm用的是GDI+的即时模式绘图,而WPF用的是保留模式的矢量渲染。不过我们可以用以下几种方式实现类似的绘图需求,适配你的条码生成场景:

1. 用WriteableBitmap做像素级操作(最贴近原代码思路)

如果你还是习惯像原来那样直接操控像素,WriteableBitmap是WPF里最接近Bitmap+Graphics组合的工具。它支持直接修改像素缓冲区,模拟你原来的绘图逻辑:

string barcode = textBox1.Text; // 假设WPF里的TextBox控件名字和原代码一致
int width = barcode.Length * 40;
int height = 150;

// 创建WPF可写位图
WriteableBitmap writeableBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr24, null);

// 锁定位图,开始操作像素
writeableBitmap.Lock();
try
{
    IntPtr backBuffer = writeableBitmap.BackBuffer;
    int stride = writeableBitmap.BackBufferStride;

    // 先绘制黑色背景(模拟原Graphics的背景填充)
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            IntPtr pixelPtr = backBuffer + y * stride + x * 3;
            // 设置BGR颜色值(这里是黑色)
            System.Runtime.InteropServices.Marshal.WriteByte(pixelPtr, 0);     // B
            System.Runtime.InteropServices.Marshal.WriteByte(pixelPtr + 1, 0); // G
            System.Runtime.InteropServices.Marshal.WriteByte(pixelPtr + 2, 0); // R
        }
    }

    // 这里插入你原有的条码绘制逻辑,比如根据barcode内容绘制白色条
    // ... 你的条码像素绘制代码 ...

    // 通知WPF更新位图区域
    writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
}
finally
{
    writeableBitmap.Unlock();
}

// 把生成的位图绑定到WPF的Image控件上
imageControl.Source = writeableBitmap;

2. 用DrawingVisual+DrawingContext(WPF推荐的保留模式)

这是WPF官方更推荐的方式,属于保留模式绘图——WPF会自动帮你管理渲染、重绘和资源释放。你可以自定义一个控件,在OnRender方法里用DrawingContext完成绘图:

public class BarcodeControl : Control
{
    // 定义依赖属性,让条码文本可以绑定
    public static readonly DependencyProperty BarcodeTextProperty =
        DependencyProperty.Register("BarcodeText", typeof(string), typeof(BarcodeControl), 
            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender));

    public string BarcodeText
    {
        get => (string)GetValue(BarcodeTextProperty);
        set => SetValue(BarcodeTextProperty, value);
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        string barcode = BarcodeText;
        if (string.IsNullOrEmpty(barcode)) return;

        int width = barcode.Length * 40;
        int height = 150;

        // 绘制黑色背景
        drawingContext.DrawRectangle(Brushes.Black, null, new Rect(0, 0, width, height));

        // 根据条码内容绘制白色条(示例逻辑:假设字符'1'代表白色条)
        for (int i = 0; i < barcode.Length; i++)
        {
            if (barcode[i] == '1')
            {
                drawingContext.DrawRectangle(Brushes.White, null, new Rect(i * 40, 0, 30, height));
            }
        }
    }
}

然后在XAML里直接用这个自定义控件,还能绑定文本:

<local:BarcodeControl BarcodeText="{Binding Text, ElementName=textBox1}" Width="Auto" Height="150"/>

3. 用第三方条码库(最省心的偷懒方案)

如果你的核心需求只是生成条码,完全没必要自己手动绘图!WPF有成熟的第三方库,比如ZXing.Net,直接生成WPF可用的ImageSource,省掉所有底层绘图麻烦:

using ZXing;
using ZXing.Windows.Compatibility;

string barcode = textBox1.Text;
var writer = new BarcodeWriterPixelData
{
    Format = BarcodeFormat.CODE_128, // 按需选择条码格式
    Options = new ZXing.Common.EncodingOptions
    {
        Width = barcode.Length * 40,
        Height = 150,
        Margin = 0
    }
};

var pixelData = writer.Write(barcode);
// 转换为WPF的BitmapSource
var bitmapSource = BitmapSource.Create(
    pixelData.Width, pixelData.Height,
    96, 96, PixelFormats.Gray8, null,
    pixelData.Pixels, pixelData.Width);

imageControl.Source = bitmapSource;

额外小提醒:关于BitmapImage

你提到已经把Bitmap换成了BitmapImage,但要注意:BitmapImage主要用来加载现有图片文件/流,并不适合动态绘图场景——动态生成图像优先用WriteableBitmap或者上面的保留模式方案哦。

内容的提问来源于stack exchange,提问作者Mab Kiani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:17:46