在 C# 中绘制到新“层”

2024-01-04

构建一个小绘画程序并尝试合并图层的概念。

我使用 PictureBox 控件来显示图像,并从 PictureBox 显示的图像中获取 Graphics 对象并绘制到该对象。

我的问题是我试图弄清楚如何绘制覆盖在图片框顶部的新 Graphics 对象,并能够获取新绘制的图像without原始图像吸收到图形中。

如果我做类似的事情:

Graphics gr = Graphics.FromImage(myPictureBox.image);
gr.DrawRectangle(blah blah)

...我正在编辑图片框中的原始图像。我想要一种方法来仅捕获正在绘制的新内容作为单独的图像,但仍然将其显示为覆盖在已有内容之上。

有人能指出我正确的方向吗?谢谢!


我会考虑使用透明控件并进行一些修改,以便它可以用作图像层:

http://www.codeproject.com/Articles/26878/Making-Transparent-Controls-No-Flickering http://www.codeproject.com/Articles/26878/Making-Transparent-Controls-No-Flickering

可能是这样的(根据需要进行任何修改)。

class LayerControl : UserControl
{
    private Image image;
    private Graphics graphics;

    public LayerControl(int width, int height)
    {
        this.Width = width;
        this.Height = height;

        image = new Bitmap(width, height);

        graphics = Graphics.FromImage(image);

        // Set style for control
        SetStyle(ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint, true);
    }

    // this function will draw your image
    protected override void OnPaint(PaintEventArgs e)
    {
        var bitMap = new Bitmap(image);
        // by default the background color for bitmap is white
        // you can modify this to follow your image background 
        // or create a new Property so it can dynamically assigned
        bitMap.MakeTransparent(Color.White);

        image = bitMap;

        Graphics g = e.Graphics;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
        g.CompositingQuality = CompositingQuality.GammaCorrected;

        float[][] mtxItens = {
            new float[] {1,0,0,0,0},
            new float[] {0,1,0,0,0},
            new float[] {0,0,1,0,0},
            new float[] {0,0,0,1,0},
            new float[] {0,0,0,0,1}};

        ColorMatrix colorMatrix = new ColorMatrix(mtxItens);

        ImageAttributes imgAtb = new ImageAttributes();
        imgAtb.SetColorMatrix(
            colorMatrix,
            ColorMatrixFlag.Default,
            ColorAdjustType.Bitmap);

        g.DrawImage(image,
                    ClientRectangle,
                    0.0f,
                    0.0f,
                    image.Width,
                    image.Height,
                    GraphicsUnit.Pixel,
                    imgAtb);
    }

    // this function will grab the background image to the control it self
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        base.OnPaintBackground(e);
        Graphics g = e.Graphics;

        if (Parent != null)
        {
            BackColor = Color.Transparent;
            int index = Parent.Controls.GetChildIndex(this);

            for (int i = Parent.Controls.Count - 1; i > index; i--)
            {
                Control c = Parent.Controls[i];
                if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
                {
                    Bitmap bmp = new Bitmap(c.Width, c.Height, g);
                    c.DrawToBitmap(bmp, c.ClientRectangle);

                    g.TranslateTransform(c.Left - Left, c.Top - Top);
                    g.DrawImageUnscaled(bmp, Point.Empty);
                    g.TranslateTransform(Left - c.Left, Top - c.Top);
                    bmp.Dispose();
                }
            }
        }
        else
        {
            g.Clear(Parent.BackColor);
            g.FillRectangle(new SolidBrush(Color.FromArgb(255, Color.Transparent)), this.ClientRectangle);
        }
    }

    // simple drawing circle function
    public void DrawCircles()
    {
        using (Brush b = new SolidBrush(Color.Red))
        {
            using (Pen p = new Pen(Color.Green, 3))
            {
                this.graphics.DrawEllipse(p, 25, 25, 20, 20);
            }
        }
    }

    // simple drawing rectable function
    public void DrawRectangle()
    {
        using (Brush b = new SolidBrush(Color.Red))
        {
            using (Pen p = new Pen(Color.Red, 3))
            {
                this.graphics.DrawRectangle(p, 50, 50, 40, 40);
            }
        }
    }

    // Layer control image property
    public Image Image
    {
        get
        {
            return image;
        }
        set
        {
            image = value;
            // this will make the control to be redrawn
            this.Invalidate();
        }
    }
}

如何使用它的示例:

LayerControl lc = new LayerControl(100, 100);
lc.Location = new Point(0, 0);
lc.DrawRectangle();

LayerControl lc2 = new LayerControl(100, 100);
lc2.Location = new Point(0, 0);
lc2.DrawCircles();

LayerControl lc3 = new LayerControl(100, 100);
lc3.Location = new Point(0, 0);
lc3.Image = new Bitmap(@"<Image Path>");

// adding control
this.Controls.Add(dc);
this.Controls.Add(dc2);
this.Controls.Add(dc3);

使用这种方法,您可以拥有多个可以相互重叠的图层(由于它具有透明功能)。

如果您想将其添加到 PictureBox 的顶部,请确保重新排序该控件。 Layer 控件应添加在 PictureBox 控件之前。

// adding control
this.Controls.Clear();
this.Controls.Add(dc);
this.Controls.Add(dc2);
this.Controls.Add(dc3);
this.Controls.Add(PictureBox1);

希望它有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中绘制到新“层” 的相关文章

