C# DrawReversibleFrame侧控件无效时不需要的行为(消失,混乱的绘制)
我正在使用DrawReversibleFrame根据鼠标在名为SelectionTest的控件上的位置绘制一个具有反转颜色的矩形。使用DrawReversibleFrame的基本代码取自此 如果在区域选择期间重新绘制控件(在无效或刷新之后),则矩形可能会消失或具有多个不同大小的副本。您可能会问我,为什么要刷新控件?事实上,我不是!控件绘制事件也不会引发 我发现只有当矩形被画在另外两个控件之间,并且很快失效时(例如:鼠标移动事件或计时器),才会发生重画 为了重现这个主题,我创建了两个示例类: 选择测试,处理DrawReversibleFrame。复选框This.Invalidate timer可启用/禁用调用SelectionTest的Invalidate的计时器。如果激活它,可以轻松复制不需要的DrawReversibleFrame行为。请注意,这(Invalidade调用)只是复制错误的“欺骗”。在我的应用程序中,我没有调用Invalidate或要求以任何方式重新绘制控件。正如我所说,在我的应用程序上,绘画事件没有被引发 Form1拥有两个面板之间的SelectionTest。它有两个主要复选框,分别控制鼠标移动时的无效和计时器无效。如果同时选中这两个选项,则不需要的行为更为明显 这是一个不想要的行为截图。注意中央(较暗区域)控件右上角的选择: 问题:C# DrawReversibleFrame侧控件无效时不需要的行为(消失,混乱的绘制),c#,winforms,drawing,C#,Winforms,Drawing,我正在使用DrawReversibleFrame根据鼠标在名为SelectionTest的控件上的位置绘制一个具有反转颜色的矩形。使用DrawReversibleFrame的基本代码取自此 如果在区域选择期间重新绘制控件(在无效或刷新之后),则矩形可能会消失或具有多个不同大小的副本。您可能会问我,为什么要刷新控件?事实上,我不是!控件绘制事件也不会引发 我发现只有当矩形被画在另外两个控件之间,并且很快失效时(例如:鼠标移动事件或计时器),才会发生重画 为了重现这个主题,我创建了两个示例类: 选择
使用系统;
使用系统图;
使用System.Windows.Forms;
命名空间DrawReversibleFrameTest
{
公共部分类SelectionTest:UserControl
{
定时器=新定时器();
公共选择测试()
{
初始化组件();
this.MouseDown+=SelectionTest\u MouseDown;
this.MouseMove+=SelectionTest\u MouseMove;
this.MouseUp+=SelectionTest\u MouseUp;
计时器。间隔=100;
timer.Tick+=定时器_Tick;
timer.Enabled=ckbTimerEnabled.Checked;
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
基础漆(e);
Console.WriteLine(“SelectionTestonPaint”);
}
PaintBackground上受保护的覆盖无效(PaintEventArgs e)
{
根据背景(e);
Console.WriteLine(“在绘画背景上进行选择测试”);
}
无效计时器勾号(对象发送方,事件参数e)
{
这个。使无效();
}
//以下三种方法将绘制一个矩形并允许
//用户可以使用鼠标调整矩形的大小。如果
//矩形与控件的客户端矩形相交
//控件的颜色将更改。
bool-isDrag=false;
矩形矩形=新矩形(新点(0,0),新大小(0,0));
点起点;
private void SelectionTest_MouseDown(对象发送方,System.Windows.Forms.MouseEventArgs e)
{
//将isDrag变量设置为true并获取起点
//通过使用PointToScreen方法转换表单
//坐标到屏幕坐标。
if(e.Button==MouseButtons.Left)
{
isDrag=true;
}
控制=(控制)发送方;
//使用PointToScreen计算起始点
//方法。
开始点=控制点到屏幕(新点(e.X,e.Y));
}
私有点lastPosition=点.空;
private void SelectionTest_MouseMove(对象发送方,System.Windows.Forms.MouseEventArgs e)
{
if(lastPosition==e.Location)
回来
lastPosition=e.位置;
//如果正在拖动鼠标,
//在鼠标移动时取消绘制并重新绘制矩形。
如果(isDrag)
//通过调用
//具有相同参数的DrawReversibleFrame方法。
{
ControlPaint.DrawReversibleFrame(矩形、this.BackColor、FrameStyle.虚线);
//计算新结构的端点和尺寸
//矩形,再次使用PointToScreen方法。
点端点=((控制)发送方)。点到屏幕(新点(e.X,e.Y));
int width=endPoint.X-startPoint.X;
int height=endPoint.Y-startPoint.Y;
矩形=新矩形(起点.X,起点.Y,宽度,高度);
//通过调用DrawReversibleFrame绘制新矩形
//再说一遍。
ControlPaint.DrawReversibleFrame(矩形、this.BackColor、FrameStyle.虚线);
}
}
private void SelectionTest_MouseUp(对象发送方,System.Windows.Forms.MouseEventArgs e)
{
//如果发生MouseUp事件,则用户没有拖动。
isDrag=false;
//绘制要计算的矩形。设置虚线框样式
//使用FrameStyle枚举。
ControlPaint.DrawReversibleFrame(矩形,
此选项为(背景色、框架样式、虚线);
//找出与矩形和矩形相交的控件
using System;
using System.Drawing;
using System.Windows.Forms;
namespace DrawReversibleFrameTest
{
public partial class SelectionTest : UserControl
{
Timer timer = new Timer();
public SelectionTest()
{
InitializeComponent();
this.MouseDown += SelectionTest_MouseDown;
this.MouseMove += SelectionTest_MouseMove;
this.MouseUp += SelectionTest_MouseUp;
timer.Interval = 100;
timer.Tick += timer_Tick;
timer.Enabled = ckbTimerEnabled.Checked;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Console.WriteLine("SelectionTest OnPaint");
}
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
Console.WriteLine("SelectionTest OnPaintBackground");
}
void timer_Tick(object sender, EventArgs e)
{
this.Invalidate();
}
// The following three methods will draw a rectangle and allow
// the user to use the mouse to resize the rectangle. If the
// rectangle intersects a control's client rectangle, the
// control's color will change.
bool isDrag = false;
Rectangle theRectangle = new Rectangle(new Point(0, 0), new Size(0, 0));
Point startPoint;
private void SelectionTest_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
// Set the isDrag variable to true and get the starting point
// by using the PointToScreen method to convert form
// coordinates to screen coordinates.
if (e.Button == MouseButtons.Left)
{
isDrag = true;
}
Control control = (Control)sender;
// Calculate the startPoint by using the PointToScreen
// method.
startPoint = control.PointToScreen(new Point(e.X, e.Y));
}
private Point lastPosition = Point.Empty;
private void SelectionTest_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (lastPosition == e.Location)
return;
lastPosition = e.Location;
// If the mouse is being dragged,
// undraw and redraw the rectangle as the mouse moves.
if (isDrag)
// Hide the previous rectangle by calling the
// DrawReversibleFrame method with the same parameters.
{
ControlPaint.DrawReversibleFrame(theRectangle, this.BackColor, FrameStyle.Dashed);
// Calculate the endpoint and dimensions for the new
// rectangle, again using the PointToScreen method.
Point endPoint = ((Control)sender).PointToScreen(new Point(e.X, e.Y));
int width = endPoint.X - startPoint.X;
int height = endPoint.Y - startPoint.Y;
theRectangle = new Rectangle(startPoint.X, startPoint.Y, width, height);
// Draw the new rectangle by calling DrawReversibleFrame
// again.
ControlPaint.DrawReversibleFrame(theRectangle, this.BackColor, FrameStyle.Dashed);
}
}
private void SelectionTest_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
// If the MouseUp event occurs, the user is not dragging.
isDrag = false;
// Draw the rectangle to be evaluated. Set a dashed frame style
// using the FrameStyle enumeration.
ControlPaint.DrawReversibleFrame(theRectangle,
this.BackColor, FrameStyle.Dashed);
// Find out which controls intersect the rectangle and
// change their color. The method uses the RectangleToScreen
// method to convert the Control's client coordinates
// to screen coordinates.
Rectangle controlRectangle;
for (int i = 0; i < Controls.Count; i++)
{
controlRectangle = Controls[i].RectangleToScreen
(Controls[i].ClientRectangle);
if (controlRectangle.IntersectsWith(theRectangle))
{
Controls[i].BackColor = Color.BurlyWood;
}
}
// Reset the rectangle.
theRectangle = new Rectangle(0, 0, 0, 0);
}
private void ckbTimerEnabled_CheckedChanged(object sender, EventArgs e)
{
timer.Enabled = ckbTimerEnabled.Checked;
}
#region Designer
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.ckbTimerEnabled = new System.Windows.Forms.CheckBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// ckbTimerEnabled
//
this.ckbTimerEnabled.AutoSize = true;
this.ckbTimerEnabled.Location = new System.Drawing.Point(3, 114);
this.ckbTimerEnabled.Name = "ckbTimerEnabled";
this.ckbTimerEnabled.Size = new System.Drawing.Size(120, 17);
this.ckbTimerEnabled.TabIndex = 7;
this.ckbTimerEnabled.Text = "This.Invalidate timer";
this.ckbTimerEnabled.UseVisualStyleBackColor = true;
this.ckbTimerEnabled.CheckedChanged += new System.EventHandler(this.ckbTimerEnabled_CheckedChanged);
//
// comboBox1
//
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(29, 28);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 21);
this.comboBox1.TabIndex = 6;
//
// button1
//
this.button1.Location = new System.Drawing.Point(29, 64);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 5;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(165, 36);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 13);
this.label1.TabIndex = 4;
this.label1.Text = "label1";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(130, 74);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(35, 13);
this.label2.TabIndex = 8;
this.label2.Text = "label2";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(130, 98);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(35, 13);
this.label3.TabIndex = 9;
this.label3.Text = "label3";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(171, 74);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(35, 13);
this.label4.TabIndex = 10;
this.label4.Text = "label4";
//
// SelectionTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label4);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.ckbTimerEnabled);
this.Controls.Add(this.comboBox1);
this.Controls.Add(this.button1);
this.Controls.Add(this.label1);
this.Name = "SelectionTest";
this.Size = new System.Drawing.Size(226, 134);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.CheckBox ckbTimerEnabled;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
#endregion
}
}
using System;
using System.Drawing;
using System.Windows.Forms;
namespace DrawReversibleFrameTest
{
public partial class Form1 : Form
{
Timer invalidateTimer = new Timer();
public Form1()
{
InitializeComponent();
invalidateTimer.Interval = 100;
invalidateTimer.Tick += invalidateTimer_Tick;
invalidateTimer.Enabled = ckbInvalidateTimer.Checked;
}
void invalidateTimer_Tick(object sender, EventArgs e)
{
this.panel1.Invalidate();
this.panel2.Invalidate();
}
private void selectionTest1_MouseMove(object sender, MouseEventArgs e)
{
if (this.ckbInvalidatePanelsOnMove.Checked)
{
this.panel1.Invalidate();
this.panel2.Invalidate();
//Console.WriteLine("Mouse move invalidate");
}
}
private void Panel1_Paint(object sender, PaintEventArgs e)
{
if (ckbPanel1DrawRectangle.Checked)
e.Graphics.FillRectangle(Brushes.Red, new Rectangle(new Point(2, 2), new Size(20, 60)));
}
private void Panel2_Paint(object sender, PaintEventArgs e)
{
if (ckbPanel2DrawRectangle.Checked)
e.Graphics.FillRectangle(Brushes.Red, new Rectangle(new Point(2, 2), new Size(20, 60)));
}
private void ckbInvalidateTimer_CheckedChanged(object sender, EventArgs e)
{
invalidateTimer.Enabled = ckbInvalidateTimer.Checked;
}
#region Designer
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.panel2 = new System.Windows.Forms.Panel();
this.ckbInvalidatePanelsOnMove = new System.Windows.Forms.CheckBox();
this.ckbInvalidateTimer = new System.Windows.Forms.CheckBox();
this.ckbPanel1Visible = new System.Windows.Forms.CheckBox();
this.ckbPanel2Visible = new System.Windows.Forms.CheckBox();
this.ckbPanel1DrawRectangle = new System.Windows.Forms.CheckBox();
this.ckbPanel2DrawRectangle = new System.Windows.Forms.CheckBox();
this.selectionTest1 = new DrawReversibleFrameTest.SelectionTest();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.SystemColors.Highlight;
this.panel1.Location = new System.Drawing.Point(12, 12);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(49, 184);
this.panel1.TabIndex = 5;
this.panel1.Paint += new System.Windows.Forms.PaintEventHandler(this.Panel1_Paint);
//
// panel2
//
this.panel2.BackColor = System.Drawing.SystemColors.Highlight;
this.panel2.Location = new System.Drawing.Point(350, 12);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(49, 130);
this.panel2.TabIndex = 6;
this.panel2.Paint += new System.Windows.Forms.PaintEventHandler(this.Panel2_Paint);
//
// ckbInvalidatePanelsOnMove
//
this.ckbInvalidatePanelsOnMove.AutoSize = true;
this.ckbInvalidatePanelsOnMove.Location = new System.Drawing.Point(12, 256);
this.ckbInvalidatePanelsOnMove.Name = "ckbInvalidatePanelsOnMove";
this.ckbInvalidatePanelsOnMove.Size = new System.Drawing.Size(150, 17);
this.ckbInvalidatePanelsOnMove.TabIndex = 7;
this.ckbInvalidatePanelsOnMove.Text = "Invalidate panels on move";
this.ckbInvalidatePanelsOnMove.UseVisualStyleBackColor = true;
//
// ckbInvalidateTimer
//
this.ckbInvalidateTimer.AutoSize = true;
this.ckbInvalidateTimer.Location = new System.Drawing.Point(12, 279);
this.ckbInvalidateTimer.Name = "ckbInvalidateTimer";
this.ckbInvalidateTimer.Size = new System.Drawing.Size(97, 17);
this.ckbInvalidateTimer.TabIndex = 8;
this.ckbInvalidateTimer.Text = "Invalidate timer";
this.ckbInvalidateTimer.UseVisualStyleBackColor = true;
this.ckbInvalidateTimer.CheckedChanged += new System.EventHandler(this.ckbInvalidateTimer_CheckedChanged);
//
// ckbPanel1Visible
//
this.ckbPanel1Visible.AutoSize = true;
this.ckbPanel1Visible.Checked = true;
this.ckbPanel1Visible.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbPanel1Visible.Location = new System.Drawing.Point(168, 256);
this.ckbPanel1Visible.Name = "ckbPanel1Visible";
this.ckbPanel1Visible.Size = new System.Drawing.Size(94, 17);
this.ckbPanel1Visible.TabIndex = 9;
this.ckbPanel1Visible.Text = "Panel 1 visible";
this.ckbPanel1Visible.UseVisualStyleBackColor = true;
this.ckbPanel1Visible.CheckedChanged += new System.EventHandler(this.ckbPanel1Visible_CheckedChanged);
//
// ckbPanel2Visible
//
this.ckbPanel2Visible.AutoSize = true;
this.ckbPanel2Visible.Checked = true;
this.ckbPanel2Visible.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbPanel2Visible.Location = new System.Drawing.Point(168, 279);
this.ckbPanel2Visible.Name = "ckbPanel2Visible";
this.ckbPanel2Visible.Size = new System.Drawing.Size(94, 17);
this.ckbPanel2Visible.TabIndex = 10;
this.ckbPanel2Visible.Text = "Panel 2 visible";
this.ckbPanel2Visible.UseVisualStyleBackColor = true;
this.ckbPanel2Visible.CheckedChanged += new System.EventHandler(this.ckbPanel2Visible_CheckedChanged);
//
// ckbPanel1DrawRectangle
//
this.ckbPanel1DrawRectangle.AutoSize = true;
this.ckbPanel1DrawRectangle.Checked = true;
this.ckbPanel1DrawRectangle.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbPanel1DrawRectangle.Location = new System.Drawing.Point(268, 256);
this.ckbPanel1DrawRectangle.Name = "ckbPanel1DrawRectangle";
this.ckbPanel1DrawRectangle.Size = new System.Drawing.Size(135, 17);
this.ckbPanel1DrawRectangle.TabIndex = 11;
this.ckbPanel1DrawRectangle.Text = "Panel 1 draw rectangle";
this.ckbPanel1DrawRectangle.UseVisualStyleBackColor = true;
//
// ckbPanel2DrawRectangle
//
this.ckbPanel2DrawRectangle.AutoSize = true;
this.ckbPanel2DrawRectangle.Checked = true;
this.ckbPanel2DrawRectangle.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbPanel2DrawRectangle.Location = new System.Drawing.Point(268, 279);
this.ckbPanel2DrawRectangle.Name = "ckbPanel2DrawRectangle";
this.ckbPanel2DrawRectangle.Size = new System.Drawing.Size(135, 17);
this.ckbPanel2DrawRectangle.TabIndex = 12;
this.ckbPanel2DrawRectangle.Text = "Panel 2 draw rectangle";
this.ckbPanel2DrawRectangle.UseVisualStyleBackColor = true;
//
// selectionTest1
//
this.selectionTest1.BackColor = System.Drawing.SystemColors.ControlDark;
this.selectionTest1.Location = new System.Drawing.Point(67, 12);
this.selectionTest1.Name = "selectionTest1";
this.selectionTest1.Size = new System.Drawing.Size(277, 238);
this.selectionTest1.TabIndex = 0;
this.selectionTest1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.selectionTest1_MouseMove);
//
// Form7_DrawReversibleRectangleTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(449, 313);
this.Controls.Add(this.ckbPanel2DrawRectangle);
this.Controls.Add(this.ckbPanel1DrawRectangle);
this.Controls.Add(this.ckbPanel2Visible);
this.Controls.Add(this.ckbPanel1Visible);
this.Controls.Add(this.ckbInvalidateTimer);
this.Controls.Add(this.ckbInvalidatePanelsOnMove);
this.Controls.Add(this.panel2);
this.Controls.Add(this.panel1);
this.Controls.Add(this.selectionTest1);
this.Name = "Form7_DrawReversibleRectangleTest";
this.Text = "Form7_DrawReversibleRectangleTest";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private DrawReversibleFrameTest.SelectionTest selectionTest1;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.CheckBox ckbInvalidatePanelsOnMove;
private System.Windows.Forms.CheckBox ckbInvalidateTimer;
private System.Windows.Forms.CheckBox ckbPanel1Visible;
private System.Windows.Forms.CheckBox ckbPanel2Visible;
private System.Windows.Forms.CheckBox ckbPanel1DrawRectangle;
private System.Windows.Forms.CheckBox ckbPanel2DrawRectangle;
#endregion
private void ckbPanel1Visible_CheckedChanged(object sender, EventArgs e)
{
this.panel1.Visible = ckbPanel1Visible.Checked;
}
private void ckbPanel2Visible_CheckedChanged(object sender, EventArgs e)
{
this.panel2.Visible = ckbPanel2Visible.Checked;
}
}
}