为什么新窗体在快速移动鼠标时不会粘到鼠标移动位置?

时间:2013-04-15 17:26:33

标签: c# mousecapture

我有这个事件:

protected override void OnMouseDown(MouseEventArgs e)
{
    mOffset = new Point(Width / 2 - e.X, Height / 2 - e.Y);
    mCurrentPoint = PointToScreen(new Point(e.X + mOffset.X, e.Y + mOffset.Y));
    mTargetPoint = mCurrentPoint;
    mTimer.Enabled = true;
}

这个事件:

protected override void OnMouseMove(MouseEventArgs e)
{
    mTargetPoint = PointToScreen(new Point(e.X + mOffset.X, e.Y + mOffset.Y));
    mTimer.Enabled = true;
}

如果我只是快速移动鼠标,我就会失去对我正在移动的表格的焦点,并且表格只留下鼠标移动。

但是,如果我单击鼠标按下按钮,然后移动鼠标,快速表格一直处于焦点。

所以我尝试将OnMouseDown事件中的两行复制到OnMouseMove事件:

mOffset = new Point(Width / 2 - e.X, Height / 2 - e.Y);
mTargetPoint = mCurrentPoint;

但是,一旦我将这两行移动到Move事件,就没有任何事情发生。无论我做什么,表格根本不会移动。

如果需要,那么这就是完整的表单代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing.Imaging;

namespace Magnifier20070401
{
    public partial class MagnifierForm : Form
    {
        public MagnifierForm()//Configuration configuration, Point startPoint)
        {
            InitializeComponent();

            //--- My Init ---
            //mConfiguration = configuration;
            FormBorderStyle = FormBorderStyle.None;

            ShowInTaskbar = false;//mConfiguration.ShowInTaskbar;
            TopMost = true;//mConfiguration.TopMostWindow;
            Width = 150;// mConfiguration.MagnifierWidth;
            Height = 150;// mConfiguration.MagnifierHeight;

            // Make the window (the form) circular
            GraphicsPath gp = new GraphicsPath();
            gp.AddEllipse(ClientRectangle);
            Region = new Region(gp);

            mImageMagnifier = ScreenVideoRecorder.Properties.Resources.magnifierGlass;

            mTimer = new Timer();
            mTimer.Enabled = true;
            mTimer.Interval = 20;
            mTimer.Tick += new EventHandler(HandleTimer);

            mScreenImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                     Screen.PrimaryScreen.Bounds.Height);

            mStartPoint = new Point(500, 500);// startPoint;
            mTargetPoint = new Point(500, 500); // startPoint;

            /*if (mConfiguration.ShowInTaskbar)
                ShowInTaskbar = true;
            else
                ShowInTaskbar = false;*/
        }

        protected override void OnShown(EventArgs e)
        {
            RepositionAndShow();
        }

        private delegate void RepositionAndShowDelegate();

        private void RepositionAndShow()
        {
            if (InvokeRequired)
            {
                Invoke(new RepositionAndShowDelegate(RepositionAndShow));
            }
            else
            {
                // Capture the screen image now!
                Graphics g = Graphics.FromImage(mScreenImage);
                g.CopyFromScreen(0, 0, 0, 0, new Size(mScreenImage.Width, mScreenImage.Height));
                g.Dispose();                

                //if (mConfiguration.HideMouseCursor)
                  //  Cursor.Hide();
                //else
                    Cursor = Cursors.Cross;

                Capture = true;

                /*if (mConfiguration.RememberLastPoint)
                {
                    mCurrentPoint = mLastMagnifierPosition;
                    Cursor.Position = mLastMagnifierPosition;
                    Left = (int)mCurrentPoint.X - Width / 2;
                    Top = (int)mCurrentPoint.Y - Height / 2;
                }
                else
                {*/
                    mCurrentPoint = Cursor.Position;
                //}
                Show();
            }
        }

        void HandleTimer(object sender, EventArgs e)
        {
            float dx = /*mConfiguration.SpeedFactor*/ (float)0.35 * (mTargetPoint.X - mCurrentPoint.X);
            float dy = /*mConfiguration.SpeedFactor*/ (float)0.35 * (mTargetPoint.Y - mCurrentPoint.Y);

            if (mFirstTime)
            {
                mFirstTime = false;

                mCurrentPoint.X = mTargetPoint.X;
                mCurrentPoint.Y = mTargetPoint.Y;

                Left = (int)mCurrentPoint.X - Width / 2;
                Top = (int)mCurrentPoint.Y - Height / 2;

                return;
            }

            mCurrentPoint.X += dx;
            mCurrentPoint.Y += dy;

            if (Math.Abs(dx) < 1 && Math.Abs(dy) < 1)
            {
                mTimer.Enabled = false;
            }
            else
            {
                // Update location
                Left = (int)mCurrentPoint.X - Width / 2;
                Top = (int)mCurrentPoint.Y - Height / 2;
                mLastMagnifierPosition = new Point((int)mCurrentPoint.X, (int)mCurrentPoint.Y);
            }

            Refresh();
        }


        protected override void OnMouseDown(MouseEventArgs e)
        {
            mOffset = new Point(Width / 2 - e.X, Height / 2 - e.Y);
            mCurrentPoint = PointToScreen(new Point(e.X + mOffset.X, e.Y + mOffset.Y));
            mTargetPoint = mCurrentPoint;
            mTimer.Enabled = true;
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            //if (mConfiguration.CloseOnMouseUp)
            //{
             /*   Close();
                mScreenImage.Dispose();
            //}

            Cursor.Show();
            Cursor.Position = mStartPoint;   */         
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            //if (e.Button == MouseButtons.Left)
            //{
                mOffset = new Point(Width / 2 - e.X, Height / 2 - e.Y);
                mTargetPoint = PointToScreen(new Point(e.X + mOffset.X, e.Y + mOffset.Y));
                //mTargetPoint = mCurrentPoint;
                mTimer.Enabled = true;
            //} 
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            /*if (mConfiguration.DoubleBuffered)
            {
                // Do not paint background (required for double buffering)!
            }
            else
            {
                base.OnPaintBackground(e);
            }*/
            base.OnPaintBackground(e);
        }

        protected override void  OnPaint(PaintEventArgs e)
        {
            if (mBufferImage == null)
            {
                mBufferImage = new Bitmap(Width, Height);
            }
            Graphics bufferGrf = Graphics.FromImage(mBufferImage);

            Graphics g;

            /*if (mConfiguration.DoubleBuffered)
            {
                g = bufferGrf;
            }
            else
            {*/
                g = e.Graphics;
            //}

            if (mScreenImage != null)
            {
                Rectangle dest = new Rectangle(0, 0, Width, Height);
                int w = (int)(Width / 3.0);//mConfiguration.ZoomFactor);
                int h = (int)(Height / 3.0);//mConfiguration.ZoomFactor);
                int x = Left - w / 2 + Width / 2;
                int y = Top - h / 2 + Height / 2;

                g.DrawImage(
                    mScreenImage,
                    dest,
                    x, y,
                    w, h,
                    GraphicsUnit.Pixel);
            }

            if (mImageMagnifier != null)
            {
                g.DrawImage(mImageMagnifier, 0, 0, Width, Height);
            }

           //if (mConfiguration.DoubleBuffered)
            //{
                e.Graphics.DrawImage(mBufferImage, 0, 0, Width, Height);
            //}      
        }


        //--- Data Members ---
        #region Data Members
        private Timer mTimer;
        private Configuration mConfiguration;
        private Image mImageMagnifier;
        private Image mBufferImage = null;
        private Image mScreenImage = null;
        private Point mStartPoint;
        private PointF mTargetPoint;
        private PointF mCurrentPoint;
        private Point mOffset;
        private bool mFirstTime = true;
        private static Point mLastMagnifierPosition = Cursor.Position;
        #endregion

        private void MagnifierForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode.ToString() == "M")
            {
                this.Close();
            }
        }
    }
}

在Form1中,我只为表单创建一个新实例,然后我可以移动它。 为什么在没有按下鼠标时快速移动鼠标会失去焦点呢?

2 个答案:

答案 0 :(得分:2)

在您的MouseDown中,您应该将this.Capture = true;放入您的MouseUp中this.Capture.false;

如果您快速移动鼠标,它可能会移动到窗口外,默认情况下,只有鼠标所在的窗口才会显示鼠标消息。使用Control.Capture修复了该问题。

答案 1 :(得分:2)

这不是一个事件,它是一种方法。并且您没有获得默认行为(捕获鼠标),因为您忘记调用base.OnMouseDown()。 MSDN库严厉警告:

  

对继承者的说明:

当在派生类中重写OnMouseDown时,   一定要调用基类的OnMouseDown方法以便注册   代表们会收到这个活动。

好吧,以及基类方法所做的其他事情。就像捕捉鼠标一样。当你真正知道自己在做什么时,才跳过调用基类方法。这很难弄明白,你真的需要知道基类方法的作用。 总是只有触发事件一样简单。通常,类越精细,它就越有可能将基本方法中的某些代码抛弃。 DataGridView是松鼠之王。您可以从参考源获取该信息。

只需在方法底部添加此行即可解决您的问题:

   base.OnMouseDown(e);

在OnMouseMove()覆盖中执行相同的操作。不是因为这是解决这个特定问题所必需的,因为文档说你应该这样做。

相关问题