C#基础(②音乐播发器MCI(Media Control Interface))

发布于:2025-09-01 ⋅ 阅读:(36) ⋅ 点赞:(0)

winmm.dll 是 Windows 操作系统中一个重要的动态链接库(DLL)文件,全称为 Windows Multimedia Library(Windows 多媒体库)。它包含了一系列用于处理多媒体相关功能的函数,是 Windows 系统实现音频、视频等多媒体操作的核心组件之一。

核心函数:mciSendString

[DllImport("winmm.dll")]
private static extern long mciSendString(
    string command,       // 要执行的MCI命令(字符串)
    StringBuilder returnValue,  // 存储返回结果的缓冲区
    int returnLength,     // 缓冲区长度
    IntPtr winHandle      // 窗口句柄(通常传IntPtr.Zero)
);

常用 MCI 命令及用法

1. 打开媒体文件

// 格式:open "文件路径" type 类型 alias 别名
// 作用:加载媒体文件并给它起一个别名(方便后续操作)
SendMCICommand("open \"C:\\music.mp3\" type mpegvideo alias MediaFile");

type mpegvideo:指定媒体类型(音频通常用 mpegvideo 或 waveaudio)
alias MediaFile:给文件起个别名 “MediaFile”,后续命令用别名操作,无需重复写路径

2. 播放 / 暂停 / 继续 / 停止

// 播放(从当前位置开始)
SendMCICommand("play MediaFile");

// 暂停
SendMCICommand("pause MediaFile");

// 继续(从暂停处恢复)
SendMCICommand("resume MediaFile");

// 停止并回到开头
SendMCICommand("stop MediaFile");
SendMCICommand("seek MediaFile to start"); // 定位到开始位置

3. 调整音量

// 格式:setaudio 别名 volume to 音量值(范围0-1000)
SendMCICommand("setaudio MediaFile volume to 500"); // 50%音量

注意:MCI 音量范围是 0-1000,代码中通过 currentVolume * 10 转换(0-100 → 0-1000)

4. 获取媒体信息(需接收返回值)

// 获取当前播放位置(毫秒)
string position = GetMCIString("status MediaFile position");

// 获取媒体总长度(毫秒)
string length = GetMCIString("status MediaFile length");

// 获取播放状态(playing/paused/stopped)
string status = GetMCIString("status MediaFile mode");

5. 定位播放位置

// 格式:seek 别名 to 位置(毫秒)
SendMCICommand("seek MediaFile to 10000"); // 定位到10秒位置(10000毫秒)

6. 关闭媒体文件

// 关闭单个文件(通过别名)
SendMCICommand("close MediaFile");

// 关闭所有打开的媒体文件
SendMCICommand("close all");

完整代码

Form1.Designer.cs