随机推荐

  • 如何取回现有的消息队列 ID

    我正在使用 msgget 系统调用来获取新的消息队列 我在其中使用了 IPC CREAT 和 IPC EXCL 标志 喜欢message queue msgget ftok tmp 100 0666 IPC CREAT IPC EXCL 现
  • Python copy:如何继承默认的复制行为?

    好吧 这可能是一个愚蠢的问题 但我现在找不到答案 我需要实现一个对象的复制 我想要复制该对象的所有属性 除了我想要完全控制复制的一两个属性 这是对象的标准复制行为 gt gt gt class test object def init se
  • 尝试在 MatLab 中编译 C mex 文件

    嘿 我试图在 MatLab 中编译一个 C 文件 但我收到了这个错误 我正在尝试理解它 非常感谢任何和所有指导 gt gt mex BDS unpack mex5 c xcrun error SDK macosx10 7 cannot be
  • Python IndexError:列表索引超出范围

    我试图让 Python 用 500 只股票的收盘价填充列表 虽然该代码似乎只适用于少数股票 但数量过多就会带来问题 Python 不断给我以下错误 OneClose append Data i 4 IndexError list index
  • 将数据从 C++ 传递到 PHP

    我需要将一个值从 PHP 传递到 C 我想我可以用 PHP 来做passthru 功能 然后我希望 C 对该值执行某些操作并将结果返回给 PHP 这是我无法解决的问题 有谁知道如何将数据从 C 传递到 PHP 我不想使用中间文件 因为我认为
  • 如何使用VBA截取网页截图?

    如何在Excel中使用VBA截取网页截图 问题是 屏幕截图只能通过按键盘的 F6 键来进行 因为 Screenhunter 就是用于此目的的 打印屏幕键被禁用 我使用了以下代码 但意识到无法使用sendkey函数 sub test appl
  • Numpy n 个奇数根(包括负值)

    我想在Python中计算一些数字的n次奇根 Numpy 作为立方根函数 使用该函数我可以计算 x 1 3 x np linspace 100 100 100 np cbrt x gt gt gt array 4 64158883 4 268
  • 如何设置 CultureInfo.InvariantCulture 默认值?

    当我在 C 中有这样一段代码时 double a 0 003 Console WriteLine a 它打印 0 003 如果我还有另一段代码 double a 0 003 Console WriteLine a ToString Cult
  • Mathematica:如何清除符号的缓存,即取消设置无模式的 DownValues

    我是一个糟糕的缓存器 有时 当没有人在看时 我会缓存结果而不包含完整的上下文 如下所示 f x f x x a a 2 f 1 DownValues f Out 2 HoldPattern f 1 gt 3 HoldPattern f x
  • InnoDB Write Log效率太高超过100%(1953.15%)?

    我的服务器上有 MariaDB 具有 16 32 个 CPU 核心 运行 mysqltuner 时一切似乎都正常 除了InnoDB写日志效率 采取1953 15 想知道这正常吗 或者有什么解决方案可以解决这个问题吗 感谢您的建议 InnoD
  • C++——如何重载运算符+=?

    鉴于以下代码片段 class Num public Num int iNumber 0 m iNumber iNumber Num operator const Num rhs this gt m iNumber this gt m iNu
  • 带图像的 Xamarin Forms ListView |文字|时间

    我目前正在使用 xamarin 表单构建一个混合应用程序 我正在尝试构建一个列表视图 显示带有图标和时间戳的错误 这是我想重新制作成 xamarin 形式的概念设计 我用了一个ImageCell尝试让带有一些文本的图标正常工作 但现在我想在
  • MongoDB 中复合 _id 的预期行为?

    我有一个包含 3 个数字属性的复合 id id KeyA 0 KeyBOARD 0 Key 0 相关数据库的 KeyA 有 200 万个相同值 KeyB 有 50 万个相同值的集群 我的理解是 我可以使用以下命令有效地查询 KeyA 和 K
  • 如何在 JupyterLab 中拆分和合并单元格

    In Jupyter实验室 https jupyterlab readthedocs io en latest 给定以下代码单元格 如何将其拆分为多个单元格 同样 给定以下单元格 如何将它们组合成单个单元格 直接使用 JupyterLab
  • opencv颜色检测

    使用opencv 可以在图像或视频帧中检测某种颜色 在一定范围的rgb值之间 吗 您需要定义 RGB 阈值 并处理图像中适合定义的像素 希望不是整个图像 而是较小的感兴趣区域 可能是移动的前景形状 与所讨论的内容类似here http ww
  • Symfony2:验证因第一个错误而停止

    看来 validator gt validate class Symfony2 的验证服务 http symfony com doc current book validation html在 if 返回之前运行所有验证检查 error班级
  • 尽管 rasterized=True,为什么 matplotlib 图文件大小很大?

    一个简单的例子 from matplotlib pyplot import plot savefig from numpy random import randn plot randn 100 randn 100 500 k alpha 0
  • 智能生成String排列组合的方法

    String database a b c 我想根据给定生成以下字符串序列database a b c aa ab ac ba bb bc ca cb cc aaa 我只能想到一个相当 虚拟 的解决方案 public class JavaA
  • 为什么 findstr 不能正确处理大小写(在某些情况下)?

    在 cmd exe 中编写最近的一些脚本时 我需要使用findstr使用正则表达式 客户需要标准 cmd exe 命令 无 GnuWin32 Cygwin VBS 或 Powershell 我只是想知道变量是否包含任何大写字符并尝试使用 g
  • 在 C# 中绘制到新“层”

    构建一个小绘画程序并尝试合并图层的概念 我使用 PictureBox 控件来显示图像 并从 PictureBox 显示的图像中获取 Graphics 对象并绘制到该对象 我的问题是我试图弄清楚如何绘制覆盖在图片框顶部的新 Graphics