Wiggling the mouse

Viewed 15006

OK. This is a bit of a vanity app, but I had a situation today at work where I was in a training class and the machine was set to lock every 10 minutes. Well, if the trainers got excited about talking - as opposed to changing slides - the machine would lock up.

I'd like to write a teeny app that has nothing but a taskbar icon that does nothing but move the mouse by 1 pixel every 4 minutes.

I can do that in 3 ways with Delphi (my strong language) but I'm moving to C# for work and I'd like to know the path of least resistance there.

6 Answers

for C# 3.5

without notifyicon therefore you will need to terminate this application in task manager manually

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

The "correct" way to do this is to respond to the WM_SYSCOMMAND message. In C# this looks something like this:

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

According to MSDN, if the screensaver password is enabled by policy on Vista or above, this won't work. Presumably programmatically moving the mouse is also ignored, though I have not tested this.

Something like this should work (though, you will want to change the interval).

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

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

Instead of faking activity, you could

inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running

using SetThreadExecutionState, as described on 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();
        }
    }
}

The Timer is a System.Threading.Timer, with its handy constructor, and it uses AutoResetEvent.WaitOne() to avoid exiting immediately.

Raf provided a graceful answer to the problem for Win10 world, but unfortunately, his autoResetEvent.WaitOne() instruction blocks the thread, and therefore it must be in a separate thread of its own.

What worked for me can actually run in the main thread, the code doesn't have to be placed in the Main() method, and you can actually have a button to enable this functionality and one to disable it.

First, you certainly need to define the execution state flags:

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

Now, whenever you want to keep your system awake and block your monitor from turning off or idling to sleep, all you need to do, is execute a single command:

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

Then, if you want to undo this action and return your system back to its original execution state, just issue the following command:

SetThreadExecutionState(ExecutionState.ES_CONTINUOUS);

Keep in mind, each command will return the previous execution state, which means, when you first alter this state, you can cache the returned value locally and use it if/when you want to restore the previous state.

Related