- 浏览: 11428322 次
文章分类
最新评论
-
wahahachuang8:
我觉得这种东西自己开发太麻烦了,就别自己捣鼓了,找个第三方,方 ...
WebSocket和node.js -
xhpscdx:
写的这么详细,全面,对架构师的工作职责,个人能力都进行了梳理。 ...
架构师之路---王泽宾谈架构师的职责 -
xgbzsc:
是http://www.haoservice.com 吗?
android WIFI定位 -
lehehe:
http://www.haoservice.com/docs/ ...
android WIFI定位 -
lehehe:
http://www.haoservice.com/docs/ ...
android WIFI定位
学生时代做的一个非常低级的卡拉OK播放器
学生时代做的一个非常低级的C#卡拉OK播放器。
实现了桌面卡拉OK[单行,双行],繁简转换,歌曲搜索,3种播放模式[单首,循环,随机],全屏歌词,全局快捷键,XML配置,指定歌词文件夹,等等一些简单的功能。
无意中翻出来了,看看,听听歌,有别有一番乐趣,想当初做这个的时候才接触编程1年。里面用了太多的集合,歌词判断也非常不准备。呵呵。算是用一种非常笨的方法实现的吧。里面没什么高深的技术。主要就是用到了双缓冲[一种防止歌词刷新时屏幕闪烁的技术]、注册全局快捷键等。
已经好久没有接触C#了,虽然这是曾经非常感兴趣的东西,却为了学习编程思想选择了JAVA。如果现在再让我做,我一定会把里面的代码简化简化再简化吧。看着那些乱七八糟的代码,想想自己当年的何其的菜鸟水平的作品。也是一种人生的乐趣。
主界面:
窗体卡拉OK
桌面卡拉OK显示[支持单行,双行]:
配置:
歌词配置[当时我还没有学XML,实现来源于网上]:
<configuration> <appSettings> <add key="lrcDir" value="E:\music\AIRPLAY.DAT\Lyrics" /> <add key="playState" value="2" /> <add key="sound" value="28" /> <add key="DeskIsDoubleline" value="true" /> <add key="DeskFontFamily" value="英章楷书" /> <add key="DeskFontSize" value="27.75" /> <add key="DeskFontStyle" value="bold" /> <add key="DeskNormalColor" value="-65536" /> <add key="DeskLightColor" value="-16711936" /> <add key="FontSize" value="15" /> <add key="NormalColor" value="-4144960" /> <add key="LightColor" value="-16711872" /> <add key="BackColor" value="-16777216" /> <add key="FontStyle" value="bold" /> <add key="FontFamily" value="英章楷书" /> <add key="DeskBackColor" value="-16777216" /> </appSettings> </configuration>
读取配置文件的核心处理类:
using System; using System.Collections.Generic; using System.Text; using System.Xml; namespace LrcCollection { internal class Config { public static string GetValue(string AppKey) { try { XmlDocument document = new XmlDocument(); document.Load(System.AppDomain.CurrentDomain.BaseDirectory + "LrcSet.xml"); XmlElement element = (XmlElement)document.SelectSingleNode("//appSettings").SelectSingleNode("//add[@key='" + AppKey + "']"); if (element != null) { return element.GetAttribute("value"); } return null; } catch { return null; } } public static void SetValue(string AppKey, string AppValue) { try { XmlDocument document = new XmlDocument(); document.Load(System.AppDomain.CurrentDomain.BaseDirectory + "LrcSet.xml"); XmlNode node = document.SelectSingleNode("//appSettings"); XmlElement element = (XmlElement)node.SelectSingleNode("//add[@key='" + AppKey + "']"); if (element != null) { element.SetAttribute("value", AppValue); } else { XmlElement newChild = document.CreateElement("add"); newChild.SetAttribute("key", AppKey); newChild.SetAttribute("value", AppValue); node.AppendChild(newChild); } document.Save(System.AppDomain.CurrentDomain.BaseDirectory + "LrcSet.xml"); } catch { SetValue(AppKey, AppValue, true); } } public static void SetValue(string AppKey, string AppValue, bool tt) { XmlDocument document = new XmlDocument(); XmlNode node = document.CreateNode(XmlNodeType.Element, "configuration", ""); document.AppendChild(node); XmlNode node2 = document.CreateNode(XmlNodeType.Element, "appSettings", ""); node.AppendChild(node2); XmlElement newChild = document.CreateElement("add"); newChild.SetAttribute("key", AppKey); newChild.SetAttribute("value", AppValue); node2.AppendChild(newChild); document.Save(System.AppDomain.CurrentDomain.BaseDirectory + "LrcSet.xml"); } } }
下面是画歌词的处理类[现在自己都看不懂当初是如何实现的了,贴在这里吧。]:
说一说主要的思想:
画歌词的面板一定要继承UserControl类,然后重写其protected override void OnPaint(PaintEventArgs pe)方法,实现双缓冲,在这里面画歌词。
画卡拉OK歌词的原理是:先画背景[底层],再画你要显示的所有歌词[中间层],每行歌词都是顺序向下的,中间有间距,然后再你画好的歌词上面,画卡拉OK歌词,也就是高亮显示的那一行歌词[最上层],这一行歌词会覆盖之前画的中间层歌词的那一行,当然这样它还不是卡拉OK显示的,卡拉OK显示就要取出当前这句歌词和下一句歌词之间的时间,然后从左至右,匀速的画上高亮显示的这一行,看起来就是卡拉OK显示出来了。像酷狗这种歌词是经过精准处理的。
桌面歌词就很简单了,主要是一个无标题的窗体,做上鼠标移动事件即可拖动,单行,双行歌词也只不过是多了一层判断。双行就是每次唱完一句就取出下一句画在面板上。单行就是唱一句画一句。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Text; using System.Drawing.Drawing2D; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Collections; using LrcCollection; namespace MediaPlayer { public partial class DeskLrcControl : UserControl { public DeskLrcControl() { InitializeComponent(); Size1(this.Size); Components(); this.DoubleBuffered = true; } #region 字段 public LrcPanel lrcPanel = null; private ArrayList lrcConfig = new ArrayList(); int width = 0; Bitmap imgBack; Bitmap imgLrc; int middleTime = 0; public string currentPosition = null; int minute; int second; public Dictionary<int, string> lrcSortedList = new Dictionary<int, string>();//用来保存歌词和时间排序后的集合 private SolidBrush backBrush; private SolidBrush lightBrush; private Color backColor; private Font fontStyle; private StringFormat stringFormatter; [Description("普通歌词颜色"), Category("歌词样式设置")] public SolidBrush BackBrush { get { return backBrush; } set { backBrush = value; } } [Description("高亮歌词颜色"), Category("歌词样式设置")] public SolidBrush LightBrush { get { return lightBrush; } set { lightBrush = value; } } [Description("歌词背景颜色"), Category("歌词样式设置")] public Color BackColors { get { return backColor; } set { backColor = value; } } [Description("当前歌曲时间"), Category("歌词样式设置")] public string CurrentPosition { get { return currentPosition; } set { currentPosition = value; } } [Description("歌词字体样式"), Category("歌词样式设置")] public Font FontSty { get { return fontStyle; } set { fontStyle = value; } } [Description("歌词字体排序"), Category("歌词样式设置")] public StringFormat StringFormatter { get { return stringFormatter; } set { stringFormatter = value; } } public override Color BackColor { get { return backColor; } set { base.BackColor = value; } } public void Size1(Size s) { if (imgBack != null) { imgBack.Dispose(); } if (imgLrc != null) { imgLrc.Dispose(); } imgBack = new Bitmap(s.Width, s.Height); imgLrc = new Bitmap(s.Width, s.Height); //maxWidth = 0; //lrcSortedList.Clear(); //Graphics g = Graphics.FromHwnd(this.contextMenuStrip1.Handle); //for (int i = 0; i < tempTime.Length; i++) //{ // if (i + 1 < tempTime.Length) // { // if (g.MeasureString(lrcList.ElementAt(i).Value, fontStyle).Width > maxWidth) // { // maxWidth = (int)g.MeasureString(lrcList.ElementAt(i).Value, fontStyle).Width; // } // } // lrcSortedList.Add(tempTime[i], lrcList[tempTime[i]]); //} //g.Dispose(); //imgBack = new Bitmap(maxWidth + 2, this.Height); //imgLrc = new Bitmap(maxWidth + 2, this.Height); //this.Refresh(); } public override Size MinimumSize { get { return new Size(200, 20); } set { base.MinimumSize = value; } } #endregion protected override void OnPaint(PaintEventArgs pe) { if (currentPosition != null) { if (load == false) { Components(); load = true; } DrawString(currentPosition, pe.Graphics, BackBrush, LightBrush, this.fontStyle, this.BackColor, stringFormatter); pe.Dispose(); } } bool load = false; #region //初始化 public void Components() { try { backBrush = new SolidBrush(Color.FromArgb(Convert.ToInt32(Config.GetValue("DeskNormalColor")))); lightBrush = new SolidBrush(Color.FromArgb(Convert.ToInt32(Config.GetValue("DeskLightColor")))); backColor = Color.FromArgb(Convert.ToInt32(Config.GetValue("DeskBackColor"))); FontStyle f = FontStyle.Regular; if (Config.GetValue("DeskFontStyle") == "bold") { f = FontStyle.Bold; } else if (Config.GetValue("DeskFontStyle") == "italic") { f = FontStyle.Italic; } else if (Config.GetValue("DeskFontStyle") == "strikeout") { f = FontStyle.Strikeout; } else if (Config.GetValue("DeskFontStyle") == "underline") { f = FontStyle.Underline; } else { f = FontStyle.Regular; } fontStyle = new Font(Config.GetValue("DeskFontFamily"), float.Parse(Config.GetValue("DeskFontSize")),f); if (Config.GetValue("DeskIsDoubleline") != null) { isDoubleLine = Convert.ToBoolean(Config.GetValue("DeskIsDoubleline")); } stringFormatter = new StringFormat(); stringFormatter.Alignment = StringAlignment.Center; stringFormatter.LineAlignment = StringAlignment.Center; stringFormatter.Trimming = StringTrimming.Character; } catch { backBrush = new SolidBrush(Color.Blue); lightBrush = new SolidBrush(Color.Red); backColor = Color.Black; fontStyle = new Font("幼圆", 34f); stringFormatter = new StringFormat(); stringFormatter.Alignment = StringAlignment.Center; stringFormatter.LineAlignment = StringAlignment.Center; stringFormatter.Trimming = StringTrimming.Character; } } #endregion #region 画歌词 public bool isKana = true; public bool isTranKey = true; public bool isDoubleLine = true; SizeF imgSize = SizeF.Empty; SizeF img1 = SizeF.Empty; public string DrawString(string nowTime, Graphics g, SolidBrush backBrush, SolidBrush lightBrush, Font f, Color backColor, StringFormat format) { if (isTranKey == true) { this.BackColors = Color.Transparent; this.FindForm().BackColor = Color.Turquoise; this.FindForm().TransparencyKey = Color.Turquoise; } if (lrcSortedList.Count > 0 && LrcConnections.lrcPath != null) { Size1(this.FindForm().Size);//歌词居中 imgLrc = DrawLrcImg(nowTime, lightBrush, backBrush, f, backColor, format); if (isKana == true) { imgBack = ShowLrc(backBrush, f, backColor, format);//画背景歌词 g.CompositingQuality = CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.AntiAlias; g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; if (imgLrc != null && imgBack != null) { Rectangle rec = new Rectangle(0, 0, width, this.imgLrc.Height); g.DrawImage(imgBack, 0, 0); //画当前高亮显示的歌词,其实就是画歌词图像的一部分,以像素显示会呈现卡拉OK歌词 g.DrawImage(imgLrc, 0, 0, rec, GraphicsUnit.Pixel); //g.Flush(); } } else if (imgLrc != null) { g.DrawImage(imgLrc, 0, 0); //g.Flush(); } } else { if (LrcConnections.lrcPath == null) { Graphics gg = Graphics.FromImage(imgBack); gg.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; gg.CompositingQuality = CompositingQuality.HighQuality; gg.SmoothingMode = SmoothingMode.AntiAlias; SizeF imgSize = gg.MeasureString("对不起,没有找到歌词,您可以手动指定歌词", f);//当前歌词长度 this.FindForm().Size = new Size((int)imgSize.Width, (int)imgSize.Height); Size1(this.Size); gg.Dispose(); gg = Graphics.FromImage(imgBack); gg.DrawString("对不起,没有找到歌词,您可以手动指定歌词", f, backBrush, 0, 0); gg.Dispose(); g.DrawImage(imgBack, 0, 0); } } return null; } #endregion #region 显示高亮歌词的方法 private Bitmap DrawLrcImg(string currentTime, SolidBrush lightBrush, SolidBrush backBrush, Font f, Color backColor, StringFormat format) { if (currentTime == "" || currentTime == null) { return null; } if (imgLrc == null) { return null; } Graphics gra = Graphics.FromImage(imgLrc); gra.Clear(backColor); minute = Convert.ToInt32(currentTime.Substring(0, 2)) * 60;//分钟转为秒 second = Convert.ToInt32(currentTime.Substring(3)); for (int i = 0; i < lrcSortedList.Count - 1; i++) { if (lrcSortedList.ElementAt(i).Key == (minute + second))//高亮显示当前歌词 { //float lrcWidth = g.MeasureString(lrcSortedList.ElementAt(i).Value, f).Width; UserHelper.currentLrcIndex = i; width = 0; break; } } if ((UserHelper.currentLrcIndex + 1) <= lrcSortedList.Count) { middleTime = lrcSortedList.ElementAt(UserHelper.currentLrcIndex + 1).Key - lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Key; } imgSize = gra.MeasureString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f);//当前歌词长度 if (isDoubleLine == false) { this.FindForm().Size = new Size((int)imgSize.Width, (int)imgSize.Height); Size1(this.Size); } else//如果是双行的话 { if (UserHelper.currentLrcIndex < lrcSortedList.Count - 1) { img1 = gra.MeasureString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex + 1).Value, f); } if (imgSize.Width > img1.Width) { this.FindForm().Size = new Size((int)imgSize.Width, (int)imgSize.Height * 2); Size1(this.Size); } else { this.FindForm().Size = new Size((int)img1.Width, (int)img1.Height * 2); Size1(this.Size); } gra.Dispose(); } if (width == 0) { width++; } else { width += (int)(imgSize.Width / (middleTime * 6));//歌词匀速以卡拉OK形式前进,毫秒化为秒 } Graphics g = Graphics.FromImage(imgLrc); g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; g.CompositingQuality = CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.AntiAlias; if (isDoubleLine == false) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f, lightBrush, 0, 0); } else { if (UserHelper.currentLrcIndex % 2 == 0) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f, lightBrush, 0, 0); if (UserHelper.currentLrcIndex < lrcSortedList.Count - 1) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex + 1).Value, f, backBrush, 0, f.Height); } } else { if (UserHelper.currentLrcIndex < lrcSortedList.Count - 1) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex + 1).Value, f, backBrush, 0, 0); } g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f, lightBrush, 0, f.Height); } } //g.Flush(); g.Dispose(); return imgLrc; } #endregion #region 显示背景歌词的方法 public Bitmap ShowLrc(SolidBrush backBrush, Font f, Color backColor, StringFormat format) { Graphics gra = Graphics.FromImage(imgBack); gra.Clear(backColor); //Font f1 = new Font(f.FontFamily, f.Size + 0.2f, FontStyle.Regular); //for (int index = 0; index < lrcSortedList.Count - 1; index++) //{ // Graphics g = Graphics.FromImage(imgBack); // g.SmoothingMode = SmoothingMode.AntiAlias; // g.DrawString(lrcSortedList.ElementAt(index).Value, f1, new SolidBrush(Color.Blue), this.imgBack.Width / 2, f.Height * (index + space + 1 + lines), format); // g.Dispose(); //} //f1.Dispose(); //显示歌词 Graphics g = Graphics.FromImage(imgBack); g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; g.CompositingQuality = CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.AntiAlias; if (isDoubleLine == false) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f, backBrush, 0, 0); } else { if (UserHelper.currentLrcIndex % 2 == 0) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f, backBrush, 0, 0); if (UserHelper.currentLrcIndex < lrcSortedList.Count - 1) { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex + 1).Value, f, backBrush, 0, f.Height); } } else { g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex + 1).Value, f, backBrush, 0, 0); g.DrawString(lrcSortedList.ElementAt(UserHelper.currentLrcIndex).Value, f, backBrush, 0, f.Height); } } //g.Flush(); g.Dispose(); return imgBack; } #endregion } }
歌词繁简转换也很容易:
/// <summary> /// 简体到繁体转换 /// </summary> /// <param name="simplifiedChinese">简体</param> /// <returns>繁体</returns> private string SimplifiedToTraditional(string simplifiedChinese) { string traditionalChinese = string.Empty; System.Globalization.CultureInfo vCultureInfo = new System.Globalization.CultureInfo("zh-CN", false); traditionalChinese = Microsoft.VisualBasic.Strings.StrConv(simplifiedChinese, Microsoft.VisualBasic.VbStrConv.TraditionalChinese, vCultureInfo.LCID); return traditionalChinese; } /// <summary> /// 繁体到简体转换 /// </summary> /// <param name="traditionalChinese">繁体</param> /// <returns>简体</returns> private string TraditionalToSimplified(string traditionalChinese) { string simplifiedChinese = string.Empty; System.Globalization.CultureInfo vCultureInfo = new System.Globalization.CultureInfo("zh-CN", false); simplifiedChinese = Microsoft.VisualBasic.Strings.StrConv(traditionalChinese, Microsoft.VisualBasic.VbStrConv.SimplifiedChinese, vCultureInfo.LCID); return simplifiedChinese; }
歌词窗体出现时是动态显示的,以及全局快捷键的[当时只知道使用系统的user32.dll实现的]代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Runtime.InteropServices; using System.Collections; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace MediaPlayer { public partial class LrcFrm : Form { public AxWMPLib.AxWindowsMediaPlayer axWmplayer; public System.Windows.Forms.Timer timer; //动画窗体调用 [System.Runtime.InteropServices.DllImport("user32")] private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags); const int AW_HOR_POSITIVE = 0x0002; const int AW_HOR_NEGATIVE = 0x0004; const int AW_VER_POSITIVE = 0x0008; const int AW_VER_NEGATIVE = 0x00016; const int AW_CENTER = 0x0010; const int AW_HIDE = 0x10000; const int AW_ACTIVATE = 0x20000; const int AW_SLIDE = 0x20000; const int AW_BLEND = 0x80000; public LrcFrm(AxWMPLib.AxWindowsMediaPlayer axWmplayer,System.Windows.Forms.Timer timer) { InitializeComponent(); this.DoubleBuffered = true; LrcConnections.lrcfrm = this; LrcConnections.lrcPanel = this.lrcPanel1; this.axWmplayer = axWmplayer; this.timer = timer; } #region 字段 public override Size MinimumSize { get { return new Size(100, 100); } set { base.MinimumSize = value; } } #endregion #region //注册热键 [DllImport("user32.dll", SetLastError = true)] public static extern bool RegisterHotKey( IntPtr hWnd, // handle to window int id, // hot key identifier KeyModifiers fsModifiers, // key-modifier options System.Windows.Forms.Keys vk // virtual-key code ); [DllImport("user32.dll", SetLastError = true)] public static extern bool UnregisterHotKey( IntPtr hWnd, // handle to window int id // hot key identifier ); [Flags] public enum KeyModifiers { None = 0, Alt = 1, Control = 2, Shift = 4, Windows = 8 } private const int WM_HOTKEY = 0x312; //窗口消息-热键 private const int WM_CREATE = 0x1; //窗口消息-创建 private const int WM_DESTROY = 0x2; //窗口消息-销毁 private const int MOD_ALT = 0x1; //ALT private const int MOD_CONTROL = 0x2; //CTRL private const int MOD_SHIFT = 0x4; //SHIFT private const int VK_SPACE = 0x20; //SPACE protected override void WndProc(ref Message m) { //base.WndProc(ref m); switch (m.Msg) { case WM_HOTKEY: //窗口消息-热键 switch (m.WParam.ToString()) { case "1989": this.lrcPanel1.showFullScreen(); break; case "11": //热键ID this.lrcPanel1.KanaOK(); break; case "12": this.lrcPanel1.showLrcSetFrm(); break; case "13": this.lrcPanel1.showLrc(); break; case "14": this.lrcPanel1.showFullScreen(); break; case "15": //热键ID Helper.main.PlayNext(); break; case "16": Helper.main.playPre(); break; //case "17": // this.lrcPanel1.showLrc(); // break; //case "18": // this.lrcPanel1.showFullScreen(); // break; default: break; } break; case WM_CREATE: //窗口消息-创建 RegisterHotKey(this.Handle, 1989, KeyModifiers.None, Keys.Escape); RegisterHotKey(this.Handle, 11, KeyModifiers.Control | KeyModifiers.Alt, Keys.K); RegisterHotKey(this.Handle, 12, KeyModifiers.Control | KeyModifiers.Alt, Keys.G); RegisterHotKey(this.Handle, 13, KeyModifiers.Control | KeyModifiers.Alt, Keys.D); RegisterHotKey(this.Handle, 14, KeyModifiers.Control | KeyModifiers.Alt, Keys.F); //播放控制 //下一首 RegisterHotKey(this.Handle, 15, KeyModifiers.Control | KeyModifiers.Alt, Keys.Right); //上一首 RegisterHotKey(this.Handle, 16, KeyModifiers.Control | KeyModifiers.Alt, Keys.Left); //音量加 // RegisterHotKey(this.Handle, 17, KeyModifiers.Control | KeyModifiers.Alt, Keys.Up); //音量减 // RegisterHotKey(this.Handle, 18, KeyModifiers.Control | KeyModifiers.Alt, Keys.Down); break; case WM_DESTROY: //窗口消息-销毁 UnregisterHotKey(this.Handle, 1989); UnregisterHotKey(this.Handle, 11); //销毁热键 UnregisterHotKey(this.Handle, 12); UnregisterHotKey(this.Handle, 13); UnregisterHotKey(this.Handle, 14); UnregisterHotKey(this.Handle, 15); UnregisterHotKey(this.Handle, 16); // UnregisterHotKey(this.Handle, 17); // UnregisterHotKey(this.Handle, 18); break; default: break; } base.WndProc(ref m); } #endregion private void LrcFrm_Load(object sender, EventArgs e) { Thread t = new Thread(loadLrc); t.IsBackground = true; t.Start(); //动画由小渐大,现在取消 AnimateWindow(this.Handle, 2000, AW_CENTER | AW_ACTIVATE); } private void loadLrc() { int i = 0; while (LrcConnections.isReading == true) { Thread.Sleep(1000); i++; if (LrcConnections.isReading == false || i == 5) { break; } } if (LrcConnections.isReading == false) { this.lrcPanel1.lrcSortedList = LrcConnections.lrcSortedList; } Thread.CurrentThread.Abort(); } #region//改变窗体大小时 歌词面板改变 private void LrcFrm_Resize(object sender, EventArgs e) { this.lrcPanel1.Size1(this.Size);//歌词居中 this.lrcPanel1.ChangeSize(); } #endregion private void LrcFrm_FormClosing(object sender, FormClosingEventArgs e) { this.Visible = false; e.Cancel = true; //存储当前状态 } } }
如果你想单独试试双缓冲,可以试试这个,你可以拿它和没有使用双缓冲的timer比较下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; namespace MediaPlayer { public partial class myLabel : UserControl { public myLabel() { InitializeComponent(); Timer t = new Timer(); this.DoubleBuffered = true; t.Interval = 1000; t.Tick += new EventHandler(t_Tick); t.Enabled = true; } protected override void OnPaint(PaintEventArgs pe) { Draw(pe.Graphics); pe.Dispose(); } //程序人生 人生如戏 戏如人生 却不能游戏人生 void t_Tick(object sender, EventArgs e) { this.Refresh(); } private void Draw(Graphics g) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; Font f = new Font("华文行楷", 35F, FontStyle.Italic); SolidBrush fontB = new SolidBrush(Color.Gray); SolidBrush fontA = new SolidBrush(Color.Red); //先画阴影,坐标偏移5 g.DrawString("程序", f, fontB, 15, 30); g.DrawString("人生", f, fontB, 15, this.Size.Height / 2 + 15); //再画字体 g.DrawString("程序", f, fontA, 0, 15); g.DrawString("人生", f, fontA, 0, this.Size.Height / 2); } //Font f1 = new Font("幼圆", 15F, FontStyle.Regular); //SolidBrush fontC = new SolidBrush(Color.LightGray); //for (int i = 0; i <= 360; i += 60) //{ // //平移Graphics对象到窗体中心 // g.TranslateTransform(this.Width / 2, this.Height / 2); // //设置Graphics对象的输出角度 // g.RotateTransform(i); // //设置文字填充颜色 // //旋转显示文字 // g.DrawString("土豆水印", f1, fontC, 10, 10); // //恢复全局变换矩阵 // g.ResetTransform(); //} } }
搜索歌词的方法,一种很笨的方法:
string song = null; List<int> songIndex = new List<int>(); private void btnFind_Click(object sender, EventArgs e) { if (song != null && song != txtSong.Text.Trim()) { songIndex.Clear(); song = txtSong.Text.Trim(); } else if (song == null) { song = txtSong.Text.Trim(); } if (song != null && song != "") { for (int flag = 0; flag < lbPlayerList.Items.Count; flag++) { if (songIndex.Contains(flag)) { continue; } if (lbPlayerList.Items[flag].ToString().Contains(txtSong.Text.Trim())) { songIndex.Add(flag); lbPlayerList.SelectedIndex = flag; break; } else { //如果到了末尾,清空集合。下次从新开始 if (flag == lbPlayerList.Items.Count - 1) { MessageBox.Show("已经到了末尾..."); songIndex.Clear(); } } } } }
如果你看到了关于窗体,你可能找不到上面显示的文字从哪来,事实上里面有2个dll文件,它描述的版本,作者,制作时间等信息,只有用特性和反射机制才可能读出来。
特性:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using AttributeTudou; namespace AttributeReflection { /// <summary> /// 特性,更新版本时可用反射读取此程序的信息 /// /// 作者,创建时间,最后修改时间,公司名称,产品名称,版本,声明 /// </summary> [AttibuteTuDou("很拽の土豆", "2009年12月", "2011年2月", "土豆工作室", "雅风随风", "1.0.0", "CopyRight 2011 很拽の土豆 All Rights Reserved", "以上一切信息版权归原作者所有\r\n\r\n郑重声明:版权所有,翻版不究\r\n\r\n\r\t\r\t2009.12\r\t很拽の土豆\r\nQQ:475589699\r\n邮箱:yaerfeng1989@163.com")] public class Tudou { } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeTudou { [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]//允许多个访问,可以对任何应用程序的元素应用此特性 public class AttibuteTuDou : Attribute { public AttibuteTuDou() { } public AttibuteTuDou(string author,string createDate,string lastUpDate,string comp,string producter,string version,string copyRight,string otherDesc) { this.Author = author; this.CreateDate = createDate; this.LastUpTime = lastUpDate; this.Company = comp; this.Producter = producter; this.Version = version; this.CopyRight = copyRight; this.OtherDesc =otherDesc; } private string author; public string Author { get { return author; } set { author = value; } } private string createDate; public string CreateDate { get { return createDate; } set { createDate = value; } } private string lastUpTime; public string LastUpTime { get { return lastUpTime; } set { lastUpTime = value; } } private string version; public string Version { get { return version; } set { version = value; } } private string company; public string Company { get { return company; } set { company = value; } } private string producter; public string Producter { get { return producter; } set { producter = value; } } private string otherDesc; public string OtherDesc { get { return otherDesc; } set { otherDesc = value; } } private string copyRight; public string CopyRight { get { return copyRight; } set { copyRight = value; } } } }
如何读取:
如果你眼睛好,你会发现这里面还有2个方法
1个是用记事本打开歌词的,1个是定位文件[给一个路经它,它会自动在电脑上帮你定位这个文件]的。前者可能简单,但后者却更实用。
实现方法分别为:
System.Diagnostics.Process.Start("NOTEPAD.EXE", 文本的路径);
System.Diagnostics.Process.Start("explorer.exe", "/select," + 文本的路径);
整体代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using LrcCollection; using AttributeTudou; using System.Reflection; namespace MediaPlayer { public partial class LrcSetFrm : Form { //private Font fontStyle; private Color normalColor; private Color lightColor; private Color backColor; private LrcPanel lrcPanel; public LrcSetFrm(LrcPanel lrcPanel) { InitializeComponent(); this.lrcPanel = lrcPanel; tudou = AssemblyTitle; this.Text = String.Format("关于 {0}", AssemblyProduct); this.labelProductName.Text = AssemblyProduct; this.labelVersion.Text = String.Format("版本 {0}", AssemblyVersion); this.labelCopyright.Text = AssemblyCopyright; this.labelCompanyName.Text = AssemblyCompany; this.textBoxDescription.Text = AssemblyDescription; } private void btnOpenLrc_Click(object sender, EventArgs e) { if (txtPath.Text.Trim() != "" && txtPath.Text.Trim() != null) { if (File.Exists(txtPath.Text)) { System.Diagnostics.Process.Start("NOTEPAD.EXE", txtPath.Text); } else { MessageBox.Show("对不起,不存在该文件!"); } } } private void btnOpenLrcFile_Click(object sender, EventArgs e) { if (textBox1.Text.Trim() != "" && textBox1.Text.Trim() != null) { if (Directory.Exists(textBox1.Text)) { System.Diagnostics.Process.Start("explorer.exe", "/select," + textBox1.Text); } else { MessageBox.Show("对不起,不存在该文件夹,请重新指定文件夹!"); } } } AttibuteTuDou tudou = null; #region 程序集属性访问器 public AttibuteTuDou AssemblyTitle { get { Assembly ass = Assembly.Load("AttributeReflection"); Type[] t = ass.GetTypes(); foreach (Type type in t) { Attribute[] attributes = Attribute.GetCustomAttributes(type); if (attributes.Length > 0) { foreach (Attribute a in attributes) { tudou = (AttibuteTuDou)a; return tudou; } } } return null; } } public string AssemblyVersion { get { if (tudou != null) { return tudou.Version; } return "1.0.0"; } } public string AssemblyDescription { get { if (tudou != null) { return tudou.OtherDesc; } return "支持作者 支持原创"; } } public string AssemblyProduct { get { if (tudou != null) { return tudou.Producter; } return "土豆作品"; } } public string AssemblyCopyright { get { if (tudou != null) { return tudou.CopyRight; } return "CopyRights € 2010"; } } public string AssemblyCompany { get { if (tudou != null) { return tudou.Company; } return "土豆工作室"; } } public string CreateDate { get { if (tudou != null) { return tudou.CreateDate; } return null; } } public string LastUpDate { get { if (tudou != null) { return tudou.LastUpTime; } return null; } } public string author { get { if (tudou != null) { return tudou.Author; } return "很拽の土豆"; } } #endregion private void btnDel_Click(object sender, EventArgs e) { if (this.txtPath.Text != null) { FileInfo f = new FileInfo(this.txtPath.Text); if (f.Exists) { if (MessageBox.Show("确认永久删除歌词" + f.FullName + "?","警告",MessageBoxButtons.OKCancel,MessageBoxIcon.Warning) == DialogResult.OK) { f.Delete(); } } } } } }
想想曾经为做这个付出的心血,不得不自己苦笑一下,兴趣吧,也许只是因为曾经的兴趣,有机会,我会再研究一下C#的。等我快老了吧。
一个非常简单的东西我却会用到高级特性,反射,系统热键注册,双缓冲,也许是因为有了需求,才有了结果吧。
先学好JAVA,做好当前事。
相关推荐
Android MP3播放器,带卡拉OK字幕.zip项目安卓应用源码下载Android MP3播放器,带卡拉OK字幕.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
前几年的Android应用源码Demo,主要面向的是学生毕业设计学习。
学生时代做的一个个人网站
1--[卡拉OK 1.3].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--[卡拉OK 1.3].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--[卡拉OK 1.3].zip源码scratch2.0 3.0编程项目源文件源码案例...
1--[卡拉OK 1.4].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--[卡拉OK 1.4].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--[卡拉OK 1.4].zip源码scratch2.0 3.0编程项目源文件源码案例...
2--[卡拉OK1.2].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--[卡拉OK1.2].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--[卡拉OK1.2].zip源码scratch2.0 3.0编程项目源文件源码案例素材源...
2--[卡拉OK 1.0].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--[卡拉OK 1.0].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--[卡拉OK 1.0].zip源码scratch2.0 3.0编程项目源文件源码案例...
还有以下两个成员函数:一个用于初始化学生姓名、学号、性别和年龄的构造函数,一个用于输出学生信息的函数。编写一个主函数。声明一个学学生对象。然后调用成员函数在屏幕输出学生信息。 编程环境:vs2010,语言:...
易语言卡拉OK系统源码.zip易语言项目例子源码下载易语言卡拉OK系统源码.zip易语言项目例子源码下载 1.合个人学习技术做项目参考 2.适合学生做毕业设计参考 3.适合小团队开发项目参考
简约怀旧格子本【告别学生时代】模板.zip毕业答辩模板打包下载简约怀旧格子本【告别学生时代】模板.zip毕业答辩模板打包下载简约怀旧格子本【告别学生时代】模板.zip毕业答辩模板打包下载简约怀旧格子本【告别学生...
提供了实现透明自绘的listbox控件源码,还有加载完整PNG图片的函数,这2个比较有价值吧。本人自制的播放器,代码做了大部分注释,类可能没分好。
一个简单的课程设计,学生管理系统1、每一条记录包括一个学生的学号、姓名、3门课成绩、平均成绩。 2、输入功能:可以一次完成若干条记录的输入。 3、显示功能:完成全部学生记录的显示。 4、查找功能:完成按...
8. ASP.NET一个简单的媒体播放器的设计与实现.zip:这个项目展示了一个简单的媒体播放器的设计和实现。用户可以播放音乐和视频文件,调整播放进度和音量,并提供基本的播放控制功能。 9. ASP.NET一种多商家网络商店...
Android 卡拉OK,歌词同步程序.zip项目安卓应用源码下载Android 卡拉OK,歌词同步程序.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
大数据时代下高职院校学生创新创业能力的培养策略.pdf
用C#做的一个学生综合信息管理系统, 在高校中由于学生众多,学籍信息量庞大,需要一个合理的软件平台来将信息整理保存。所以各个高校都有自己的学生个人信息系统便于学生及校方信息存放,并且双方能够通过此平台更...
Android 卡拉OK,歌词同步程序,练手项目,软著参考、实际项目框架参考、比赛练习案例,学习实例,开箱即用。适用于实际项目开发参考、教学案例、毕业设计、出书项目实例、学生面试前能力提升、开发辅助。
界面非常漂亮的音乐播放器.zipIOS应用例子源码下载界面非常漂亮的音乐播放器.zipIOS应用例子源码下载 1.适合学生学习研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
互联网时代下大学生的网络素养现状与培育.docx互联网时代下大学生的网络素养现状与培育.docx互联网时代下大学生的网络素养现状与培育.docx互联网时代下大学生的网络素养现状与培育.docx互联网时代下大学生的网络素养...