在运行Windows 8时,使用SendMessage/SC_MONITORPOWER无法打开显示器

18

我使用以下代码来打开和关闭我的监视器:

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

private const int WM_SYSCOMMAND = 0x0112;
private const int SC_MONITORPOWER = 0xF170;
private const int MonitorTurnOn = -1;
private const int MonitorShutoff = 2;

//Turn them off
SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)MonitorShutoff);

//Turn them on
SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)MonitorTurnOn);

这个代码之前是可以正常工作的,但在安装Windows 8后 (我认为这是原因,因为我看到其他人也有同样的问题),打开屏幕就无法正常工作。我仍然可以关闭它,但无论我运行多少次带有MonitorTurnOn的SendMessage()函数,我仍然需要移动鼠标或按键才能重新打开显示器。

有没有关于如何在Windows 8上使其正常工作的建议?


是否可以关闭特定的显示器? - Dor
据我所知,没有。 - Erlend D.
4个回答

16

我有过同样的问题,我找到的解决方法是移动鼠标:

mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, NULL);
Sleep(40);
mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, NULL);

它会唤醒显示器。 Earlypearl


1
谢谢,虽然这不是一个完美的解决方案,但似乎能够工作。我没有权限编辑您的答案以包含 DllImport 和常量,所以我在下面自己添加了一个。 - Erlend D.
10
这里不需要任何的“Sleep”。只需进行一次增量为0,0的移动即可。 - David Heffernan
为什么在两个动作之间要使用延迟?我尝试过不用,也能正常工作。而且为什么恰好是40毫秒? - Martin

8
以下是Earlypearl的回答和所需内容:

这里是Earlypearl的回答,需要包含以下内容:

[DllImport("user32.dll")]
static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);

private const int MOUSEEVENTF_MOVE = 0x0001;

private void Wake(){
    mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);
    Sleep(40);
    mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero);
}

虽然这个问题标记为C#,但有些人可能也在寻找在.bat文件、PowerShell脚本或任务计划程序操作中执行此操作的方法,在这种情况下,此答案https://superuser.com/a/1371383提供了一种解决方案。在.bat文件中,此行将把鼠标向右移动40个像素:`powershell (Add-Type '[DllImport("user32.dll")]^public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, int dwExtraInfo);' -Name user32 -PassThru)::mouse_event(1,40,0,0,0)`。 - Doin

2

我对这个问题有相同的想法。只是稍微修改了 dear earlypearl 的解决方案,并在 Windows XP、7、8、Server 2008 上进行了测试,所有都完美地工作了。

mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);

不需要调用两次。


虽然只需要一次移动就可以打开显示器,但应该通过向另一个方向的移动来撤销它,因为用户可能在之前将光标定位在特定的GUI元素上,而盲目点击其他位置可能会导致意外操作。如果有多次触发移动的机会,这尤其正确。 - Martin

0
我发现了一个在Windows 8.1上运行的技巧。
关闭它们。
SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)MonitorShutoff);

打开它们

SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)1);

根据MSN的说法,“1”是将监视器切换到“低功耗”模式,但这样做可以解决问题。屏幕将不再自动关闭。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接