【问题标题】:Wiggling the mouse晃动鼠标
【发布时间】:2010-09-05 08:02:51
【问题描述】:

好的。这是一个有点虚荣的应用程序,但我今天在工作中遇到了一种情况,我在培训班上,机器设置为每 10 分钟锁定一次。好吧,如果培训师对谈话感到兴奋——而不是更换幻灯片——机器就会锁定。

我想编写一个只有任务栏图标的小应用程序,它除了每 4 分钟移动鼠标 1 个像素外什么都不做。

我可以用 Delphi(我的强语言)通过 3 种方式做到这一点,但我正在转向 C# 工作,我想知道那里阻力最小的路径。

【问题讨论】:

  • 你试过 Lubso 的回答了吗?虽然它会摆动鼠标,但我不确定它是否会阻止屏幕保护程序启动!
  • 写一个启用和禁用屏幕保护程序的快捷方式不是更好吗?
  • 这在 Windows XP 上使用受密码保护的屏幕保护程序确实有效。
  • 刚刚在 XP 的公司锁定环境中尝试过(强制密码),但没有帮助。

标签: c# winapi mouse


【解决方案1】:

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

【讨论】:

  • Lubos - 我喜欢!我将对其进行修改以在移动之间交替,以便在一天后,光标不会被埋在屏幕的角落,但这很挑剔——也许他们甚至会喜欢这样。 :) 非常感谢您快速、出色的回答!
  • 这真的有用吗?从内存中,启动屏幕保护程序的“超时”是在操作系统的某个地方完成的,与输入有关。移动鼠标位置不会采用相同的逻辑路径,因此用户实际上并没有重置倒计时!
【解决方案2】:

这样的事情应该可以工作(不过,您想要更改间隔)。

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

【讨论】:

    【解决方案3】:

    执行此操作的“正确”方法是响应 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或以上的策略启用了屏保密码,这将不起作用。大概以编程方式移动鼠标也会被忽略,尽管我没有对此进行测试。

    【讨论】:

      【解决方案4】:

      当我在家工作时,我会将鼠标线系在一个左右摆动的桌面风扇上。它使鼠标保持移动并防止工作站进入睡眠状态。

      【讨论】:

        【解决方案5】:

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

        Timer 是一个System.Threading.Timer,具有方便的构造函数,它使用AutoResetEvent.WaitOne() 来避免立即退出。

        【讨论】:

          【解决方案6】:

          Raf 为 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);
          

          请记住,每个命令都会返回之前的执行状态,这意味着,当您第一次更改此状态时,您可以在本地缓存返回的值,并在您想要恢复之前的状态时使用它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-08-08
            • 2015-10-10
            • 1970-01-01
            • 2023-03-23
            相关资源
            最近更新 更多