学生时代做的一个非常低级的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,做好当前事。