locked
Screen Saver notifications RRS feed

  • Pergunta

  •  

    I want to get notifications of various System Events in my C# app (Shut down, logoff, Session change, etc). So far I found that the SystemEvents class is very useful (http://msdn2.microsoft.com/en-us/library/microsoft.win32.systemevents_members.aspx)

     

    However it is missing the notifications for Screen Saver start and stop. I want to be notified as soon as the screen saver starts to stop a 3D animation preview in my app. And then, resume the preview when the screen saver stops.

     Does anybody have an idea to subscribe to Screen Saver events?

     

    Regards

    terça-feira, 10 de outubro de 2006 18:54

Respostas

  • Your top-level application window gets a WM_SYSCOMMAND message with WParam == SC_SCREENSAVER when the screen saver turns on.  To detect it turning off, you can poll the return value of the SystemParametersInfo() API function, asking if the screen saver is still running.  The code below demonstrates the technique, it worked well when I tried it:

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace WindowsApplication1 {
      public partial class Form1 : Form {
        private Timer mTimer;
        public Form1() {
          InitializeComponent();
        }
        // P/Invoke declarations
        private const int WM_SYSCOMMAND = 0x0112;
        private const int SC_SCREENSAVE = 0xF140;
        private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
        [DllImport("user32.dll", SetLastError=true)]
        static extern bool SystemParametersInfo(int action, int param, ref int retval, int updini);

        protected override void WndProc(ref Message m) {
          Console.WriteLine(m.ToString());
          if (m.Msg == WM_SYSCOMMAND && (m.WParam.ToInt32() & 0xfff0) == SC_SCREENSAVE) ScreenSaverActive();
          base.WndProc(ref m);
        }
        private void ScreenSaverActive() {
          // Screen saver turned on, start timer to check when it turns off
          Console.WriteLine("Screen saver active on at {0}", DateTime.Now);
          mTimer.Enabled = true;
        }
        private void mTimer_Tick(object sender, EventArgs e) {
          // Checks if the screen saver is still active
          int active = 1;
          SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref active, 0);
          if (active == 0) {
            Console.WriteLine("Screen saver off at {0}", DateTime.Now);
            mTimer.Enabled = false;
          }
        }
        private void Form1_Load(object sender, EventArgs e) {
          mTimer = new Timer();
          mTimer.Interval = 1000;
          mTimer.Tick += mTimer_Tick;
        }
      }
    }

    • Editado nobugz quarta-feira, 27 de novembro de 2013 16:27
    terça-feira, 10 de outubro de 2006 19:38

Todas as Respostas

  • Your top-level application window gets a WM_SYSCOMMAND message with WParam == SC_SCREENSAVER when the screen saver turns on.  To detect it turning off, you can poll the return value of the SystemParametersInfo() API function, asking if the screen saver is still running.  The code below demonstrates the technique, it worked well when I tried it:

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace WindowsApplication1 {
      public partial class Form1 : Form {
        private Timer mTimer;
        public Form1() {
          InitializeComponent();
        }
        // P/Invoke declarations
        private const int WM_SYSCOMMAND = 0x0112;
        private const int SC_SCREENSAVE = 0xF140;
        private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
        [DllImport("user32.dll", SetLastError=true)]
        static extern bool SystemParametersInfo(int action, int param, ref int retval, int updini);

        protected override void WndProc(ref Message m) {
          Console.WriteLine(m.ToString());
          if (m.Msg == WM_SYSCOMMAND && (m.WParam.ToInt32() & 0xfff0) == SC_SCREENSAVE) ScreenSaverActive();
          base.WndProc(ref m);
        }
        private void ScreenSaverActive() {
          // Screen saver turned on, start timer to check when it turns off
          Console.WriteLine("Screen saver active on at {0}", DateTime.Now);
          mTimer.Enabled = true;
        }
        private void mTimer_Tick(object sender, EventArgs e) {
          // Checks if the screen saver is still active
          int active = 1;
          SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref active, 0);
          if (active == 0) {
            Console.WriteLine("Screen saver off at {0}", DateTime.Now);
            mTimer.Enabled = false;
          }
        }
        private void Form1_Load(object sender, EventArgs e) {
          mTimer = new Timer();
          mTimer.Interval = 1000;
          mTimer.Tick += mTimer_Tick;
        }
      }
    }

    • Editado nobugz quarta-feira, 27 de novembro de 2013 16:27
    terça-feira, 10 de outubro de 2006 19:38
  • Thanks for the hints. It could have been great to have a system notification event for the screen off as well :)

     

    Regards

    terça-feira, 10 de outubro de 2006 19:50
  • Yes it would be nice. But you could poll if the screen saver process is running. The registry key Computer\HKEY_CURRENT_USER\Control Panel\Desktop SCRNSAVE.EXE has a path to the screen saver scr (exe) file and you could use that to detect if that process is (still) running.
    segunda-feira, 19 de outubro de 2020 09:39