Prevent screen from sleeping with C# - c#

I have created a small C# console app to move the pointer around the screen, in the hope that this would prevent the screen from sleeping / locking after a few minutes. Unfortunately the screen still goes to sleep after a few minutes.
Does anyone know if it's actually possible to write something in C# which will act like user input (either mouse or keyboard), and prevent the screen from sleeping / locking automatically?
Here is what I have, which I thought might do the trick.
class Program
{
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
static Random rnd = new Random();
static void Main(string[] args)
{
Rectangle screenRes = Screen.PrimaryScreen.Bounds;
int widtMax = screenRes.Width;
int heighMax = screenRes.Height;
int w;
int h;
do
{
while (!Console.KeyAvailable)
{
w = rnd.Next(1, widtMax);
h = rnd.Next(1, heighMax);
SetCursorPos(w, h);
System.Threading.Thread.Sleep(1000);
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}

You can make use of SetThreadExecutionState
Enables an application to 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.
Remarks
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets
the idle timer; to keep the display or system in the working state,
the thread must call SetThreadExecutionState periodically.
To run properly on a power-managed computer, applications such as fax
servers, answering machines, backup agents, and network management
applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when
they process events. Multimedia applications, such as video players
and presentation applications, must use ES_DISPLAY_REQUIRED when they
display video for long periods of time without user input.
Applications such as word processors, spreadsheets, browsers, and
games do not need to call SetThreadExecutionState.
DllImport
[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
Enums
[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
Usage
void PreventSleep ()
{
// Prevent Idle-to-Sleep (monitor not affected) (see note above)
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
}
UPDATE 02/08/2021:
In case anyone is looking for a complete example, here is a project I found on github that has implemented this: https://github.com/pedrolcl/screensaver-disabler

Related

C# cursor moving doesn't avoid screen saver [duplicate]

I have created a small C# console app to move the pointer around the screen, in the hope that this would prevent the screen from sleeping / locking after a few minutes. Unfortunately the screen still goes to sleep after a few minutes.
Does anyone know if it's actually possible to write something in C# which will act like user input (either mouse or keyboard), and prevent the screen from sleeping / locking automatically?
Here is what I have, which I thought might do the trick.
class Program
{
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
static Random rnd = new Random();
static void Main(string[] args)
{
Rectangle screenRes = Screen.PrimaryScreen.Bounds;
int widtMax = screenRes.Width;
int heighMax = screenRes.Height;
int w;
int h;
do
{
while (!Console.KeyAvailable)
{
w = rnd.Next(1, widtMax);
h = rnd.Next(1, heighMax);
SetCursorPos(w, h);
System.Threading.Thread.Sleep(1000);
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
You can make use of SetThreadExecutionState
Enables an application to 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.
Remarks
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets
the idle timer; to keep the display or system in the working state,
the thread must call SetThreadExecutionState periodically.
To run properly on a power-managed computer, applications such as fax
servers, answering machines, backup agents, and network management
applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when
they process events. Multimedia applications, such as video players
and presentation applications, must use ES_DISPLAY_REQUIRED when they
display video for long periods of time without user input.
Applications such as word processors, spreadsheets, browsers, and
games do not need to call SetThreadExecutionState.
DllImport
[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
Enums
[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
Usage
void PreventSleep ()
{
// Prevent Idle-to-Sleep (monitor not affected) (see note above)
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
}
UPDATE 02/08/2021:
In case anyone is looking for a complete example, here is a project I found on github that has implemented this: https://github.com/pedrolcl/screensaver-disabler

How can I get better timed events for my games?

I have written an ordinary dispatcher timer method for creating a gameloop in WPF. I notice though that if it is set to a shorter interval than say 200 ms, it doesn't catch up correctly.
I printed the seconds to screen (see code below) and compared it to my wrist watch. With a setting of 500 ms, it's okay, but if I set it much lower there is a huge discrepancy. I tried a setting of 10 ms, and that meant that the time onscreen passed only 38 seconds in a (real) minute! (Note that all my game engine code was removed during testing, so it's just the timer loop that is called. Also, it doesn't matter if I run the code from VS or the exe file in the Debug folder.)
Note that the games I create run smoothly, it's just that my (standard) Each_Tick method doesn't get called at the correct times. This in turn means that my games will run faster on a faster computer.
So how do I keep correct track of time and make sure that the Each_Tick method fires at the same time, independently of the computer (or cellphone) used? That is, I would rather have a limit on the number of game objects, collision detection precision etc, but on time, rather than just going as fast as possible. Put differently, if I set the timer increment value to 50ms (which I think is reasonable as that would mean 20 times per second), I really want the game to be updated 20 times per second.
I really don't want to get into threading etc if it's possible to avoid it, as the games themselves run fine now. I just want them to play back at the same speed.
I looked up some great replies at How to control frame rate in WPF by using dispatcher timer accurately? but this still doesn't answer my question: how do I get my games to run at the same speed, regardless of (modern) computer/cell phone and whether it's WPF/UWP or perhaps something else?
Or is this impossible to do in a rather easy manner, and I should just accept that game speed depends on the computer used?
Thanks!
Code:
public void StartTimer()
{
//This variable is used to get to the controls (labels etc) of the MainWindow (WPF)
MainWindow mainWin = System.Windows.Application.Current.Windows.Cast<System.Windows.Window>().FirstOrDefault(window => window is MainWindow) as MainWindow;
time = TimeSpan.FromSeconds(0);
//What the code below does is this:
//For each 10 ms, call the different methods. Then add 10 ms to the current time.
timer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 10), DispatcherPriority.Normal, delegate
{
if (runGame == false) return; //only go on if not in pause mode
mainWin.txtInfo.Text = time.ToString("mm\\:ss");//Shows the timer in a textbox, only showing minutes and seconds.
//Collision code etc removed during the test
time = time.Add(TimeSpan.FromMilliseconds(10)); //adds a specified time to the current time
}, System.Windows.Application.Current.Dispatcher);
}
Note that the code above was added for testing purposes. The original code (facing the same problems) looks like this:
public void StartTimer()
{
//A note on the dispatcherTimer http://www.wpf-tutorial.com/misc/dispatchertimer/
var timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 10); // Each every n milliseconds (set low to avoid flicker)
timer.Tick += EachTick;
timer.Start();
}
// A testing counter
int counter = 0;
// Raised every tick while the DispatcherTimer is active.
private void EachTick(object sender, object e)
{ etc
Build in timers are not very accurate. Use this code snippet. Ive used this timer many times. This timer is really accurate. Kudos to John
public class AccurateTimer
{
private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2);
private const int TIME_PERIODIC = 1;
private const int EVENT_TYPE = TIME_PERIODIC;
[DllImport("winmm.dll")]
private static extern int timeBeginPeriod(int msec);
[DllImport("winmm.dll")]
private static extern int timeEndPeriod(int msec);
[DllImport("winmm.dll")]
private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType);
private readonly int _mTimerId;
public AccurateTimer(int delay)
{
timeBeginPeriod(1);
_mTimerId = timeSetEvent(delay, 0, TimerTick, IntPtr.Zero, EVENT_TYPE);
}
public void Stop()
{
timeEndPeriod(1);
System.Threading.Thread.Sleep(100);// Ensure callbacks are drained
}
private void TimerTick(int id, int msg, IntPtr user, int dw1, int dw2)
{
Console.WriteLine("Tick " + DateTime.Now.TimeOfDay.TotalMilliseconds);
}
}

A way to concatenate Console.Beep sounds

I've been playing around with some C# and specifically making sounds... because it's fun. So I've got it all working but there's something bugging me to do with Console.Beep(): it doesn't directly concatenate sounds. For example, running the code below will result in a series of 250-millisecond bursts of sound - but instead of all being run together and sounding as if they are one, they become disjointed, with a ~50ms pause in between each sound.
for(int i = 0; i < 11; i++)
{
Console.Beep(980, 250);
}
So the question is, is there any programmatic way to make the system run the sounds together? I have to say I don't really expect there to be but I figured it was worth an ask, since many other resources seem to just accept the fact that it doesn't.
You can't, that method uses kernel's functions. I will prove:
[SecuritySafeCritical]
[HostProtection(SecurityAction.LinkDemand, UI = true)]
public static void Beep(int frequency, int duration)
{
if (frequency < 37 || frequency > 32767)
{
throw new ArgumentOutOfRangeException("frequency", frequency, Environment.GetResourceString("ArgumentOutOfRange_BeepFrequency", new object[]
{
37,
32767
}));
}
if (duration <= 0)
{
throw new ArgumentOutOfRangeException("duration", duration, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
}
Win32Native.Beep(frequency, duration);
}
This is the Console.Beep's code, it uses Win32Native.Beep to actually perform beep (Aside from the checks above it), and that method leads to:
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool Beep(int frequency, int duration);
A function that imported from kernel.
Unless you hard-code and modify your kernel, you can't. (Which I am sure you don't want to)
I can give you an alternative: http://naudio.codeplex.com/, you can instead control your sound by using this tool and giving it stream. (You can create stream that don't use file as source)

Mouse Simulation In .exe window

I want to make a mouse macroer. Which can both do simulated mouse events, or using my computers own cursor on screen.
The macro shall be created by typing in methods in the IDE. These methods shall then execute mouse events on a certain .exe´s window. By using coordinates.
For example this is my goal of a method executing a simulated or not simulated mouse left click on a certain .exe´s window:
Psuedo code:
//Following method left clicks with the offset (x, y)
//from the windows top left corner. If the bool isSimulated
//is set to true the click will be simulated else the computers
//own mouse cursor will be moved and execute the mouse event.
LeftMouseClickOnWindow(x, y, isSimulated);
To chrisp the problem even more, simulated mouse clicks should function while the window is minimized or when unfocused.
I am wondering what the best approach to create this kind of util is.
Is user32.dll´s functions a good approach?
Is it easier to do it in C++ rather than C#?
Any advices, sources, example codes and comments is warmly appreciated!
Both C++ and C# are great. AutoHotKey can do the job, but I'm like you - I love to write my own stuff. Another option is AutoIt, and you can use its dll in your C# project... but then you have to make sure that it's installed on every system... not a luxury that I've encountered often.
Here's something to play around with. Hopefully it'll get you going... note that it's C#. Before you run this code, make sure that you don't have anything important open where your mouse is at... this will move 20 times in a diagonal to the lower right and perform a click every time it moves. You don't want this to close your stuff accidentally. So, just minimize it all, prior to running this.
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ConsoleApplication
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
//private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
//private const int MOUSEEVENTF_RIGHTUP = 0x10;
public void DoMouseStuff()
{
Cursor.Current = new Cursor(Cursor.Current.Handle);
var point = new Point(Cursor.Position.X, Cursor.Position.Y);
for (int i = 0; i < 20; i++, point.X += 10, point.Y += 10)
{
Cursor.Position = point;
Program.mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, (uint)Cursor.Position.X, (uint)Cursor.Position.Y, 0, 0);
System.Threading.Thread.Sleep(100);
}
}
static void Main(string[] args)
{
var prog = new Program();
prog.DoMouseStuff();
}
}
}
You'll need to set references for System.Windows.Forms & System.Drawing, if you don't have those set already. I made it as a console app, so, setting for me was required. As you notice, I included System.Threading.Thread.Sleep(100);... this is so that you can see what's going on. So, I'm basically slowing down the whole thing. It moves and it clicks every time it moves (which is approximately once every 100 milliseconds).
Familiarize yourself with the Cursor and user32.dll.
Last, but not least, here's MSDN documentation on mouse & keyboard simulation: http://msdn.microsoft.com/en-us/library/ms171548.aspx

What's the best way to enter numbers in Windows Mobile? (.NET CF 3.5)

There must be a better way than a constrained numeric updown control.
The easiest way to enter numbers (especially non-integer numbers) in Windows Mobile (or in a regular Windows application) is to just have a text box that the users type into, and then validate that they've entered a proper number.
The problem with this approach in Windows Mobile is that the default SIP (Soft Input Panel aka little pop-up keyboard) looks like this:
alt text http://img510.imageshack.us/img510/6210/sipreg.jpg
On a real Windows Mobile device, the SIP looks even smaller than this, and it is a gigantic pain in the keister to hit the little number keys at the top correctly. What you want to use for this purpose is the Numeric mode, which you get by clicking the "123" button in the upper left corner, and looks like this:
alt text http://img16.imageshack.us/img16/6128/sipnum.jpg
The problem with this is that there is no (simple) way programatically to make this mode of the SIP appear instead of the regular keyboard. To get the SIP to appear in numeric mode, add a reference to your project to Microsoft.WindowsCE.Forms, and then add this code as a class named "SIPHandler" (you will have to change the namespace to your project's namespace):
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using Microsoft.WindowsCE.Forms;
namespace DeviceApplication1
{
/// <summary>
/// Handles showing and hiding of Soft Input Panel (SIP). Better to use these
/// methods than having an InputControl on a form. InputControls behave oddly
/// if you have multiple forms open.
/// </summary>
public class SIPHandler
{
public static void ShowSIP()
{
SipShowIM(1);
}
public static void ShowSIPNumeric()
{
SipShowIM(1);
SetKeyboardToNumeric();
}
public static void ShowSIPRegular()
{
SipShowIM(1);
SetKeyboardToRegular();
}
public static void HideSIP()
{
SipShowIM(0);
}
private static void SetKeyboardToRegular()
{
// Find the SIP window
IntPtr hWnd = FindWindow("SipWndClass", null);
// Go one level below as the actual SIP window is a child
hWnd = GetWindow(hWnd, GW_CHILD);
// Obtain its context and get a color sample
// The premise here is that the numeric mode is controlled by a virtual button in the top left corner
// Whenever the numeric mode is active, the button background will be of COLOR_WINDOW_TEXT
IntPtr hDC = GetDC(hWnd);
int pixel = GetPixel(hDC, 2, 2);
// Notice that we cannot simply compare the color to the system color as the system color is 24 bit (or palette)
// and the real color is dithered to 15-16 bits for most devices, so white (0xff, 0xff, 0xff) becomes
// almost white (oxf8, 0xfc, 0xf8)
// ken's hack: here we only want to simulate the click if the keyboard is in numeric mode, in
// which case the back color will be WindowText
//int clrText = (SystemColors.Window.R) | (SystemColors.Window.G << 8) | (SystemColors.Window.B << 16);
int clrText = (SystemColors.WindowText.R) | (SystemColors.WindowText.G << 8) | (SystemColors.WindowText.B << 16);
SetPixel(hDC, 2, 2, clrText);
int pixelNew = GetPixel(hDC, 2, 2);
// Restore the original pixel
SetPixel(hDC, 2, 2, pixel);
if (pixel == pixelNew)
{
// Simulate stylus click
Message msg = Message.Create(hWnd, WM_LBUTTONDOWN, new IntPtr(1), new IntPtr(0x00090009));
MessageWindow.SendMessage(ref msg);
msg = Message.Create(hWnd, WM_LBUTTONUP, new IntPtr(0), new IntPtr(0x00090009));
MessageWindow.SendMessage(ref msg);
}
// Free resources
ReleaseDC(hWnd, hDC);
}
private static void SetKeyboardToNumeric()
{
// Find the SIP window
IntPtr hWnd = FindWindow("SipWndClass", null);
// Go one level below as the actual SIP window is a child
hWnd = GetWindow(hWnd, GW_CHILD);
// Obtain its context and get a color sample
// The premise here is that the numeric mode is controlled by a virtual button in the top left corner
// Whenever the numeric mode is active, the button background will be of COLOR_WINDOW_TEXT
IntPtr hDC = GetDC(hWnd);
int pixel = GetPixel(hDC, 2, 2);
// Notice that we cannot simply compare the color to the system color as the system color is 24 bit (or palette)
// and the real color is dithered to 15-16 bits for most devices, so white (0xff, 0xff, 0xff) becomes
// almost white (oxf8, 0xfc, 0xf8)
int clrText = (SystemColors.Window.R) | (SystemColors.Window.G << 8) | (SystemColors.Window.B << 16);
SetPixel(hDC, 2, 2, clrText);
int pixelNew = GetPixel(hDC, 2, 2);
// Restore the original pixel
SetPixel(hDC, 2, 2, pixel);
if (pixel == pixelNew)
{
// Simulate stylus click
Message msg = Message.Create(hWnd, WM_LBUTTONDOWN, new IntPtr(1), new IntPtr(0x00090009));
MessageWindow.SendMessage(ref msg);
msg = Message.Create(hWnd, WM_LBUTTONUP, new IntPtr(0), new IntPtr(0x00090009));
MessageWindow.SendMessage(ref msg);
}
// Free resources
ReleaseDC(hWnd, hDC);
}
[DllImport("coredll.dll")]
private extern static bool SipShowIM(int dwFlag);
[DllImport("coredll.dll")]
private extern static IntPtr FindWindow(string wndClass, string caption);
[DllImport("coredll.dll")]
private extern static IntPtr GetWindow(IntPtr hWnd, int nType);
[DllImport("coredll.dll")]
private extern static int GetPixel(IntPtr hdc, int nXPos, int nYPos);
[DllImport("coredll.dll")]
private extern static void SetPixel(IntPtr hdc, int nXPos, int nYPos, int clr);
[DllImport("coredll.dll")]
private extern static IntPtr GetDC(IntPtr hWnd);
[DllImport("coredll.dll")]
private extern static void ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("coredll.dll")]
private static extern bool SipSetCurrentIM(byte[] clsid);
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
const int GW_CHILD = 5;
}
}
Sorry about the length. To pop the SIP up in numeric mode, you just use this line:
SIPHandler.ShowSIPNumeric();
or to make it appear in regular keyboard mode:
SIPHandler.ShowSIPRegular();
And to hide it again:
SIPHandler.HideSIP();
The basic trick behind this code is to sort of "peek" the color in the upper left corner to determine whether the SIP is already in regular keyboard or numeric mode, and then to simulate a mouse click (if necessary) in the same corner to ensure that the SIP is in the mode desired.
Note: this is "borrowed" web code, but I no longer know where I got it from. If anyone on SO knows where this hack came from, please let me know and I'll be happy to attribute it to the original author.
Update: well, after 2 seconds of Googling, I've found that the proximate source of this code was Daniel Moth:
http://www.danielmoth.com/Blog/InputPanelEx.cs
... who credits Alex Feinman with the original:
http://www.alexfeinman.com/download.asp?doc=IMSwitch.zip
Thanks, guys! This code actually brought me to tears once (I was chopping onions at the time, but that couldn't have been it).
The MaskedTextBox might be of use. Failing that, I recommend using an ordinary TextBox with an OnTextChange event handler that checks to make sure the value entered is actually a number. Any non-numerical characters, and you can bang out a message box, or simply remove those characters completely, depending on your needs.
The NumericUpDown controls are slow to use sometimes, but they have intrinsic data validation which in some cases is quite useful. If the control is one the user is not going to use often, consider using it. Otherwise the MaskedTextBox or TextBox is the way to go.
Another approach to this problem is to use a multi-level ContextMenu, where the first layer of options covers ranges of numbers, and the second layers let the users pick specific values, like this:
alt text http://img19.imageshack.us/img19/6329/dropdowns.jpg
You can create the full menu structure ahead of time (kind of a pain) or just load the structure dynamically depending on the range of values and the resolutions required. You can do this with hundreds of menu items in much less than a second, even on Windows Mobile devices.
This approach also works very well for entering monetary values.

Categories

Resources