问题描述
我编写了一个 Winforms 应用程序,它通过使用 WMPLib.WindowsMediaPlayer 播放声音来为某些事件发出警报。但问题是,当系统休眠时,它不播放任何内容。
只要我按下键盘上的一些按钮,您就会看到 Windows 指纹/PIN 屏幕,如果闹钟事件处于活动状态,声音就会开始播放。
我怎样才能让它播放声音而不管系统处于睡眠状态。
在这种情况下,我是否必须用代码唤醒计算机?如果是这样,如何?
解决方法
我不确定,但您似乎可以创建一个计时器,它会在所需的时刻唤醒系统。然后你就可以像往常一样播放你的声音了。 思路如下:
- 使用
CreateWaitableTimerW
创建一个可等待的计时器 - 使用
SetWaitableTimer
将计时器设置为所需时间,传递fResume=TRUE
- 用
WaitForSingleObject
等待计时器 - 像往常一样播放您的声音。
您可以使用 SetThreadExecutionState 函数。
SetThreadExecutionState。使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入睡眠状态或关闭显示器。
- 显示屏关闭,但系统处于活动状态。
SetThreadExecutionState(ExecutionState.ES_CONTINUOUS | ExecutionState.ES_AWAYMODE_REQUIRED );
- 显示始终开启
SetThreadExecutionState(ExecutionState.ES_CONTINUOUS | ExecutionState.ES_AWAYMODE_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED);
在本例中,程序每 30 秒调用一次 SetThreadExecutionState 函数。
您可以在 https://github.com/JomaStackOverflowAnswers/PreventWmplayerStopWhenSleep
上查看/下载此代码代码
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace PreventSleep
{
public partial class FrmMain : Form
{
const int REFRESH_MILLISECONDS = 30000;//Change this value. 30000ms = 30s.
[Flags]
public enum ExecutionState : uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,ES_CONTINUOUS = 0x80000000,ES_DISPLAY_REQUIRED = 0x00000002,ES_SYSTEM_REQUIRED = 0x00000001
}
[DllImport("kernel32.dll",CharSet = CharSet.Auto,SetLastError = true)]
static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);
Stopwatch stopwatch;
private Timer timerRefresh;
public FrmMain()
{
InitializeComponent();
}
private void FrmMain_Load(object sender,EventArgs e)
{
stopwatch = new Stopwatch();
stopwatch.Start();
axWindowsMediaPlayer1.URL = Directory.GetCurrentDirectory() + "\\Music.mp3";
axWindowsMediaPlayer1.settings.setMode("loop",true);
axWindowsMediaPlayer1.Ctlcontrols.play();
axWindowsMediaPlayer1.uiMode = "none";
timerRefresh = new Timer();
timerRefresh.Enabled = true;
timerRefresh.Interval = 1000;
timerRefresh.Tick += new EventHandler(this.timerRefresh_Tick);
}
private void timerRefresh_Tick(object sender,EventArgs e)
{
if((stopwatch.ElapsedMilliseconds / REFRESH_MILLISECONDS) == 1 )
{
stopwatch.Restart();
SetThreadExecutionState(ExecutionState.ES_CONTINUOUS | ExecutionState.ES_AWAYMODE_REQUIRED ); //Display is OFF but the system is active.
//SetThreadExecutionState(ExecutionState.ES_CONTINUOUS | ExecutionState.ES_AWAYMODE_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED); //Display is allways ON.
}
}
private void FrmMain_FormClosing(object sender,FormClosingEventArgs e)
{
stopwatch.Stop();
axWindowsMediaPlayer1.Ctlcontrols.stop();
SetThreadExecutionState(ExecutionState.ES_CONTINUOUS);
}
}
}