如何在Qt应用中读取并控制Windows当前播放的媒体信息?
实现Windows端Qt媒体控制小部件的方案
核心依赖:Windows Media Session API
Windows 10及以上系统提供的Media Session API(WinRT组件)是实现系统级媒体控制的关键,它能让Qt应用和系统媒体传输控件(SMTC)交互,获取媒体信息、控制播放状态、读取专辑封面等,和锁屏显示的媒体控制逻辑同源。
具体实现步骤
1. 配置Qt项目支持WinRT
在Qt项目的.pro文件中添加以下配置,确保能调用WinRT相关API:
QT += core gui widgets CONFIG += c++17 win32 { CONFIG += windows LIBS += -lole32 -loleaut32 -lshlwapi # 引入WinRT头文件路径 INCLUDEPATH += $$(WindowsSdkDir)Include/$$(WindowsSDKVersion)/winrt }
2. 封装WinRT媒体控制逻辑
C++调用WinRT需先初始化运行环境,再通过MediaSessionManager获取当前活跃媒体会话,核心操作代码示例如下:
#include <winrt/Windows.Media.Control.h> #include <winrt/Windows.Foundation.h> #include <winrt/Windows.Storage.Streams.h> using namespace winrt; using namespace Windows::Media::Control; using namespace Windows::Foundation; using namespace Windows::Storage::Streams; // 初始化WinRT环境 void initWinRT() { winrt::init_apartment(); } // 获取当前活跃的媒体会话 GlobalSystemMediaTransportControlsSession getActiveSession() { auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get(); return manager.GetCurrentSession(); } // 读取媒体元数据(歌曲名、艺术家、专辑、封面) void getMediaMetadata(GlobalSystemMediaTransportControlsSession session) { auto props = session.TryGetMediaPropertiesAsync().get(); if (!props) return; hstring title = props.Title(); hstring artist = props.Artist(); hstring album = props.AlbumTitle(); // 处理专辑封面:将WinRT流转换为Qt图像 auto thumbnail = props.Thumbnail(); if (thumbnail) { DataReader reader(thumbnail.GetInputStreamAt(0)); reader.LoadAsync(thumbnail.Size()).get(); Buffer buffer(thumbnail.Size()); reader.ReadBuffer(buffer); QByteArray imgData(buffer.data(), buffer.Length()); QImage cover = QImage::fromData(imgData); // 后续可将cover设置到QLabel显示 } } // 播放/暂停控制 void togglePlayback(GlobalSystemMediaTransportControlsSession session) { auto controls = session.GetControls(); if (controls.IsPlayEnabled()) { session.TryPlayAsync().get(); } else if (controls.IsPauseEnabled()) { session.TryPauseAsync().get(); } } // 切换曲目 void skipToPrevious(GlobalSystemMediaTransportControlsSession session) { session.TrySkipPreviousAsync().get(); } void skipToNext(GlobalSystemMediaTransportControlsSession session) { session.TrySkipNextAsync().get(); } // 获取播放进度 void getPlaybackProgress(GlobalSystemMediaTransportControlsSession session, qint64& posMs, qint64& durationMs) { auto timelineProps = session.GetTimelineProperties(); posMs = timelineProps.Position().count() / 10000; // WinRT时间单位为100纳秒,转毫秒 durationMs = timelineProps.EndTime().count() / 10000; } // 设置播放进度 void setPlaybackProgress(GlobalSystemMediaTransportControlsSession session, qint64 posMs) { TimeSpan targetPos; targetPos.count(posMs * 10000); // 转回100纳秒单位 session.TryChangePlaybackPositionAsync(targetPos).get(); }
3. Qt界面集成
- 用
QLabel展示歌曲名、艺术家信息和专辑封面 - 用
QPushButton绑定播放/暂停、上一曲/下一曲的控制逻辑 - 用
QSlider实现进度拖动,绑定sliderReleased信号调用setPlaybackProgress - 定时(如1秒)调用
getPlaybackProgress更新滑块位置,同时刷新媒体元数据
4. 监听媒体会话切换
通过CurrentSessionChanged事件捕获活跃媒体会话的切换,及时更新界面内容:
void setupSessionListener() { auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get(); manager.CurrentSessionChanged([this](auto&&, auto&&) { auto newSession = manager.GetCurrentSession(); getMediaMetadata(newSession); // 同步播放状态和进度 }); }
注意事项
- 仅支持Windows 10 1507及以上版本(WinRT API最低兼容版本)
- WinRT异步操作需用
.get()等待完成,或结合Qt的QFuture封装异步逻辑 - 部分媒体应用可能限制外部控制权限,需确保目标应用支持SMTC交互
内容的提问来源于stack exchange,提问作者Tianming
相关产品推荐
相关产品推荐

