如何防止 WMPLib.WindowsMediaPlayer 在计算机休眠时停止播放音乐?

问题描述

我编写了一个 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);
        }
    }
}

我的设置 enter image description here