winapi - destacado - Programe programáticamente el protector de pantalla de Windows para iniciar
protector de pantalla para windows 7 (12)
¿Hay alguna manera recomendada de evitar que se inicie el protector de pantalla de Windows? Lo más parecido que he encontrado es este artículo , pero lo que realmente me gustaría hacer es decirle a Windows que la computadora no está inactiva en lugar de engañar con los valores de salvapantallas establecidos actualmente.
@Eyal - hey, gracias por la idea; nunca se me ocurrió que un delta de 0,0 podría funcionar. Agregué esa opción como "Zen jiggle" a 1.2 (dejando el original también para aquellas personas que se ponen nerviosas cuando no pueden verlo realmente funcionando).
Desde MSDN :
Windows no inicia el protector de pantalla si existe alguna de las siguientes condiciones:
- La aplicación activa no es una aplicación basada en Windows.
- Una ventana CBT está presente.
- La aplicación activa recibe el mensaje WM_SYSCOMMAND con el parámetro wParam establecido en el valor SC_SCREENSAVE, pero no pasa el mensaje a la función DefWindowProc.
Sin embargo, hay una advertencia:
Windows Vista y versiones posteriores: si la política habilita la protección mediante contraseña, el protector de pantalla se inicia independientemente de lo que haga una aplicación con la notificación SC_SCREENSAVE.
Esto parece aplicarse incluso si usa SetThreadExecutionState con ES_CONTINUOUS.
Entonces, si no fuera por la advertencia, sus elecciones serían:
- SetThreadExecutionState con ES_CONTINUOUS (como se describe en otras respuestas).
- Coloque una ventana de capacitación basada en computadora (que requiere ganchos).
- No permita que WM_SYSCOMMAND con SC_SCREENSAVE pase a DefWindowProc. (Suponiendo que solo le importa cuando su aplicación es la aplicación activa).
- Instale un dongle que simule el jiggle del mouse .
La última opción es buena ya que funciona incluso con la política de protección con contraseña.
En Windows 7+, use PowerSetRequest()
Power Management API con PowerRequestDisplayRequired
https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85).aspx
En versiones anteriores de Windows, intercepte el mensaje WM_SYSCOMMAND - SC_SCREENSAVE como se detalla en la respuesta de Eddie Parker.
No puedo creer que nadie haya señalado la solución fácil y obvia:
#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);
}
}
Para la prueba, configuré el protector de pantalla en 1 minuto y requirió una contraseña.
Intenté capturar SC_SCREENSAVE y devolver -1 en VB .Net. Como se comentó, funciona cuando no hay una contraseña de protector de pantalla pero falla si la contraseña del salvapantallas está activa. (Lo probé en Windows XP). También puse esto en el evento Tick''s Tick, cada 1000 milisegundos:
Static dir As Integer = 4
Cursor.Position = Cursor.Position + New Size(dir, dir)
dir = -dir
No funciona El cursor se mueve hacia adelante y hacia atrás y luego de 1 minuto, el protector de pantalla parpadea para una breve instancia y luego se apaga. El protector de pantalla se enciende solo por un momento, no lo suficiente como para requerir una contraseña. Pero aún así, el flash es feo.
Entonces traté de usar SetCursorPos de user32.dll y GetCursorPos. Puedes buscarlos en Pinvoke. Mismo resultado que el anterior.
Luego eché un vistazo al código de "JiggleMouse" mencionado en otra parte de esta pregunta. JiggleMouse usa SendInput. SendInput funciona! Sin flash del protector de pantalla. Puse una llamada a SendInput dentro de un temporizador que se dispara cada 50 segundos (justo menos que el tiempo mínimo de protector de pantalla de 60 segundos). Es suficiente mover el mouse por un delta de 0,0, sin movimiento real. Eso funciona El código para poner en el evento Tick:
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)))
Esto viene de 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
Puede utilizar SystemParametersInfo para obtener el SCREENSAVETIMEOUT
y luego establecer inmediatamente el tiempo de espera en el mismo valor. Haga esto periódicamente en un temporizador por el tiempo que desee para evitar que el protector de pantalla continúe.
Esto tiene el efecto de restablecer el temporizador de cuenta atrás actual sin cambiar realmente la configuración del sistema.
Probablemente también quiera llamar a SetThreadExecutionState
para que afecte el poder como lo mencionan otras respuestas.
Simplemente reinicia el contador de tiempo de espera con
SystemParametersInfo (SPI_SETSCREENSAVEACTIVE, 1, nil, SPIF_SENDWININICHANGE);
Sutil. La forma oficial de decirle a Windows que el sistema no está inactivo es SetThreadExecutionState. Esto restablece el temporizador inactivo, (o lo apaga, si pasa ES_CONTINUOUS
). Sin embargo, aunque SetThreadExecutionState restablece el temporizador inactivo, ¡ no detiene el protector de pantalla!
Uso Mouse Jiggler para restablecer el estado inactivo. Esto soluciona una política de grupo que tiende a iniciar mi protector de pantalla (y bloquear la máquina) en momentos inoportunos: cuando estoy leyendo un documento largo, estudiando un fragmento complejo de código, o hablando / escuchando / no constantemente escribiendo durante un reunión.
Como puede ser un poco molesto que el mouse salte 1px en diagonal por segundo, pretendo usar AutoHotKey para escribir un script que básicamente hace lo mismo, pero solo después de un tiempo de espera configurado para teclado / mouse, y quizás use la tecla Shift ( o Bloq Despl) en lugar de un movimiento del mouse.
Ver respuesta a esta pregunta:
¿Representación fuera de pantalla cuando la computadora portátil apaga la pantalla?
Esta publicación de blog detalla lo que debe hacer en C ++.
El fragmento de código real del sitio web:
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);
}
Específicamente, el parámetro SPI_SETSCREENSAVEACTIVE
.
¿Esto no funciona? Me sorprendió que no lo haya visto aquí. Tenga en cuenta que SetThreadExecutionState no afectará en absoluto al protector de pantalla, solo a la hora de dormir de la pantalla.