我正在向鼠标方向移动PictureBox
,但是它仅在PictureBox
内部起作用。 PictureBox
是200x200
,所以它引起了一些小故障,我猜是因为空间太紧。我还有一个使PictureBox
跟随鼠标的功能。在PictureBox
沿鼠标方向旋转的同时,有什么方法可以使鼠标在屏幕上移动吗?
private float _angle;
private void Spiller_MouseMove(object sender, MouseEventArgs e)
{
(float centerX, float centerY) = GetCenter(spiller.ClientRectangle);
_angle = (float)(Math.Atan2(e.Y - centerY, e.X - centerX) * 180.0 / Math.PI);
spiller.Invalidate();
}
private void Spiller_Paint(object sender, PaintEventArgs e)
{
Bitmap image = Resource1.spillerr;
float scale = (float)spiller.Width / image.Width;
(float centerX, float centerY) = GetCenter(e.ClipRectangle);
e.Graphics.TranslateTransform(centerX, centerY);
e.Graphics.RotateTransform(_angle);
e.Graphics.TranslateTransform(-centerX, -centerY);
e.Graphics.ScaleTransform(scale, scale);
e.Graphics.DrawImage(image, 0, 0);
}
private static (float, float) GetCenter(Rectangle rect)
{
float centerX = (rect.Left + rect.Right) * 0.5f;
float centerY = (rect.Top + rect.Bottom) * 0.5f;
return (centerX, centerY);
}
答案 0 :(得分:0)
您可以使用间隔很小的Timer
组件(16ms〜= 60fps)来创建sudo-active图形。然后在计时器的每个滴答声中调用Invalidate
。
为减少不断刷新的控件的闪烁,您可能需要如下设置其样式:
class CustomPictureBox : PictureBox
{
public CustomPictureBox() {
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
}
// change the type of spiller in Form1.designer.cs
private System.Windows.Forms.PictureBox spiller;
// becomes
private CustomPictureBox spiller;
// and
spiller = new System.Windows.Forms.PictureBox();
// becomes
spiller = new CustomPictureBox();
可以通过Control.MousePosition
在绘画例程中获取屏幕上鼠标的全局位置。
答案 1 :(得分:0)
一种方法是使用 WH_MOUSE_LL 钩子。
我刚刚通过在VS 2015中修改示例在Windows 10上进行了测试,它工作正常,没有任何闪烁,只需要 ScreenToClient 将屏幕坐标转换为图片坐标
主要声明:
public const int WH_MIN = (-1);
public const int WH_MSGFILTER = (-1);
public const int WH_JOURNALRECORD = 0;
public const int WH_JOURNALPLAYBACK = 1;
public const int WH_KEYBOARD = 2;
public const int WH_GETMESSAGE = 3;
public const int WH_CALLWNDPROC = 4;
public const int WH_CBT = 5;
public const int WH_SYSMSGFILTER = 6;
public const int WH_MOUSE = 7;
public const int WH_HARDWARE = 8;
public const int WH_DEBUG = 9;
public const int WH_SHELL = 10;
public const int WH_FOREGROUNDIDLE = 11;
public const int WH_CALLWNDPROCRET = 12;
public const int WH_KEYBOARD_LL = 13;
public const int WH_MOUSE_LL = 14;
public const int WH_MAX = 14;
public const int WH_MINHOOK = WH_MIN;
public const int WH_MAXHOOK = WH_MAX;
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MSLLHOOKSTRUCT
{
public System.Drawing.Point pt;
public int mouseData;
public int flags;
public int time;
public uint dwExtraInfo;
}
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public uint dwExtraInfo;
}
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
public POINT(int X, int Y)
{
this.x = X;
this.y = Y;
}
}
[DllImport("User32.dll", SetLastError = true)]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);