web-dev-qa-db-ja.com

プログラムでWindowsスクリーンセーバーが起動しないようにする

Windowsスクリーンセーバーが起動しないようにするための推奨される方法はありますか?私が見つけた最も近いものは この記事 ですが、私が本当にやりたいのは、現在設定されているスクリーンセーバーの値にだまされるのではなく、コンピューターがアイドル状態ではないことをWindowsに伝えることです。

24
Michael Kelley

テストのために、スクリーンセーバーを1分に設定し、パスワードが必要でした。

SC_SCREENSAVEをキャプチャし、VB.Net。Netで-1を返してみました。コメントされているように、スクリーンセーバーのパスワードがない場合は機能しますが、スクリーンセーバーの場合は失敗しますパスワードはアクティブです(Windows XPで試しました)。また、これをタイマーのティックイベントに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は機能します!スクリーンセーバーのフラッシュはありません。 50秒ごとにトリガーされるタイマー内でSendInputを呼び出します(スクリーンセーバーの最小タイムアウトである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
10
Eyal

SystemParametersInfo

具体的には、SPI_SETSCREENSAVEACTIVEパラメータ。

これは機能しませんか?ここに見えなかったのでびっくりしました。 SetThreadExecutionStateはスクリーンセーバーにはまったく影響せず、ディスプレイのスリープだけに影響することに注意してください。

9
adzm

微妙。システムがアイドル状態ではないことをWindowsに通知する公式の方法は、SetThreadExecutionStateです。これにより、アイドルタイマーがリセットされます(または、ES_CONTINUOUSを渡すとオフになります)。ただし、SetThreadExecutionStateがアイドルタイマーをリセットしても、スクリーンセーバーは停止しません!

7
MSalters

Mouse Jiggler を使用してアイドル状態をリセットします。これは、スクリーンセーバーを開始する(そしてマシンをロックする)傾向のあるグループポリシーを回避します。長いドキュメントを読んでいるとき、複雑なコードのチャンクを勉強しているとき、または話しているとき/聞いているとき/常に入力していないときなどです。会議。

マウスが毎秒1px斜めにジャンプするのは少し面倒なので、 AutoHotKey を使用して、基本的に同じことを行うスクリプトを作成するつもりですが、設定されたキーボード/マウスのアイドルタイムアウトの後のみです。マウスを動かす代わりにShiftキー(またはScroll Lock)を使用することもできます。

6
system PAUSE

誰も簡単で明白な解決策を指摘していないとは信じられません:

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

から [〜#〜] msdn [〜#〜]

次のいずれかの条件が存在する場合、Windowsはスクリーンセーバーを起動しません。

  • アクティブなアプリケーションはWindowsベースのアプリケーションではありません。
  • CBTウィンドウが存在します。
  • アクティブなアプリケーションは、wParamパラメーターがSC_SCREENSAVE値に設定されたWM_SYSCOMMANDメッセージを受信しますが、メッセージをDefWindowProc関数に渡しません。

ただし、注意点があります。

Windows Vista以降:ポリシーによってパスワード保護が有効になっている場合、アプリケーションがSC_SCREENSAVE通知をどのように処理するかに関係なく、スクリーンセーバーが開始されます。

これは、ES_CONTINUOUSでSetThreadExecutionStateを使用する場合でも当てはまるようです。

したがって、警告がなかった場合、選択は次のようになります。

  1. ES_CONTINUOUSを使用したSetThreadExecutionState(他の回答で説明されているように)。
  2. コンピュータベースのトレーニングウィンドウ(フックが必要)を設置します。
  3. SC_SCREENSAVEを含むWM_SYSCOMMANDをDefWindowProcに渡さないでください。 (アプリケーションがアクティブなアプリケーションである場合にのみ気にすることを前提としています。)
  4. マウスのジグルをシミュレートするドングル をインストールします。

最後のオプションは、パスワード保護ポリシーでも機能するという点でニースです。

5
Adrian McCarthy

このブログ投稿 C++で何をする必要があるかを詳しく説明します。

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

}

4
Eddie Parker

Windows 7以降では、Power ManagementAPIのPowerSetRequest()PowerRequestDisplayRequiredとともに使用します

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

以前のバージョンのWindowsでは、Eddie Parkerの回答で詳しく説明されているように、WM_SYSCOMMAND-SC_SCREENSAVEメッセージをインターセプトします。

3
David Jeske

SystemParametersInfo を使用してSCREENSAVETIMEOUTを取得し、すぐにタイムアウトを同じ値に戻すことができます。スクリーンセーバーが実行されないようにする限り、タイマーで定期的にこれを実行します。

これには、実際にシステム設定を変更せずに、現在のカウントダウンタイマーをリセットする効果があります。

他の回答が述べているように、パワーに影響を与えるためにSetThreadExecutionStateを呼び出すこともできます。

2
Brett Wilson

タイムアウトカウンターをリセットするだけです

SystemParametersInfo(SPI_SETSCREENSAVEACTIVE、1、nil、SPIF_SENDWININICHANGE);

1
AGraef

AutoHotkeyは、スクリプトで1ライナーのDllCallを使用してSystemParametersInfo(SPI_SETSCREENSAVEACTIVE)を設定し、.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の切り替え
SKAN -- スクリーンセーバーを一時的に無効にする方法

0
robertcollier4

From JD Design Freeware -- Flipss.exe(download 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.
0
robertcollier4