c# bass入门学习
据说bass挺好用的,所以又搞了个音乐播放器
这是参考了别人的bass教学结合自己的理解写的bass操作类
public class BassHelper { private static BassHelper bassHelper; static string fileName;//全路径文件名 static int stream = 0; //音频流句柄 public static BassHelper BassInit(int deviceId, int rate, BASSInit bassInit, IntPtr intPtr) { if (bassHelper == null) { bassHelper = new BassHelper(deviceId, rate, bassInit, intPtr); } return bassHelper; } public BassHelper(int deviceId, int rate, BASSInit bassInit, IntPtr intPtr) { if (!Bass.BASS_Init(deviceId, rate, bassInit, intPtr)) { throw new ApplicationException(" Bass初始化出错! " + Bass.BASS_ErrorGetCode().ToString()); } } //创建音频流 public static void CreateStream() { if (stream != 0) { if (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING || Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PAUSED) { Bass.BASS_ChannelStop(stream); } Bass.BASS_StreamFree(stream); } stream = Bass.BASS_StreamCreateFile(fileName, 0L, 0L, BASSFlag.BASS_MUSIC_FLOAT); } //全路径文件名 public static string FileName { get { return fileName; } set { fileName = value; } } //播放 public static void Play(bool restart) { Bass.BASS_ChannelPlay(stream, restart); } //停止 public static void Stop() { if (stream != 0 && Bass.BASS_ChannelIsActive(stream) != BASSActive.BASS_ACTIVE_STOPPED) { Bass.BASS_ChannelStop(stream); } } //暂停 public static void Puase() { if (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) { Bass.BASS_ChannelPause(stream); } } //总时间 public static double Duration { get { return Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream)); } } //当前时间 public static double CurrentPosition { get { return Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetPosition(stream)); } set { Bass.BASS_ChannelSetPosition(stream, value); } } //音量 public static int Volume { get { return Bass.BASS_GetConfig(BASSConfig.BASS_CONFIG_GVOL_STREAM) / 100; } set { Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_GVOL_STREAM, value * 100); } } //歌曲信息 public static MusicTags GetMusicTags(string fileName) { MusicTags mt = new MusicTags(); mt.FileName = fileName; int channel = Bass.BASS_StreamCreateFile(fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT); string[] tags = Bass.BASS_ChannelGetTagsID3V1(channel); if (tags != null) { mt.Title = tags[0]; mt.Artist = tags[1]; mt.Album = tags[2]; mt.Year = tags[3]; mt.Comment = tags[4]; if (!string.IsNullOrEmpty(tags[5])) { int gId = 12; int.TryParse(tags[5], out gId); if (gId < 0 || gId >= MusicTags.ID3v1Genre.Length) { gId = 12; } mt.Genre = MusicTags.ID3v1Genre[gId]; } } return mt; } //播放进度0—1 public static double Schedule { get { double schedule = 0;//播放进度 if (stream == 0 || Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetPosition(stream)) == -1) { schedule = 0; } else { schedule = Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetPosition(stream)) / Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream)); } return schedule; } set { double temp = value * Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream)); Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, temp)); } } // 获取FFT采样数据,返回512个浮点采样数据 public static float[] GetFFTData() { float[] fft = new float[512]; Bass.BASS_ChannelGetData(stream, fft, (int)BASSData.BASS_DATA_FFT1024); return fft; } // 当前播放状态 public static PlayStates PlayState { get { PlayStates state = PlayStates.Stopped; switch (Bass.BASS_ChannelIsActive(stream)) { case BASSActive.BASS_ACTIVE_PAUSED: state = PlayStates.Pause; break; case BASSActive.BASS_ACTIVE_PLAYING: state = PlayStates.Play; break; case BASSActive.BASS_ACTIVE_STALLED: state = PlayStates.Stalled; break; case BASSActive.BASS_ACTIVE_STOPPED: state = PlayStates.Stopped; break; } return state; } } //加载插件 public static bool LoadBasic(string path) { int handle = Bass.BASS_PluginLoad(path); if (handle != 0) { return true; } else { return false; } } public static void Dispose(object obj) { Bass.BASS_ChannelStop(stream); Bass.BASS_StreamFree(stream); Bass.BASS_Stop(); //停止 Bass.BASS_Free(); //释放 GC.SuppressFinalize(obj); } } /// <summary> /// 播放状态枚举 /// </summary> public enum PlayStates { /// <summary> /// 正在播放 /// </summary> Play = BASSActive.BASS_ACTIVE_PLAYING, /// <summary> /// 暂停 /// </summary> Pause = BASSActive.BASS_ACTIVE_PAUSED, /// <summary> /// 停止 /// </summary> Stopped = BASSActive.BASS_ACTIVE_STOPPED, /// <summary> /// 延迟 /// </summary> Stalled = BASSActive.BASS_ACTIVE_STALLED, }
用之前要先初始化
BassHelper.BassInit(-1, 44100, BASSInit.BASS_DEVICE_CPSPEAKERS, this.Handle);
Win32
#region API声明 class Win32 { [StructLayout(LayoutKind.Sequential)] public struct Size { public Int32 cx; public Int32 cy; public Size(Int32 x, Int32 y) { cx = x; cy = y; } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BLENDFUNCTION { public byte BlendOp; public byte BlendFlags; public byte SourceConstantAlpha; public byte AlphaFormat; } [StructLayout(LayoutKind.Sequential)] public struct Point { public Int32 x; public Int32 y; public Point(Int32 x, Int32 y) { this.x = x; this.y = y; } } public const byte AC_SRC_OVER = 0; public const Int32 ULW_ALPHA = 2; public const byte AC_SRC_ALPHA = 1; [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern IntPtr CreateCompatibleDC(IntPtr hDC); [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetDC(IntPtr hWnd); [DllImport("gdi32.dll", ExactSpelling = true)] public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj); [DllImport("user32.dll", ExactSpelling = true)] public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern int DeleteDC(IntPtr hDC); [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern int DeleteObject(IntPtr hObj); [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)] public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags); [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern IntPtr ExtCreateRegion(IntPtr lpXform, uint nCount, IntPtr rgnData); } #endregion
还有几个问题:
1.加载的解码器插件不工作
原因:我用的是64位的,结果加载的是32位的
2.本来打算用UpdateLayeredWindow画不规则窗体的,结果控件都出不来了,用了简单的,结果好多毛边
解决:获得控件图片,再画上去,进度条当值改变时,就重新画一遍
3.进度条好难看,下次重写个
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace MusicBar { public partial class MusicBar: UserControl { private Color backgroundColor = Color.White;//进度条背景颜色 private Color foregroundColor = Color.Gray;//进度条前景颜色 private Color setRectColor = Color.Black;//控制块颜色 private Color borderColor = Color.Black;//边框颜色 private int maximum = 100;//最大值 private int minimum = 0;//最小值 private double myValue = 0.0;//进度值 private Rectangle foreRect;//前景方块 private Rectangle backRect;//背景方块 private Rectangle setRect;//控制方块 protected EventHandler OnValueChanged;//当进度值改变事件 private Point originPoint;//当前鼠标位置 private Point originsetRectPoint;//当前控制块位置 private bool setRectDown = false;//控制块是否点下 public MusicBar() { InitializeComponent(); this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true); this.MouseDown += new MouseEventHandler(this.MySlider_MouseDown); this.MouseMove += new MouseEventHandler(this.MySlider_MouseMove); this.MouseUp += new MouseEventHandler(this.MySlider_MouseUp); this.BackColor = Color.Transparent; } #region 属性 [Category("进度条"), Description("进度条的最大值"), Browsable(true)] public int Maximum { get { return maximum; } set { maximum = value; Invalidate(); } } [Category("进度条"), Description("进度条的最小值"), Browsable(true)] public int Minimum { get { return minimum; } set { minimum = value; Invalidate(); } } [Category("进度条"), Description("进度条的背景色,总长度(底部白色矩形)"), Browsable(true)] public Color BackgroundColor { get { return backgroundColor; } set { this.backgroundColor = value; Invalidate(); } } [Category("进度条"), Description("进度条的前景色,已加载长度(灰色矩形)"), Browsable(true)] public Color ForegroundColor { get { return foregroundColor; } set { this.foregroundColor = value; Invalidate(); } } [Category("进度条"), Description("进度条控制块的颜色(黑色矩形)"), Browsable(true)] public Color SetRectColor { get { return setRectColor; } set { this.setRectColor = value; Invalidate(); } } [Category("进度条"), Description("进度条边框的颜色(黑色)"), Browsable(true)] public Color SetBorderColor { get { return borderColor; } set { this.borderColor = value; Invalidate(); } } [Category("General"), Description("控件的宽度"), Browsable(true)] public new int Width { get { return base.Width; } set { base.Width = value; setRect.Width = base.Height/10*9; foreRect.X = backRect.X = setRect.Width / 2; backRect.Width = base.Width - setRect.Width - (base.Height - setRect.Width); foreRect.Width = (int)(myValue / maximum * backRect.Width); setRect.X = foreRect.Width; Invalidate(); } } [Category("General"), Description("控件的高度"), Browsable(true)] public new int Height { get { return base.Height; } set { base.Height = value; setRect.Height = base.Height / 10 * 9; setRect.Y = (base.Height - setRect.Height) / 2; foreRect.Height = backRect.Height = setRect.Height / 4; foreRect.Y = backRect.Y = (base.Height - backRect.Height) / 2; Invalidate(); } } [Category("进度条"), Description("进度条的值"), Browsable(true)] public double Value { get { return myValue; } set { if (myValue < Minimum) throw new ArgumentException("小于最小值"); if (myValue > Maximum) throw new ArgumentException("超过最大值"); myValue = value; foreRect.Width = (int)(myValue / maximum * backRect.Width); if ((myValue - maximum) > 0) { foreRect.Width = backRect.Width; } if ((myValue - minimum) < 0) { foreRect.Width = 0; } setRect.X = foreRect.Width; //如果添加了响应函数,则执行该函数 if (OnValueChanged != null) { OnValueChanged(this, EventArgs.Empty); } Invalidate(); } } #endregion public event EventHandler ValueChanged { add { if (OnValueChanged != null) { foreach (Delegate d in OnValueChanged.GetInvocationList()) { if (object.ReferenceEquals(d, value)) { return; } } } OnValueChanged = (EventHandler)Delegate.Combine(OnValueChanged, value); } remove { OnValueChanged = (EventHandler)Delegate.Remove(OnValueChanged, value); } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); this.DrawRect(e.Graphics); } private void DrawRect(Graphics e) { Pen pen = new Pen(borderColor); e.FillRectangle((Brush)new SolidBrush(this.backgroundColor), this.backRect); e.DrawRectangle(pen, this.backRect); e.FillRectangle((Brush)new SolidBrush(this.foregroundColor), this.foreRect); e.DrawRectangle(pen, this.foreRect); e.FillEllipse((Brush)new SolidBrush(this.setRectColor), this.setRect); e.DrawEllipse(pen, this.setRect); } protected override void OnResize(EventArgs e) { base.OnResize(e); this.Width = this.Width; this.Height = this.Height; this.Invalidate(); } private void MySlider_MouseUp(object sender, MouseEventArgs e) { this.setRectDown = false; } private void MySlider_MouseMove(object sender, MouseEventArgs e) { if (setRectDown) { //移动长度 int dd = e.Location.X - originPoint.X; //百分比 double percent = (double)(originsetRectPoint.X + dd - this.backRect.X) / this.backRect.Width; if (percent < 0) { percent = 0; } else if (percent > 1) { percent = 1; } this.Value = percent * maximum; this.foreRect.Width = (int)(percent * this.backRect.Width); //this.setRect.X = originsetRectPoint.X + dd; this.setRect.X = foreRect.Width; Invalidate(); } } private void MySlider_MouseDown(object sender, MouseEventArgs e) { if (setRect.Contains(e.Location)) { this.originPoint = e.Location; originsetRectPoint = this.setRect.Location; this.setRectDown = true; } } } }
代码
http://pan.baidu.com/s/1o8tzUkE
参考
http://tieba.baidu.com/p/2643045626
界面效果