Шевелить мышью

OK. Это немного похоже на приложение для тщеславия, но сегодня на работе у меня была ситуация, когда я был в учебном классе, и машина была настроена на блокировку каждые 10 минут. Что ж, если инструкторы увлечены разговором - а не сменой слайдов - тренажер зависнет.

Я хотел бы написать маленькое приложение, в котором нет ничего, кроме значка на панели задач, который ничего не делает, кроме как перемещать мышь на 1 пиксель каждые 4 минуты.

Я могу сделать это тремя способами с помощью Delphi (мой сильный язык), но я перехожу на C# по работе, и мне хотелось бы узнать, как там можно найти наименьшее сопротивление.

Ответов (6)

Решение

для C# 3.5

без значка уведомления, поэтому вам нужно будет закрыть это приложение в диспетчере задач вручную

using System;
using System.Drawing;
using System.Windows.Forms;

static class Program
{
    static void Main()
    {
        Timer timer = new Timer();
        // timer.Interval = 4 minutes
        timer.Interval = (int)(TimeSpan.TicksPerMinute * 4 / TimeSpan.TicksPerMillisecond);
        timer.Tick += (sender, args) => { Cursor.Position = new Point(Cursor.Position.X + 1, Cursor.Position.Y + 1); };
        timer.Start();
        Application.Run();
    }
}

Когда я работаю дома, я привязываю шнур мыши к настольному вентилятору, который колеблется слева направо. Он заставляет мышь двигаться и не дает рабочей станции перейти в спящий режим.

Раф изящно ответил на проблему для мира Win10, но, к сожалению, его инструкция autoResetEvent.WaitOne () блокирует поток, и поэтому он должен находиться в отдельном собственном потоке.

То, что сработало для меня, на самом деле может выполняться в основном потоке, код не нужно помещать в метод Main (), и у вас действительно может быть кнопка для включения этой функции и одна для ее отключения.

Во-первых, вам обязательно нужно определить флаги состояния выполнения:

[Flags]
private enum ExecutionState : uint // options to control monitor behavior
{
  ES_AWAYMODE_REQUIRED = 0x00000040, // prevent idle-to-sleep
  ES_CONTINUOUS = 0x80000000, // allow monitor power down
  ES_DISPLAY_REQUIRED = 0x00000002, // prevent monitor power down
  ES_SYSTEM_REQUIRED = 0x00000001 // keep system awake
}

Теперь, когда вы хотите, чтобы ваша система не спала и заблокировала выключение монитора или переход в спящий режим на холостом ходу, все, что вам нужно сделать, это выполнить одну команду:

SetThreadExecutionState(ExecutionState.ES_AWAYMODE_REQUIRED | ExecutionState.ES_CONTINUOUS | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_SYSTEM_REQUIRED);

Затем, если вы хотите отменить это действие и вернуть вашу систему в исходное состояние выполнения, просто введите следующую команду:

SetThreadExecutionState(ExecutionState.ES_CONTINUOUS);

Имейте в виду, что каждая команда будет возвращать предыдущее состояние выполнения, что означает, что при первом изменении этого состояния вы можете кэшировать возвращаемое значение локально и использовать его, если / когда вы хотите восстановить предыдущее состояние.

(Windows 10 / .Net 5 / C# 9.0)

Вместо того, чтобы притворяться, вы можете

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

используя SetThreadExecutionState , как описано на PInvoke.net :

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace VanityApp
{
    internal static class Program
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);

        [Flags]
        private enum ExecutionState : uint
        {
            ES_AWAYMODE_REQUIRED = 0x00000040,
            ES_CONTINUOUS = 0x80000000,
            ES_DISPLAY_REQUIRED = 0x00000002,
            ES_SYSTEM_REQUIRED = 0x00000001
        }

        private static void Main()
        {
            using AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            using Timer timer = new Timer(state => SetThreadExecutionState(ExecutionState.ES_AWAYMODE_REQUIRED | ExecutionState.ES_CONTINUOUS | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_SYSTEM_REQUIRED), autoResetEvent, 0, -1);
            autoResetEvent.WaitOne();
        }
    }
}

Таймер - это System.Threading.Timer с удобным конструктором, который использует AutoResetEvent.WaitOne (), чтобы избежать немедленного выхода.

Нечто подобное должно работать (хотя, вы будете хотеть , чтобы изменить интервал).

public Form1()
{
    InitializeComponent();
    Timer Every4Minutes = new Timer();
    Every4Minutes.Interval = 10;
    Every4Minutes.Tick += new EventHandler(MoveNow);
    Every4Minutes.Start();
}

void MoveNow(object sender, EventArgs e)
{
    Cursor.Position = new Point(Cursor.Position.X - 1, Cursor.Position.Y - 1);
}

«Правильный» способ сделать это - ответить на сообщение WM_SYSCOMMAND. В C# это выглядит примерно так:

protected override void WndProc(ref Message m)
{
    // Abort screensaver and monitor power-down
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MONITOR_POWER = 0xF170;
    const int SC_SCREENSAVE = 0xF140;
    int WParam = (m.WParam.ToInt32() & 0xFFF0);

    if (m.Msg == WM_SYSCOMMAND &&
        (WParam == SC_MONITOR_POWER || WParam == SC_SCREENSAVE)) return;

    base.WndProc(ref m);
}

Согласно MSDN , если пароль заставки включен политикой в ​​Vista или более поздней версии, это не сработает. Предположительно программное перемещение мыши также игнорируется, хотя я это не тестировал.