延迟是使用鼠标坐标更新状态栏窗格

时间:2016-06-06 12:28:00

标签: c# winforms statusstrip

请参阅此事件处理程序的最后一位:

[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中,您可以绘制矩形并拖动线条,状态栏会立即更新。所以必须有办法做到这两点。

0 个答案:

没有答案