Программно предотвратить запуск заставки Windows - PullRequest
24 голосов
/ 21 января 2009

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

Ответы [ 10 ]

10 голосов
/ 04 ноября 2009

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

Я попытался перехватить SC_SCREENSAVE и вернуть -1 в VB .Net. Как уже отмечалось, он работает, когда нет пароля заставки, но не удается , если активен пароль заставки. (Я попробовал это в Windows XP). Я также помещаю это в событие тика Timer, каждые 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
8 голосов
/ 12 октября 2009

SystemParametersInfo

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

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

7 голосов
/ 23 января 2009

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

6 голосов
/ 17 сентября 2009

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

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

5 голосов
/ 15 августа 2011

С MSDN :

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

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

Есть предостережение:

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

Это, кажется, применимо, даже если вы используете SetThreadExecutionState с ES_CONTINUOUS.

Итак, если бы не оговорка, ваш выбор был бы:

  1. SetThreadExecutionState с ES_CONTINUOUS (как описано в других ответах).
  2. Откройте окно обучения на компьютере (для этого требуются хуки).
  3. Не позволяйте WM_SYSCOMMAND с SC_SCREENSAVE передаваться в DefWindowProc. (Если вы заботитесь только о том, когда ваше приложение является активным приложением.)
  4. Установите ключ, имитирующий колебание мыши .

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

5 голосов
/ 14 января 2011

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

#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);
   }
}
4 голосов
/ 21 января 2009

В этом блоге подробно рассказывается, что вам нужно делать в 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);

}

3 голосов
/ 21 июня 2017

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

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

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

2 голосов
/ 18 апреля 2012

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

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

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

1 голос
/ 12 августа 2013

Просто сбросьте счетчик тайм-аута с помощью

SystemParametersInfo (SPI_SETSCREENSAVEACTIVE, 1, ноль, SPIF_SENDWININICHANGE);

...