我正在编写一个应用程序,有时会以烤面包机消息的形式向用户发送通知.
如果用户不在,他看不到通知.所以我想做的是能够检查用户是否已锁定屏幕或是否正在激活屏幕保护程序.
当用户重新登录并恢复其会话时,在用户看不到它时触发的任何通知都将被延迟并显示.
我自己在Windows 7上,但我更喜欢一种适用于Windows XP及以上版本的解决方案.
我最近从之前的博客文章中再次检查了此代码,以确保它适用于Windows XP到7,x86和x64的版本,并对其进行了一些清理.
这是最新的极简主义代码,它检查工作站是否被锁定,以及屏幕保护程序是否运行包装在两个易于使用的静态方法中:
using System;
using System.Runtime.InteropServices;
namespace BrutalDev.Helpers
{
public static class NativeMethods
{
// Used to check if the screen saver is running
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uAction,
uint uParam,
ref bool lpvParam,
int fWinIni);
// Used to check if the workstation is locked
[DllImport("user32", SetLastError = true)]
private static extern IntPtr OpenDesktop(string lpszDesktop,
uint dwFlags,
bool fInherit,
uint dwDesiredAccess);
[DllImport("user32", SetLastError = true)]
private static extern IntPtr OpenInputDesktop(uint dwFlags,
bool fInherit,
uint dwDesiredAccess);
[DllImport("user32", SetLastError = true)]
private static extern IntPtr CloseDesktop(IntPtr hDesktop);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SwitchDesktop(IntPtr hDesktop);
// Check if the workstation has been locked.
public static bool IsWorkstationLocked()
{
const int DESKTOP_SWITCHDESKTOP = 256;
IntPtr hwnd = OpenInputDesktop(0, false, DESKTOP_SWITCHDESKTOP);
if (hwnd == IntPtr.Zero)
{
// Could not get the input desktop, might be locked already?
hwnd = OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP);
}
// Can we switch the desktop?
if (hwnd != IntPtr.Zero)
{
if (SwitchDesktop(hwnd))
{
// Workstation is NOT LOCKED.
CloseDesktop(hwnd);
}
else
{
CloseDesktop(hwnd);
// Workstation is LOCKED.
return true;
}
}
return false;
}
// Check if the screensaver is busy running.
public static bool IsScreensaverRunning()
{
const int SPI_GETSCREENSAVERRUNNING = 114;
bool isRunning = false;
if (!SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0))
{
// Could not detect screen saver status...
return false;
}
if (isRunning)
{
// Screen saver is ON.
return true;
}
// Screen saver is OFF.
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新:根据评论中的建议更新代码.
当工作站被锁定时,OpenInputDesktop方法不会返回句柄,因此我们可以在OpenDesktop上回退一个句柄,以确保通过尝试切换来锁定它.如果未锁定,则不会激活默认桌面,因为OpenInputDesktop将返回您正在查看的桌面的有效句柄.