为什么当快速移动鼠标时,新窗体不粘在鼠标移动位置上
本文关键字:鼠标 移动 窗体 位置 新窗体 为什么 | 更新日期: 2023-09-27 18:09:11
我有这个事件:
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中,我只是为表单创建了一个新实例,然后我可以移动它。为什么当快速移动鼠标而不按下鼠标键时,它会失去焦点?
这不是一个事件,它是一个方法。你没有获得默认行为(捕获鼠标),因为你忘记调用base.OnMouseDown()。MSDN库对此发出严厉警告:
当在派生类中重写OnMouseDown时,一定要调用基类的OnMouseDown方法以便注册委托接收事件。
以及基类方法所做的其他事情。比如抓老鼠。只有当你真正知道你在做什么时,才会跳过调用基类方法。这很难弄清楚,你需要知道基类的方法是做什么的。它是而不是,总是像触发事件一样简单。通常,类越复杂,它就越有可能在基方法中隐藏一些代码。DataGridView是松鼠之王。你可以从参考源中获得这些信息。
只需在方法的底部添加这一行就可以解决您的问题:
base.OnMouseDown(e);
在OnMouseMove()重写中做同样的事情。不是因为这是解决这个特定问题所必需的,因为文档说您应该这样做。
在MouseDown中输入this.Capture = true;
,在MouseUp中输入this.Capture.false;
如果你快速移动鼠标,它可能会移动到窗口外,默认情况下,只有鼠标所在的窗口才会收到鼠标消息。使用Control.Capture
可以解决这个问题。