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