【问题标题】:PictureBox with overriden OnPaint method in C#在 C# 中具有重写 OnPaint 方法的 PictureBox
【发布时间】:2012-03-26 21:08:01
【问题描述】:

我想在 PictureBox 中绘制一些小图片(连续 4 x 32px 图像)所以我应该重写 OnPaint 方法还是需要制作扩展 PictureBox 的新组件? 我试过这个,它在 Java 中工作,但不是在这里:

        this.pictureBox1 = new System.Windows.Forms.PictureBox()
        {
            protected override void OnPaint(PaintEventArgs e)
            {
               // If there is an image and it has a location, 
               // paint it when the Form is repainted.
                Graphics g = e.Graphics;

                // Draw a string on the PictureBox.
                g.DrawString("Test, is that working?",
                new Font("Arial", 10), System.Drawing.Brushes.Blue, new Point(30, 30));
             }
        }

InitializeComponent 方法的完整代码:

   private void InitializeComponent()
    {
        System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Tools));
        this.pictureBox1 = new System.Windows.Forms.PictureBox()
        {
            protected override void OnPaint(PaintEventArgs e)
            {
               // If there is an image and it has a location, 
               // paint it when the Form is repainted.
                Graphics g = e.Graphics;

                // Draw a string on the PictureBox.
                g.DrawString("Test, is that working?",
                new Font("Arial", 10), System.Drawing.Brushes.Blue, new Point(30, 30));
             }
        }
        this.vscrollb = new System.Windows.Forms.VScrollBar();
        this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
        this.SuspendLayout();
        // 
        // pictureBox1
        // 
        this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Left;
        this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
        this.pictureBox1.InitialImage = null;
        this.pictureBox1.Location = new System.Drawing.Point(0, 0);
        this.pictureBox1.Name = "pictureBox1";
        this.pictureBox1.Size = new System.Drawing.Size(264, 262);
        this.pictureBox1.TabIndex = 0;
        this.pictureBox1.TabStop = false;
        this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
        // 
        // vscrollb
        // 
        this.vscrollb.Location = new System.Drawing.Point(0, 0);
        this.vscrollb.Name = "vscrollb";
        this.vscrollb.Size = new System.Drawing.Size(20, 80);
        this.vscrollb.TabIndex = 0;
        // 
        // vScrollBar1
        // 
        this.vScrollBar1.Dock = System.Windows.Forms.DockStyle.Right;
        this.vScrollBar1.Location = new System.Drawing.Point(267, 0);
        this.vScrollBar1.Name = "vScrollBar1";
        this.vScrollBar1.Size = new System.Drawing.Size(17, 262);
        this.vScrollBar1.TabIndex = 1;
        this.vScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.HandleScroll);
        // 
        // Tools
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.BackColor = System.Drawing.Color.Black;
        this.ClientSize = new System.Drawing.Size(284, 262);
        this.Controls.Add(this.vScrollBar1);
        this.Controls.Add(this.pictureBox1);
        this.Name = "Tools";
        this.Text = "Tools";
        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
        this.ResumeLayout(false);

    }

【问题讨论】:

  • 这段代码运行良好,有什么问题?
  • 我已将此添加到 InitializeComponent 方法中。这是完整的代码:
  • @PiotrŁużecki:不要向“InitializeComponent”添加任何内容,因为此方法将在每次更改时被设计器覆盖。您可以在构造函数中调用“InitializeComponent”“之后”添加它。
  • 我正在尝试按照您所说的执行此操作,但我在第一个括号附近出现编译错误:初始化程序成员声明器无效。我不能在那里覆盖方法?

标签: c# picturebox onpaint


【解决方案1】:

这只是无效的 C# 代码。重写像 OnPaint() 这样的虚拟方法很好,但您只能在派生自 PictureBox 的类中这样做。效果很好,编译后你会自动将新控件添加到工具箱中,这样你就可以把它放在表单上。

但这不是必需的。您可以简单地为控件实现 Paint 事件。您已经这样做了,您将其命名为 pictureBox1_Paint()。只需将您的代码移到那里即可。

其他重要提示:永远不要编辑 InitializeComponent()。它是由设计师自动生成的。一旦您修改了表单的设计,您将丢失在那里编写的任何代码。这也是使表单不可设计的一种非常好的方法,当设计器加载表单时会触发异常。如果你确实重写了 OnPaint(),那么调用 base.OnPaint() 很重要。以便正常的 PictureBox 管道继续工作。包括绘制 Image 和引发 Paint 事件。请务必至少遵循教程或阅读有关 Winforms 编程的书籍,如果您不这样做,将会有很多尝试和错误。

【讨论】:

    【解决方案2】:

    我建议从PictureBox 继承并在那里添加您的逻辑。所以你不必在不属于它的地方(父控件)添加逻辑。

    public class SpecialPictureBox : PictureBox
    {
        protected override void OnPaint(PaintEventArgs e)
        {
            // if you want to execute the original PaintBox logic before you execute your own code, use the next line of code.
            base.OnPaint(e);
    
            // now do whatever you want
    
        }
    }
    

    然后,您可以在任何地方使用SpecialPictureBox

    编辑:在代码示例中添加了base.OnPaint

    【讨论】:

    • 所以我不能在不上新课的情况下做到这一点?我是否必须调用一些事件,如 OnPaint 或其他?我可以将它添加到工具箱吗?
    • 你可以在不创建新类的情况下做到这一点,但我不推荐它,因为它是一个典型的 OOP 主体,需要继承以添加特殊功能。除了 OnPaint' 方法的新实现之外,新类的行为与之前完全相同。编译项目后,新控件将在工具箱中可用。
    • 还有一件事:如果重写 OnPaint 方法,PictureBox 将不会像以前那样绘制图片,因为您重写了逻辑。如果您希望 pb 在添加您的逻辑之前执行其自己的逻辑,则必须执行 base.OnPaint(e) 作为覆盖方法中的第一个调用。
    • 我可以在 SpecialPictureBox 中使用 this.Image,但是当我在 visulstudio 表单设计器中使用 specialPictureBox 时,它会抛出一个错误,意思是 this is NULL...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    相关资源
    最近更新 更多