我采用了以下代码实现了橡皮筋:
https://support.microsoft.com/en-gb/kb/314945
这是我的密码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
namespace Test
{
public partial class TestX: UserControl
{
private Boolean m_bLeftButton { get; set; }
private Boolean m_bMiddleButton { get; set; }
private Boolean m_bZoomWindow { get; set; }
Point m_ptOriginal = new Point();
Point m_ptLast = new Point();
public TestX()
{
m_bZoomWindow = false;
m_bLeftButton = false;
m_bMiddleButton = false;
}
// Called when the left mouse button is pressed.
public void MyMouseDown(Object sender, MouseEventArgs e)
{
if(m_bZoomWindow && e.Button == MouseButtons.Left)
{
// Make a note that we "have the mouse".
m_bLeftButton = true;
// Store the "starting point" for this rubber-band rectangle.
m_ptOriginal.X = e.X;
m_ptOriginal.Y = e.Y;
// Special value lets us know that no previous
// rectangle needs to be erased.
m_ptLast.X = -1;
m_ptLast.Y = -1;
}
}
// Convert and normalize the points and draw the reversible frame.
private void MyDrawReversibleRectangle(Point p1, Point p2)
{
Rectangle rc = new Rectangle();
// Convert the points to screen coordinates.
p1 = PointToScreen(p1);
p2 = PointToScreen(p2);
// Normalize the rectangle.
if (p1.X < p2.X)
{
rc.X = p1.X;
rc.Width = p2.X - p1.X;
}
else
{
rc.X = p2.X;
rc.Width = p1.X - p2.X;
}
if (p1.Y < p2.Y)
{
rc.Y = p1.Y;
rc.Height = p2.Y - p1.Y;
}
else
{
rc.Y = p2.Y;
rc.Height = p1.Y - p2.Y;
}
// Draw the reversible frame.
ControlPaint.DrawReversibleFrame(rc,
Color.WhiteSmoke, FrameStyle.Thick);
}
// Called when the left mouse button is released.
public void MyMouseUp(Object sender, MouseEventArgs e)
{
if(m_bZoomWindow && e.Button == MouseButtons.Left)
{
// Set internal flag to know we no longer "have the mouse".
m_bZoomWindow = false;
m_bLeftButton = false;
// If we have drawn previously, draw again in that spot
// to remove the lines.
if (m_ptLast.X != -1)
{
Point ptCurrent = new Point(e.X, e.Y);
MyDrawReversibleRectangle(m_ptOriginal, m_ptLast);
// Do zoom now ...
}
// Set flags to know that there is no "previous" line to reverse.
m_ptLast.X = -1;
m_ptLast.Y = -1;
m_ptOriginal.X = -1;
m_ptOriginal.Y = -1;
}
}
// Called when the mouse is moved.
public void MyMouseMove(Object sender, MouseEventArgs e)
{
Point ptCurrent = new Point(e.X, e.Y);
if(m_bLeftButton)
{
// If we "have the mouse", then we draw our lines.
if (m_bZoomWindow)
{
// If we have drawn previously, draw again in
// that spot to remove the lines.
if (m_ptLast.X != -1)
{
MyDrawReversibleRectangle(m_ptOriginal, m_ptLast);
}
// Update last point.
if(ptCurrent != m_ptLast)
{
m_ptLast = ptCurrent;
// Draw new lines.
MyDrawReversibleRectangle(m_ptOriginal, ptCurrent);
}
}
}
}
// Set up delegates for mouse events.
protected override void OnLoad(System.EventArgs e)
{
MouseDown += new MouseEventHandler(MyMouseDown);
MouseUp += new MouseEventHandler(MyMouseUp);
MouseMove += new MouseEventHandler(MyMouseMove);
MouseWheel += new MouseEventHandler(MyMouseWheel);
m_bZoomWindow = false;
}
}
}它本身工作,但矩形闪烁。其他程序,如CAD软件包,在绘制矩形时没有闪烁。
我的表单被设置为使用DoubleBuffering,所以我认为它是可以的。还有其他人遇到过这个问题吗?
更新:我想我应该回到开始,用一个表格布局面板和一个嵌入式用户控件来测试winforms项目。我将用户控件设置为与所提供的答案相同的工作方式。唯一的区别是,我将用户控件构造函数设置为:
public MyUserControl()
{
InitializeComponent();
_selectionPen = new Pen(Color.Black, 3.0f);
SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
Dock = DockStyle.Fill;
Margin = new Padding(1);
}注意到附加的控制样式AllPaintingInWmPaint和UserPaint吗?除了OptimizedDoubleBuffer风格之外,我似乎还需要这些东西。我还将表单设置为双缓冲。
当我做这些调整,我可以画一个闪烁的橡胶带。好啊!但是,当我在用户控件中添加用于呈现DWG的嵌入式类时,我会发现一种冲突而不是强制另一种。
这就是我所处的位置,我将等待从DWG查看器类的供应商那里收集到什么。
发布于 2016-05-31 18:27:55
为了演示如何使用Paint事件,从我的评论到OP。
我所能得到的最光滑的方块绘制是在Paint中完成并在控件上设置ControlStyles.OptimizeDoubleBuffer。当然,这取决于您的框的预定边界--这不会超过控件本身的界限(即不会在窗体或桌面上绘制):
using System.Drawing;
using System.Windows.Forms;
namespace WinformsScratch.RubberBand
{
public class TestY : Control
{
private Point? _selectionStart;
private Point? _selectionEnd;
private readonly Pen _selectionPen;
public TestY()
{
_selectionPen = new Pen(Color.Black, 3.0f);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
MouseDown += (s, e) => {
if (e.Button == MouseButtons.Left)
_selectionStart = _selectionEnd = e.Location;
};
MouseUp += (s, e) => {
if (e.Button == MouseButtons.Left)
{
_selectionStart = _selectionEnd = null;
Invalidate(false);
}
};
MouseMove += (s, e) => {
if (_selectionStart.HasValue &&
_selectionEnd.HasValue &&
_selectionEnd.Value != e.Location)
{
_selectionEnd = e.Location;
Invalidate(false);
}
};
Paint += (s, e) => {
if (_selectionStart.HasValue && _selectionEnd.HasValue)
e.Graphics.DrawRectangle(_selectionPen, GetSelectionRectangle());
};
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_selectionPen != null) _selectionPen.Dispose();
}
base.Dispose(disposing);
}
private Rectangle GetSelectionRectangle()
{
Rectangle rc = new Rectangle();
if (_selectionStart.HasValue && _selectionEnd.HasValue)
{
// Normalize the rectangle.
if (_selectionStart.Value.X < _selectionEnd.Value.X)
{
rc.X = _selectionStart.Value.X;
rc.Width = _selectionEnd.Value.X - _selectionStart.Value.X;
}
else
{
rc.X = _selectionEnd.Value.X;
rc.Width = _selectionStart.Value.X - _selectionEnd.Value.X;
}
if (_selectionStart.Value.Y < _selectionEnd.Value.Y)
{
rc.Y = _selectionStart.Value.Y;
rc.Height = _selectionEnd.Value.Y - _selectionStart.Value.Y;
}
else
{
rc.Y = _selectionEnd.Value.Y;
rc.Height = _selectionStart.Value.Y - _selectionEnd.Value.Y;
}
}
return rc;
}
}
}https://stackoverflow.com/questions/37549531
复制相似问题