C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: スクリーンセーバー起動の抑止


(過去ログ 102 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■61080 / inTopicNo.1)  スクリーンセーバー起動の抑止
  
□投稿者/ 赤星 (1回)-(2011/08/01(Mon) 15:24:39)

分類:[Windows 全般] 

みなさまこんにちわ。

とある長い処理の間、スクリーンセーバーが起動されないようにしたいです。

過去に自分で調べたことがありまして、APIのSetThreadExecutionStateを使えばよいということはわかりました。
実際、このAPIを別スレッドで数秒おきに呼び出すことで、スクリーンセーバー(電源制御も含む)は起動されませんでした。

---------------------------------------------------------
SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_CONTINUOUS);
while ( 1 ) {
SetThreadExecutionState(ES_DISPLAY_REQUIERD);
SetThreadExecutionState(ES_USER_PRESENT);
Sleep(5000);
}
---------------------------------------------------------

が、WindowsVistaがSP2になってから、この手法が有効でなくなり、一定時間後にスクリーンセーバーが起動されるようになってしまいました。

SetThreadExecutionStateのパラメータを変えることによってVistaSP2でも対応できるのか、それとも別の手段があるのか、お知恵をお貸しいただければと思います。


※ちなみにですが、現在は仕方ないので、レジストリ設定とSystemParametersInfoを使用して、長時間処理の開始前にスクリーンセーバーの設定を変更することで対応しています。
が、処理を強制終了した場合に、設定が変更されたままになってしまう(処理後の設定を戻す箇所が動かない)ので、できれば設定を変更せずに済ませたいと思っています。

引用返信 編集キー/
■61083 / inTopicNo.2)  Re[1]: スクリーンセーバー起動の抑止
□投稿者/ とっちゃん (586回)-(2011/08/01(Mon) 16:20:33)
とっちゃん さんの Web サイト
No61080 (赤星 さん) に返信
> みなさまこんにちわ。
>
使ったことがないので、何とも言えませんがMSDNライブラリにはVistaSP2でどうの。。。という記述はありませんね。

もしかしたら利用方法がダメなだけなのかも。。。

日本語のリファレンスには書いていませんが、英語のリファレンスにサンプルコードも出ています。
http://msdn.microsoft.com/en-us/library/aa373208.aspx

そちらを参考にして書き直してみてはいかがでしょう?

引用返信 編集キー/
■61089 / inTopicNo.3)  Re[2]: スクリーンセーバー起動の抑止
□投稿者/ Jitta (3回)-(2011/08/01(Mon) 21:04:29)
Jitta さんの Web サイト
 とっちゃんさんが示されている URL によると、ES_USER_PRESENT はサポートされておらず、XP 等で使用する場合は ES_CONTINUOUS と共に使用する必要がある様です。また、「ES_CONTINUOUS | ES_DISPLAY_REQUIRED」と指定すれば、定期的に SetThreadExecutionState を行う必要もなさそうです。
 なお、Remarks の最後に「This function does not stop the screen saver from executing.」と書かれています。これが、「実行中のスクリーン セーバーを止めるものではない」のか、「スクリーン セーバーが起動されることを止めるものではない」のか、判別出来ませんでした。

引用返信 編集キー/
■61091 / inTopicNo.4)  Re[3]: スクリーンセーバー起動の抑止
□投稿者/ shu (898回)-(2011/08/01(Mon) 22:10:50)
Win7 HomePre VB.NET2010Exp
以下の内容をFormに記述することで
スクリーンセーバーを抑止出来た感じでした。
マイクロソフトのサポート参照
http://support.microsoft.com/kb/403844/ja

    Protected Overrides Sub DefWndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_SYSCOMMAND As Integer = &H112
        Const SC_SCREENSAVE As Integer = &HF140

        Select Case m.Msg
            Case WM_SYSCOMMAND
                If m.WParam.ToInt32 = SC_SCREENSAVE Then
                    m.Result = New IntPtr(1)
                    Exit Sub
                End If
        End Select

        MyBase.DefWndProc(m)
    End Sub

引用返信 編集キー/
■61094 / inTopicNo.5)  Re[2]: スクリーンセーバー起動の抑止
□投稿者/ 赤星 (2回)-(2011/08/02(Tue) 08:44:01)
No61083 (とっちゃん さん) に返信

ありがとうございます。
Exsamplesにあったコードも試してみましたが、やはりVistaSP2ではダメでした。
XP SP3/VistaSPなし/VistaSP1では、今までのコードでも問題なかったんですけどね・・・

引用返信 編集キー/
■61095 / inTopicNo.6)  Re[3]: スクリーンセーバー起動の抑止
□投稿者/ 赤星 (3回)-(2011/08/02(Tue) 09:00:45)
No61089 (Jitta さん) に返信

「ES_CONTINUOUS | ES_DISPLAY_REQUIRED」の指定ですが、XP SP3で試してみました。
確かにモニタの電源は切れなくなりましたが、スクリーンセーバーに対しては有効にならないようでした。
やはり定期的に「SetThreadExecutionState(ES_DISPLAY_REQUIRED)」としないとダメなようです。


>  なお、Remarks の最後に「This function does not stop the screen saver from executing.」と書かれています。これが、「実行中のスクリーン セーバーを止めるものではない」のか、「スクリーン セーバーが起動されることを止めるものではない」のか、判別出来ませんでした。

なるほど、「スクリーン セーバーが起動されることを止めるものではない」だとすると、今までは副作用的にたまたま起動されなかっただけかもしれません。
だとすると、別の手段を考えないとダメかもしれませんね。

ありがとうございました。

