Есть ли рекомендуемый способ предотвратить запуск заставки Windows? Самая близкая вещь, которую я нашел, - это эта статья, но мне бы очень хотелось просто сказать Windows, что компьютер не простаивает, вместо того, чтобы вводить в заблуждение текущие установленные значения заставки.
@Eyal - привет, спасибо за идею; Мне никогда не приходило в голову, что дельта 0,0 может работать. Я добавил эту опцию как "Zen jiggle" в 1.2 (оставив также оригинал, для тех людей, которые нервничают, когда не могут на самом деле видеть это работает).





Это сообщение в блоге подробно описывает, что вам нужно делать в 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);
}
Обратите внимание, что согласно MSDN, это НЕ работает для Windows Vista, если для заставки настроен пароль.
Роб, у вас есть ссылка, где написано, что это не работает с Vista?
Ах, обнаружил: «Microsoft Windows Vista и более поздние версии: если защита паролем включена политикой, хранитель экрана запускается независимо от того, что приложение делает с уведомлением SC_SCREENSAVE, даже если не может передать его в DefWindowProc».
Тонкий. Официальный способ сообщить Windows, что система не простаивает, - SetThreadExecutionState. Это сбрасывает таймер простоя (или выключает его, если вы проходите ES_CONTINUOUS). Однако, хотя SetThreadExecutionState сбрасывает таймер простоя, это не останавливает заставку!
Почему за этот ответ было положено 6 голосов? Сам ответ гласит, что он не отвечает на вопрос.
@GraemePerrow: Вопрос задан 6 лет назад, и тогда сообщество не так много комментировало проблемы XY. Сегодня этот вопрос вполне может быть закрыт как неясный. В теле вопроса конкретно говорится: «просто скажите Windows, что компьютер не простаивает», что и делает этот ответ.
Я использую Мышь Джигглер для сброса состояния ожидания. Это обходит групповую политику, которая имеет тенденцию запускать мою заставку (и блокировать машину) в неподходящее время: когда я читаю длинный документ, изучаю сложный фрагмент кода или говорю / слушаю / не набираю постоянно во время встреча.
Поскольку это может немного раздражать, когда мышь прыгает на 1 пиксель по диагонали каждую секунду, я намерен использовать AutoHotKey для написания скрипта, который делает в основном то же самое, но только после настроенного тайм-аута простоя клавиатуры / мыши и, возможно, использовать клавишу Shift ( или Scroll Lock) вместо движения мыши.
очень хорошо, мне нравится это предложение
2 обновления, касающихся Mouse Jiggler: последняя версия поддерживает режим «Дзен», в котором мышь перемещает нулевые пиксели (т.е. совсем не перемещает). Однако похоже, что в Windows 7 и более поздних версиях есть новые параметры групповой политики, которые каким-то образом игнорируют движения мыши.
Найдите SPI_SETBLOCKSENDINPUTRESETS
В частности, параметр SPI_SETSCREENSAVEACTIVE.
Это не работает? Я был удивлен, что не увидел его здесь. Обратите внимание, что SetThreadExecutionState вообще не повлияет на хранитель экрана, а только на спящий режим дисплея.
Пожалуйста, не изменяйте глобальные настройки пользователя без явного уведомления и согласия пользователя.
Вековой метод и способ в для предотвращения запуска заставки в Windows. Но об этой уловке, кажется, никто не помнит. Я запомнил фокус, но не название функции или параметра. Однозначно недостаточно голосов.
не работает, не повредив пользовательские настройки. (отсутствие обновления профиля делает его 100% неработающим, кажется)
Для этого есть исходный код на C++, доступный по адресу jacquelin.potier.free.fr/disablescreensaver.
Для тестирования я установил заставку на 1 минуту и потребовал пароль.
Я попытался захватить SC_SCREENSAVE и вернуть -1 в VB .Net. Как уже отмечалось, он работает, когда нет пароля заставки, но терпит неудачу, если пароль заставки активен. (Пробовал в Windows XP). Я также помещаю это в событие тика таймера каждые 1000 миллисекунд:
Static dir As Integer = 4
Cursor.Position = Cursor.Position + New Size(dir, dir)
dir = -dir
Не работает. Курсор покачивается взад и вперед, и через 1 минуту заставка на короткое время мигает, а затем гаснет. Заставка включается только на мгновение, недостаточно долго, чтобы запрашивать пароль. Но все же вспышка уродливая.
потом Я пробовал использовать SetCursorPos и GetCursorPos из user32.dll. Вы можете посмотреть их на pinvoke. Тот же результат, что и выше.
потом Я взглянул на код "JiggleMouse", упомянутый в другом месте в этом вопросе. JiggleMouse использует SendInput. SendInput работает! Не мигает заставка. Я вызываю SendInput внутри таймера, который срабатывает каждые 50 секунд (чуть меньше минимального тайм-аута заставки, равного 60 секундам). Достаточно переместить мышь с дельтой 0,0, реального движения нет. Это делает работает. Код для вставки в событие 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)))
Это пришло с сайта 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
Этот код работает? Я попытался преобразовать его в C#, но не смог заставить его работать (XP и Win7). Я не уверен, что проблема в моем переносе кода или он не работает. У кого-нибудь есть это на C#?
На всякий случай еще актуально: да, работает. Я перенес его на Delphi, и он успешно предотвратил запуск заставки в Windows 8.
Портирован на C# и успешно используется для предотвращения отключения дисплея планшета Win 8 (запущенного как устаревшее приложение). перенесенный код здесь: codejournal.blogspot.com/2014/01/…
Не могу поверить, что никто не указал на простое и очевидное решение:
#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);
}
}
Этот было предложено больше, чем на год раньше вас. Однако вместо фактического перемещения курсора мыши (как это делает ваш код) исходное решение не работает (но все еще работает). Этот ответ - плохая реализация существующего ответа.
Спасибо @myforwik за код. К сожалению, при компиляции я получаю следующую ошибку. c:\C\Project>gcc test.c -o test test.c: In function 'main': test.c:6:7: error: unknown type name 'INPUT' INPUT input; ^ test.c:7:12: error: request for member 'type' in something not a structure or union input.type = INPUT_MOUSE; ^
От MSDN:
Windows does not start the screen saver if any of the following conditions exist:
- The active application is not a Windows-based application.
- A CBT window is present.
- The active application receives the WM_SYSCOMMAND message with the wParam parameter set to the SC_SCREENSAVE value, but it does not pass the message to the DefWindowProc function.
Однако есть предостережение:
Windows Vista and later: If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification.
Кажется, это применимо, даже если вы используете SetThreadExecutionState с ES_CONTINUOUS.
Итак, если бы не предостережение, ваш выбор был бы следующим:
Последний вариант хорош тем, что работает даже с политикой защиты паролем.
Вы можете использовать SystemParametersInfo
чтобы получить SCREENSAVETIMEOUT, а затем сразу же установить для тайм-аута то же значение. Делайте это периодически по таймеру, пока хотите, чтобы заставка не срабатывала.
Это приводит к сбросу текущего таймера обратного отсчета без фактического изменения настроек системы.
Вы, вероятно, также захотите вызвать SetThreadExecutionState, чтобы повлиять на мощность, как упоминается в других ответах.
Отличная идея, но почему бы не использовать флаг SPI_SETSCREENSAVEACTIVE с той же функцией? По сути, он делает вид, что хранитель экрана работает уже, предотвращая запуск другой. По крайней мере, это использовалось десять или двенадцать лет назад.
Просто сбросьте счетчик тайм-аута с помощью
SystemParametersInfo (SPI_SETSCREENSAVEACTIVE, 1, ноль, SPIF_SENDWININICHANGE);
В Windows 7+ используйте PowerSetRequest() API управления питанием с PowerRequestDisplayRequired
https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85).aspx
В предыдущих версиях окон перехватывайте сообщение WM_SYSCOMMAND - SC_SCREENSAVE, как подробно описано в ответе Эдди Паркера.
Из Бесплатное ПО JD Design - Flipss.exe (скачать 12kb) - это утилита командной строки, которая устанавливает для вас SPI_SETSCREENSAVEACTIVE.
"FlipSS.exe -h" to see the current state.
"FlipSS.exe /on" to set the screensaver on.
"FlipSS.exe /off" to set the screensaver off.
AutoHotkey может установить SystemParametersInfo (SPI_SETSCREENSAVEACTIVE) с помощью однострочного DllCall в сценарии, чтобы легко выполнить это с помощью сценария .ahk.
Код AutoHotkey для отключения заставки:
DllCall("SystemParametersInfo", Int, 17, Int, 0, UInt, NULL, Int, 2)
Код AutoHotkey для включения заставки:
DllCall("SystemParametersInfo", Int, 17, Int, 1, UInt, NULL, Int, 2)
Справочные темы форума:
F13Key - Включение экранной заставки с помощью SystemParametersInfo
СКАН - Как временно отключить заставку
Как Адриан Маккарти упомянул из MSDN, что:
If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification.
Поэтому перехватите событие от WM_SYSCOMMAND с помощью UINT SC_SCREENSAVE и отбросьте его, вернув 0 или создав поддельное движение мыши ("mouse_event (MOUSEEVENTF_MOVE, 0, 1, 0, 0)"), не будет работать должным образом, если пользователь включил опцию хранителя экрана, защищенную паролем.
Используйте SetThreadExecutionState winAPI, чтобы сообщить операционной системе, что поток используется, даже если пользователь не взаимодействует с компьютером. Это предотвратит появление заставки и остановит автоматическую остановку машины.
Есть ряд флагов, чтобы указать новое состояние для текущего потока:
As it's a winAPI, you can call this directly in win32 or mfc application
//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);
}
}
Если кто-то хочет использовать это в C#, необходимо PInvoke это:
[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);
}
}
Согласно MSDN этот API безопасен в использовании.
The system maintains a count of applications that have called SetThreadExecutionState. The system tracks each thread that calls SetThreadExecutionState and adjusts the counter accordingly. If this counter reaches zero and there has not been any user input, the system enters sleep.
Если приложение вылетело до сброса флага, система настроится и сбросится автоматически.
... вам также нужно отключить систему / экран от перехода в спящий режим? Прошло довольно много времени с тех пор, как я действительно видел заставку на моем мониторе. (Сон кажется более вероятным.)