Есть ли способ, которым я могу использовать PictureBox MouseMove, но все еще перемещаться по всему экрану? - PullRequest
2 голосов
/ 11 июня 2019

Я делаю 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);
}

Ответы [ 2 ]

0 голосов
/ 11 июня 2019

Это можно сделать с помощью WH_MOUSE_LL .

Я только что проверил на Windows 10, адаптировав свой образец в VS 2015, он отлично работает без мерцания и просто нуждается в 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);
0 голосов
/ 11 июня 2019

Вы можете создавать sudo-active графику с помощью компонента Timer, который имеет небольшой интервал (16ms ~ = 60fps).И вызывая 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...