请参阅此事件处理程序的最后一位:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Action<OdGePoint3d> StatusUpdate { get; set; }
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Location != _Location)
_Location = e.Location;
if (_bZoomWindowing)
{
if (!_selectionStart.IsEmpty && !_selectionEnd.IsEmpty && _selectionEnd != e.Location)
{
_selectionEnd = e.Location;
_rcRubberBand = GetSelectionRectangle();
}
}
if(_bPanWindowMode)
_RubberLineEnd = e.Location;
_pDevice.invalidate();
Invalidate();
if (_pDevice != null)
StatusUpdate?.Invoke(GetWorldCoordinates(e.Location));
base.OnMouseMove(e);
}
请参阅StatusUpdate?
这在我的表格中定义如下:
m_oViewerControl.StatusUpdate = p => toolStripCoordinate.Text = String.Format("{0:0.000},{1:0.000}", p.x, p.y); ;
一切正常。唯一的问题是,在我停止移动鼠标之前,显示器实际上并未更新。
更新
这是因为这幅画。如果我删除了绘制十字准线的代码并将失效限制为一个矩形,那么statusstruip会立即更新。
所以就是这样,因为双缓冲屏幕正在更新并且需要重新绘制整个thng,因为它们有点扼流圈。是否正确的做法是存储旧的鼠标点,然后使最后两个“线”无效,而不是使整个显示无效?
这就是说,在视图中呈现的任何延迟会引起翻倒到屏幕读数。我该怎么做?
我发现这类似:
https://mentaljetsam.wordpress.com/2007/08/09/updating-a-statusstrip-from-a-worker-thread/
public partial class Main : Form
{
delegate void SetStatusCallback(String text, int nPercent);
private void buttonGo_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void SetStatus(String text, int nPercent)
{
if (statusStrip1.InvokeRequired) {
SetStatusCallback d = new SetStatusCallback(SetStatus);
this.Invoke(d, new object[] { text, nPercent } );
} else {
labelStatus.Text = text;
progressStatus.Value = nPercent;
}
}
private void backgroundWorker1_DoWork(
object sender,
DoWorkEventArgs e)
{
SetStatus("Creating HTTP Request", 20) ;
...
SetStatus("Using POST method", 40) ;
...
}
}
但我只知道如何使用workerthread来完成特定任务。如果我要使用工作线程来更新状态栏,那么我需要它在应用程序的生命周期中保持活动状态。我们可以这样做吗?
更新
我知道我可以将其中的一部分转化为整洁的方法,但这就是我现在所拥有的:
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Location != _Location)
_Location = e.Location;
if (_bZoomWindowing)
{
// Do we need to erase the old one?
if (!_rcLastRubberBand.IsEmpty)
{
using (Region r = new Region(Rectangle.Inflate(_rcLastRubberBand, 2, 2)))
{
r.Exclude(Rectangle.Inflate(_rcLastRubberBand, -2, -2));
_pDevice.invalidate(new OdGsDCRect(_rcLastRubberBand.Left-2, _rcLastRubberBand.Right+2,
_rcLastRubberBand.Top-2, _rcLastRubberBand.Bottom+2));
Invalidate(r);
}
}
// Draw the new one
if (!_selectionStart.IsEmpty && !_selectionEnd.IsEmpty && _selectionEnd != e.Location)
{
_rcLastRubberBand = _rcRubberBand;
_selectionEnd = e.Location;
_rcRubberBand = GetSelectionRectangle();
using (Region r = new Region(Rectangle.Inflate(_rcRubberBand, 2, 2)))
{
r.Exclude(Rectangle.Inflate(_rcRubberBand, -2, -2));
_pDevice.invalidate(new OdGsDCRect(_rcRubberBand.Left-2, _rcRubberBand.Right+2,
_rcRubberBand.Top-2, _rcRubberBand.Bottom+2));
Invalidate(r);
}
}
}
if (_bPanWindowMode)
{
// Do we need to erase the last rubber band line? (Rectangle already expanded by 2 pixels)
if(!_rcLastRubberBandLine.IsEmpty)
{
using (Region r = new Region(_rcLastRubberBandLine))
{
_pDevice.invalidate(new OdGsDCRect(_rcLastRubberBandLine.Left, _rcLastRubberBandLine.Right,
_rcLastRubberBandLine.Top, _rcLastRubberBandLine.Bottom));
Invalidate(r);
}
}
// Draw the new one now
_RubberLineEnd = e.Location;
_rcLastRubberBandLine = GetSelectionRectangle(_RubberLineStart, _RubberLineEnd);
_rcLastRubberBandLine.Inflate(2, 2);
using (Region r = new Region(_rcLastRubberBandLine))
{
_pDevice.invalidate(new OdGsDCRect(_rcLastRubberBandLine.Left, _rcLastRubberBandLine.Right,
_rcLastRubberBandLine.Top, _rcLastRubberBandLine.Bottom));
Invalidate(r);
}
}
/*
OdGsDCRect rcHorz;
OdGsDCRect rcVert;
if (!_LastLocation.IsEmpty)
{
rcHorz = new OdGsDCRect(_LastLocation.X-1, _LastLocation.X+1, 0, Height);
rcVert = new OdGsDCRect(0, Width, _LastLocation.Y-1, _LastLocation.Y+1);
rcHorz.normalize();
rcVert.normalize();
_pDevice.invalidate(rcHorz);
_pDevice.invalidate(rcVert);
Invalidate(Rectangle.FromLTRB(_LastLocation.X-1, 0, _LastLocation.X+1, Height));
Invalidate(Rectangle.FromLTRB(0, _LastLocation.Y-1, Width, _LastLocation.Y+1));
_LastLocation = _Location;
}
rcHorz = new OdGsDCRect(_Location.X-1, _Location.X+1, 0, Height);
rcVert = new OdGsDCRect(0, Width, _Location.Y-1, _Location.Y+1);
rcHorz.normalize();
rcVert.normalize();
_pDevice.invalidate(rcHorz);
_pDevice.invalidate(rcVert);
Invalidate(Rectangle.FromLTRB(_Location.X - 1, 0, _Location.X + 1, Height));
Invalidate(Rectangle.FromLTRB(0, _Location.Y - 1, Width, _Location.Y + 1));
*/
//_pDevice.invalidate();
//Invalidate();
if (_pDevice != null)
StatusUpdate?.Invoke(GetWorldCoordinates(e.Location));
base.OnMouseMove(e);
}
这样做效果更好。我们只会在平移或缩放窗口时激活所需的内容。在制作矩形或创建平移线时,坐标读数不会更新。不好的一面是我现在没有我的十字线。
在AutoCAD中,您可以绘制矩形并拖动线条,状态栏会立即更新。所以必须有办法做到这两点。