引用返信 編集キー/
■61097 / inTopicNo.7)  Re[4]: スクリーンセーバー起動の抑止
□投稿者/ 赤星 (4回)-(2011/08/02(Tue) 09:19:12)
No61091 (shu さん) に返信

そういえば以前調べたときに、同じようにSC_SCREENSAVEを捕らえる方法を使ったDelphiのコードを見かけたことがありました。
その時は確か、「フォームがアクティブでないとメッセージが飛んでこない」とか書いてあったので、結局試すことなく終わってました。

SetThreadExecutionStateを使った方法が今のところうまくいかないので、こちらの手段で調査した方が可能性はありそうです。

この方法でいろいろと試してみます。
ありがとうございました。

引用返信 編集キー/
■61100 / inTopicNo.8)  Re[4]: スクリーンセーバー起動の抑止
□投稿者/ 赤星 (5回)-(2011/08/02(Tue) 11:10:29)
No61091 (shu さん) に返信

SC_SCREENSAVEをキャッチする作戦で試してみました。
やはり、フォームがアクティブでないと、メッセージが飛んでこないようです。

またフォームがアクティブでも、スクリーンセーバーのパスワード保護が有効になっていると起動されてしまいました。
(メッセージ自体は飛んできてます)

うーん、なかなか一筋縄ではいかないです・・・

引用返信 編集キー/
■61101 / inTopicNo.9)  Re[5]: スクリーンセーバー起動の抑止
□投稿者/ shu (899回)-(2011/08/02(Tue) 11:44:30)
No61100 (赤星 さん) に返信
> ■No61091 (shu さん) に返信
>
> SC_SCREENSAVEをキャッチする作戦で試してみました。
> やはり、フォームがアクティブでないと、メッセージが飛んでこないようです。
>
> またフォームがアクティブでも、スクリーンセーバーのパスワード保護が有効になっていると起動されてしまいました。
> (メッセージ自体は飛んできてます)
>
> うーん、なかなか一筋縄ではいかないです・・・

マウスを移動したことにするという方法みたいです↓
http://dora.bk.tsukuba.ac.jp/~takeuchi/index.php?%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%2F%A3%C3%A1%F4%2F%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%BB%A1%BC%A5%D0%A1%BC%B5%AF%C6%B0%A4%CE%B2%F3%C8%F2

引用返信 編集キー/
■61107 / inTopicNo.10)  Re[3]: スクリーンセーバー起動の抑止
□投稿者/ YAS (17回)-(2011/08/02(Tue) 13:20:46)
試しにと思って作ってみたのですが,Shuさんのリンク先と同じやり方でした。
でもせっかく作ったので,投稿しちゃいます。
SendInputでマウスを「その場」に動かします。実験ではスクリーンセーバーは起動しませんでした。

Imports System.Runtime.InteropServices

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Timer1.Interval = 1000
        Me.Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        SendInput.SendInput(0, 0, 0, dwFlags.MOUSEEVENTF_MOVED)
    End Sub

End Class

Public Module SendInput

    Public Enum dwFlags As Integer
        MOUSEEVENTF_MOVED = &H1
        MOUSEEVENTF_LEFTDOWN = &H2
        MOUSEEVENTF_LEFTUP = &H4
        MOUSEEVENTF_RIGHTDOWN = &H8
        MOUSEEVENTF_RIGHTUP = &H10
        MOUSEEVENTF_MIDDLEDOWN = &H20
        MOUSEEVENTF_MIDDLEUP = &H40
        MOUSEEVENTF_WHEEL = &H80
        MOUSEEVENTF_XDOWN = &H100
        MOUSEEVENTF_XUP = &H200
        MOUSEEVENTF_ABSOLUTE = &H8000
    End Enum

    Private Enum type As Integer
        INPUT_MOUSE = 0
        INPUT_KEYBOARD = 1
        INPUT_HARDWARE = 2
    End Enum

    <DllImport("user32.dll")> _
    Private Function SendInput( _
        ByVal nInputs As Integer, _
        ByRef pInputs As INPUT, _
        ByVal cbSize As Integer) _
        As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Function GetMessageExtraInfo() _
        As IntPtr
    End Function

    Public Sub SendInput(ByVal dx As Integer, ByVal dy As Integer, ByVal mouseData As Integer, ByVal Flags As Integer)
        Dim inputevents As New INPUT
        inputevents.type = type.INPUT_MOUSE
        inputevents.mi.dx = dx
        inputevents.mi.dy = dy
        inputevents.mi.mouseData = mouseData
        inputevents.mi.dwFlags = Flags
        inputevents.mi.time = 0
        inputevents.mi.dwExtraInfo = GetMessageExtraInfo()
        SendInput(1, inputevents, Marshal.SizeOf(inputevents))
    End Sub

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure INPUT
        <FieldOffset(0)> Dim type As Integer
        <FieldOffset(4)> Dim mi As MOUSEINPUT
    End Structure

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure MOUSEINPUT
        <FieldOffset(0)> Public dx As Integer
        <FieldOffset(4)> Public dy As Integer
        <FieldOffset(8)> Public mouseData As Integer
        <FieldOffset(12)> Public dwFlags As Integer
        <FieldOffset(16)> Public time As Integer
        <FieldOffset(20)> Public dwExtraInfo As IntPtr
    End Structure

End Module

引用返信 編集キー/
■61109 / inTopicNo.11)  Re[4]: スクリーンセーバー起動の抑止
□投稿者/ ツ栓柏ッ (1回)-(2011/08/02(Tue) 13:57:45)
No61101 (shu さん) に返信
No61107 (YAS さん) に返信

まとめて返信失礼します。

SendInputでバッチリうまくいきました!
以前、SetCursorPosを使ったときはダメだったのですが、SendInputだとうまくいくのですね。
ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -