Pertanyaan Mengapa Form baru tidak menempel pada posisi gerakan mouse saat menggerakkan mouse dengan cepat?


Saya memiliki acara ini:

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;
}

Dan acara ini:

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

Jika saya hanya menggerakkan mouse dengan cepat, saya kehilangan fokus pada bentuk yang saya pindahkan dan bentuk yang tersisa di tempat hanya gerakan mouse.

Tetapi jika saya mengklik tombol mouse ke bawah kemudian gerakkan mouse dan cepat bentuknya dalam fokus sepanjang jalan.

Jadi saya mencoba menyalin dua baris dari OnMouseDown acara ke OnMouseMove peristiwa:

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

Tetapi setelah saya memindahkan dua baris ini ke Peristiwa pemindahan, tidak terjadi apa-apa. Bentuknya tidak bergerak sama sekali tidak masalah yang saya lakukan.

Jika diperlukan maka ini adalah kode formulir lengkap:

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();
            }
        }
    }
}

Di Form1 saya hanya membuat contoh baru untuk formulir, maka saya bisa memindahkannya. Kenapa itu kehilangan fokus ketika menggerakkan mouse dengan cepat ketika tidak membuat tombol di mouse?


4
2018-04-15 17:26


asal


Jawaban:


Ini bukan suatu peristiwa, itu adalah metode. Dan Anda tidak mendapatkan perilaku default (menangkap mouse) karena Anda lupa memanggil base.OnMouseDown (). Perpustakaan MSDN memperingatkan keras tentang hal ini:

Catatan untuk Inheritors: 

  Saat menimpa OnMouseDown di kelas turunan,   pastikan untuk memanggil metode OnMouseDown kelas dasar agar terdaftar   delegasi menerima acara tersebut.

Yah, dan hal-hal lain yang dilakukan oleh metode kelas dasar. Seperti menangkap mouse. Hanya melewati panggilan metode kelas dasar ketika Anda Benar-benar Tahu Apa yang Anda Lakukan. Yang sulit untuk diketahui, Anda benar-benar perlu tahu apa yang dilakukan oleh metode kelas dasar. ini tidak selalu hanya sesederhana menembaki kejadian. Biasanya kelas yang lebih rumit, semakin mungkin ia menyemprotkan beberapa kode dalam metode dasar. DataGridView adalah raja tupai. Anda bisa mendapatkan info itu dari Sumber Referensi.

Cukup tambahkan baris ini di bagian bawah metode untuk memecahkan masalah Anda:

   base.OnMouseDown(e);

Dan lakukan hal yang sama dalam pengaktifan OnMouseMove (). Bukan karena itu perlu untuk memecahkan masalah khusus ini, karena dokumen mengatakan Anda harus.


2
2018-04-15 18:03



Di MouseDown Anda harus meletakkan this.Capture = true; dan di MouseUp Anda this.Capture.false;

Jika Anda menggerakkan mouse dengan cepat, itu mungkin bergerak di luar jendela, dan secara default hanya jendela di mana mouse berakhir akan mendapatkan pesan mouse. Menggunakan Control.Capture memperbaiki masalah itu.


2
2018-04-15 17:29