Winapi 以编程方式阻止Windows屏幕保护程序启动

Winapi 以编程方式阻止Windows屏幕保护程序启动,winapi,windows-vista,windows-xp,screensaver,Winapi,Windows Vista,Windows Xp,Screensaver,有没有推荐的方法来阻止Windows屏幕保护程序启动?我发现的最接近的是,但是我真正想做的就是告诉Windows计算机不是空闲的,而不是欺骗当前设置的屏幕保护程序值。 详细说明了C++中需要做的事情。 网站中的实际代码片段: LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SYSCOMMA

有没有推荐的方法来阻止Windows屏幕保护程序启动?我发现的最接近的是,但是我真正想做的就是告诉Windows计算机不是空闲的,而不是欺骗当前设置的屏幕保护程序值。

详细说明了C++中需要做的事情。 网站中的实际代码片段:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg)                  
  {
    case WM_SYSCOMMAND:
    {
      switch (wParam)
      {
        case SC_SCREENSAVE:  
          return 0;
        case SC_MONITORPOWER:
          return 0;      
      }
      break;      
    }

    case WM_CLOSE:                
    {
      PostQuitMessage(0);            
      return 0;        
    }
  }
  return DefWindowProc(hWnd,uMsg,wParam,lParam);

}微妙。告诉Windows系统未空闲的官方方法是SetThreadExecutionState。这将重置空闲计时器(或关闭它,如果您通过
ES_CONTINUOUS
)。但是,即使SetThreadExecutionState重置空闲计时器,它也不会停止屏幕保护程序

我用来重置空闲状态。这就绕过了一个群体策略,该策略倾向于在不合适的时候启动我的屏幕保护程序(并锁定机器):当我阅读一个长文档、研究一段复杂的代码时,或者在会议期间说话/听/不经常打字时

由于让鼠标每秒沿对角线跳1px可能会有点烦人,我打算用它来编写一个基本上做相同事情的脚本,但只在配置键盘/鼠标空闲超时后,并且可能使用Shift键(或滚动锁)而不是鼠标移动。

具体而言,
SPI_SETSCREENSAVEACTIVE
参数


这不管用吗?我很惊讶我没有在这里看到它。请注意,SetThreadExecutionState根本不会影响屏幕保护程序,只会影响显示器的睡眠。

为了进行测试,我将屏幕保护程序设置为1分钟,并需要密码

我尝试在VB.Net中捕获SC_屏幕保存并返回-1。如前所述,它在没有屏幕保护程序密码时工作,但如果屏幕保护程序密码处于活动状态,将失败。(我在Windows XP中试用过)。我还将其放入计时器的滴答事件中,每1000毫秒一次:

Static dir As Integer = 4
Cursor.Position = Cursor.Position + New Size(dir, dir)
dir = -dir
它不起作用。光标来回摆动,1分钟后屏幕保护程序会在短时间内闪烁,然后关闭。屏幕保护程序只打开一小会儿,时间不够长,不需要密码。但是,闪光仍然是丑陋的

然后我尝试使用user32.dll的SetCursorPos和GetCursorPos。你可以在平沃克查一下。结果同上

然后我偷看了一下这个问题中其他地方提到的“JiggleMouse”代码。JiggleMouse使用SendInputSendInput有效屏幕保护程序不闪烁。我把SendInput的调用放在一个计时器内,计时器每50秒触发一次(刚好小于屏幕保护程序的最小超时60秒)。将鼠标移动0,0的增量就足够了,没有实际的移动。这确实有效。要放入勾号事件的代码:

Dim i(0) As INPUT
i(0).dwType = INPUT.InputType.INPUT_MOUSE
i(0).mkhi = New MOUSEKEYBDHARDWAREINPUT
i(0).mkhi.mi = New MOUSEINPUT
i(0).mkhi.mi.dx = 0
i(0).mkhi.mi.dy = 0
i(0).mkhi.mi.mouseData = 0
i(0).mkhi.mi.dwFlags = MOUSEINPUT.MouseEventFlags.MOUSEEVENTF_MOVE
i(0).mkhi.mi.time = 0
i(0).mkhi.mi.dwExtraInfo = IntPtr.Zero
SendInput(1, i(0), Marshal.SizeOf(i(0)))
这来自pinvoke.com:

