3

我们非常清楚创建一个 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,而且我做到了,但是伙计,那里有很多代码 :))

感谢任何想法。

4

1 回答 1

0

试试这个(参见 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-06-01T19:06:53.863 回答