Подтвердить что ты не робот

Программно предотвратить запуск заставки Windows

Есть ли рекомендуемый способ предотвратить запуск заставки Windows? Самое близкое, что я нашел, это в этой статье, но мне бы очень хотелось просто сказать Windows, что компьютер не праздный а не обманывать текущие установленные значения заставки.

4b9b3361

Ответ 1

Для тестирования я установил заставку на 1 минуту и ​​потребовал пароль.

Я попытался захватить SC_SCREENSAVE и вернуть -1 в VB.Net. Как отмечалось, он работает, когда нет пароля заставки, но не удается, если активен пароль заставки. (Я попробовал это в Windows XP). Я также помещал это в событие Timer tick, каждые 1000 миллисекунд:

Static dir As Integer = 4
Cursor.Position = Cursor.Position + New Size(dir, dir)
dir = -dir

Это не работает. Курсор перемещается вперед и назад, и через 1 минуту скринсейвер мигает на короткий экземпляр и затем выключается. Заставка включается только на мгновение, недостаточно долго, чтобы требовать пароль. Но тем не менее, вспышка уродливая.

Затем я попытался использовать user32.dll SetCursorPos и ​​GetCursorPos. Вы можете посмотреть их на 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

Ответ 2

SystemParametersInfo

В частности, параметр SPI_SETSCREENSAVEACTIVE.

Не работает ли это? Я был удивлен, что я не видел его здесь. Обратите внимание, что SetThreadExecutionState вообще не влияет на экранную заставку, просто на спящем дисплее.

Ответ 3

Тонкое. Официальным способом сказать Windows, что система не праздна, является SetThreadExecutionState. Это сбрасывает таймер простоя (или отключает его, если вы проходите ES_CONTINUOUS). Однако, даже если SetThreadExecutionState сбрасывает таймер простоя, он не останавливает скринсейвер!

Ответ 4

Я использую Mouse Jiggler для reset состояния бездействия. Это связано с групповой политикой, которая, как правило, запускает мою заставку (и блокирует ее) в неподходящие моменты: когда я читаю длинный документ, изучая сложный фрагмент кода или разговаривая/слушаю/не постоянно печатаю во время встречи.

Как можно немного раздражать, чтобы каждый раз прыгать мышь 1px по диагонали, я намерен использовать AutoHotKey для записи script, что делает в основном то же самое, но только после настроенного тайм-аута клавиатуры/мыши и, возможно, вместо нажатия мыши можно использовать клавишу Shift (или Scroll Lock).

Ответ 5

Этот пост в блоге подробно описывает, что вам нужно сделать на С++.

Фактический фрагмент кода с веб-сайта:

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

}

Ответ 6

@Эйял - эй, спасибо за идею; мне никогда не приходило в голову, что дельта 0,0 может работать. Я добавил эту опцию как "джигль дзэн" на 1.2 (оставляя оригинал также, для тех людей, которые нервничают, когда они не могут видеть, как он работает).

Ответ 7

Не могу поверить, что никто не указал на простое и очевидное решение:

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

Ответ 8

Из MSDN:

Windows не запускает экранную заставку, если существует одно из следующих условий:

  • Активное приложение не является приложением на базе Windows.
  • Имеется окно CBT.
  • Активное приложение получает сообщение WM_SYSCOMMAND с параметром wParam, установленным в значение SC_SCREENSAVE, но оно не передает сообщение функции DefWindowProc.

Там есть оговорка:

Windows Vista и более поздняя версия: если защита паролем включена политикой, заставка запускается независимо от того, что приложение делает с уведомлением SC_SCREENSAVE.

Это похоже, даже если вы используете SetThreadExecutionState с ES_CONTINUOUS.

Итак, если бы не оговорка, ваши варианты были бы следующими:

  • SetThreadExecutionState с ES_CONTINUOUS (как описано в других ответах).
  • Создайте компьютерное учебное окно (для которого требуются перехватчики).
  • Не допускайте передачи WM_SYSCOMMAND с SC_SCREENSAVE в DefWindowProc. (Предполагая, что вы заботитесь только тогда, когда ваше приложение является активным приложением.)
  • Установите ключ, который имитирует дрожание мыши.

Последний вариант хорош тем, что он работает даже с политикой защиты паролем.

Ответ 10

Вы можете использовать SystemParametersInfo для получения SCREENSAVETIMEOUT, а затем сразу же установите тайм-аут на то же значение. Выполняйте это периодически на таймере до тех пор, пока вы не хотите, чтобы экранная заставка продолжалась.

Это приводит к сбросу текущего таймера обратного отсчета без фактического изменения настроек системы.

Вероятно, вы также хотите вызвать SetThreadExecutionState, чтобы повлиять на мощность, как упоминают другие ответы.

Ответ 11

Просто reset счетчик тайм-аута с

SystemParametersInfo (SPI_SETSCREENSAVEACTIVE, 1, nil, SPIF_SENDWININICHANGE);

Ответ 12

В Windows 7+ используйте API управления питанием PowerSetRequest() с PowerRequestDisplayRequired

https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85).aspx

В предыдущих версиях Windows перехватите сообщение WM_SYSCOMMAND - SC_SCREENSAVE, как описано в ответе Эдди Паркера.