【问题标题】:Turn off/on monitor: can't turn on [duplicate]关闭/打开显示器:无法打开[重复]
【发布时间】:2014-07-29 16:34:31
【问题描述】:

我在谷歌上找到了这个:

版本 1:

SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2); //turn off
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);  //turn on

版本 2:

HWND h = FindWindow(0, 0);
SendMessage(h, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
SendMessage(h, WM_SYSCOMMAND, SC_MONITORPOWER, -1);

在我的笔记本电脑上(Win8.1+Visual Studio 2010): 对于这两个版本,turnoff 有效,但 turnon 无效。当执行开启代码时,屏幕会立即打开然后再次关闭。

另一件有趣的事: 在我的桌面(Win8.1+VS2013),程序会卡在版本1的任一行。但是,它可以通过版本2。关闭工作,但打开完全无效。

【问题讨论】:

  • 您不应广播此消息。将其发送到有效窗口。要么自己创建,要么发送到桌面窗口。

标签: winapi


【解决方案1】:

WM_SYSCOMMANDSC_MONITOR 似乎无法唤醒显示器,因为 Windows 8 具有更高级的节能功能,而睡眠工作正常。

您也可以在核心系统级别触发一个小的鼠标移动以正确触发唤醒,C# 中的示例代码,但应该很容易移植到 C++:

void Main( object )
{
  int MOUSEEVENTF_MOVE = 0x0001;

  mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);
  System.Threading.Thread.Sleep( 40 );
  mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero);
}

Documentation。正式地,您应该使用SendInput,但mouse_event 不会很快出现(自Vista 以来它已被半弃用)。

【讨论】:

  • 非常感谢!这个对我有用。有谁知道为什么 SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);作用不同的计算机。两台计算机都运行 Win 8.1 x64 2014 更新。恐怕我的代码会卡在其他电脑上。
  • @HanchenLi 我在对你的问题的评论中提到了这一点。对于它的价值,这个答案中的代码非常糟糕。尼尔斯在没有真正理解的情况下通过从其他来源复制来发布它。但是您不应该使用此代码。睡眠很疯狂。一次调用SendInput 就足够了。
  • 不,睡眠毫无意义。 SendInput 将消息放入活动窗口的线程队列中。实际上,在 C++ 中执行此操作的正确方法是使用以下代码:INPUT input = { INPUT_MOUSE }; input.mi.dwFlags = MOUSEEVENTF_MOVE; SendInput(1, &input, sizeof(INPUT));
  • 不,SendInput 肯定不会那样工作。它在系统级别上运行,而不是在任何窗口级别上运行。系统本身处理输入队列——要么由鼠标和键盘驱动程序提供,要么由SendInputmouse_event 等旧功能提供。在解析这些并查看可用窗口的 Z 顺序之后,它会使用PostMessage 在其 GUI 线程的消息队列中向相关窗口通知更高级别的消息,例如 WM_MOUSEMOVE
  • SendInput 确实像我描述的那样工作。它不接收窗口句柄作为输入。然而,系统知道哪个窗口是活动的,以及哪个线程拥有那个窗口。然后它将输入事件放置到该线程的队列中。 Z 顺序完全无关紧要。我上面评论中的代码是执行此操作的正确方法。具有空鼠标移动的单个输入事件。不睡觉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-10
  • 2014-07-26
  • 2017-12-28
  • 2013-03-03
  • 1970-01-01
  • 2015-02-23
  • 1970-01-01
相关资源
最近更新 更多