namespace music
{
    partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.btnPlay = new System.Windows.Forms.Button();
            this.btnPause = new System.Windows.Forms.Button();
            this.btnStop = new System.Windows.Forms.Button();
            this.btnAdd = new System.Windows.Forms.Button();
            this.btnPrev = new System.Windows.Forms.Button();
            this.btnNext = new System.Windows.Forms.Button();
            this.listBoxMusic = new System.Windows.Forms.ListBox();
            this.trackBarProgress = new System.Windows.Forms.TrackBar();
            this.trackBarVolume = new System.Windows.Forms.TrackBar();
            this.lblCurrentSong = new System.Windows.Forms.Label();
            this.lblTime = new System.Windows.Forms.Label();
            this.timerProgress = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            // 
            // btnPlay
            // 
            this.btnPlay.Location = new System.Drawing.Point(106, 347);
            this.btnPlay.Name = "btnPlay";
            this.btnPlay.Size = new System.Drawing.Size(75, 23);
            this.btnPlay.TabIndex = 0;
            this.btnPlay.Text = "播放";
            this.btnPlay.UseVisualStyleBackColor = true;
            // 
            // btnPause
            // 
            this.btnPause.Location = new System.Drawing.Point(297, 347);
            this.btnPause.Name = "btnPause";
            this.btnPause.Size = new System.Drawing.Size(75, 23);
            this.btnPause.TabIndex = 1;
            this.btnPause.Text = "暂停";
            this.btnPause.UseVisualStyleBackColor = true;
            // 
            // btnStop
            // 
            this.btnStop.Location = new System.Drawing.Point(500, 381);
            this.btnStop.Name = "btnStop";
            this.btnStop.Size = new System.Drawing.Size(75, 23);
            this.btnStop.TabIndex = 2;
            this.btnStop.Text = "停止";
            this.btnStop.UseVisualStyleBackColor = true;
            this.btnStop.Click += new System.EventHandler(this.button3_Click);
            // 
            // btnAdd
            // 
            this.btnAdd.Location = new System.Drawing.Point(679, 380);
            this.btnAdd.Name = "btnAdd";
            this.btnAdd.Size = new System.Drawing.Size(75, 23);
            this.btnAdd.TabIndex = 3;
            this.btnAdd.Text = "添加音乐";
            this.btnAdd.UseVisualStyleBackColor = true;
            // 
            // btnPrev
            // 
            this.btnPrev.Location = new System.Drawing.Point(859, 380);
            this.btnPrev.Name = "btnPrev";
            this.btnPrev.Size = new System.Drawing.Size(75, 23);
            this.btnPrev.TabIndex = 4;
            this.btnPrev.Text = "上一首";
            this.btnPrev.UseVisualStyleBackColor = true;
            // 
            // btnNext
            // 
            this.btnNext.Location = new System.Drawing.Point(1051, 393);
            this.btnNext.Name = "btnNext";
            this.btnNext.Size = new System.Drawing.Size(75, 23);
            this.btnNext.TabIndex = 5;
            this.btnNext.Text = "下一首";
            this.btnNext.UseVisualStyleBackColor = true;
            // 
            // listBoxMusic
            // 
            this.listBoxMusic.FormattingEnabled = true;
            this.listBoxMusic.ItemHeight = 15;
            this.listBoxMusic.Location = new System.Drawing.Point(542, 115);
            this.listBoxMusic.Name = "listBoxMusic";
            this.listBoxMusic.Size = new System.Drawing.Size(510, 214);
            this.listBoxMusic.TabIndex = 6;
            // 
            // trackBarProgress
            // 
            this.trackBarProgress.Location = new System.Drawing.Point(223, 48);
            this.trackBarProgress.Name = "trackBarProgress";
            this.trackBarProgress.Size = new System.Drawing.Size(427, 56);
            this.trackBarProgress.TabIndex = 7;
            // 
            // trackBarVolume
            // 
            this.trackBarVolume.Location = new System.Drawing.Point(816, 48);
            this.trackBarVolume.Name = "trackBarVolume";
            this.trackBarVolume.Size = new System.Drawing.Size(276, 56);
            this.trackBarVolume.TabIndex = 8;
            // 
            // lblCurrentSong
            // 
            this.lblCurrentSong.AutoSize = true;
            this.lblCurrentSong.Location = new System.Drawing.Point(172, 199);
            this.lblCurrentSong.Name = "lblCurrentSong";
            this.lblCurrentSong.Size = new System.Drawing.Size(52, 15);
            this.lblCurrentSong.TabIndex = 9;
            this.lblCurrentSong.Text = "歌曲名";
            // 
            // lblTime
            // 
            this.lblTime.AutoSize = true;
            this.lblTime.Location = new System.Drawing.Point(278, 264);
            this.lblTime.Name = "lblTime";
            this.lblTime.Size = new System.Drawing.Size(67, 15);
            this.lblTime.TabIndex = 10;
            this.lblTime.Text = "播放时间";
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1274, 541);
            this.Controls.Add(this.lblTime);
            this.Controls.Add(this.lblCurrentSong);
            this.Controls.Add(this.trackBarVolume);
            this.Controls.Add(this.trackBarProgress);
            this.Controls.Add(this.listBoxMusic);
            this.Controls.Add(this.btnNext);
            this.Controls.Add(this.btnPrev);
            this.Controls.Add(this.btnAdd);
            this.Controls.Add(this.btnStop);
            this.Controls.Add(this.btnPause);
            this.Controls.Add(this.btnPlay);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            ((System.ComponentModel.ISupportInitialize)(this.trackBarProgress)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button btnPlay;
        private System.Windows.Forms.Button btnPause;
        private System.Windows.Forms.Button btnStop;
        private System.Windows.Forms.Button btnAdd;
        private System.Windows.Forms.Button btnPrev;
        private System.Windows.Forms.Button btnNext;
        private System.Windows.Forms.ListBox listBoxMusic;
        private System.Windows.Forms.TrackBar trackBarProgress;
        private System.Windows.Forms.TrackBar trackBarVolume;
        private System.Windows.Forms.Label lblCurrentSong;
        private System.Windows.Forms.Label lblTime;
        private System.Windows.Forms.Timer timerProgress;
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace music
{
    public partial class Form1 : Form
    {
        // MCI API 声明
        [DllImport("winmm.dll")]
        private static extern long mciSendString(string command, StringBuilder returnValue, int returnLength, IntPtr winHandle);

        private List<string> playlist;
        private int currentSongIndex = -1;
        private bool isDragging = false;
        private bool isPlaying = false;
        private bool isPaused = false;
        private int songLength = 0;
        private int currentVolume = 50;

        public Form1()
        {
            InitializeComponent();
            playlist = new List<string>();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 初始化界面
            trackBarVolume.Maximum = 100;
            trackBarVolume.Minimum = 0;
            trackBarVolume.Value = 50;
            currentVolume = 50;
            
            trackBarProgress.Maximum = 1000;
            trackBarProgress.Minimum = 0;
            trackBarProgress.Value = 0;
            
            lblCurrentSong.Text = "未选择歌曲";
            lblTime.Text = "00:00 / 00:00";
            
            // 绑定事件
            btnPlay.Click += BtnPlay_Click;
            btnPause.Click += BtnPause_Click;
            btnStop.Click += BtnStop_Click;
            btnAdd.Click += BtnAdd_Click;
            btnPrev.Click += BtnPrev_Click;
            btnNext.Click += BtnNext_Click;
            
            listBoxMusic.SelectedIndexChanged += ListBoxMusic_SelectedIndexChanged;
            trackBarVolume.Scroll += TrackBarVolume_Scroll;
            trackBarProgress.MouseDown += TrackBarProgress_MouseDown;
            trackBarProgress.MouseUp += TrackBarProgress_MouseUp;
            trackBarProgress.Scroll += TrackBarProgress_Scroll;
            
            timerProgress.Interval = 1000;
            timerProgress.Tick += TimerProgress_Tick;
            timerProgress.Start();
        }

        // MCI 帮助方法
        private void SendMCICommand(string command)
        {
            mciSendString(command, null, 0, IntPtr.Zero);
        }

        private string GetMCIString(string command)
        {
            StringBuilder buffer = new StringBuilder(128);
            mciSendString(command, buffer, 128, IntPtr.Zero);
            return buffer.ToString();
        }

        private void LoadSong(string filePath)
        {
            try
            {
                SendMCICommand("close all");
                SendMCICommand($"open \"{filePath}\" type mpegvideo alias MediaFile");
                
                // 获取歌曲长度
                string lengthStr = GetMCIString("status MediaFile length");
                if (int.TryParse(lengthStr, out songLength))
                {
                    // MCI返回的时间单位是毫秒
                    songLength = songLength / 1000; // 转换为秒
                }
                
                // 设置音量
                SendMCICommand($"setaudio MediaFile volume to {currentVolume * 10}");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载音乐文件失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void BtnPlay_Click(object sender, EventArgs e)
        {
            if (currentSongIndex >= 0 && currentSongIndex < playlist.Count)
            {
                if (isPaused)
                {
                    SendMCICommand("resume MediaFile");
                    isPaused = false;
                    isPlaying = true;
                }
                else if (!isPlaying)
                {
                    LoadSong(playlist[currentSongIndex]);
                    SendMCICommand("play MediaFile");
                    isPlaying = true;
                    isPaused = false;
                    UpdateCurrentSongDisplay();
                }
            }
            else if (playlist.Count > 0)
            {
                currentSongIndex = 0;
                listBoxMusic.SelectedIndex = 0;
                LoadSong(playlist[currentSongIndex]);
                SendMCICommand("play MediaFile");
                isPlaying = true;
                isPaused = false;
                UpdateCurrentSongDisplay();
            }
        }

        private void BtnPause_Click(object sender, EventArgs e)
        {
            if (isPlaying && !isPaused)
            {
                SendMCICommand("pause MediaFile");
                isPaused = true;
            }
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            SendMCICommand("stop MediaFile");
            SendMCICommand("seek MediaFile to start");
            isPlaying = false;
            isPaused = false;
            trackBarProgress.Value = 0;
            lblTime.Text = "00:00 / 00:00";
        }

        private void BtnAdd_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "音乐文件|*.mp3;*.wav;*.wma;*.flac;*.m4a|所有文件|*.*";
            openFileDialog.Multiselect = true;
            openFileDialog.Title = "选择音乐文件";

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                foreach (string fileName in openFileDialog.FileNames)
                {
                    playlist.Add(fileName);
                    listBoxMusic.Items.Add(Path.GetFileNameWithoutExtension(fileName));
                }
            }
        }

        private void BtnPrev_Click(object sender, EventArgs e)
        {
            if (playlist.Count > 0)
            {
                currentSongIndex--;
                if (currentSongIndex < 0)
                    currentSongIndex = playlist.Count - 1;
                
                listBoxMusic.SelectedIndex = currentSongIndex;
                LoadSong(playlist[currentSongIndex]);
                SendMCICommand("play MediaFile");
                isPlaying = true;
                isPaused = false;
                UpdateCurrentSongDisplay();
            }
        }

        private void BtnNext_Click(object sender, EventArgs e)
        {
            if (playlist.Count > 0)
            {
                currentSongIndex++;
                if (currentSongIndex >= playlist.Count)
                    currentSongIndex = 0;
                
                listBoxMusic.SelectedIndex = currentSongIndex;
                LoadSong(playlist[currentSongIndex]);
                SendMCICommand("play MediaFile");
                isPlaying = true;
                isPaused = false;
                UpdateCurrentSongDisplay();
            }
        }

        private void ListBoxMusic_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxMusic.SelectedIndex >= 0)
            {
                currentSongIndex = listBoxMusic.SelectedIndex;
                UpdateCurrentSongDisplay();
            }
        }

        private void TrackBarVolume_Scroll(object sender, EventArgs e)
        {
            currentVolume = trackBarVolume.Value;
            SendMCICommand($"setaudio MediaFile volume to {currentVolume * 10}");
        }

        private void TrackBarProgress_MouseDown(object sender, MouseEventArgs e)
        {
            isDragging = true;
        }

        private void TrackBarProgress_MouseUp(object sender, MouseEventArgs e)
        {
            isDragging = false;
            if (isPlaying && songLength > 0)
            {
                int newPosition = (int)((double)trackBarProgress.Value / trackBarProgress.Maximum * songLength * 1000);
                SendMCICommand($"seek MediaFile to {newPosition}");
                if (!isPaused)
                {
                    SendMCICommand("play MediaFile");
                }
            }
        }

        private void TrackBarProgress_Scroll(object sender, EventArgs e)
        {
            if (isDragging && songLength > 0)
            {
                double newPosition = (double)trackBarProgress.Value / trackBarProgress.Maximum * songLength;
                UpdateTimeDisplay(newPosition, songLength);
            }
        }

        private int GetCurrentPosition()
        {
            string positionStr = GetMCIString("status MediaFile position");
            if (int.TryParse(positionStr, out int position))
            {
                return position / 1000; // 转换为秒
            }
            return 0;
        }

        private string GetPlayStatus()
        {
            return GetMCIString("status MediaFile mode");
        }

        private void TimerProgress_Tick(object sender, EventArgs e)
        {
            if (isPlaying && !isDragging)
            {
                string status = GetPlayStatus();
                
                // 检查是否还在播放
                if (status == "stopped" && isPlaying)
                {
                    // 歌曲播放完成,自动播放下一首
                    if (playlist.Count > 1)
                    {
                        BtnNext_Click(sender, e);
                        return;
                    }
                    else
                    {
                        isPlaying = false;
                        isPaused = false;
                        trackBarProgress.Value = 0;
                        lblTime.Text = "00:00 / 00:00";
                        return;
                    }
                }
                
                if (status == "playing" || status == "paused")
                {
                    int currentPosition = GetCurrentPosition();
                    
                    if (songLength > 0)
                    {
                        int progress = (int)((double)currentPosition / songLength * trackBarProgress.Maximum);
                        trackBarProgress.Value = Math.Min(progress, trackBarProgress.Maximum);
                    }
                    
                    UpdateTimeDisplay(currentPosition, songLength);
                }
            }
        }

        private void UpdateCurrentSongDisplay()
        {
            if (currentSongIndex >= 0 && currentSongIndex < playlist.Count)
            {
                string fileName = Path.GetFileNameWithoutExtension(playlist[currentSongIndex]);
                lblCurrentSong.Text = fileName;
            }
        }

        private void UpdateTimeDisplay(double currentPosition, double duration)
        {
            string currentTime = TimeSpan.FromSeconds(currentPosition).ToString(@"mm\:ss");
            string totalTime = TimeSpan.FromSeconds(duration).ToString(@"mm\:ss");
            lblTime.Text = $"{currentTime} / {totalTime}";
        }

        private void button3_Click(object sender, EventArgs e)
        {
            BtnStop_Click(sender, e);
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            // 清理MCI资源
            SendMCICommand("close all");
            base.OnFormClosing(e);
        }
    }
}

123