在 windows 中关闭显示器
Posted
技术标签:
【中文标题】在 windows 中关闭显示器【英文标题】:Turn off the monitor in windows 【发布时间】:2021-10-26 23:18:03 【问题描述】:我需要在代码中关闭我的显示器。我用谷歌搜索并找到了一些应该这样做的代码,但是当我运行它时,什么都没有发生,我只得到一个 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!");
【问题讨论】:
如果你发送MONITOR_STANBY = 1
而不是MONITOR_OFF = 2
,你有同样的问题吗?用HWND_BROADCAST = 0xFFFF
代替GetDesktopWindow()
怎么样?
广播在这里很可怕而且是错误的。
尝试 GetShellWindow 而不是 GetDesktopWindow docs.microsoft.com/en-us/windows/win32/api/winuser/…
@SimonMourier Explorer 可能没有运行
@Anders - 当然。
【参考方案1】:
来自Fumbling around in the dark and stumbling across the wrong solution:
the desktop window is a very special window 和 通常应该避免,因为它的行为不像应用程序创建的窗口。特别是,作者试图将消息发布到桌面窗口。这曾经在 historically open world of the window manager 中工作,但安全性和稳健性问题已经优先于兼容性。
真正的解决方案是创建自己的窗口并将消息发送给它,其他任何东西都是 hack。
如果你不介意黑客攻击,至少尝试找到一个合适的窗口:
[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,所以有时它可能不起作用。您借用的窗口可能会在您发布消息之前被破坏。您可能无权向其发送消息 (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);
这仍然有点像 hack,因为它实际上从未泵送消息。
【讨论】:
实际上 - 效果很好 - 但 (-1) 上的监视器没有:( @DarrenOakey "Monitor on" 在最新版本的 Windows 上不起作用,您必须使用 SendInput/mouse_event 来伪造鼠标移动。在 *** 上搜索这个,我相信你会找到一些关于它的问题。 非常古老而简单的mouse_event
在 Windows 10 中运行良好。带有(IntPtr)(-1)
的 SendMessage 在 Windows 7 中运行。 -- 由于您使用的是 C#,因此您可以构建一个 NativeWindow,创建为,例如,class MonitorWindow : NativeWindow public MonitorWindow() var cp = new CreateParams(); CreateHandle(cp);
,而不是调用CreateWindowEx()
并添加ShutOff()
和WakeUp()
方法(这样您就可以将所有PInvoke 内容放在一个地方)。不再需要时调用其DestroyHandle()
方法。
是的 - 鼠标事件触发对我有用 - 谢谢大家!以上是关于在 windows 中关闭显示器的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中关闭键盘时,UIToolbar 不再显示在视图中