在微风 IM 版本2中我们实现了局域网内的p2p通信,具体见:
【开源下载】c#编写的聊天程序微风IM 版本2 增加局域网P2P通信
前面有朋友说微风IM的UI有点朴素,也确实,于是到网上去淘了件新衣服。
新的UI来自于网上开源程序,由“翱翔的雄鹰”老师编写的完全开源的QQ2010.(c# WinForm).新的UI中有许多自定义控件,我从其中学到了很多Winfrom控件制作的知识。
比如,带边框的文本框
using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Text;using System.Windows.Forms;using SimpleIMClient.Skin;namespace SimpleIMClient.Skin{ public partial class BasicQQTextBox : UserControl { private Graphics g = null; private Bitmap Bmp = null; private Color borderColor = Color.FromArgb(84, 165, 213); private Bitmap _icon; public BasicQQTextBox() { this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.ResizeRedraw, true); Bmp = ResClass.GetImgRes("frameBorderEffect_normalDraw"); Icon = ResClass.GetImgRes("keyboard"); InitializeComponent(); } [Description("文本"), Category("Appearance")] public string Texts { get { return textBox1.Text; } set { textBox1.Text = value; this.Invalidate(); } } [Description("图标"), Category("Appearance")] public Bitmap Icon { get { return _icon; } set { _icon = value; this.Invalidate(); } } [Description("密码框"), Category("Appearance")] public bool IsPass { get { return textBox1.UseSystemPasswordChar; } set { textBox1.UseSystemPasswordChar = value; if(value) Icon = ResClass.GetImgRes("keyboard"); } } [Description("只读"), Category("Appearance")] public bool ReadOn { get { return textBox1.ReadOnly; } set { textBox1.ReadOnly = value; if (value) textBox1.BackColor = Color.Gray; else textBox1.BackColor = Color.White; } } public System.Windows.Forms.TextBox textBox { get { return textBox1; } set { textBox1 = value; } } [Description("右键菜单"), Category("Appearance")] public override ContextMenuStrip ContextMenuStrip { get { return textBox1.ContextMenuStrip; } set { textBox1.ContextMenuStrip = value; } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); g = e.Graphics; if(Bmp==null) Bmp = ResClass.GetImgRes("frameBorderEffect_normalDraw"); if (Bmp != null) { g.DrawImage(Bmp, new Rectangle(0, 0, 4, 4), 0, 0, 4, 4, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(4, 0, this.Width - 8, 4), 4, 0, Bmp.Width - 8, 4, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(this.Width - 4, 0, 4, 4), Bmp.Width - 4, 0, 4, 4, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(0, 4, 4, this.Height - 6), 0, 4, 4, Bmp.Height - 8, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(this.Width - 4, 4, 4, this.Height - 6), Bmp.Width - 4, 4, 4, Bmp.Height - 6, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(0, this.Height - 2, 2, 2), 0, Bmp.Height - 2, 2, 2, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(2, this.Height - 2, this.Width - 2, 2), 2, Bmp.Height - 2, Bmp.Width - 4, 2, GraphicsUnit.Pixel); g.DrawImage(Bmp, new Rectangle(this.Width - 2, this.Height - 2, 2, 2), Bmp.Width - 2, Bmp.Height - 2, 2, 2, GraphicsUnit.Pixel); } if (Icon != null) g.DrawImage(Icon, new Rectangle(1, 1, Bmp.Width, Bmp.Height), 0, 0, Bmp.Width, Bmp.Height, GraphicsUnit.Pixel); } private void textBox1_MouseEnter(object sender, EventArgs e) { Bmp = ResClass.GetImgRes("frameBorderEffect_mouseDownDraw"); this.Invalidate(); } private void textBox1_MouseLeave(object sender, EventArgs e) { Bmp = ResClass.GetImgRes("frameBorderEffect_normalDraw"); this.Invalidate(); } protected override void OnParentFontChanged(EventArgs e) { base.OnParentFontChanged(e); textBox1.Font = this.Font; } protected override void OnParentForeColorChanged(EventArgs e) { base.OnParentForeColorChanged(e); textBox1.ForeColor = this.ForeColor; } private void textBox1_Enter(object sender, EventArgs e) { if (!textBox1.UseSystemPasswordChar) { if (textBox1.Text.Equals("<请输入帐号>")) { textBox1.Text = ""; textBox1.ForeColor = Color.Black; } } } private void textBox1_Leave(object sender, EventArgs e) { if (!textBox1.UseSystemPasswordChar) { if (textBox1.Text.Equals("")) { textBox1.Text = "<请输入帐号>"; textBox1.ForeColor = Color.DarkGray; } } } }}
鼠标经过时,显示边框的按钮
using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Text;using System.Windows.Forms;using SimpleIMClient.Skin;namespace SimpleIMClient.Skin{ public partial class LoginButton : UserControl { private Graphics g = null; private Bitmap Bmp = null; public LoginButton() { Bmp = ResClass.GetImgRes("login_btn_normal"); if (this.Focused) Bmp = ResClass.GetImgRes("login_btn_focus"); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.BackColor = Color.Transparent; this.Size = new Size(74,27); } [Description("文本"), Category("Appearance")] public string Texts { get { return Text; } set { Text = value; this.Invalidate(); } } private PointF GetPointF(string text) { float x, y; switch (text.Length) { case 1: x = (float)(this.Width - 12.5 * 1) / 2; y = 4; break; case 2: x = (float)(this.Width - 12.5 * 2) / 2; y = 4; break; case 3: x = (float)(this.Width - 12.5 * 3) / 2; y = 4; break; case 4: x = (float)(this.Width - 12.5 * 4) / 2; y = 4; break; case 5: x = (float)(this.Width - 12.3 * 5) / 2; y = 4; break; case 6: x = (float)(this.Width - 12.3 * 6) / 2; y = 4; break; default: x = (float)(this.Width - 12.3 * 4) / 2; y = 4; break; } return new PointF(x, y); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); g = e.Graphics; if (Bmp != null) { g.DrawImage(Bmp, new Rectangle(0, 0, this.Width, this.Height), 0, 0, Bmp.Width, Bmp.Height, GraphicsUnit.Pixel); } PointF point = GetPointF(this.Text); if (this.Enabled) g.DrawString(this.Texts, new Font("微软雅黑", 9F), Brushes.Black, point); else g.DrawString(this.Texts, new Font("微软雅黑", 9F), Brushes.Gray, point); } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); Bmp = ResClass.GetImgRes("login_btn_highlight"); this.Invalidate(); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); Bmp = ResClass.GetImgRes("login_btn_normal"); if (this.Focused) Bmp = ResClass.GetImgRes("login_btn_focus"); this.Invalidate(); } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); Bmp = ResClass.GetImgRes("login_btn_down"); this.Invalidate(); } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); Bmp = ResClass.GetImgRes("login_btn_normal"); if (this.Focused) Bmp = ResClass.GetImgRes("login_btn_focus"); this.Invalidate(); } }}
鼠标经过时显示边框效果的CheckBox
using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Text;using System.Windows.Forms;using SimpleIMClient.Skin;namespace SimpleIMClient.Skin{ [DefaultEvent("CheckedChanged")] public partial class BasicCheckBox : UserControl { private Graphics g = null; private bool m_Checked = false; private string m_buttonText = "CheckBox"; public enum CheckStates { Unchecked, Checked, Indeterminate } private CheckStates m_CheckState = CheckStates.Unchecked; public delegate void CheckedChangedEventHandler(object sender, bool Checked); public event CheckedChangedEventHandler CheckedChanged; private Bitmap Bmp = null; public BasicCheckBox() { if (Checked) { switch (CheckState) { case CheckStates.Checked: Bmp = ResClass.GetImgRes("cb_c_l"); break; case CheckStates.Indeterminate: Bmp = ResClass.GetImgRes("cb_b_l"); break; default: Bmp = ResClass.GetImgRes("cb_c_l"); break; } } else { Bmp = ResClass.GetImgRes("cb_n_l"); } this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.BackColor = Color.Transparent; this.Size = new Size(95,20); } [Description("按钮上的文本"), Category("Appearance")] public string Texts { get { return m_buttonText; } set { m_buttonText = value; this.Invalidate(); } } [Description("是否选中"), Category("Appearance")] public bool Checked { get { return m_Checked; } set { m_Checked = value; if (value) CheckState = CheckStates.Checked; else CheckState = CheckStates.Unchecked; if (CheckedChanged != null) CheckedChanged(this, value); } } [Description("选中状态"), Category("Appearance")] public CheckStates CheckState { get { return m_CheckState; } set { m_CheckState = value; switch (value) { case CheckStates.Unchecked: m_Checked = false; Bmp = ResClass.GetImgRes("cb_n_e"); break; case CheckStates.Checked: m_Checked = true; Bmp = ResClass.GetImgRes("cb_c_e"); break; case CheckStates.Indeterminate: m_Checked = true; Bmp = ResClass.GetImgRes("cb_b_e"); break; } this.Invalidate(new Rectangle(0, (Height - 15) / 2, 15, 15)); } } protected override void OnPaint(PaintEventArgs e) { if (Bmp != null) { g = e.Graphics; g.DrawImage(Bmp, new Rectangle(0, (this.Height - 15) / 2, 15, 15), 0, 0, Bmp.Width, Bmp.Height, GraphicsUnit.Pixel); g.DrawString(m_buttonText, this.Font, Brushes.Black, 16, (this.Height - 15) / 2); } } protected override void OnResize(EventArgs e) { base.OnResize(e); this.MinimumSize = new Size(15, 15); } protected override void OnClick(EventArgs e) { if (!Checked) { Checked = true; } else { Checked = false; } } protected override void OnDoubleClick(EventArgs e) { if (!Checked) { Checked = true; } else { Checked = false; } } protected override void OnMouseEnter(EventArgs e) { if (Checked) { switch (CheckState) { case CheckStates.Checked: Bmp = ResClass.GetImgRes("cb_c_e"); break; case CheckStates.Indeterminate: Bmp = ResClass.GetImgRes("cb_b_e"); break; default: Bmp = ResClass.GetImgRes("cb_c_e"); break; } } else { Bmp = ResClass.GetImgRes("cb_n_e"); } this.Invalidate(new Rectangle(0,(Height - 15)/2,15,15)); } protected override void OnMouseLeave(EventArgs e) { if (Checked) { switch (CheckState) { case CheckStates.Checked: Bmp = ResClass.GetImgRes("cb_c_l"); break; case CheckStates.Indeterminate: Bmp = ResClass.GetImgRes("cb_b_l"); break; default: Bmp = ResClass.GetImgRes("cb_c_l"); break; } } else { Bmp = ResClass.GetImgRes("cb_n_l"); } this.Invalidate(new Rectangle(0, (Height - 15) / 2, 15, 15)); } }}
我们看一下新的微风V3的UI
我们实现了登陆功能,注册新账号,找回密码等都没有实现,是原来UI 上面有的
聊天窗口:
支持更换皮肤
服务器端、数据库、通信框架没有变化,请去 微风IM V1,或 微风IM V2相关文章下载。
祝大家新年快乐
谢谢大家的支持
源码包含以下四个工程文件,通信框架需要另行下载
3.1版本已经发布
[c#源码]微风IM V3.1 支持TCP通信发送图片
微风IM3.2已发布
请见 [源码分享]微风IM 3.2 实现新用户注册 含详细过程
有朋友问性能的问题,请参见下面这篇文章
- 24楼流浪命
- mark
- 23楼King.Kes
- 推荐一个
- 22楼wongdavid
- 语音视频如何实现?
- Re: networkcomms通信框架
- @wongdavid,您好,对视频音频这方面不熟悉,希望熟悉的朋友能把这方面加上
- 21楼朝岑
- 赞一个
- 20楼时之沙漠
- 赞一个
- 19楼硬盘很大
- ding
- Re: networkcomms通信框架
- @硬盘很大,@时之沙漠,@WillBreak,@tom_and_jerry,@花儿笑弯了腰,@流浪命,感谢支持
- 18楼greystar
- 不错,赞个。问下,需要服务端支持的吧?
- Re: networkcomms通信框架
- @greystar,服务器端及客户端和数据库(sql2005),所有的源码都已经传上去了:)谢谢支持
- Re: networkcomms通信框架
- @greystar,@酷小孩,@朝岑,@猎风,@飞翔蚂蚁,@阿超-,@岁月如刀,@King.Kes, ,感谢支持
- 17楼安度
- 很好
- Re: networkcomms通信框架
- @安度,谢谢支持
- 16楼networkcomms通信框架
- 我重新传了一下 这次没有问题了 http://download.csdn.net/detail/networkcomms/8459381 和,,http://download.csdn.net/detail/networkcomms/8459417
- 15楼networkcomms通信框架
- http://www.cnblogs.com/networkcomms/p/4295115.html
- 14楼tom_and_jerry
- 感谢分享~
- 13楼networkcomms通信框架
- Csdn不知道为什么删除了,回去再试试能否重传上,您发个邮箱给我,我给您发一下
- 12楼阿超-
- 非常感谢。
- 11楼networkcomms通信框架
- 下载不需要积分:)
- Re: 岁月如刀
- @networkcomms通信框架,感谢博主~~
- Re: 灵雨飘零
- @networkcomms通信框架,资源已经删除了~~~~~~~~~~~
- 10楼飞翔蚂蚁
- 已经推荐,求源码下载学习!
- 9楼岁月如刀
- 推荐了,能贴出开源的QQ2010相关地址吗?
- Re: networkcomms通信框架
- @岁月如刀,qq2010原来的网址是www.seezt.com 由翱翔的雄鹰老师开发,但是现在网站打不开了,我已经qq2010相关的资源传到csdn上了。 ,http://download.csdn.net/detail/networkcomms/8455481 和 http://download.csdn.net/detail/networkcomms/8455485
- 8楼猎风
- 赞一个
- 7楼networkcomms通信框架
- 在我的工作环境中,只用到不到100个客户端,是个公文处理系统,服务器端CPU占用率非常低,也非常稳定,更多就没有测试了
- 6楼WillBreak
- 赞一个
- 5楼fishkuro
- 有做负载测试么
- Re: networkcomms通信框架
- @fishkuro,刚刚发现 networkcommsv3自带了压力测试工具,真是踏破铁鞋无觅处,得来全不费工夫,我整理一下,近期发布,谢谢大家
- 4楼networkcomms通信框架
- 曾经想创建一个,但没有做成,主要原因是NetworkComms框架在客户端创建连接时,会自动判断与服务器端的连接是否存在,如果已经存在则调用已经存在的连接。以至于我无法在客户端模拟出多个连接,多次努力无果,有兴趣的高手朋友可以指点一下,非常感谢 您可以用这个程序大概看下cpu使用率什么的
- 3楼networkcomms通信框架
- 刚刚发现 networkcommsv3自带了压力测试工具,真是踏破铁鞋无觅处,得来全不费工夫,我整理一下,近期发布,谢谢大家
- 2楼花儿笑弯了腰
- 不错不错
- 1楼酷小孩
- 赞一个