Como invocar a proteção de tela no Windows em C #?
-
06-09-2019 - |
Pergunta
Eu gostaria de invocar o protetor de tela do usuário se tal for definida, em um ambiente Windows.
Eu sei que isso pode ser feito usando puro código C ++ (e, em seguida, a embalagem em C # é bastante simples), como sugerido aqui .
Ainda assim, para a curiosidade, eu gostaria de saber se tal tarefa pode ser realizada por código puramente gerenciados usando o Dot Net Framework (versão 2.0 e superior), sem p / invocar e sem visitar o C lado ++ (que, em por sua vez, pode usar o Windows API muito facilmente).
Solução
Eu tenho uma idéia, eu não tenho certeza de como consistentemente isso iria funcionar, então você precisa pesquisar um pouco eu acho, mas espero que seja o suficiente para você começar.
Um protetor de tela é apenas um executável, e as lojas de registro a localização deste executável em HKCU\Control Panel\Desktop\SCRNSAVE.EXE
Em minha cópia do Vista, isso funcionou para mim:
RegistryKey screenSaverKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop");
if (screenSaverKey != null)
{
string screenSaverFilePath = screenSaverKey.GetValue("SCRNSAVE.EXE", string.Empty).ToString();
if (!string.IsNullOrEmpty(screenSaverFilePath) && File.Exists(screenSaverFilePath))
{
Process screenSaverProcess = Process.Start(new ProcessStartInfo(screenSaverFilePath, "/s")); // "/s" for full-screen mode
screenSaverProcess.WaitForExit(); // Wait for the screensaver to be dismissed by the user
}
}
Outras dicas
Eu acho que ter uma função de biblioteca Net que faz isso é altamente improvável - Eu não estou ciente de qualquer. Uma rápida pesquisa retornou este projeto de código tutorial que contém um exemplo de um wrapper gerenciado que você mencionou na sua pergunta.
P / invoke existe para que você esteja recursos específicos do OS acessar, dos quais protetores de tela são um exemplo.
Eu não tenho certeza que você pode usar completamente o código gerenciado para fazer isso.
Este usa o Windows API, mas ainda é muito simples: Lançamento Sistema Screensaver de C # Windows Form
Trabalho em qualquer versão do windows ...
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace HQ.Util.Unmanaged
{
public class ScreenSaverHelper
{
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
private static extern IntPtr GetDesktopWindow();
// Signatures for unmanaged calls
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags);
// Constants
private const int SPI_GETSCREENSAVERACTIVE = 16;
private const int SPI_SETSCREENSAVERACTIVE = 17;
private const int SPI_GETSCREENSAVERTIMEOUT = 14;
private const int SPI_SETSCREENSAVERTIMEOUT = 15;
private const int SPI_GETSCREENSAVERRUNNING = 114;
private const int SPIF_SENDWININICHANGE = 2;
private const uint DESKTOP_WRITEOBJECTS = 0x0080;
private const uint DESKTOP_READOBJECTS = 0x0001;
private const int WM_CLOSE = 16;
public const uint WM_SYSCOMMAND = 0x112;
public const uint SC_SCREENSAVE = 0xF140;
public enum SpecialHandles
{
HWND_DESKTOP = 0x0,
HWND_BROADCAST = 0xFFFF
}
public static void TurnScreenSaver(bool turnOn = true)
{
// Does not work on Windows 7
// int nullVar = 0;
// SystemParametersInfo(SPI_SETSCREENSAVERACTIVE, 1, ref nullVar, SPIF_SENDWININICHANGE);
// Does not work on Windows 7, can't broadcast. Also not needed.
// SendMessage(new IntPtr((int) SpecialHandles.HWND_BROADCAST), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, (IntPtr)SC_SCREENSAVE, (IntPtr)0);
}
}
}