Public Declare Function SendInput Lib "user32" (ByVal nInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer

Public Structure INPUT
    Enum InputType As Integer
        INPUT_MOUSE = 0
        INPUT_KEYBOARD = 1
        INPUT_HARDWARE = 2
    End Enum

    Dim dwType As InputType
    Dim mkhi As MOUSEKEYBDHARDWAREINPUT
End Structure

Public Structure MOUSEINPUT
    Enum MouseEventFlags As Integer
        MOUSEEVENTF_MOVE = &H1
        MOUSEEVENTF_LEFTDOWN = &H2
        MOUSEEVENTF_LEFTUP = &H4
        MOUSEEVENTF_RIGHTDOWN = &H8
        MOUSEEVENTF_RIGHTUP = &H10
        MOUSEEVENTF_MIDDLEDOWN = &H20
        MOUSEEVENTF_MIDDLEUP = &H40
        MOUSEEVENTF_XDOWN = &H80
        MOUSEEVENTF_XUP = &H100
        MOUSEEVENTF_WHEEL = &H800
        MOUSEEVENTF_VIRTUALDESK = &H4000
        MOUSEEVENTF_ABSOLUTE = &H8000
    End Enum

    Dim dx As Integer
    Dim dy As Integer
    Dim mouseData As Integer
    Dim dwFlags As MouseEventFlags
    Dim time As Integer
    Dim dwExtraInfo As IntPtr
End Structure

Public Structure KEYBDINPUT
    Public wVk As Short
    Public wScan As Short
    Public dwFlags As Integer
    Public time As Integer
    Public dwExtraInfo As IntPtr
End Structure

Public Structure HARDWAREINPUT
    Public uMsg As Integer
    Public wParamL As Short
    Public wParamH As Short
End Structure

Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1
Const KEYEVENTF_KEYUP As UInt32 = &H2
Const KEYEVENTF_UNICODE As UInt32 = &H4
Const KEYEVENTF_SCANCODE As UInt32 = &H8
Const XBUTTON1 As UInt32 = &H1
Const XBUTTON2 As UInt32 = &H2

<StructLayout(LayoutKind.Explicit)> Public Structure MOUSEKEYBDHARDWAREINPUT
    <FieldOffset(0)> Public mi As MOUSEINPUT
    <FieldOffset(0)> Public ki As KEYBDINPUT
    <FieldOffset(0)> Public hi As HARDWAREINPUT
End Structure
将函数SendInput Lib“user32”(ByVal nInputs作为整数,ByRef pInputs作为输入,ByVal cbSize作为整数)公开声明为整数
公共结构投入
将InputType枚举为整数
输入\鼠标=0
键盘输入=1
输入硬件=2
结束枚举
Dim dwType作为InputType
将mkhi调暗为MOUSEKEYBDHARDWAREINPUT
端部结构
公共结构鼠标输入
将MouseEventFlags枚举为整数
MOUSEEVENTF_MOVE=&H1
MOUSEEVENTF_LEFTDOWN=&H2
MOUSEEVENTF_LEFTUP=&H4
MOUSEEVENTF_RIGHTDOWN=&H8
MOUSEEVENTF_RIGHTUP=&H10
MOUSEEVENTF_MIDDLEDOWN=&H20
MOUSEEVENTF_MIDDLEUP=&H40
MOUSEEVENTF_XDOWN=&H80
MOUSEEVENTF_XUP=&H100
MOUSEEVENTF_滚轮=&H800
MOUSEEVENTF_VIRTUALDESK=&H4000
MOUSEEVENTF_绝对值=&H8000
结束枚举
作为整数的Dim dx
作为整数的Dim-dy
将mouseData设置为整数
将dwFlags变暗为MouseeEventFlags
将时间变暗为整数
将dwExtraInfo设置为IntPtr
端部结构
公共结构键输入
公共wVk为短
公共无线传感器网络
作为整数的公共标志
作为整数的公共时间
公共dwExtraInfo作为IntPtr
端部结构
公共结构硬件输入
作为整数的公共uMsg
公共wParamL简称
公共wParamH简称
端部结构
Const KEYEVENTF_扩展键为UInt32=&H1
常量KEYEVENTF\u KEYUP为UInt32=&H2
Const KEYEVENTF_UNICODE作为UInt32=&H4
Const KEYEVENTF_扫描代码为UInt32=&H8
常量XBUTTON1为UInt32=&H1
常数XBUTTON2为UInt32=&H2
公共结构MOUSEKEYBDHARDWAREINPUT
作为鼠标输入的公共mi
公共ki作为KEYBDINPUT
公共hi作为硬件输入
端部结构

真不敢相信没有人指出简单而明显的解决方案:

#include <windows.h>

void main()
{
   while(1){
      INPUT input;
      input.type = INPUT_MOUSE;
      input.mi.dx = 1;
      input.mi.dy = 1;
      input.mi.mouseData = 0;
      input.mi.dwFlags = MOUSEEVENTF_MOVE;
      input.mi.time = 0;
      input.mi.dwExtraInfo = 0;
      SendInput( 1, &input, sizeof(input) );
      sleep(60000);
   }
}
#包括
void main()
{
而(1){
输入;
input.type=输入\鼠标;
input.mi.dx=1;
input.mi.dy=1;
input.mi.mouseData=0;
input.mi.dwFlags=MOUSEEVENTF_MOVE;
input.mi.time=0;
input.mi.dwExtraInfo=0;
SendInput(1,&input,sizeof(input));
睡眠(60000);
}
}
来自:

如果存在以下任何情况,Windows不会启动屏幕保护程序:

  • 活动应用程序不是基于Windows的应用程序
  • 存在CBT窗口
  • 活动应用程序接收wParam参数设置为SC_SCREENSAVE值的WM_SYSCOMMAND消息,但不会将消息传递给DefWindowProc函数
不过有一个警告:

Windows Vista及更高版本:如果策略启用了密码保护,则无论应用程序如何处理SC_屏幕保存通知,屏幕保护程序都会启动

即使将SetThreadExecutionState与ES_CONTINUOUS一起使用,这似乎也适用

因此,如果没有警告,您的选择将是:

  • SetThreadExecutionState,ES_连续(如其他答案中所述)
  • 建立一个基于计算机的培训窗口(需要挂钩)
  • 不要让带有SC_SCREENSAVE的WM_SYSCOMMAND传递到DefWindowProc。(假设你只关心w
    "FlipSS.exe -h" to see the current state.
    "FlipSS.exe /on" to set the screensaver on.
    "FlipSS.exe /off" to set the screensaver off.
    
    DllCall("SystemParametersInfo", Int, 17, Int, 0, UInt, NULL, Int, 2)
    
    DllCall("SystemParametersInfo", Int, 17, Int, 1, UInt, NULL, Int, 2)
    
    //To stop/start screen saver and monitor power off event
    void SetKeepScreenOn(BOOL isKeepScreenOn)
    {
       if (isKeepScreenOn == TRUE)
       {
           SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED /*| ES_AWAYMODE_REQUIRED*/);        
       }
       else
       {
           SetThreadExecutionState(ES_CONTINUOUS);      
       }
    }
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
    static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
    
    [FlagsAttribute]
    public enum EXECUTION_STATE :uint
    {
       ES_AWAYMODE_REQUIRED = 0x00000040,
       ES_CONTINUOUS = 0x80000000,
       ES_DISPLAY_REQUIRED = 0x00000002,
       ES_SYSTEM_REQUIRED = 0x00000001
    }
    
    void SetKeepScreenOn(bool isKeepScreenOn)
    {
        if (isKeepScreenOn == true)
        {
             //You can combine several flags and specify multiple behaviors with a single call
             SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED /*| EXECUTION_STATE.ES_AWAYMODE_REQUIRED*/);        
        }
        else
        {
             //To reset or allow those event again you have to call this API with only ES_CONTINUOUS
             SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);      
        }
     }