我需要在代码中关闭显示器。 我用谷歌搜索并找到了一些应该执行此操作的代码,但是当我运行它时,什么也没有发生,我只得到 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!");
}
}
摘自Raymond Chen的文章在黑暗中摸索并偶然发现错误的解决方案:
桌面窗口是一个非常特殊的窗口并且通常应该避免,因为它的行为不像应用程序创建的窗口。特别是,作者尝试向桌面窗口发布消息。这曾经在“历史上开放的窗口管理器世界”中起作用,但安全性和稳健性问题已经优先于兼容性。
真正的解决方案是创建自己的窗口并向其发送消息,其他任何方法都是黑客。
如果你不介意黑客攻击,至少尝试找到一个合适的窗口:
[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);
}
因为它是一种黑客攻击,所以有时它可能不起作用。在您发布消息之前,您借用的窗口可能会被销毁。您可能无权向其发送消息 (UAC)。或者它可能决定不将此消息传递给
DefWindowProc
。
另一个稍微好一点的技巧是创建一个临时窗口:[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);
}
}
这仍然有点像黑客,因为它实际上从未发送消息。