我对DrawReversibleFrame()
方法的使用导致绘制拖动操作的偏移和反转阴影。方法的名称(DrawReversibleFrame()
)似乎表明这可能是它应该工作的方式(绘制反转图像,而不是忠实地模仿你的动作)。但是,我想要相反(似乎没有简单的DrawFrame()
方法)。
我尝试了两个在发布初始问题后显示的示例:How do I draw a rectangle based on the movement of the mouse?
这两个尝试可以在这里找到:
filled rubber band in Winforms Application
..在这里:
http://www.switchonthecode.com/tutorials/winforms-painting-on-top-of-child-controls
......但两人都不适合我。
首先,在我运行它们时,在两个示例的事件中调用base。*会导致StackOverflows(没有双关语)(通常我甚至不需要为StackOverflows做任何事情来炸毁我的应用程序)
我能够从DrawReversibleFrame()
示例(上面的第二个链接)ALMOST工作中获取代码。但是,当我用鼠标向右和向下拖动(从左上到右下)时,绘制的矩形从右下角开始向上移动到左上角(但是我正在向相反的方向拖动 - 从左上角到右下角) - 移动的尺寸/数量似乎恰到好处。
此外,绘制操作开始的时间点也不在正确的位置 - 它在我的初始点左侧和上方开始。
注意:我正在使用PointToScreen()
,因为拖动操作发生在TableLayoutPanel
上,该public partial class Form1 : Form
{
private bool _IsSelecting = false;
private Point _StartPoint = Point.Empty;
private Rectangle _FrameRect = Rectangle.Empty; //1
public Form1()
{
InitializeComponent();
// DoubleBuffered = true; //makes no apparent difference either way
}
private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
_IsSelecting = true;
_StartPoint = PointToScreen(e.Location);
_FrameRect = new Rectangle(_StartPoint, Size.Empty);
}
private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
Point pt = PointToScreen(e.Location);
_FrameRect.Width = _StartPoint.X - pt.X;
_FrameRect.Height = _StartPoint.Y - pt.Y;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
}
private void tableLayoutPanel1_MouseUp(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect,
Color.Black, FrameStyle.Dashed);
_IsSelecting = false;
_FrameRect = Rectangle.Empty;
_StartPoint = Point.Empty;
}
}
已放置在表单顶部。如果我不使用它,我看不到任何绘图。
我的代码是:
_FrameRect.Width = pt.X - _StartPoint.X;
_FrameRect.Height = pt.Y - _StartPoint.Y;
在回应John的评论时,我在这里颠倒了数学:
private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
_IsSelecting = true;
_StartPoint = PointToScreen(e.Location);
//_StartPoint = PointToClient(e.Location); //<- this makes it way worse - the rectangle is way too big, and starts even further up and to the left
_FrameRect = new Rectangle(_StartPoint, Size.Empty);
}
private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
Point pt = PointToScreen(e.Location);
//Point pt = PointToClient(e.Location); //worse
_FrameRect.Width = pt.X - _StartPoint.X;
_FrameRect.Height = pt.Y - _StartPoint.Y;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
}
private void tableLayoutPanel1_MouseUp(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect,
Color.Black, FrameStyle.Dashed);
_IsSelecting = false;
_FrameRect = Rectangle.Empty;
_StartPoint = Point.Empty;
}
...但这只是为了取笑我,因为它使几乎工作,但是将PointToScreen()的调用更改为PointToClient()会使它变得更糟(进一步向左和顶部,有时候太大的矩形)。
这是现在的代码(矩形是完美的大小,但是从鼠标左侧和上方开始):
log.Debug(String.Format("Mouse Down Location.Y = {0}", e.Location.Y));
_StartPoint = PointToScreen(e.Location);
log.Debug(String.Format("Mouse Down PointToScreen Location.Y = {0}", _StartPoint.Y));
注意:我正在动态创建的TableLayoutPanel上执行mousedown,它位于面板上,该面板位于表单上。
当我添加下面的代码时,值为25,然后是146.所以它似乎应该可以工作 - 它补偿了当TableLayoutPanel将Y值转换为146时有些事情。但它不是够了,还是...... ???
private void HighlightAllTextBoxValsBetweenPoints() {
foreach (Control ctrl in tableLayoutPanelGreatgooglyMoogly.Controls) {
var tb = ctrl as TextBox;
if (tb == null)
continue;
if (RectangleToScreen(tb.Bounds).IntersectsWith(_FrameRect)) {
//MessageBox.Show(String.Format("{0}", tb.Name));
tb.BackColor = PSEUDO_HIGHLIGHT_COLOR;
}
}
}
我终于能够在矩形下面发现TextBoxes并回答我的问题(我无法在StackOverflow上发布新问题,因为我超过了30天内的50个问题限制) :
...但现在我还有另一个问题:
下面的代码确实找到了它下面的控件,因为它遍历面板上TextBoxes的所有,它确实发现了绘制的矩形下方的正确数量的控件(如果我拖动九个TextBox,找到九个。
但是,标记为找到的TextBox会不是正确的 - 它们不是我拖过的那些,而是位于TableLayoutPanel中的几行!
绘制的_FrameRect是从PointToScreen()转换而来的,textBox.Bounds是从RectangleToScreen()转换的,所以它们应该是同步的,但它们不是......(如果我没有这些转换相对位置的绝对位置,根本没有发现任何文本框。
// Declare a rectangle and a point:
Rectangle describedRect;
Point startingPoint;
private bool _IsSelecting = false; // <- already had this
// In the MouseDown event:
_IsSelecting = true;
startingPoint = e.Location;
// In the MouseMove event:
if (!_IsSelecting)
return;
describedRect = Rectangle.FromLTRB(startingPoint.X, startingPoint.Y, e.X, e.Y);
// In the MouseUp event:
if (!_IsSelecting)
return;
HighlightAllTextBoxValsBetweenPoints();
_IsSelecting = false;
private void HighlightAllTextBoxValsBetweenPoints() {
foreach (Control ctrl in tableLayoutPanelGreatGooglyMoogly.Controls) {
var tb = ctrl as TextBox;
if (tb == null)
continue;
if (describedRect.IntersectsWith(tb.Bounds)) {
tb.BackColor = PSEUDO_HIGHLIGHT_COLOR;
}
}
}
同样,找到了正确数量的控件,它们被“突出显示”(backColor属性已更改),但它们不是正确的。
基于代码,我在这里上传了一只猫(或者一个frogleg):
http://www.c-sharpcorner.com/Forums/Thread/170813/
......我能够获得控件的伪高亮显示功能。这是相关的代码:
{{1}}
答案 0 :(得分:1)
您需要使用您尝试使用的PointToScreen
控件的TableLayoutPanel
方法:
private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button != MouseButtons.Left)
return;
_IsSelecting = true;
_StartPoint = tableLayoutPanel1.PointToScreen(e.Location);
_FrameRect = new Rectangle(_StartPoint, Size.Empty);
}
private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e) {
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
Point pt = tableLayoutPanel1.PointToScreen(e.Location);
_FrameRect.Width = pt.X - _StartPoint.X;
_FrameRect.Height = pt.Y - _StartPoint.Y;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
}