在 windows 中关闭显示器

Turn off the monitor in windows

我需要在代码中关闭我的显示器。我用谷歌搜索并找到了一些应该执行此操作的代码,但是当我 运行 这样做时,什么也没有发生,我只得到 0 WinAPI 结果。我做错了什么?

class Program
{
    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll")]
    private static extern IntPtr GetDesktopWindow();

    const int SC_MONITORPOWER = 0xF170;
    const int WM_SYSCOMMAND = 0x0112;
    const int MONITOR_OFF = 2;

    static void Main(string[] args)
    {
        Console.WriteLine(
            SendMessage( 
                GetDesktopWindow(), 
                WM_SYSCOMMAND, 
                (IntPtr) SC_MONITORPOWER, 
                (IntPtr) MONITOR_OFF));
        Console.WriteLine("Hello World!");
    }
}

来自Fumbling around in the dark and stumbling across the wrong solution

the desktop window is a very special window and as a rule should be avoided, since it won't behave like windows created by applications. In particular, the author tried to post a message to the desktop window. This used to work in the historically open world of the window manager, but security and robustness concerns have come to take priority over compatibility.

真正的解决方案是创建您自己的 window 并向其发送消息,其他任何方式都是 hack。

如果你不介意破解,至少尝试找到合适的 window:

[DllImport("user32.dll", SetLastError = false)]
public static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

const int SC_MONITORPOWER = 0xF170;
const int WM_SYSCOMMAND = 0x0112;
const int MONITOR_OFF = 2;

static void Main(string[] args)
{
    IntPtr w;
    for (; IntPtr.Zero == (w = GetForegroundWindow());) System.Threading.Thread.Sleep(1000);
    PostMessage(w, WM_SYSCOMMAND, (IntPtr) SC_MONITORPOWER, (IntPtr) MONITOR_OFF);
}

而且因为它是一种 hack,所以有时它可能无法正常工作。您借用的 window 可能会在您 post 消息之前被销毁。您可能无权向其发送消息 (UAC)。或者它可能决定不将此消息传递给 DefWindowProc.

另一个稍微好一点的 hack 是创建一个临时 window:

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
static extern int DestroyWindow(IntPtr hWnd);

[DllImport("user32.dll", SetLastError=true)]
public static extern IntPtr CreateWindowEx(uint dwExStyle, string lpClassName, IntPtr cap, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

const int SC_MONITORPOWER = 0xF170;
const int WM_SYSCOMMAND = 0x0112;
const int MONITOR_OFF = 2;

static void Main(string[] args)
{
    IntPtr w = CreateWindowEx(0, "Button", IntPtr.Zero, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
    if (w != IntPtr.Zero)
    {
        SendMessage(w, WM_SYSCOMMAND, (IntPtr) SC_MONITORPOWER, (IntPtr) MONITOR_OFF);
        DestroyWindow(w);
    }
}

这仍然有点像 hack,因为它从未真正发送消息。