【问题标题】:Interact with "system-wide" media player与“系统范围”的媒体播放器交互
【发布时间】:2023-04-04 14:57:01
【问题描述】:

我想开发一款适用于 Windows 10 的音乐应用,我很好奇 Groove Music 在音量栏旁边提供的界面。我试过谷歌搜索以获取有关它的更多信息,但我没有任何成功。当我在 Groove Music 中播放音乐并提高或降低音量时,当前歌曲的名称以及艺术家和专辑插图会显示在音量指示器旁边的音乐控件中:

我想知道如何在我自己的应用程序中创建此对话框,以及我必须研究哪些 Windows API。

【问题讨论】:

  • 我还在寻找一种以编程方式访问 Groove Music 中播放的歌曲信息的方法。我什么也没找到。

标签: c# windows microsoft-metro media-player windows-10


【解决方案1】:

即使@Stamos 已经给出了很好的答案,我仍将对此添加我的输入,因为我发现实际上可以从本机 Windows 应用程序中使用 SystemMediaTransportControls(不仅通用应用程序)。

首先,它仍然需要引用通用的winmd 文件,因此它只能在 Win10 上运行。它们将位于 10 sdk 中,您可以通过常规 Add Reference -> Browse 添加它们,但您可能需要将对话框右下角的过滤器更改为“所有文件”才能显示它们。它们可以在我的电脑上找到:

  • Windows.Foundation.UniversalApiContract
    C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\1.0.0.0\Windows.Foundation.UniversalApiContract.winmd
  • Windows.Foundation.FoundationContract:
    C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd

在获得必要的引用后,您将遇到另一个问题 - 您无法通过通常的 SystemMediaTransportControls.GetForCurrentView(); 访问传输控件(它会引发异常),因为您实际上没有通用视图。使用以下方法可以缓解这种情况:

SystemMediaTransportControls systemControls =
    BackgroundMediaPlayer.Current.SystemMediaTransportControls;

在此之后,您可以随意使用任何在线示例或 Stamos 的答案。

【讨论】:

    【解决方案2】:

    你需要使用SystemMediaTransportControls

    这是播放和暂停的基本设置。如果您想启用更多控件,您可以使用 ex 的可用属性。

    systemControls.IsNextEnabled = true;

    你必须在按钮开关中添加case

    case SystemMediaTransportControlsButton.Next:
                        //handle next song
                        break;
    

    xaml

    <MediaElement x:Name="mediaElement" Height="100" Width="100" AreTransportControlsEnabled="True"/>
    

    C#

    public MainPage()
    {
        this.InitializeComponent();
    
        systemControls = SystemMediaTransportControls.GetForCurrentView();
    
        // Register to handle the following system transpot control buttons.
        systemControls.ButtonPressed += SystemControls_ButtonPressed;
    
        mediaElement.CurrentStateChanged += MediaElement_CurrentStateChanged;
    
    
        systemControls.IsPlayEnabled = true;
        systemControls.IsPauseEnabled = true;
    }
    
    private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
    {
        switch (mediaElement.CurrentState)
        {
            case MediaElementState.Playing:
                systemControls.PlaybackStatus = MediaPlaybackStatus.Playing;
                break;
            case MediaElementState.Paused:
                systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
                break;
            case MediaElementState.Stopped:
                systemControls.PlaybackStatus = MediaPlaybackStatus.Stopped;
                break;
            case MediaElementState.Closed:
                systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
                break;
            default:
                break;
        }
    }
    
    
    
    void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
    {
        switch (args.Button)
        {
            case SystemMediaTransportControlsButton.Play:
                PlayMedia();
                break;
            case SystemMediaTransportControlsButton.Pause:
                PauseMedia();
                break;
            case SystemMediaTransportControlsButton.Stop:
                StopMedia();
                break;
            default:
                break;
        }
    }
    
    private async void StopMedia()
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            mediaElement.Stop();
        });
    }
    
    async void PlayMedia()
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            if (mediaElement.CurrentState == MediaElementState.Playing)
                mediaElement.Pause();
            else
                mediaElement.Play();
        });
    }
    
    async void PauseMedia()
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            mediaElement.Pause();
        });
    }
    

    输出

    此外,如果您希望所有这些都在后台运行,则必须在 Package.appxmanifest 中为后台任务声明,启用音频并添加一个入口点,如 TestUWP.MainPage

    【讨论】:

    • 很好的答案,但我确实找到了一种从本机应用程序中使用它的方法,所以我还发布了一个详细说明这个问题的答案。
    【解决方案3】:
    <MediaElement x:Name="Media"
                  AreTransportControlsEnabled="True">
        <MediaElement.TransportControls>
            <MediaTransportControls 
                Style="{StaticResource MediaTCStyle}"/>
        </MediaElement.TransportControls>
    </MediaElement>
    

    样式很大所以我附上一个链接 MediaTransportControls styles and templates 我从文章(上面的链接)中获得了样式,并在我自己的 ResourceDictionary 中对其进行了修改。

    【讨论】:

    • 对,现在正确使用的是SystemMediaTransportControls,这个答案让我明白了。仍然好奇是否有任何方法可以将其作为本机 Windows 应用程序而不是通用应用程序访问。
    • @caesay SystemMediaTransportControls 仅适用于“Metro”应用程序,@DanielFilipov TransportControls 用于 Element 本身的 MediaElements 默认控件,而不是 SystemMediaTransportControls。
    • @Stamos 我同意你的回答更清楚,但我仍然不明白为什么在其他人已经评论它有用之后你会投反对票。
    • @DanielFilipov 正如我在评论中所说,TransportControls 用于 MediaElement 默认控件,它与 SystemMediaTransportControl 不同。我投了反对票,因为它不是答案,并且与您的问题无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2022-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多