【问题标题】:WinForms - WPF like paintingWinForms - 像画一样的WPF
【发布时间】:2012-05-31 06:17:08
【问题描述】:

我们非常清楚创建一个 WPF 应用程序是多么容易,用户可以在其中使用鼠标绘制一个矩形。为此,您只需创建一个 Rectangle 控件并设置它的坐标,您不必担心 DoubleBuffering、重新绘制等。好吧,我很高兴您将 WPF 用于用户可以绘制不同形状的应用程序,但客户坚持使用 WinForms 应用程序。所以这里的解决方案是使用 XOR 或 ROP 操作,就像在旧的良好 WinAPI 年代一样,我不太喜欢这样。这并没有给我一个在 XOR 模式下移动文本的好选择。

所以我在想如何在 WinForms 应用程序中获得与在 WPF 中相同的流畅绘画体验。将这样的代码放在一起,我想在其中创建一个单独的图层,在其中绘制当前形状,同时保持其余对象不变。我在 iPad 应用程序中使用了相同的技术并且效果很好。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace TestPainting
{
    public partial class Form1 : Form
    {
        private bool _isMouseDown;
        private Graphics _bufferGraphics;
        private Point _startPos;
        private TransparentPanel _paintBuffer;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            _isMouseDown = true;
            _paintBuffer = new TransparentPanel
                            {
                                Size = Size,
                            };
            Controls.Add(_paintBuffer);
            _paintBuffer.BringToFront();

            _bufferGraphics = Graphics.FromHwnd(_paintBuffer.Handle);
            _startPos = e.Location;
            Capture = true;
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_isMouseDown)
                return;

            _bufferGraphics.Clear(Color.Transparent);
            _bufferGraphics.DrawRectangle(Pens.Green, _startPos.X, _startPos.Y, e.X - _startPos.X, e.Y - _startPos.Y);

        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            _isMouseDown = false;
            Capture = false;
            _bufferGraphics.Dispose();
            Controls.Remove(_paintBuffer);
            _paintBuffer.Dispose();
        }
    }

    public class TransparentPanel : Panel
    {
        public TransparentPanel()
        {
            DoubleBuffered = true;
        }

        [Browsable(false)]
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x20;
                return cp;
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Do Nothing
        }
    }
}

如果课程不能按需要工作。按下鼠标而不是透明面板时,我得到一个黑色面板。加上绘制时的矩形闪烁很多,即使我确实设置了 DoubleBuffering 的东西。

有人可以提供一些关于这种实现的更好的想法,或者也许还有一些其他的开源项目,我可以看到其他人在做什么。我需要有与 Paint.NET 相同的经验,可惜不再是开源的了。 (我知道我可以使用 Reflector,而且我做到了,但是伙计,那里有大量代码 :))

感谢任何想法。

【问题讨论】:

  • 是否可以通过 ElementHost 在 WinForms 应用程序中嵌入 WPF 内容?
  • 甚至没有关闭。从现在开始,在我的所有项目中都禁止使用 WPF 这个词。 :)
  • 我发现了这个:c-sharpcorner.com/uploadfile/chetanvnadgouda/…。也许会有所帮助。
  • 更近一点,但它们在相同的表单上绘制而没有任何双缓冲,当用户使用鼠标绘制形状时,它们也会重新绘制所有形状。就我而言,我需要在用户绘画时保持其他图形不变。
  • 这里我有一个小样本可以说明问题。我得到了所需的行为,但一切都很慢。示例网址:designleon.com/temp/TestPainting.zip

标签: wpf winforms double-buffering


【解决方案1】:

试试这个(参见 FIX #1 和 FIX #2):

    private void Form1_MouseDown( object sender, MouseEventArgs e )
    {
        _isMouseDown = true;
        _paintBuffer = new TransparentPanel
        {
            Size = Size,
        };
        Controls.Add( _paintBuffer );
        _paintBuffer.BringToFront();

        // FIX #1:
        //
        this.Refresh();

        _bufferGraphics = Graphics.FromHwnd( _paintBuffer.Handle );

        _startPos = e.Location;
        Capture = true;
    }

    private void Form1_MouseMove( object sender, MouseEventArgs e )
    {
        if ( !_isMouseDown )
            return;

        //FIX #2:
        //   _bufferGraphics.Clear( Color.Transparent );
        _bufferGraphics.Clear( this.BackColor );

        _bufferGraphics.DrawRectangle( Pens.Green, _startPos.X, _startPos.Y, e.X - _startPos.X, e.Y - _startPos.Y );

    }

【讨论】:

  • 这实际上并不好,因为我的图层不再透明,所以当用户绘制他的形状时,它下面的复杂形状将不可见。另外,在绘制矩形时,它会严重闪烁。
猜你喜欢
  • 2012-01-19
  • 1970-01-01
  • 2023-03-17
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
相关资源
最近更新 更多