首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止我的橡皮筋闪烁?

防止我的橡皮筋闪烁?
EN

Stack Overflow用户
提问于 2016-05-31 15:14:58
回答 1查看 484关注 0票数 0

我采用了以下代码实现了橡皮筋:

https://support.microsoft.com/en-gb/kb/314945

这是我的密码:

代码语言:javascript
复制
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项目。我将用户控件设置为与所提供的答案相同的工作方式。唯一的区别是,我将用户控件构造函数设置为:

代码语言:javascript
复制
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);
}

注意到附加的控制样式AllPaintingInWmPaintUserPaint吗?除了OptimizedDoubleBuffer风格之外,我似乎还需要这些东西。我还将表单设置为双缓冲。

当我做这些调整,我可以画一个闪烁的橡胶带。好啊!但是,当我在用户控件中添加用于呈现DWG的嵌入式类时,我会发现一种冲突而不是强制另一种。

这就是我所处的位置,我将等待从DWG查看器类的供应商那里收集到什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-31 18:27:55

为了演示如何使用Paint事件,从我的评论到OP。

我所能得到的最光滑的方块绘制是在Paint中完成并在控件上设置ControlStyles.OptimizeDoubleBuffer。当然,这取决于您的框的预定边界--这不会超过控件本身的界限(即不会在窗体或桌面上绘制):

代码语言:javascript
复制
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;
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37549531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档