7

我知道这个问题之前一定被问过数百次,所以,也许,我只是做错了什么。但是我有一个我正在编写的 WinForms 程序,试图保持系统处于活动状态,以阻止它注册空闲。

我认为在我的表单上有一个计时器并做一些简单的事情,比如通过移动鼠标System.Windows.Forms.Cursor.Position或使用该SendKeys.Send方法就足以注册用户交互,但它没有注册为用户操作,并且仍然让系统在设置后显示为非活动状态多少时间。

我的代码相当简单......要么:

Private Sub Updater_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Updater.Tick
    SendKeys.Send("+")
End Sub

或者按照以下方式做一些事情:

Private Sub Updater_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Updater.Tick
    Dim MyMousePosition As Point
    MyMousePosition = Windows.Forms.Cursor.Position

    Windows.Forms.Cursor.Position = New Point(MyMousePosition.X - 10, MyMousePosition.Y)
End Sub

但两者都不是诀窍......我怎样才能让它工作,并且最好以一种对用户来说最不方便的方式,如果他们实际使用系统?(这意味着我不想发送一堆键,如果它们实际上处于活动状态或将鼠标移过屏幕,可能会弄乱用户)

我知道这个 coce 在 VB 中,但我很擅长 VB/C# 解决方案。

谢谢!!!


编辑

作为对这个问题的补充,我使用GetLastInputInfofromUser32.dll来检查系统活动。

即使我的鼠标/键盘事件链接到该Timer_Tick事件,GetLastInputInfo只有在我物理移动鼠标/在计算机上执行某些操作时才会重置...

我想我的问题是 我可以添加哪些事件到我的 Timer_Tick 事件中来重置GetLastInputInfo- 换句话说,让 Windows 相信用户实际上在机器上做了什么?

谢谢!!!

4

3 回答 3

8

在玩了很多之后,我想出了一个可行的解决方案,我正在回答这个问题,以帮助任何可能正在寻找相同信息的人。

(用VB编码):

在声明部分:

Private Declare Function SendInput Lib "user32.dll" (ByVal nInputs As Integer, ByRef pInputs As INPUT_TYPE, ByVal cbSize As Integer) As Integer
Const INPUT_MOUSE = 0
Const MOUSEEVENTF_MOVE = &H1

Public Structure MOUSEINPUT
    Public dx As Integer
    Public dy As Integer
    Public mouseData As Integer
    Public dwFlags As Integer
    Public dwtime As Integer
    Public dwExtraInfo As Integer
End Structure

Public Structure INPUT_TYPE
    Public dwType As Integer
    Public xi As MOUSEINPUT
End Structure

Sub 移动鼠标:

Public Sub MoveMouse(ByVal x As Integer, ByVal y As Integer, ByVal flag As Integer)

    Dim inputEvents As INPUT_TYPE
    Dim xi As New MOUSEINPUT

    xi.dx = x
    xi.dy = y
    xi.mouseData = 0
    xi.dwtime = 0
    xi.dwFlags = flag
    xi.dwExtraInfo = 0

    inputEvents.dwType = INPUT_MOUSE
    inputEvents.xi = xi

    SendInput(1, inputEvents, Len(inputEvents))
End Sub

Timer_Tick 事件中的代码:

Private Sub Updater_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Updater.Tick

    ' Move the mouse (relatively) 1 pixel away and then back
    MoveMouse(1, 1, MOUSEEVENTF_MOVE)
    MoveMouse(-1, -1, MOUSEEVENTF_MOVE)

End Sub

我使用GetLastInputInfoAPI 函数对此进行了测试,它可以工作!!

...我发现的最有用的链接是这个: http ://homeofcox-cs.blogspot.com/2008/07/c-simulate-mouse-and-keyboard-events.html

谢谢大家的帮助,我希望这对其他人也有帮助!!

于 2013-08-15T21:53:48.540 回答
1

当我们需要系统不空闲时(在 WM 6.0 中,当我们有很长的逻辑并且设备空闲时,逻辑停止工作)我们使用

  [DllImport("CoreDll.dll")]
  public static extern void SystemIdleTimerReset();

它重置了空闲计时器,不干扰用户的操作,它就像魅力一样

于 2013-08-14T05:51:38.027 回答
1

有一种更简单的方法,即调用Win32 函数

EXECUTION_STATE WINAPI SetThreadExecutionState(
  _In_  EXECUTION_STATE esFlags
);

ES_SYSTEM_REQUIRED | ES_CONTINUOUS作为论据。不管怎样,从这个SO issue 看来,即使ES_CONTINUOUS使用了,效果似乎也不会持续。在这种情况下,您应该定期调用该函数,比如每分钟一次,以重置空闲计时器。重要的是该函数只适用于调用它的线程,并且当线程终止时它的效果也终止。

完成后,您应该调用SetThreadExecutionState(ES_CONTINUOUS)以允许系统再次空闲。

于 2013-08-15T22:31:03.780 回答