仿QQ聊天软件MyQQ源代码教学(北大青鸟完整版)
qq源代码
UserHelper..cs类代码using System;using System.Collections.Generic;using System.Text;namespace MyQQ{//记录登录的用户Idclass UserHelper{public static int loginId; //登录的用户Id}}using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Data.SqlClient;namespace MyQQ{///<summary>///聊天窗体///</summary>public partial class ChatForm : Form{public int friendId; // 当前聊天的好友号码public string nickName; // 当前聊天的好友昵称public int faceId; // 当前聊天的好友头像Idpublic ChatForm(){InitializeComponent();}// 窗体加载时的动作private void ChatForm_Load(object sender, EventArgs e){// 设置窗体标题this.Text = string.Format("与{0}聊天中",nickName);// 设置窗体顶部显示的好友信息picFace.Image = ilFaces.Images[faceId];lblFriend.Text = string.Format("{0}({1})",nickName,friendId);// 读取所有的未读消息,显示在窗体中ShowMessage();}// 关闭窗体private void btnClose_Click(object sender, EventArgs e){this.Close();}// 发送消息private void btnSend_Click(object sender, EventArgs e){if (txtChat.Text.Trim() == "") // 不能发送空消息{MessageBox.Show("不能发送空消息!", "提示", MessageBoxButtons.OK, rmation);return;}else if (txtChat.Text.Trim().Length > 50){MessageBox.Show("消息内容过长,请分为几条发送!", "提示", MessageBoxButtons.OK, rmation);return;}else// 发送消息,写入数据库{// MessageTypeId:1-表示聊天消息,为简化操作没有读取数据表,到S2可以用常量或者枚举实现// MessageState:0-表示消息状态是未读int result = -1; // 表示操作数据库的结果string sql = string.Format("INSERT INTO Messages (FromUserId, ToUserId, Message, MessageTypeId,MessageState) VALUES ({0},{1},'{2}',{3},{4})",UserHelper.loginId, friendId, txtChat.Text.Trim(), 1, 0);try{// 执行命令SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();result = command.ExecuteNonQuery();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}if (result != 1){MessageBox.Show("服务器出现意外错误!", "抱歉", MessageBoxButtons.OK, MessageBoxIcon.Error);}txtChat.Text = ""; // 输入消息清空this.Close();}}///<summary>///读取所有的未读消息,显示在窗体中///</summary>private void ShowMessage(){string messageIdsString = ""; // 消息的Id组成的字符串string message; // 消息内容string messageTime; // 消息发出的时间// 读取消息的SQL语句string sql = string.Format("SELECT Id, Message,MessageTime From Messages WHERE FromUserId={0} AND ToUserId={1} AND MessageTypeId=1 AND MessageState=0",friendId,UserHelper.loginId);try{SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();SqlDataReader reader = command.ExecuteReader();// 循环将消息添加到窗体上while (reader.Read()){messageIdsString += Convert.ToString(reader["Id"]) + "_";message = Convert.ToString(reader["Message"]);messageTime = Convert.ToDateTime(reader["MessageTime"]).ToString(); // 转换为日期类型,告诉学员lblMessages.Text += string.Format("\n{0} {1}\n{2}",nickName,messageTime,message);}reader.Close();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 把显示出的消息置为已读if (messageIdsString.Length > 1){messageIdsString.Remove(messageIdsString.Length - 1);SetMessageRead(messageIdsString, '_');}}///<summary>///把显示出的消息置为已读///</summary>private void SetMessageRead(string messageIdsString, char separator){string[] messageIds = messageIdsString.Split(separator); // 分割出每个消息Idstring sql = "Update Messages SET MessageState=1 WHERE Id="; // 更新状态的SQL语句的固定部分string updateSql; // 执行的SQL语句try{SqlCommand command = new SqlCommand(); // 创建Command对象command.Connection = DBHelper.connection; // 指定数据库连接DBHelper.connection.Open(); // 打开数据库连接foreach (string id in messageIds){if (id != ""){updateSql = sql + id; // 补充完整的SQL语句 mandText = updateSql; // 指定要执行的SQL语句int result = command.ExecuteNonQuery(); // 执行命令}}}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}}ChatForm.cs代码using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Data.SqlClient;namespace MyQQ{///<summary>///聊天窗体///</summary>public partial class ChatForm : Form{public int friendId; // 当前聊天的好友号码public string nickName; // 当前聊天的好友昵称public int faceId; // 当前聊天的好友头像Idpublic ChatForm(){InitializeComponent();}// 窗体加载时的动作private void ChatForm_Load(object sender, EventArgs e){// 设置窗体标题this.Text = string.Format("与{0}聊天中",nickName);// 设置窗体顶部显示的好友信息picFace.Image = ilFaces.Images[faceId];lblFriend.Text = string.Format("{0}({1})",nickName,friendId);// 读取所有的未读消息,显示在窗体中ShowMessage();}// 关闭窗体private void btnClose_Click(object sender, EventArgs e){this.Close();}// 发送消息private void btnSend_Click(object sender, EventArgs e){if (txtChat.Text.Trim() == "") // 不能发送空消息{MessageBox.Show("不能发送空消息!", "提示", MessageBoxButtons.OK, rmation);return;}else if (txtChat.Text.Trim().Length > 50){MessageBox.Show("消息内容过长,请分为几条发送!", "提示", MessageBoxButtons.OK, rmation);return;}else// 发送消息,写入数据库{// MessageTypeId:1-表示聊天消息,为简化操作没有读取数据表,到S2可以用常量或者枚举实现// MessageState:0-表示消息状态是未读int result = -1; // 表示操作数据库的结果string sql = string.Format("INSERT INTO Messages (FromUserId, ToUserId, Message, MessageTypeId, MessageState) VALUES ({0},{1},'{2}',{3},{4})",UserHelper.loginId, friendId, txtChat.Text.Trim(), 1, 0);try{// 执行命令SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();result = command.ExecuteNonQuery();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}if (result != 1){MessageBox.Show("服务器出现意外错误!", "抱歉", MessageBoxButtons.OK, MessageBoxIcon.Error);}txtChat.Text = ""; // 输入消息清空this.Close();}}///<summary>///读取所有的未读消息,显示在窗体中///</summary>private void ShowMessage(){string messageIdsString = ""; // 消息的Id组成的字符串string message; // 消息内容string messageTime; // 消息发出的时间// 读取消息的SQL语句string sql = string.Format("SELECT Id, Message,MessageTime From Messages WHERE FromUserId={0} AND ToUserId={1} AND MessageTypeId=1 AND MessageState=0",friendId,UserHelper.loginId);try{SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();SqlDataReader reader = command.ExecuteReader();// 循环将消息添加到窗体上while (reader.Read()){messageIdsString += Convert.ToString(reader["Id"]) + "_";message = Convert.ToString(reader["Message"]);messageTime = Convert.ToDateTime(reader["MessageTime"]).ToString(); // 转换为日期类型,告诉学员lblMessages.Text += string.Format("\n{0} {1}\n{2}",nickName,messageTime,message);}reader.Close();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 把显示出的消息置为已读if (messageIdsString.Length > 1){messageIdsString.Remove(messageIdsString.Length - 1);SetMessageRead(messageIdsString, '_');}}///<summary>///把显示出的消息置为已读///</summary>private void SetMessageRead(string messageIdsString, char separator){string[] messageIds = messageIdsString.Split(separator); // 分割出每个消息Idstring sql = "Update Messages SET MessageState=1 WHERE Id="; // 更新状态的SQL语句的固定部分string updateSql; // 执行的SQL语句try{SqlCommand command = new SqlCommand(); // 创建Command对象command.Connection = DBHelper.connection; // 指定数据库连接DBHelper.connection.Open(); // 打开数据库连接foreach (string id in messageIds){if (id != ""){updateSql = sql + id; // 补充完整的SQL语句 mandText = updateSql; // 指定要执行的SQL语句int result = command.ExecuteNonQuery(); // 执行命令}}}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}}private void lblMessages_Click(object sender, EventArgs e){}}}DBHelper.cs类代码using System;using System.Collections.Generic;using System.Text;using System.Data.SqlClient;namespace MyQQ{// 数据库帮助类,维护数据库连接字符串和数据库连接对象class DBHelper{private static string connString = "Data Source=.;database=MyQQ;integrated security=sspi";public static SqlConnection connection = new SqlConnection(connString);}}using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;namespace MyQQ{///<summary>///头像选择窗体///</summary>public partial class FacesForm : Form{public PersonalInfoForm personalInfoForm; // 个人信息窗体public FacesForm(){InitializeComponent();}1.FacesForm.cs代码private void FacesForm_Load(object sender, EventArgs e){for (int i = 0; i < ilFaces.Images.Count; i++){lvFaces.Items.Add(i.ToString());lvFaces.Items[i].ImageIndex = i;}}// 确定选择头像private void btnOK_Click(object sender, EventArgs e){if (lvFaces.SelectedItems.Count == 0){MessageBox.Show("请选择一个头像!", "提示", MessageBoxButtons.OK, rmation);}else{int faceId = lvFaces.SelectedItems[0].ImageIndex; // 获得当前选中的头像的索引personalInfoForm.ShowFace(faceId); // 设置个人信息窗体中显示的头像this.Close();}}// 双击时选择头像private void lvIcons_MouseDoubleClick(object sender, MouseEventArgs e){int faceId = lvFaces.SelectedItems[0].ImageIndex; // 获得当前选中的头像的索引 personalInfoForm.ShowFace(faceId); // 设置个人信息窗体中显示的头像this.Close();}// 关闭窗体private void btnCancel_Click(object sender, EventArgs e){this.Close();}}}LoginForm.csusing System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Data.SqlClient;namespace MyQQ{///<summary>///登录窗体///</summary>public partial class LoginForm : Form{public LoginForm(){InitializeComponent();}// 取消按钮的事件处理private void btnCancel_Click(object sender, EventArgs e){Application.Exit();}// 打开申请号码界面private void llbl_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {RegisterForm registerForm = new RegisterForm();registerForm.Show();}// 登录按钮事件处理private void btnLogin_Click(object sender, EventArgs e){bool error = false; // 标志在执行数据库操作的过程中是否出错// 如果输入验证成功,就验证身份,并转到相应的窗体if (ValidateInput()){int num = 0; // 数据库操作结果try{// 查询用的sql语句string sql = string.Format("SELECT COUNT(*) FROM Users WHERE Id={0} AND LoginPwd = '{1}'",int.Parse(txtLoginId.Text.Trim()), txtLoginPwd.Text.Trim());// 创建Command 对象SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open(); // 打开数据库连接num = Convert.ToInt32(command.ExecuteScalar());}catch (Exception ex){error = true;Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close(); // 关闭数据库连接}if (!error && (num == 1)) // 验证通过{// 设置登录的用户号码UserHelper.loginId = int.Parse(txtLoginId.Text.Trim());// 创建主窗体MainForm mainForm = new MainForm();mainForm.Show(); // 显示窗体this.Visible = false; // 当前窗体不可见}else{MessageBox.Show("输入的用户名或密码有误!", "登录提示", MessageBoxButtons.OK, MessageBoxIcon.Error);}}}// 忘记密码标签private void llblFogetPwd_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {MessageBox.Show("该功能尚未开通!","提示",MessageBoxButtons.OK,rmation);}// 用户输入验证private bool ValidateInput(){// 验证用户输入if (txtLoginId.Text.Trim() == ""){MessageBox.Show("请输入登录的号码", "登录提示", MessageBoxButtons.OK, rmation);txtLoginId.Focus();return false;}else if (txtLoginPwd.Text.Trim() == ""){MessageBox.Show("请输入密码", "登录提示", MessageBoxButtons.OK, rmation);txtLoginPwd.Focus();return false;}return true;}}}MainForm.csusing System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using Aptech.UI;using System.Data.SqlClient;using System.Media;namespace MyQQ{///<summary>///登录后的主窗体///</summary>public partial class MainForm : Form{int fromUserId; // 消息的发起者int friendFaceId; // 发消息的好友的头像Idint messageImageIndex = 0; // 工具栏中的消息图标的索引public MainForm(){InitializeComponent();}// 窗体加载时发生private void MainForm_Load(object sender, EventArgs e) {// 工具栏的消息图标tsbtnMessageReading.Image = ilMessage.Images[0];// 显示个人的信息ShowSelfInfo();// 添加SideBar 的两个组sbFriends.AddGroup("我的好友");sbFriends.AddGroup("陌生人");// 向我的好友组中添加我的好友列表ShowFriendList();}// 窗体关闭后,退出应用程序private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {Application.Exit();}// 显示个人信息窗体private void tsbtnPersonalInfo_Click(object sender, EventArgs e){PersonalInfoForm personalInfoForm = new PersonalInfoForm();personalInfoForm.mainForm = this; // 将当前窗体本身传给个人信息窗体 personalInfoForm.Show();}// 显示查找好友窗体private void tsbtnSearchFriend_Click(object sender, EventArgs e){SearchFriendForm searchFriendForm = new SearchFriendForm();searchFriendForm.Show();}// 双击一项,弹出聊天窗体private void sbFriends_ItemDoubleClick(SbItemEventArgs e){// 消息timer停止运行if (tmrChatRequest.Enabled == true){tmrChatRequest.Stop();e.Item.ImageIndex = this.friendFaceId;}// 显示聊天窗体ChatForm chatForm = new ChatForm();chatForm.friendId = Convert.ToInt32(e.Item.Tag); // 号码chatForm.nickName = e.Item.Text; // 昵称chatForm.faceId = e.Item.ImageIndex; // 头像chatForm.Show();}// 点击刷新好友列表private void tsbtnUpdateFriendList_Click(object sender, EventArgs e){ShowFriendList();}// 定时扫描数据库,找到未读消息private void tmrMessage_Tick(object sender, EventArgs e){ShowFriendList(); // 刷新好友列表int messageTypeId = 1; // 消息类型int messageState = 1; // 消息状态// 找出未读消息对应的好友Idstring sql = string.Format("SELECT Top 1 FromUserId, MessageTypeId, MessageState FROM Messages WHERE ToUserId={0} AND MessageState=0", UserHelper.loginId);SqlCommand command;// 消息有两种类型:聊天消息、添加好友消息try{command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();SqlDataReader dataReader = command.ExecuteReader();// 循环读出一个未读消息if (dataReader.Read()){this.fromUserId = (int)dataReader["FromUserId"];messageTypeId = (int)dataReader["MessageTypeId"];messageState = (int)dataReader["MessageState"];}dataReader.Close();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 判断消息类型,如果是添加好友消息,就启动喇叭timer,让小喇叭闪烁if (messageTypeId == 2 && messageState == 0){SoundPlayer player = new SoundPlayer("system.wav");player.Play();tmrAddFriend.Start();}// 如果是聊天消息,就启动聊天timer,让好友头像闪烁else if (messageTypeId == 1 && messageState == 0){// 获得发消息的人的头像Idsql = "SELECT FaceId FROM Users WHERE Id=" + this.fromUserId;try{command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();this.friendFaceId = Convert.ToInt32(command.ExecuteScalar()); // 设置发消息的好友的头像索引}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 如果发消息的人没有在列表中就添加到陌生人列表中if (!HasShowUser(fromUserId)){UpdateStranger(fromUserId);}SoundPlayer player = new SoundPlayer("msg.wav");player.Play();tmrChatRequest.Start(); // 启动闪烁头像定时器}}// 控制喇叭闪烁private void tmrAddFriend_Tick(object sender, EventArgs e){// 反复修改它的图像messageImageIndex = messageImageIndex == 0 ? 1:0;tsbtnMessageReading.Image = ilMessage.Images[messageImageIndex];}// 单击时显示请求好友消息窗体private void tsbtnMessageReading_Click(object sender, EventArgs e){tmrAddFriend.Stop(); // 消息timer停止运行// 图片恢复正常messageImageIndex = 0;tsbtnMessageReading.Image = ilMessage.Images[messageImageIndex];// 显示系统消息窗体RequestForm requestForm = new RequestForm();requestForm.Show();}// 让相应的好友头像闪烁private void tmrChatRequest_Tick(object sender, EventArgs e){// 循环好友列表两个组中的每个item,找到发消息的好友,让他的头像闪烁for (int i = 0; i < 2; i++){for (int j = 0; j < sbFriends.Groups[i].Items.Count; j++){if(Convert.ToInt32(sbFriends.Groups[i].Items[j].Tag) == this.fromUserId) {if (sbFriends.Groups[i].Items[j].ImageIndex < 100){sbFriends.Groups[i].Items[j].ImageIndex = 100;// 索引为的图片是一个空白图片}else{sbFriends.Groups[i].Items[j].ImageIndex = this.friendFaceId;}sbFriends.Invalidate(); // 重新绘制,只要告诉学生需要这句话才能正常闪烁头像就行}}}}// 显示右键菜单时,控制哪些菜单不可见private void cmsFriendList_Opening(object sender, CancelEventArgs e){// 如果没有选中的项if (sbFriends.SeletedItem == null){tsmiDelete.Visible = false;}else{tsmiDelete.Visible = true;}// 如果选中的是陌生人,显示加为好友菜单if (sbFriends.SeletedItem != null && sbFriends.SeletedItem.Parent == sbFriends.Groups[1]){tsmiAddFriend.Visible = true;}else{tsmiAddFriend.Visible = false;}}// 显示大、小头像视图切换private void tsmiView_Click(object sender, EventArgs e){if (sbFriends.View == rgeIcon){sbFriends.View = SbView.SmallIcon;tsmiView.Text = "显示大头像";}else if (sbFriends.View == SbView.SmallIcon){sbFriends.View = rgeIcon;tsmiView.Text = "显示小头像";}}// 删除好友private void tsmiDelete_Click(object sender, EventArgs e){DialogResult result; // 对话框结果int deleteResult = 0; // 操作结果if (sbFriends.SeletedItem != null){result = MessageBox.Show("确实要删除该好友吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);if (result == DialogResult.Yes) // 确认删除{if (sbFriends.VisibleGroup == sbFriends.Groups[0]){string sql = string.Format("DELETE FROM Friends WHERE HostId={0} AND FriendId={1}",UserHelper.loginId, Convert.ToInt32(sbFriends.SeletedItem.Tag));try{SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();deleteResult = command.ExecuteNonQuery();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}if (deleteResult == 1){MessageBox.Show("好友已删除", "提示", MessageBoxButtons.OK, rmation);sbFriends.SeletedItem.Parent.Items.Remove(sbFriends.SeletedItem);}}else{MessageBox.Show("好友已删除", "提示", MessageBoxButtons.OK, rmation);sbFriends.SeletedItem.Parent.Items.Remove(sbFriends.SeletedItem);}}}}// 将选中的人加为好友private void tsmiAddFriend_Click(object sender, EventArgs e){int result = 0; // 操作结果string sql = string.Format("INSERT INTO Friends (HostId, FriendId) VALUES({0},{1})",UserHelper.loginId, Convert.ToInt32(sbFriends.SeletedItem.Tag));try{SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();result = command.ExecuteNonQuery();}catch (Exception ex){Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}if (result == 1){MessageBox.Show("添加成功!", "提示", MessageBoxButtons.OK, rmation);sbFriends.SeletedItem.Parent.Items.Remove(sbFriends.SeletedItem);ShowFriendList(); // 更新好友列表}else{MessageBox.Show("添加失败,请稍候再试!", "提示", MessageBoxButtons.OK, rmation);}}// 退出private void tsbtnExit_Click(object sender, EventArgs e){DialogResult result = MessageBox.Show("确实要退出吗?", "操作确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);if (result == DialogResult.Yes){Application.Exit();}}// 可见组发生变化时,发出声音private void sbFriends_VisibleGroupChanged(SbGroupEventArgs e){SoundPlayer player = new SoundPlayer("folder.wav");player.Play();}///<summary>///登录后显示个人的信息///</summary>public void ShowSelfInfo(){string nickName = ""; // 昵称int faceId = 0; // 头像索引bool error = false; // 标识是否出现错误// 取得当前用户的昵称、头像string sql = string.Format("SELECT NickName, FaceId FROM Users WHERE Id={0}",UserHelper.loginId);try{// 查询SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();SqlDataReader dataReader = command.ExecuteReader();if (dataReader.Read()){if (!(dataReader["NickName"] is DBNull)) // 判断数据库类型是否为空 {nickName = Convert.ToString(dataReader["NickName"]);}faceId = Convert.ToInt32(dataReader["FaceId"]);}dataReader.Close();}catch (Exception ex){error = true;Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 根据操作数据库结果进行不同的操作if (error){MessageBox.Show("服务器请求失败!请重新登录!", "意外错误", MessageBoxButtons.OK, MessageBoxIcon.Error);Application.Exit();}else{// 在窗体标题显示登录的昵称、号码this.Text = UserHelper.loginId.ToString();this.picFace.Image = ilFaces.Images[faceId];this.lblLoginId.Text = string.Format("{0}({1})", nickName,UserHelper.loginId.ToString());}}///<summary>///向我的好友组中添加我的好友列表///</summary>private void ShowFriendList(){// 清空原来的列表sbFriends.Groups[0].Items.Clear();bool error = false; // 标识数据库是否出错// 查找有哪些好友string sql = string.Format("SELECT FriendId,NickName,FaceId FROM Users,Friends WHERE Friends.HostId={0} AND Users.Id=Friends.FriendId",UserHelper.loginId);try{// 执行查询SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();SqlDataReader dataReader = command.ExecuteReader();// 循环添加好友列表while (dataReader.Read()){// 创建一个SideBar项SbItem item = new SbItem((string)dataReader["NickName"], (int)dataReader["FaceId"]);item.Tag = (int)dataReader["FriendId"]; // 将号码放在Tag属性中// SideBar中的组可以通过数组的方式访问,按照添加的顺序索引从开始// Groups[0]表示SideBar中的第一个组,也就是“我的好友”组sbFriends.Groups[0].Items.Add(item); // 向SideBar的“我的好友”组中添加项 }dataReader.Close();}catch (Exception ex){error = true;Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 出错了if (error){MessageBox.Show("服务器发生意外错误!请尝试重新登录", "抱歉", MessageBoxButtons.OK, MessageBoxIcon.Error);Application.Exit();}}///<summary>///判断发消息的人是否在列表中///</summary>private bool HasShowUser(int loginId){bool find = false; // 表示是否在当前显示出的用户列表中找到了该用户// 循环SideBar 中的个组,寻找发消息的人是否在列表中for (int i = 0; i < 2; i++){for (int j = 0; j < sbFriends.Groups[i].Items.Count; j++){if (Convert.ToInt32(sbFriends.Groups[i].Items[j].Tag) == loginId){find = true;}}}return find;}///<summary>///更新陌生人列表///</summary>private void UpdateStranger(int loginId){// 选出这个人的基本信息string sql = "SELECT NickName, FaceId FROM Users WHERE Id=" + loginId;bool error = false; // 用来标识是否出现错误try{SqlCommand command = new SqlCommand(sql, DBHelper.connection);DBHelper.connection.Open();SqlDataReader dataReader = command.ExecuteReader(); // 查询if (dataReader.Read()){SbItem item = new SbItem((string)dataReader["NickName"],(int)dataReader["FaceId"]);item.Tag = this.fromUserId; // 将Id记录在Tag属性中sbFriends.Groups[1].Items.Add(item); // 向陌生人组中添加项}sbFriends.VisibleGroup = sbFriends.Groups[1]; // 设定陌生人组为可见组 }catch (Exception ex){error = true;Console.WriteLine(ex.Message);}finally{DBHelper.connection.Close();}// 出错了if (error){MessageBox.Show("服务器出现意外错误!", "抱歉", MessageBoxButtons.OK, MessageBoxIcon.Error);}}}}(资料素材和资料部分来自网络,供参考。
课程设计实训项目《蓝梦教育集团即时通讯系统》(仿腾讯QQ)——构建出客户端项目和共用功能类(第1部分)
J2EE课程设计实训教学示例项目《蓝梦教育集团即时通讯系统》(仿腾讯QQ)——构建出客户端项目和共用功能类(第1部分)1.1.1构建出客户端项目和引用第三方系统库文件1、构建出客户端项目SwingGUIIMApp——添加一个Java应用程序项目,项目名称为SwingGUIIMApp2、引用第三方系统库文件(1)引用服务器端的JDIC等系统库文件jdic.jar和jdic_stub.jar包文件(2)引用服务器端的Apache Common HttpClient等系统库文件commons-httpclient-3.1和commons-codec-1.3包文件(3)引用服务器端的Apache Validate等系统库文件commons-validator.jar和jakarta-oro.jar 包文件(4)引用服务器端的利用JDom技术实现的XML解析的系统库文件jdom.jar包文件(5)引用服务器端的利用Common 日志记录处理的功能实现的系统库文件commons-logging.jar包文件1.1.2构建出客户端项目中的共用功能类1、在该项目中添加一个名称为IMSystemException的自定义异常类(1)包名称为com.px1987.imsystem.client.exception,并且从ng.Exception继承(2)代码如下package com.px1987.imsystem.client.exception; public class IMSystemException extends Exception { private static final long serialVersionUID = 1L;public IMSystemException() {}public IMSystemException(String message) {super(message);}public IMSystemException(Throwable cause) {super(cause);}public IMSystemException(String message, Throwable cause) {super(message, cause);}}2、在项目中新建一个存放图像文件的目录images和拷贝图像文件(1)新建一个存放图像文件的目录images(2)然后将客户端程序中所需要的各个图像文件拷贝到对应的文件目录中,最后为下面的状态。
模仿QQ MFC 源码
登陆框.h#pragma once#include"afxcmn.h"#include"afxwin.h"// CLoginDlg 对话框class CLoginDlg : public CDialog{DECLARE_DYNAMIC(CLoginDlg)public:CLoginDlg(CWnd* pParent = NULL); // 标准构造函数virtual ~CLoginDlg();// 对话框数据enum { IDD = IDD_DIALOG_LOGIN };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持DECLARE_MESSAGE_MAP()public:afx_msg void OnBnClickedOk();CString m_strUsername;CString m_strPassord;afx_msg void OnBnClickedButtonClose();afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);private:BOOL m_bMoving;CPoint m_ptPreMove;public:CLinkCtrl m_cLinkRegister;CLinkCtrl m_cLinkFindpwd;static DWORD m_nIconID;//用于存放登录后托盘显示的图标afx_msg void OnNMClickSyslinkRegister(NMHDR *pNMHDR, LRESULT *pResult);afx_msg void OnNMClickSyslinkFindpwd(NMHDR *pNMHDR, LRESULT *pResult);virtual BOOL OnInitDialog();afx_msg void OnBnClickedButtonList();CButton m_btnList;afx_msg void OnPaint();afx_msg void OnOnlin();afx_msg void OnQme();afx_msg void OnLeave();afx_msg void OnBusy();afx_msg void OnDarao();afx_msg void OnYinshen();afx_msg LRESULT OnShowTask(WPARAM wParam, LPARAM lParam);void ToTray(BOOL Show);CButton m_btnJianPan;CButton m_btnConfig;CToolTipCtrl toolTipCtrl[3];NOTIFYICONDATA m_nid;virtual BOOL PreTranslateMessage(MSG* pMsg);afx_msg void Onshowwindow();afx_msg void OnOpenmainpanel();afx_msg void OnHideWindows();afx_msg void OnButtonClose();afx_msg void OnBnClickedButtonMin();afx_msg void OnBnClickedButtonJianpan();afx_msg void OnCbnSelchangeComboUsername();BOOL m_isRemPassword;afx_msg void OnBnClickedCheckSavepwd();BOOL m_isAutoLogin;afx_msg void OnBnClickedCheckAutologin();afx_msg void OnTimer(UINT_PTR nIDEvent);BOOL m_isFirstLoginAccount;//hj};登陆框.cpp// LoginDlg.cpp : 实现文件//#include"stdafx.h"#include"QQDemo.h"#include"LoginDlg.h"#include"RegisterDlg.h"#include"SeekDlg.h"#define WM_SHOWTASK WM_USER+1// CLoginDlg 对话框IMPLEMENT_DYNAMIC(CLoginDlg, CDialog)DWORD CLoginDlg::m_nIconID = IDI_IMONLINE;CLoginDlg::CLoginDlg(CWnd* pParent/*=NULL*/): CDialog(CLoginDlg::IDD, pParent), m_strUsername(_T("")), m_strPassord(_T("")), m_bMoving(FALSE), m_isRemPassword(TRUE), m_isAutoLogin(FALSE), m_isFirstLoginAccount(TRUE){}CLoginDlg::~CLoginDlg(){Shell_NotifyIcon(NIM_DELETE,&m_nid);//从托盘中删除}void CLoginDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);DDX_CBString(pDX, IDC_COMBO_USERNAME, m_strUsername);DDX_Text(pDX, IDC_EDIT_PASSWORD, m_strPassord);DDX_Control(pDX, IDC_SYSLINK_REGISTER, m_cLinkRegister);DDX_Control(pDX, IDC_SYSLINK_FINDPWD, m_cLinkFindpwd);DDX_Control(pDX, IDC_BUTTON_LIST, m_btnList);DDX_Control(pDX, IDC_BUTTON_JIANPAN, m_btnJianPan);DDX_Control(pDX, IDC_BUTTON_CONFIG, m_btnConfig);DDX_Check(pDX, IDC_CHECK_SA VEPWD, m_isRemPassword);DDX_Check(pDX, IDC_CHECK_AUTOLOGIN, m_isAutoLogin);}BEGIN_MESSAGE_MAP(CLoginDlg, CDialog)ON_BN_CLICKED(IDOK, &CLoginDlg::OnBnClickedOk)ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CLoginDlg::OnBnClickedButtonClose)ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_MESSAGE(WM_SHOWTASK, &CLoginDlg::OnShowTask)ON_NOTIFY(NM_CLICK, IDC_SYSLINK_REGISTER, &CLoginDlg::OnNMClickSyslinkRegister) ON_NOTIFY(NM_CLICK, IDC_SYSLINK_FINDPWD, &CLoginDlg::OnNMClickSyslinkFindpwd) ON_BN_CLICKED(IDC_BUTTON_LIST, &CLoginDlg::OnBnClickedButtonList)ON_WM_PAINT()ON_COMMAND(IDM_ONLIN, &CLoginDlg::OnOnlin)ON_COMMAND(IDM_QME, &CLoginDlg::OnQme)ON_COMMAND(IDM_LEA VE, &CLoginDlg::OnLeave)ON_COMMAND(IDM_BUSY, &CLoginDlg::OnBusy)ON_COMMAND(IDM_DARAO, &CLoginDlg::OnDarao)ON_COMMAND(IDM_YINSHEN, &CLoginDlg::OnYinshen)ON_COMMAND(ID_showWindow, &CLoginDlg::Onshowwindow)ON_COMMAND(IDC_BUTTON_CLOSE, &CLoginDlg::OnButtonClose)ON_COMMAND(1200,OnOpenmainpanel)ON_COMMAND(1201,OnHideWindows)ON_BN_CLICKED(IDC_BUTTON_MIN, &CLoginDlg::OnBnClickedButtonMin)ON_BN_CLICKED(IDC_BUTTON_JIANPAN, &CLoginDlg::OnBnClickedButtonJianpan)ON_CBN_SELCHANGE(IDC_COMBO_USERNAME, &CLoginDlg::OnCbnSelchangeComboUsername) ON_BN_CLICKED(IDC_CHECK_SA VEPWD, &CLoginDlg::OnBnClickedCheckSavepwd)ON_BN_CLICKED(IDC_CHECK_AUTOLOGIN, &CLoginDlg::OnBnClickedCheckAutologin)ON_WM_TIMER()END_MESSAGE_MAP()// CLoginDlg 消息处理程序void CLoginDlg::ToTray(BOOL Show){if(Show){UpdateData(TRUE);Shell_NotifyIcon(NIM_ADD,&m_nid); //放入托盘中ShowWindow(SW_HIDE); //隐藏主窗口}else{Shell_NotifyIcon(NIM_DELETE,&m_nid);//从托盘中删除}}//处理托盘的回调函数(也就是对托盘的一些消息响应如单击,右击,双击)LRESULT CLoginDlg::OnShowTask(WPARAM wParam, LPARAM lParam){switch(lParam){case WM_RBUTTONDOWN:{CRect rect;CPoint p;GetCursorPos(&p);CMenu menu;if(this->IsWindowVisible()){menu.CreatePopupMenu();menu.AppendMenu(MF_STRING,1201,_T("隐藏主面板"));menu.AppendMenu(MF_STRING,WM_DESTROY,_T("关闭"));menu.TrackPopupMenu(TPM_LEFTALIGN,p.x,p.y,this);}else{menu.CreatePopupMenu();menu.AppendMenu(MF_STRING,1200,_T("打开主面板"));menu.AppendMenu(MF_STRING,WM_DESTROY,_T("关闭"));menu.TrackPopupMenu(TPM_LEFTALIGN,p.x,p.y,this);}}break;case WM_LBUTTONDOWN:ShowWindow(SW_SHOW);break;}return 0;}void CLoginDlg::OnBnClickedOk(){UpdateData();BOOL isFind = FALSE;//判断是否已经找到密码CString temp;//存储格式化字符串if(m_strUsername == _T("")){MessageBox(_T("帐号不能为空!请重新输入!"));return;}if(m_strPassord == _T("")){MessageBox(_T("密码不能为空!请输入密码!"));return;}//判断该帐号是否已经注册(在qqData.ini文件中)//int nInqqdata;CString strAccountInqqData;CString strPasswordInqqData;int nCount=::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qqData.ini"));for(int i = 0;i < nCount;i++){temp.Format(_T("%d"),i + 1);::GetPrivateProfileString(_T("admin") + temp,_T("Account") + temp,m_strUsername, strAccountInqqData.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qqData.ini"));::GetPrivateProfileString(_T("admin") + temp,_T("Password") + temp,_T(""), strPasswordInqqData.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qqData.ini"));//如果账号,密码与配置文件中的数据一致则登录成功if (strAccountInqqData == m_strUsername){if(m_strPassord == strPasswordInqqData){isFind = TRUE;break;}}}if(!isFind){MessageBox(_T("账号或密码有错误,请确认后重新登录!"));return;}int bCount = ::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qq.ini"));CString strAccount;//存储本地读取文件中的账号CString strPassword;//存储本地文件中的密码CString strRemPassword;//存储配置文件中的记住密码状态CString strAutoLogin;//存储配置文件自动登录状态CString strLastLogin;//存储配置文件是否为上次登录状态BOOL isExistInqq=FALSE;//是否存在于本地的配置文件int nIndex;//帐号在配置文件中下标if (m_isRemPassword){strRemPassword = _T("1");}strRemPassword = _T("0");if (m_isAutoLogin){strAutoLogin = _T("1");}elsestrAutoLogin = _T("0");bCount++;//判断是否本地配置文件中已经存在该帐号的信息for (int i= 0;i < bCount;i++){nIndex=i + 1;temp.Format(_T("%d"),nIndex);::GetPrivateProfileString(_T("admin") + temp,_T("Account") + temp,_T(""), strAccount.GetBuffer(MAX_PA TH),MAX_PATH,_T(".\\qq.ini"));if(strAccount==m_strUsername){isExistInqq=TRUE;break;}}if (!isExistInqq){temp.Format(_T("%d"),bCount);::WritePrivateProfileString(_T("admin") +temp,_T("Account") + temp,m_strUsername,_T(".\\qq.ini"));//写入密码,当记住密码时为账户密码,否则密码为空if(m_isRemPassword){::WritePrivateProfileString(_T("admin") + temp,_T("Password") + temp,m_strPassord,_T(".\\qq.ini"));}else::WritePrivateProfileString(_T("admin") + temp,_T("Password") + temp,_T(""),_T(".\\qq.ini"));::WritePrivateProfileString(_T("admin") +temp,_T("isRemPassword") + temp,strRemPassword,_T(".\\qq.ini"));::WritePrivateProfileString(_T("admin") +temp,_T("isAutoLogin") + temp,strAutoLogin,_T(".\\qq.ini"));::WritePrivateProfileString(_T("FileCount"),_T("Count"),temp,_T(".\\qq.ini"));else{temp.Format(_T("%d"),nIndex);if(m_isRemPassword){::WritePrivateProfileString(_T("admin") + temp,_T("Password") + temp,m_strPassord,_T(".\\qq.ini"));}else::WritePrivateProfileString(_T("admin") + temp,_T("Password") + temp,_T(""),_T(".\\qq.ini"));::WritePrivateProfileString(_T("admin") + temp,_T("isRemPassword") + temp,strRemPassword,_T(".\\qq.ini"));::WritePrivateProfileString(_T("admin") + temp,_T("isAutoLogin") + temp,strAutoLogin,_T(".\\qq.ini"));}Shell_NotifyIcon(NIM_DELETE,&m_nid);//获得此时本地文件存在的帐号数目bCount = ::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qq.ini"));for(int i = 0;i < bCount;i++){temp.Format(_T("%d"),i + 1);::WritePrivateProfileString(_T("admin") + temp,_T("isLastLogin") + temp,_T("0"),_T(".\\qq.ini"));}//为现在这个帐号设置isLastLogin的值if (isExistInqq){temp.Format(_T("%d"),nIndex);::WritePrivateProfileString(_T("admin") + temp,_T("isLastLogin") + temp,_T("1"),_T(".\\qq.ini"));}else{temp.Format(_T("%d"),bCount);::WritePrivateProfileString(_T("admin") + temp,_T("isLastLogin") + temp,_T("1"),_T(".\\qq.ini"));}//对当前帐号的排名计数器设为,并写入本地配置文件中::WritePrivateProfileString(_T("admin") + temp,_T("Rank") + temp,_T("0"),_T(".\\qq.ini"));//遍历本地配置文件,除了本次登录的帐号外,其他帐号的排名计数都加for (int i = 0;i < bCount;i++){temp.Format(_T("%d"),i + 1);::GetPrivateProfileString(_T("admin") + temp,_T("isLastLogin") + temp,_T(""),strLastLogin.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));if (strLastLogin != _T("1")){int rank = GetPrivateProfileInt(_T("admin") + temp,_T("Rank") + temp,0,_T(".\\qq.ini"));rank++;CString strRank;strRank.Format(_T("%d"),rank);::WritePrivateProfileString(_T("admin") + temp,_T("Rank") + temp,strRank,_T(".\\qq.ini"));}}OnOK();}void CLoginDlg::OnLButtonDown(UINT nFlags, CPoint point){if (point.y <= 50){m_bMoving = TRUE;m_ptPreMove = point;ClientToScreen(&m_ptPreMove);//GetCapture();}CDialog::OnLButtonDown(nFlags, point);}void CLoginDlg::OnLButtonUp(UINT nFlags, CPoint point){m_bMoving = FALSE;CDialog::OnLButtonUp(nFlags, point);}void CLoginDlg::OnMouseMove(UINT nFlags, CPoint point){if (m_bMoving){CPoint ptTemp = point;ClientToScreen(&ptTemp);CPoint ptOffset = ptTemp - m_ptPreMove;m_ptPreMove = ptTemp;CRect rectWindow;GetWindowRect(&rectWindow);rectWindow += ptOffset;MoveWindow(&rectWindow);}CDialog::OnMouseMove(nFlags, point);}void CLoginDlg::OnNMClickSyslinkRegister(NMHDR *pNMHDR, LRESULT *pResult){// TODO: 在此添加控件通知处理程序代码//PNMLINK pNMLink = (PNMLINK)pNMHDR;//::ShellExecute(m_hWnd, _T("open"), pNMLink->item.szUrl, NULL, NULL, SW_SHOWNORMAL);CRegisterDlg dlg;if(IDOK != dlg.DoModal())return;//把注册信息存入qqData注册表UpdateData();int nCount = ::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qqData.ini"));nCount++;CString temp;temp.Format(_T("%d"),nCount);::WritePrivateProfileString(_T("admin") + temp,_T("Account") + temp,dlg.m_Reg_strAccount,_T(".\\qqData.ini"));::WritePrivateProfileString(_T("admin") + temp,_T("Password") + temp,dlg.m_Reg_strPassword,_T(".\\qqData.ini"));::WritePrivateProfileString(_T("FileCount"),_T("Count"),temp,_T(".\\qqData.ini"));*pResult = 0;}void CLoginDlg::OnNMClickSyslinkFindpwd(NMHDR *pNMHDR, LRESULT *pResult){// TODO: 在此添加控件通知处理程序代码//PNMLINK pNMLink = (PNMLINK)pNMHDR;//::ShellExecute(m_hWnd, _T("open"), pNMLink->item.szUrl, NULL, NULL, SW_SHOWNORMAL);CSeekDlg dlg;dlg.DoModal();*pResult = 0;}BOOL CLoginDlg::OnInitDialog(){CDialog::OnInitDialog();// TODO: 在此添加额外的初始化ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);CBitmap map1, map2, map3;map1.LoadBitmap(IDB_BITMAP1);m_btnList.SetBitmap(map1);map2.LoadBitmap(IDB_BITMAP9);m_btnJianPan.SetBitmap(map2);map3.LoadBitmap(IDB_BITMAP10);m_btnConfig.SetBitmap(map3);for (int i=0; i<3; ++i){toolTipCtrl[i].Create(this);}toolTipCtrl[0].AddTool(GetDlgItem(IDC_BUTTON_CONFIG), _T("设置"));toolTipCtrl[1].AddTool(GetDlgItem(IDC_BUTTON_MIN), _T("最小化"));toolTipCtrl[2].AddTool(GetDlgItem(IDC_BUTTON_CLOSE), _T("关闭"));m_nid.cbSize = (DWORD) sizeof(NOTIFYICONDATA);m_nid.hWnd = m_hWnd;m_nid.uID = IDI_OFFLINE;//IDR_MAINFRAME;m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_OFFLINE));m_nid.uFlags = NIF_ICON | NIF_MESSAGE|NIF_TIP;m_nid.uCallbackMessage = WM_SHOWTASK;wcscpy_s(m_nid.szTip,_T("QQ"));//实现任务栏无图标ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW,SWP_FRAMECHANGED);Shell_NotifyIcon(NIM_ADD, &m_nid);m_cLinkRegister.SetWindowText(_T("<ahref=\"/chs/index.html?from=client&ptlang=2052®key=&ADUIN=0&ADSESSION=0&ADT AG=CLIENT.QQ.4855_NewAccount_Btn.0&ADPUBNO=26095\">注册账号</a>"));m_cLinkFindpwd.SetWindowText(_T("<ahref=\"https:///cn2/findpsw/pc/pc_find_pwd_input_account?source_id=1003&ptlang=2052&aquin=105 8072426\">忘记密码</a>"));//获得本地配置文件中已经保存的账号数目int nCount = ::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qq.ini"));CString strAccount;//保存读取配置文件后的账号CString strPassword;//保存读取配置文件后的账号的密码CString temp;//保存格式化字符串int nShow;//显示帐号的个数//如果本地文件帐号数目小于四个,则把显示的数目设为帐号数目,否则显示四个if (nCount <= 4){nShow = nCount;}elsenShow = 4;//动态构造一个数组,存储每个帐号的登录排名计数(当前登录排名为,其他排名在之前基础上加)int *a = new int [nCount + 1];memset(a,0,nCount + 1);//把每个帐号的排名计数赋值给对应的数组元素for (int i = 0;i < nCount;i++){temp.Format(_T("%d"),i + 1);a[i] = ::GetPrivateProfileInt(_T("admin") + temp,_T("Rank") + temp,0,_T(".\\qq.ini"));}//对排名计数进行排序int i;int j;int k;for(i = 0;i < nCount;i++)for(j = i + 1;j < nCount;j++)if(a[i] > a[j]){k = a[i];a[i] = a[j];a[j] = k;}//把排名计数前指定位数增加到组合框for(int n= 0;n < nShow;n++){for (j = 0;j < nCount;j++){temp.Format(_T("%d"),j+1);if (a[n] == ::GetPrivateProfileInt(_T("admin") + temp,_T("Rank") + temp,0,_T(".\\qq.ini"))){::GetPrivateProfileString(_T("admin") + temp,_T("Account") + temp,_T(""), strAccount.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));((CComboBox*)GetDlgItem(IDC_COMBO_USERNAME))->InsertString(n,strAccount);break;}}}//把上次登录的帐号显示到组合框中CString isLastLogin;////保存配置文件中的是否为上次登录的账号int nIndex = 0;//存储上次登录账号的下标CString strRemPassword;//保存配置文件中的记住密码选择状态CString strAutoLogin;//保存配置文件中的自动登录选择状态for(int i = 0;i < nCount;i++){temp.Format(_T("%d"),i + 1);::GetPrivateProfileString(_T("admin") + temp,_T("isLastLogin") + temp,_T(""),isLastLogin.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));if (isLastLogin == _T("1")){nIndex = i + 1;break;}}//获得上一次登录的帐号,密码,记住密码状态,自动登陆状态temp.Format(_T("%d"),nIndex);::GetPrivateProfileString(_T("admin") + temp,_T("Account") + temp,_T(""), strAccount.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));::GetPrivateProfileString(_T("admin") + temp,_T("Password") + temp,_T(""), strPassword.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));::GetPrivateProfileString(_T("admin") + temp,_T("isRemPassword") + temp,_T(""), strRemPassword.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));::GetPrivateProfileString(_T("admin") + temp,_T("isAutoLogin") + temp,_T(""), strAutoLogin.GetBuffer(MAX_PATH),MAX_PA TH,_T(".\\qq.ini"));if (strRemPassword == _T("1")){m_isRemPassword = TRUE;}elsem_isRemPassword = FALSE;if (strAutoLogin == _T("1")){m_isAutoLogin = TRUE;m_isRemPassword = TRUE;}elsem_isAutoLogin = FALSE;m_strPassord = strPassword;UpdateData(FALSE);SetDlgItemText(IDC_COMBO_USERNAME,strAccount);SetTimer(1,5000,NULL);//设置定时器,用于自动登录//释放内存delete []a;return TRUE; // return TRUE unless you set the focus to a control// 异常: OCX 属性页应返回FALSE}void CLoginDlg::OnBnClickedButtonList(){// TODO: 在此添加控件通知处理程序代码CMenu menu, *pMenu;menu.LoadMenu(IDR_MENU1);pMenu = menu.GetSubMenu(0);CBitmap bitmap0,bitmap1,bitmap2,bitmap3,bitmap4,bitmap5,bitmap6,bitmap7;bitmap0.LoadBitmap(IDB_BITMAP1);bitmap1.LoadBitmap(IDB_BITMAP2);bitmap2.LoadBitmap(IDB_BITMAP3);bitmap3.LoadBitmap(IDB_BITMAP4);bitmap4.LoadBitmap(IDB_BITMAP5);bitmap5.LoadBitmap(IDB_BITMAP6);/*bitmap6.LoadBitmap(IDB_BITMAP7);bitmap7.LoadBitmap(IDB_BITMAP8);*/pMenu->SetMenuItemBitmaps(0, MF_BYPOSITION, &bitmap0, &bitmap0);pMenu->SetMenuItemBitmaps(1, MF_BYPOSITION, &bitmap1, &bitmap1);pMenu->SetMenuItemBitmaps(3, MF_BYPOSITION, &bitmap2, &bitmap2);pMenu->SetMenuItemBitmaps(4, MF_BYPOSITION, &bitmap3, &bitmap3);pMenu->SetMenuItemBitmaps(5, MF_BYPOSITION, &bitmap4, &bitmap4);pMenu->SetMenuItemBitmaps(7, MF_BYPOSITION, &bitmap5, &bitmap5);/*pMenu->SetMenuItemBitmaps(6, MF_BYPOSITION, &bitmap0, &bitmap0);pMenu->SetMenuItemBitmaps(7, MF_BYPOSITION, &bitmap0, &bitmap0);*/CRect rect;GetDlgItem(IDC_BUTTON_LIST)->GetWindowRect(&rect);pMenu->TrackPopupMenu(TPM_LEFTBUTTON,rect.right-rect.Width(), rect.bottom, this, 0);}void CLoginDlg::OnPaint(){CPaintDC dc(this); // device context for paintingCBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP12);CRect rect;GetClientRect(&rect);CDC demo;demo.CreateCompatibleDC(&dc);demo.SelectObject(&bitmap);//dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &demo, 0, 0, bitMap.bmWidth, bitMap.bmHeight, SRCCOPY);dc.BitBlt(0, 0, rect.Width(), rect.Height(), &demo, 0, 0, SRCCOPY);// 不为绘图消息调用CDialog::OnPaint()}void CLoginDlg::OnOnlin(){// TODO: 在此添加命令处理程序代码CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1);m_btnList.SetBitmap(bitmap);m_nIconID = IDI_IMONLINE;}void CLoginDlg::OnQme(){CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP2);m_btnList.SetBitmap(bitmap);m_nIconID = IDI_QME;// TODO: 在此添加命令处理程序代码}void CLoginDlg::OnLeave(){// TODO: 在此添加命令处理程序代码CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP3);m_btnList.SetBitmap(bitmap);m_nIconID = IDI_AWAY;}void CLoginDlg::OnBusy(){// TODO: 在此添加命令处理程序代码CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP4);m_btnList.SetBitmap(bitmap);m_nIconID = IDI_BUSY;}void CLoginDlg::OnDarao(){// TODO: 在此添加命令处理程序代码CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP5);m_btnList.SetBitmap(bitmap);m_nIconID = IDI_MUTE;}void CLoginDlg::OnYinshen(){// TODO: 在此添加命令处理程序代码CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP6);m_btnList.SetBitmap(bitmap);m_nIconID = IDI_INVISIBLE;}BOOL CLoginDlg::PreTranslateMessage(MSG* pMsg){// TODO: 在此添加专用代码和/或调用基类if (pMsg->message== WM_LBUTTONDOWN ||pMsg->message== WM_LBUTTONUP ||pMsg->message== WM_MOUSEMOVE)for (int i=0; i<3; ++i){toolTipCtrl[i].RelayEvent(pMsg);}return CDialog::PreTranslateMessage(pMsg);}void CLoginDlg::Onshowwindow(){// TODO: 在此添加命令处理程序代码ShowWindow(SW_SHOW);}void CLoginDlg::OnButtonClose(){// TODO: 在此添加命令处理程序代码PostMessage(WM_QUIT);ToTray(TRUE);}void CLoginDlg::OnBnClickedButtonClose(){static CRect rectLarge;static CRect rectSmall;if (rectLarge.IsRectNull()){CRect rectSeparator;GetWindowRect(&rectLarge);//获得变小前的对话框面积GetDlgItem(IDC_STATIC)->GetWindowRect(&rectSeparator);rectSmall.left = rectLarge.left;rectSmall.top = rectLarge.top;rectSmall.right = rectLarge.right;rectSmall.bottom = rectSeparator.bottom;}for (int i = rectSmall.Height(); i>=0; i--){SetWindowPos(NULL, 0, 0, rectSmall.Width(), i, SWP_NOMOVE | SWP_NOZORDER);Sleep(5);}//OnOK();PostMessage(WM_QUIT);ToTray(TRUE);}void CLoginDlg::OnBnClickedButtonMin(){// TODO: 在此添加控件通知处理程序代码ShowWindow(SW_HIDE);ToTray(TRUE);}void CLoginDlg::OnBnClickedButtonJianpan(){// TODO: 在此添加控件通知处理程序代码}void CLoginDlg::OnCbnSelchangeComboUsername(){m_isFirstLoginAccount=FALSE;//表示不是第一次登录的账号//获取当前选择的行,并显示到列表框中int nIndex = ((CComboBox*)GetDlgItem(IDC_COMBO_USERNAME))->GetCurSel();int nCount = ::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qq.ini"));((CComboBox*)GetDlgItem(IDC_COMBO_USERNAME))->GetLBText(nIndex,m_strUsername);int n=0;//保存账号在配置文件中的下标CString temp;//保存格式化的字符串CString strAccount;//保存在配置文件中的读取到的账号CString strPassword;//保存在配置文件中的读取到的账号的密码CString strRemPassword;//保存最近一次账号登录的记住密码状态CString strAutoLogin;//保存最近一次账号登录的自动登录状态//遍历配置文件,判断上次保存的密码记住状态!for(int i = 0;i < nCount;i++){temp.Format(_T("%d"),i + 1);::GetPrivateProfileString(_T("admin")+temp,_T("Account")+temp,_T(""),strAccount.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));if (m_strUsername == strAccount){n=i+1;::GetPrivateProfileString(_T("admin")+temp,_T("isRemPassword")+temp,_T(""),strRemPassword.GetBuffe r(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));if (strRemPassword==_T("1")){m_isRemPassword=TRUE;}elsem_isRemPassword=FALSE;break;}}//再考虑自动登录框的选择状态::GetPrivateProfileString(_T("admin")+temp,_T("isAutoLogin")+temp,_T(""),strAutoLogin.GetBuffer(MAX_PATH),MAX_PA TH,_T(".\\qq.ini"));//如果是自动登录,那要记住密码if(strAutoLogin == _T("1")){m_isRemPassword = TRUE;m_isAutoLogin = TRUE;}elsem_isAutoLogin = FALSE;temp.Format(_T("%d"),n);::GetPrivateProfileString(_T("admin") + temp,_T("Password") + temp,_T(""), strPassword.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));m_strPassord = strPassword;SetDlgItemText(IDC_EDIT_PASSWORD,m_strPassord);CButton *ptn = (CButton*)GetDlgItem(IDC_CHECK_SA VEPWD); //获得CheckBox的指针ptn->SetCheck(m_isRemPassword);//设置记住密码框选择状态CButton *qtn = (CButton*)GetDlgItem(IDC_CHECK_AUTOLOGIN); //获得CheckBox的指针qtn->SetCheck(m_isAutoLogin);//设置自动登录框选择状态}void CLoginDlg::OnBnClickedCheckSavepwd(){//如果记住密码状态没有选,则自动登录也不能选CButton *pRemPassWord = (CButton*)GetDlgItem(IDC_CHECK_SA VEPWD);CButton *pBtnAutoLogin = (CButton*)GetDlgItem(IDC_CHECK_AUTOLOGIN);if (pRemPassWord->GetCheck() == 0){pBtnAutoLogin->SetCheck(0);}}void CLoginDlg::OnBnClickedCheckAutologin(){// TODO: 在此添加控件通知处理程序代码//如果当前不是自动登录状态,则单击后,为自动登录状态,否则取消自动登录状态if (!m_isAutoLogin){m_isAutoLogin = TRUE;m_isRemPassword = TRUE; //如果为自动登录状态,则应该记住密码CButton *q = (CButton*)GetDlgItem(IDC_CHECK_SA VEPWD);q->SetCheck(m_isRemPassword);}else{m_isAutoLogin = FALSE;}CButton *p = (CButton*)GetDlgItem(IDC_CHECK_AUTOLOGIN); //获得CheckBox的指针p->SetCheck(m_isAutoLogin);//设置选择状态}void CLoginDlg::OnTimer(UINT_PTR nIDEvent){// 如果是不是上一次登录的账号,则返回if(!m_isFirstLoginAccount)return;UpdateData();int nCount=::GetPrivateProfileInt(_T("FileCount"),_T("Count"),0,_T(".\\qq.ini"));CString temp;//存储格式化字符串CString strAccount;//存储读取文件中的账号CString strPassword;//存储读取文件中的密码CString strAutoLogin;//存储读取文件中的自动登录状态//遍历配置文件,找到当前输入的账号密码,取得该账号的自动登录的选择状态for(int i = 0;i < nCount;i++){temp.Format(_T("%d"),i + 1);::GetPrivateProfileString(_T("admin")+temp,_T("Account")+temp,m_strUsername, strAccount.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));::GetPrivateProfileString(_T("admin")+temp,_T("Password")+temp,_T(""), strPassword.GetBuffer(MAX_PA TH),MAX_PA TH,_T(".\\qq.ini"));if ((m_strUsername == strAccount)&&(m_strPassord == strPassword)){::GetPrivateProfileString(_T("admin")+temp,_T("isAutoLogin")+temp,_T(""), strAutoLogin.GetBuffer(MAX_PATH),MAX_PA TH,_T(".\\qq.ini"));//如果为自动登录状态,则调用OnOk,关闭定时器if (strAutoLogin == _T("1")){OnOK();KillTimer(1);break;}}}CDialog::OnTimer(nIDEvent);}void CLoginDlg::OnOpenmainpanel(){//托盘右键菜单实现,隐藏主面板ShowWindow(SW_SHOW);}void CLoginDlg::OnHideWindows(){//托盘右键菜单实现,打开主面板ShowWindow(SW_HIDE);}主界面.h// QQDemoDlg.h : 头文件//#pragma once#include"Linkname.h"#include"RoomDlg.h"#include"GroupDlg.h"#include"SessionDlg.h"#include"Twitter.h"#include"afxwin.h"#include"EditDlg.h"// CQQDemoDlg 对话框class CQQDemoDlg : public CDialog{// 构造public:CQQDemoDlg(CWnd* pParent = NULL); // 标准构造函数~CQQDemoDlg();// 对话框数据enum { IDD = IDD_QQDEMO_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 实现public:void ToTray(DWORD dwMessage,HICON hIcon);//用于托盘的增加,修改,删除操作protected://修正移动时窗口的大小void FixMoving(UINT fwSide, LPRECT pRect);//修正改改变窗口大小时窗口的大小void FixSizing(UINT fwSide, LPRECT pRect);//从收缩状态显示窗口void DoShow();//从显示状态收缩窗口void DoHide();//重载函数,只是为了方便调用BOOL SetWindowPos(const CWnd* pWndInsertAfter,LPCRECT pCRect, UINT nFlags = SWP_SHOWWINDOW);afx_msg void OnTimer(UINT nIDEvent);afx_msg void OnSizing(UINT fwSide, LPRECT pRect);afx_msg int OnCreate(LPCREA TESTRUCT lpCreateStruct);afx_msg void OnMoving(UINT fwSide, LPRECT pRect);。
(完整)基于MFC仿QQ聊天程序设计完整实例教程
本系统基于客户端/服务器基本原理,程序即是服务端,也是客户端,通过IP就可以相互添加好友,并且实现点到点通信,有聊天记录(未实现根据用户发送的消息而改变字体颜色,只能在客户端改),字体颜色设置(一改全改~),包含主界面MaindBord和聊天Talk两大功能模块。
(1) MaindBord模块A、登录模块登陆模块的实现过程有下面几个步骤:(1)初始化列表信息,获取用户名,服务器的IP地址,使按键失效(2)确认登陆后创建套接字,绑定,监听(3)初始化成功后,激活添加好友和隐藏功能B、好友模块添加好友的实现过程有下面几个步骤:(1)弹出对话框(2)获取对话框中的IP(3)检查对方是否在线,建立连接(4)发送请求验证C、好友列表模块(1)客户接收请求,将服务端加入列表,发送客户端信息(2)服务端得到客户端信息,加入列表(3)双击好友列表,弹出发送信息对话框D、隐藏模块(1)隐藏与显示(2)响应鼠标,弹出控制菜单(2)聊天Talk模块A、发送信息模块聊天模块中,发送信息模块的实现过程有下面几个步骤:(1)通过列表双击一个好友为聊天对象,弹出聊天窗口;(2)用户按下发送按钮后,检测对方是否在线,检测对方是否在线(3)将聊天内容发送出去(4)在本地即时聊天内容显示的编辑框中添加发送的内容并写入聊天记录。
B、接收信息模块聊天模块中,接收信息模块的实现过程有下面几个步骤:(1)由主界面判断接收到信息的类型,是否为好友发来信息,如果是,则打开聊天窗口(2)读取消息,并写入聊天记录,(3)载入字体颜色信息。
(4) 显示聊天记录C、聊天记录管理模块聊天记录管理模块的实现过程有下面几个步骤:(1)将发送内容和接收内容写入文本文件;(2)显示聊天记录;(3)删除聊天记录。
D、字体颜色模块实现字体颜色模块的过程有下面几个步骤:(1)调用系统字体,获取字体,写入存档(2) 调用系统字体颜色,获取颜色,写入存档(3)读取、更新字体颜色。
仿QQ聊天软件MyQQ源代码教学北大青鸟完整版
课时 2 2 4
4
4
4 4
软件开发流程
比尔盖子是一名建筑工人
起初只干一些比较简单的 建筑工作 凭个人技术和经验,不需要特 别设计,可以顺利完成
如同编写早期比较小的程序
软件开发流程
新任务:建造一间非常美 丽而完整的房间 工作变得复杂许多
像不断发展的软件,功能 越来越多,越来越复杂
软件开发流程
软件复杂性
阶段项目 MyQQ
阶段项目简介
任务:MyQQ 聊天工具 系统结构:C/S,通过数据库交换聊天消息 小组形式完成 学时:24学时
项目实施和课程安排
课程进度 第一次课 第二次课 第三次课 第四次课 第五次课 第六次课
描述 项目讲解 项目准备阶段 任务讲解 第一次集中编码 任务讲解 第二次集中编码 任务讲解 第三次集中编码 任务讲解 第四次集中编码 总结和答辩
QQ模拟聊天软件程序设计(编码)
QQ模拟聊天软件程序设计(编码)版本:V1.0文档名称:QQ模拟聊天软件程序设计(编码)项目名称:QQ模拟聊天软件项目负责人:XX评审日期: 2012年12月5日目录1、前言 (3)1. 背景 (3)2. 规范实施建议 (3)3. 定义和约定 (3)2、格式规范 (3)1. 缩进 (3)2. 行长度 (3)3. 声明 (4)a) 声明变量、常量 (4)b) 声明类 (4)4. 语句 (4)3、命名规范 (5)1. 通用规则 (5)2. 项目规则 (5)3. 附加说明 (6)4、组织规范 (6)1. web工程目录规范 (6)2. 引入包规范 (6)5、注释规范 (6)1. 通用注释规则 (6)a) 说明 (6)b)javadoc注释标签语法定义说明 (6)2. 类的注释 (7)3. 方法的注释 (7)4. 失效代码块的注释 (7)5. 分支语句的注释 (8)6. 变量、常量的注释 (8)6、异常处理规范 (9)7、补充规范 (9)一、前言1. 背景在项目开发维护中,编码规范作为开发规范的一个组成部分,是十分重要和必须的,它不仅仅是为了提高开发效率,也有利于降低后期维护开发的成本。
编码规范的根本目的就是要让不仅代码可以一目了然,也可以很容易的理解开发人员所编写的代码程的用途和意义。
由此,用来减少项目中因为开发维护人员的更替或由于长时间不维护造成的记忆模糊或混乱等情况带来的对代码所实现的真正功能的理解困难和歧义。
另外也提高了代码复查效率和效果。
2. 规范实施建议不是为了规范而规范,以提高软件开发质量和效率为目标,逐步改进编码规范化水平对于格式规范、注释规范等部分规范的要求,java代码可以通过使用eclipse自带的Format方法(快捷键:Ctrl+Shift+F)进行自动格式化,可以提高开发效率又符合编码规范。
3. 定义和约定第1个字符大写,其后每个单词的第1个字母大写第1个字符小写,其后每个单词的第1个字母大写二、格式规范1. 缩进使用Tab键缩进;不允许使用空格键进行缩进。
仿qq软件课课程设计
仿qq软件课课程设计一、教学目标本课程的学习目标包括知识目标、技能目标和情感态度价值观目标。
知识目标要求学生掌握QQ软件的基本功能,如即时通讯、文件传输、语音视频通话等。
技能目标要求学生能够熟练操作QQ软件,进行信息的发送和接收、文件的传输和共享、语音视频通话的建立和结束等。
情感态度价值观目标要求学生树立正确的网络交往观念,认识到网络交流的工具性,注重个人信息的保护,遵守网络道德规范,促进良好的网络环境的建设。
二、教学内容本课程的教学内容主要包括QQ软件的基本功能和使用方法。
首先,介绍QQ软件的下载和安装方法,以及账号的注册和登录过程。
然后,详细讲解QQ软件的界面结构和功能模块,如消息、联系人、群聊、文件传输等。
接着,通过实际操作演示,引导学生掌握QQ软件的使用方法,如发送和接收消息、发起语音视频通话、传输文件等。
最后,结合实例,介绍QQ软件的高级功能和技巧,如自定义QQ界面、设置消息提醒、使用QQ群功能等。
三、教学方法为了激发学生的学习兴趣和主动性,本课程将采用多种教学方法。
首先,通过讲授法,向学生传授QQ软件的基本知识和使用方法。
其次,利用讨论法,学生进行小组讨论,分享彼此的操作经验和技巧。
然后,采用案例分析法,分析实际案例,让学生了解QQ软件在实际生活中的应用和价值。
最后,运用实验法,让学生亲自动手操作QQ软件,进行实践操作和练习。
四、教学资源为了支持教学内容和教学方法的实施,丰富学生的学习体验,我们将选择和准备适当的教学资源。
教材方面,我们将使用《计算机应用基础》教材,该书详细介绍了QQ软件的使用方法和技巧。
参考书方面,我们将推荐《QQ使用技巧手册》等书籍,供学生课后阅读和参考。
多媒体资料方面,我们将制作PPT演示文稿,以图文并茂的形式展示QQ软件的操作过程和功能特点。
实验设备方面,我们将准备计算机实验室,确保每个学生都能有机会亲自操作QQ软件。
五、教学评估本课程的教学评估方式包括平时表现、作业和考试三个部分,以保证评估的客观性和公正性。
(完整)基于MFC仿QQ聊天程序设计完整实例教程
本系统基于客户端/服务器基本原理,程序即是服务端,也是客户端,通过IP就可以相互添加好友,并且实现点到点通信,有聊天记录(未实现根据用户发送的消息而改变字体颜色,只能在客户端改),字体颜色设置(一改全改~),包含主界面MaindBord和聊天Talk两大功能模块。
(1) MaindBord模块A、登录模块登陆模块的实现过程有下面几个步骤:(1)初始化列表信息,获取用户名,服务器的IP地址,使按键失效(2)确认登陆后创建套接字,绑定,监听(3)初始化成功后,激活添加好友和隐藏功能B、好友模块添加好友的实现过程有下面几个步骤:(1)弹出对话框(2)获取对话框中的IP(3)检查对方是否在线,建立连接(4)发送请求验证C、好友列表模块(1)客户接收请求,将服务端加入列表,发送客户端信息(2)服务端得到客户端信息,加入列表(3)双击好友列表,弹出发送信息对话框D、隐藏模块(1)隐藏与显示(2)响应鼠标,弹出控制菜单(2)聊天Talk模块A、发送信息模块聊天模块中,发送信息模块的实现过程有下面几个步骤:(1)通过列表双击一个好友为聊天对象,弹出聊天窗口;(2)用户按下发送按钮后,检测对方是否在线,检测对方是否在线(3)将聊天内容发送出去(4)在本地即时聊天内容显示的编辑框中添加发送的内容并写入聊天记录。
B、接收信息模块聊天模块中,接收信息模块的实现过程有下面几个步骤:(1)由主界面判断接收到信息的类型,是否为好友发来信息,如果是,则打开聊天窗口(2)读取消息,并写入聊天记录,(3)载入字体颜色信息。
(4) 显示聊天记录C、聊天记录管理模块聊天记录管理模块的实现过程有下面几个步骤:(1)将发送内容和接收内容写入文本文件;(2)显示聊天记录;(3)删除聊天记录。
D、字体颜色模块实现字体颜色模块的过程有下面几个步骤:(1)调用系统字体,获取字体,写入存档(2) 调用系统字体颜色,获取颜色,写入存档(3)读取、更新字体颜色。
《蓝梦教育集团即时通讯系统》(仿腾讯QQ)——构建出系统拖盘及系统托盘菜单相关的功能实现类(第1部分)
J2EE课程设计实训教学示例项目《蓝梦教育集团即时通讯系统》(仿腾讯QQ)——构建出系统拖盘及系统托盘菜单相关的功能实现类(第1部分)1.1.1构建出系统拖盘相关的功能实现类1、Windows系统托盘图标(1)什么是Windows系统托盘图标?Windows状态栏也称系统托盘,位于任务栏的右侧。
很多软件运行时会在系统托盘区出现一个小图标,它作为程序运行的一个标志,用户可以通过使用小图标控制程序的显示/隐藏,以及用弹出菜单的方式来控制应用程序。
这样不仅方便了用户,而且使用系统托盘图标以更好的节约Windows任务栏的资源。
这个小图标被称作Windows系统托盘图标,如:Windows系统的输入法、声音控制图标,或金山词霸、MSN、超级解霸等软件的图标。
(2)主要的特性1)能够接受任何16x16大小的JPG/GIF图片文件作为托盘图标;2)能够在鼠标移到托盘图标上面时显示提示信息;3)通过单击托盘图标显示/隐藏程序界面;4)程序最小化时不显示在任务条中;5)右键单击托盘图标弹出程序控制菜单;6)为托盘的其它鼠标事件提供接口,如双击等;7)实现了点击按钮窗体关闭,托盘图标挂于系统托盘上,鼠标双击托盘图标,窗体显示,托盘图标消失,8)在托盘图标上点右键可弹出选择菜单,分别能完成不同的任务要求。
2、JDIC的系统托盘工具类(1)类名称为IMSystemTrayUtilByJDIC,包名称为com.px1987.imsystem.client.systemtray.util(2)编程该类package com.px1987.imsystem.client.systemtray.util;import org.jdesktop.jdic.tray.TrayIcon;import com.px1987.imsystem.client.exception.IMSystemException;import com.px1987.imsystem.client.factory.GenericTypeMethodsFactory;import com.px1987.imsystem.client.systemtray.inter.IMSystemTrayInterface; import com.px1987.imsystem.client.xmlparse.ParseXMLConfFileAllTags;public class IMSystemTrayUtilByJDIC {private static TrayIcon oneTrayIcon = null;public static TrayIcon getOneTrayIcon() {return IMSystemTrayUtilByJDIC.oneTrayIcon;}public static void setOneTrayIcon(TrayIcon oneTrayIcon) {IMSystemTrayUtilByJDIC.oneTrayIcon = oneTrayIcon;}public static void createIMSystemTray() { //下面的代码是创建出系统托盘对象IMSystemTrayInterface oneIMSystemTray = null;String imSystemTrayClassName =ParseXMLConfFileAllTags.getProperty("imSystemTray.className");try {oneIMSystemTray = new GenericTypeMethodsFactory().newSomeOneInstance(imSystemTrayClassName); //利用范型工厂方法直接获得目标对象实例oneIMSystemTray.createIMSystemTray();} catch (IMSystemException exception) {exception.printStackTrace();System.out.println("出现了IMSystemException异常错误,错误信息为:" +exception.getMessage());}}}3、JDK的系统托盘工具类(1)类名称为IMSystemTrayUtilByJDK,包名称为com.px1987.imsystem.client.systemtray.util(2)编程该类package com.px1987.imsystem.client.systemtray.util;import java.awt.TrayIcon;public class IMSystemTrayUtilByJDK {private static TrayIcon oneTrayIconByJDK=null;public static TrayIcon getOneTrayIconByJDK() {return IMSystemTrayUtilByJDK.oneTrayIconByJDK;}public static void setOneTrayIconByJDK(TrayIcon oneTrayIconByJDK) {IMSystemTrayUtilByJDK.oneTrayIconByJDK = oneTrayIconByJDK;}}4、IMSystemTrayInterface接口(1)接口名称为IMSystemTrayInterface,包名称为com.px1987.imsystem.client.systemtray.inter(2)设计该接口package com.px1987.imsystem.client.systemtray.inter;import com.px1987.imsystem.client.exception.IMSystemException;public interface IMSystemTrayInterface {public void createIMSystemTray() throws IMSystemException;public void createPopupMenu();}5、IMSystemTrayInterface接口的实现类——采用JDK API实现(1)类名称为IMSystemTray_byJDK,包名称为com.px1987.imsystem.client.systemtray.imple,并且实现IMSystemTrayInterface接口(2)编程该类package com.px1987.imsystem.client.systemtray.imple;import java.awt.AWTException;import java.awt.Desktop;import java.awt.Image;import java.awt.SystemTray;import java.awt.Toolkit;import java.awt.TrayIcon;import com.px1987.imsystem.client.exception.IMSystemException;importcom.px1987.imsystem.client.systemtray.event.IMSystemTray_MouseListenerEventHandler; import com.px1987.imsystem.client.systemtray.inter.IMSystemTrayInterface;import com.px1987.imsystem.client.systemtray.popupmenu.PopupMenu_IMSystemTray_byJDK; import com.px1987.imsystem.client.systemtray.util.IMSystemTrayUtilByJDK;public class IMSystemTray_byJDK implements IMSystemTrayInterface{ //下面的代码是创建出采用JDK6中对系统托盘技术支持对象private Desktop oneDesktop= null;public Desktop getOneDesktop() {return oneDesktop;}public void setOneDesktop(Desktop oneDesktop) {this.oneDesktop = oneDesktop;}private SystemTray oneSystemTray= null;private PopupMenu_IMSystemTray_byJDK onePopupMenu= null;public PopupMenu_IMSystemTray_byJDK getOnePopupMenu() {return onePopupMenu;}public void setOnePopupMenu(PopupMenu_IMSystemTray_byJDK onePopupMenu) { this.onePopupMenu = onePopupMenu;}public IMSystemTray_byJDK() {}public void createIMSystemTray() throws IMSystemException {if (Desktop.isDesktopSupported()) { //判斷目前平台是否支援Desktop類oneDesktop = Desktop.getDesktop();}if (SystemTray.isSupported()) { //判斷目前平台是否支援系統托盤oneSystemTray = SystemTray.getSystemTray(); // 获得本操作系统托盘的实例Image systemTrayImageIcon =Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/loginIconImage.jpg")); //定义系统托盘的图片(将要显示到托盘中的图标)/** TrayIcon有三个构造* TrayIcon(Image image) 用“图标”来构造* TrayIcon(Image image, String tooltip) 用“图标”和“ToolTip”构造* TrayIcon(Image image, String tooltip, PopupMenu popup) 用“图标”,“ToolTip”,“弹出菜单”来构造一个托盘图标*/IMSystemTrayUtilByJDK.setOneTrayIconByJDK(newTrayIcon(systemTrayImageIcon,"蓝梦教育集团即时通讯系统托盘程序", onePopupMenu));try {oneSystemTray.add(IMSystemTrayUtilByJDK.getOneTrayIconByJDK()); // 将托盘图标添加到系统的托盘实例中} catch (AWTException ex) {ex.printStackTrace();throw new IMSystemException("在IMSystemTray_byJDK类中的createIMSystemTray方法中出现了");}IMSystemTrayUtilByJDK.getOneTrayIconByJDK().addMouseListener(newIMSystemTray_MouseListenerEventHandler(this,"oneTrayIcon_mouseClicked"));IMSystemTrayUtilByJDK.getOneTrayIconByJDK().displayMessage("蓝梦教育集团IM系统托盘气泡信息", "已经成功地创建了系统托盘实例!您双击本图标可以打开主窗口,而右击可以打开托盘快捷菜单!", );}}onePopupMenu = new PopupMenu_IMSystemTray_byJDK();}public SystemTray getOneSystemTray() {return oneSystemTray;}}6、JDIC API简介(1)JDesktop Integration Components (JDIC)这是一个开源的项目,目的是构建消除本机应用程序和Java 等价物之间差距的组件。
山寨QQ(韩顺平版)
这是一个简单的javaProject项目,没有涉及到数据库界面对这个项目中完成的功能进行阐述:1、qq用户登录:用户账号为1、2、3一直到50,密码都为123456,由于没有涉及到数据库,所以只是简单的在服务器进行验证。
2、实现1对1之间的聊天,实现1对多之间的聊天。
3、实现用户上线显示功能具体的演示为:1、启动服务器QqServer下com.qq.view.MyServerFrame,在该类下面启动服务器2、启动客户端QqClient下com.qq.view.QqClientLogin,在该类下面输入账号和密码登入ps:聊天时要把要把需要聊天的窗口都打开,才能看到。
比如1和2聊天,必须打开1对2聊天的窗口和2对1聊天的窗口QQ客户端:QQ服务器下面的是关于各个包的源代码,小伙伴们可以新建一个class,然后把这些拷贝上去就可以用了,当然前提是按照上面的工程创建好包Image文件夹下用到的图片:命名为:beibu.gif命名为:xiangdao.png命名为:quxiao.png命名为:qq.png命名为:mm.png命名为:clear.png命名为:dengru.pngQqClientConService类:package com.qq.client.model;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import .Socket;import com.qq.client.tools.ClientConServerThread;import com.qq.client.tools.ManageClientConServerThread; import mon.Message;import er;/*** 客户端连接服务器后台* */public class QqClientConService {public Socket client;//判断是否成功登录,成功返回true,否则返回falsepublic boolean sendLoginInfoToServer(Object o) {boolean isLogin = false;try {//创建连接client = new Socket("localhost", 9999);ObjectOutputStream oos = newObjectOutputStream(client.getOutputStream());oos.writeObject(o);ObjectInputStream ois = newObjectInputStream(client.getInputStream());Message message = (Message)ois.readObject();//登录成功的判断if(message.getMesType()==1) {isLogin = true;//登录成功,创建一个改客户端和服务器的线程ClientConServerThread ccst = new ClientConServerThread(client);//把改线程添加到管理线程的map中ManageClientConServerThread.addClientConServerThread(((User )o).getName(), ccst);//启动该线程new Thread(ccst).start();}} catch (Exception e) {e.printStackTrace();}return isLogin;}}QqClientUser类:package com.qq.client.model;import er;/*** 这是QQ客户端,发送用户名和密码** */public class QqClientUser {//调用客户端连接服务器后台的方法,返回true为成功登录,false为登入失败public boolean checkUser(User user) {return newQqClientConService().sendLoginInfoToServer(user);}}ClientConServerThread类:package com.qq.client.tools;import java.io.ObjectInputStream;import .Socket;import com.qq.client.view.QqChar;import com.qq.client.view.QqFriendList;import mon.Message;import mon.MessageType;/*** 这是客户端和服务器保持通讯的线程* */public class ClientConServerThread implements Runnable{ public Socket client;public ClientConServerThread(Socket client) {this.client = client;}@Overridepublic void run() {//不停的读取从服务器发来的消息while(true) {try {ObjectInputStream ois = newObjectInputStream(client.getInputStream());Message message = (Message) ois.readObject();//判断发来的消息包是否为普通消息包,或者是返回在线好友的包if(message.getMesType() ==MessageType.message_common_mes) {//把从服务器发来的消息显示在聊天界面:1.从管理聊天窗口的类中取得该窗口 2.调用显示方法.QqChar qqChar =ManageQqChar.getQqChar(message.getGetter()+""+message.getSender());qqChar.showMessage(message);} else if(message.getMesType() == MessageType.message_ret_onLineFriend) {String getter = message.getGetter();//修改响应的好友列表QqFriendList qqFriendList = ManageQqFriendList.getQqFriendList(getter);//更新在线好友if(qqFriendList != null) {qqFriendList.updateFriend(message);}}} catch (Exception e) {e.printStackTrace();}}}}ManageClientConServerThread类:package com.qq.client.tools;import java.util.HashMap;import java.util.Map;/*** 这是一个管理客户端和服务器保持通讯的线程类* */public class ManageClientConServerThread {public static Map map = new HashMap<String, ClientConServerThread>();//把线程添加到map中public static void addClientConServerThread(String userName, ClientConServerThread ccst) {map.put(userName, ccst);}//根据用户名取得该线程public static ClientConServerThread getClientConServerThread(String userName) {return (ClientConServerThread)map.get(userName);}}ManageQqChar类:package com.qq.client.tools;import java.util.HashMap;import java.util.Map;import com.qq.client.view.QqChar;/*** 这是一个管理用户聊天界面的类* */public class ManageQqChar {public static Map map = new HashMap<String, QqChar>();//把用户聊天界面Qqchar添加到map中public static void addQqChar(String loginAndFriend, QqChar qqchar) {map.put(loginAndFriend, qqchar);}//根据登入用户和发送用户取得该聊天界面public static QqChar getQqChar(String loginAndFriend) { return (QqChar)map.get(loginAndFriend);}}ManageQqFriendList类:package com.qq.client.tools;import java.util.HashMap;import java.util.Map;import com.qq.client.view.QqFriendList;/*** 管理好友、黑名单..界面类* */public class ManageQqFriendList {public static Map map = new HashMap<String, QqFriendList>();//把用用户列表类添加到map中public static void addQqFriendList(String userName, QqFriendList list) {map.put(userName, list);}//根据登录用户取得该用户列表类public static QqFriendList getQqFriendList(String userName) { return (QqFriendList)map.get(userName);}}package com.qq.client.view;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.ObjectOutputStream;import java.util.Date;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JTextArea;import javax.swing.JTextField;import com.qq.client.tools.ManageClientConServerThread;import mon.Message;import mon.MessageType;/*** QQ聊天窗口** */public class extends JFrame implements ActionListener { JTextField jtf;//输入的文本框JTextArea jta;//文本区域JButton jb;//发送按钮JPanel jp;//装文本框和发送按钮的panelString friend;String userName;public static void main(String[] args) {QqChar qqChar = new QqChar("1","2");}public QqChar(String userName,String friend) {erName = userName;this.friend = friend;jtf = new JTextField(15);jta = new JTextArea();jb = new JButton("发送");jb.addActionListener(this);jp = new JPanel();jp.add(jtf);jp.add(jb);this.add(jta, "Center");this.add(jp, "South");this.setTitle(userName+" 正在和 " + friend + " 聊天");this.setIconImage(newImageIcon("image/qq.png").getImage());this.setSize(300, 200);this.setVisible(true);}public void showMessage(Message message) {String info=message.getSender()+" 对"+message.getGetter()+" 说:"+message.getContext()+"\r\n";this.jta.append(info);}@Overridepublic void actionPerformed(ActionEvent e) {//当点击发送按钮时,把消息发送到服务器端if(e.getSource() == jb) {Message message = new Message();message.setMesType(MessageType.message_common_mes);message.setSender(userName);message.setGetter(friend);message.setContext(jtf.getText());jtf.setText("");message.setTime(new Date().toString());try {ObjectOutputStream oos = newObjectOutputStream(ManageClientConServerThread.getClientConSer verThread(userName).client.getOutputStream());oos.writeObject(message);} catch (Exception e1) {e1.printStackTrace();}}}}import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JPasswordField;import javax.swing.JTabbedPane;import javax.swing.JTextField;import com.qq.client.model.QqClientUser;import com.qq.client.tools.ManageClientConServerThread; import com.qq.client.tools.ManageQqFriendList;import mon.Message;import mon.MessageType;import er;/*** QQ客户端登入窗口** */public class extends JFrame implements //定义北部组件JLabel jbl1;//定义中部组件:其中中部组件有一个选项卡的窗口管理,有三个JPanel,一个文本框,一个密码框,4个JLabel,一个清除号码按钮,两个多选框JTabbedPane jtp;//选项卡窗口JPanel jp2;//QQ号码JPanel jp3;//手机号码JPanel jp4;//电子邮件JLabel jp2_jpl1;//QQ号码JLabel jp2_jpl2;//QQ密码JLabel jp2_jpl3;//忘记密码JLabel jp2_jpl4;//申请密码保护JButton jp2_jb1;//清除号码JTextField jp2_jtf;//文本框JPasswordField jp2_jpf;//密码框JCheckBox jp2_jcb1;//隐身登入JCheckBox jp2_jcb2;//记住密码//定义南部组件JPanel jp1;JButton jp1_jb1;//登入按钮JButton jp1_jb2;//取消按钮JButton jp1_jb3;//注册向导按钮public static void main(String[] args) {QqClientLogin qqClientLogin=new QqClientLogin();}public QqClientLogin() {//处理北部的组件jbl1 = new JLabel(new ImageIcon("image/beibu.gif"));//处理中部的组件jp2=new JPanel(new GridLayout(3,3));//把中部分成三行三列jp2_jpl1 = new JLabel("QQ号码", JLabel.CENTER);jp2_jpl2 = new JLabel("QQ密码", JLabel.CENTER);jp2_jpl3 = new JLabel("忘记密码", JLabel.CENTER);jp2_jpl3.setForeground(Color.blue);//把忘记密码设为蓝色jp2_jpl4 = new JLabel("申请密码保护", JLabel.CENTER);jp2_jb1 = new JButton(new ImageIcon("image/clear.png"));jp2_jtf = new JTextField();jp2_jpf = new JPasswordField();jp2_jcb1 = new JCheckBox("隐身登入");jp2_jcb2 = new JCheckBox("记住密码");//把控件按照顺序加入到jp2jp2.add(jp2_jpl1);jp2.add(jp2_jtf);jp2.add(jp2_jb1);jp2.add(jp2_jpl2);jp2.add(jp2_jpf);jp2.add(jp2_jpl3);jp2.add(jp2_jcb1);jp2.add(jp2_jcb2);jp2.add(jp2_jpl4);//创建选项卡窗口,把三个JPanel放进去,最后把选项卡放进JFrame 中jtp=new JTabbedPane();jtp.add("QQ号码",jp2);jp3= new JPanel();jtp.add("手机号码",jp3);jp4=new JPanel();jtp.add("电子邮件",jp4);//处理南部的组件jp1 = new JPanel();jp1_jb1 = new JButton(new ImageIcon("image/dengru.png"));jp1_jb1.addActionListener(this);jp1_jb2 = new JButton(new ImageIcon("image/quxiao.png"));jp1_jb3=new JButton(new ImageIcon("image/xiangdao.png"));//把三个按钮放进jp1中jp1.add(jp1_jb1);jp1.add(jp1_jb2);jp1.add(jp1_jb3);//把定义好的组件放入到JFrame中this.add(jbl1,"North");//放入北部组件this.add(jp1, "South");//放入南部组件this.add(jtp, "Center");//放入中部组件//定义JFrame的一些属性this.setSize(350, 240);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setIconImage(newImageIcon("image/qq.png").getImage());this.setResizable(false);//不允许放大,改变窗口大小等this.setVisible(true);}@Overridepublic void actionPerformed(ActionEvent e) {//用户点击登录按钮if(e.getSource()==jp1_jb1) {User user =new User();user.setName(jp2_jtf.getText().trim());user.setPassWord(newString(jp2_jpf.getPassword()).trim());QqClientUser qqClientUser = new QqClientUser();//判断是否登录成功if(qqClientUser.checkUser(user)) {try {//把创建好友列表提前QqFriendList qqList = newQqFriendList(jp2_jtf.getText());ManageQqFriendList.addQqFriendList(user.getName(), qqList);//发送一个要求返回在线好友的请求包ObjectOutputStream oos = new ObjectOutputStream(ManageClientConServerThread.getClientConServerThread(user.getName()).client.getOutputSt ream());Message message = new Message();message.setSender(user.getName());message.setMesType(MessageType.message_get_onLineFriend);//发送oos.writeObject(message);} catch (Exception e1) {e1.printStackTrace();}this.dispose();} else {JOptionPane.showMessageDialog(this,"QQ号码或者密码错误");}}}}package com.qq.client.view;import javax.swing.*;import com.qq.client.tools.ManageQqChar;import mon.Message;import java.awt.*;import java.awt.event.*;/*** 我的好友列表(包括陌生人和黑名单)* */public class extends JFrame implements //第一张卡片信息(我的好友列表)JPanel jphy1;//总panelJPanel jphy2;//中部的panelJPanel jphy3;//南部的panel,放两个buttonJButton jphy_jb1;//我的好友按钮,防在总panel的北部JButton jphy_jb2;//陌生人按钮,放在jphy3中JButton jphy_jb3;//黑名单按钮,放在jphy3中JScrollPane jsp1;//中部的滚动的paneJLabel jbls[];//中部在线好友的列表//第二张卡片信息(陌生人列表)JPanel jpmsr1;//总panelJPanel jpmsr2;//中部的panelJPanel jpmsr3;//南部的panel,放两个buttonJButton jpmsr_jb1;//我的好友按钮,放在jpmsr3中JButton jpmsr_jb2;//陌生人按钮,放在jpmsr3中JButton jpmsr_jb3;//黑名单按钮,放在总的panel的南部JScrollPane jsp2;//中部的滚动的paneString userName;//把整个JFrame变成卡片布局CardLayout c1;public static void main(String[] args) {QqFriendList qqFriendList = new QqFriendList("1");}public QqFriendList(String userName) {erName = userName;//处理第一张卡片jphy_jb1 = new JButton("我的好友");jphy_jb2 = new JButton("陌生人");jphy_jb2.addActionListener(this);jphy_jb3 = new JButton("黑名单");jphy1 = new JPanel(new BorderLayout());//总的JPaneljphy2= new JPanel(new GridLayout(50,1,4,4));//中部的JPanel,假定有五十个好友//给jphy2这个panel中初始化50个好友jbls = new JLabel[50];for(int i=0; i<jbls.length; i++) {jbls[i] = new JLabel(i+1+"", newImageIcon("image/mm.png"), JLabel.LEFT);jbls[i].setEnabled(false);if(jbls[i].getText().equals(userName)) {jbls[i].setEnabled(true);}jbls[i].addMouseListener(this);jphy2.add(jbls[i]);}jphy3 = new JPanel(new GridLayout(2, 1));//把黑名单按钮和陌生人按钮加入到jpyh3中jphy3.add(jphy_jb2);jphy3.add(jphy_jb3);//把jphy2放入滚动的pane中jsp1 = new JScrollPane(jphy2);//把jphy_jb1,jsp1,jphy3分别放入jphy1中北,中,南三个位置jphy1.add(jphy_jb1,"North");jphy1.add(jsp1,"Center");jphy1.add(jphy3,"South");//处理第二张卡片jpmsr_jb1 = new JButton("我的好友");jpmsr_jb1.addActionListener(this);jpmsr_jb2 = new JButton("陌生人");jpmsr_jb3 = new JButton("黑名单");jpmsr1 = new JPanel(new BorderLayout());//总的JPaneljpmsr2 = new JPanel(new GridLayout(20,1,4,4));//中部的JPanel,假定有二十个陌生人//给jpmsr2这个panel中初始化20个陌生人JLabel jbls2[] = new JLabel[20];for(int i=0; i<jbls2.length; i++) {jbls2[i] = new JLabel(i+1+"", newImageIcon("image/mm.png"), JLabel.LEFT);jpmsr2.add(jbls2[i]);}jpmsr3 = new JPanel(new GridLayout(2, 1));//把我的好友按钮和陌生人按钮加入到jpmsr3中jpmsr3.add(jpmsr_jb1);jpmsr3.add(jpmsr_jb2);//把jpmsr1放入滚动的pane中jsp2 = new JScrollPane(jpmsr2);//把jpmsr3,jsp2,jpmsr_jb3分别放入jpmsr1中北,中,南三个位置jpmsr1.add(jpmsr3,"North");jpmsr1.add(jsp2,"Center");jpmsr1.add(jpmsr_jb3,"South");//把卡片放入JFrame中c1 = new CardLayout();this.setLayout(c1);this.add(jphy1, "1");this.add(jpmsr1, "2");//在窗口显示自己的namethis.setTitle(userName);this.setSize(170, 450);this.setVisible(true);}//更新在线好友情况public void updateFriend(Message message) {String onLineFriend[] = message.getContext().split(" ");for(int i=0; i<onLineFriend.length; i++) {jbls[Integer.parseInt(onLineFriend[i])-1].setEnabled(true);}}@Overridepublic void mouseClicked(MouseEvent e) {//响应用户双击事件,并得到好友编号if(e.getClickCount() ==2) {String friendNo = ((JLabel)e.getSource()).getText();QqChar qqChar = new QqChar(userName,friendNo);//把新开的聊天窗口加入到管理聊天窗口的map中ManageQqChar.addQqChar(erName+" "+friendNo, qqChar);}}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {//当鼠标移上去时,使好友头像变为红色JLabel j1 = (JLabel)e.getSource();j1.setForeground(Color.red);}@Overridepublic void mouseExited(MouseEvent e) { //当把鼠标移走时,恢复成黑色JLabel j1 = (JLabel)e.getSource();j1.setForeground(Color.black);}@Overridepublic void actionPerformed(ActionEvent e) { //如果点击了陌生人按钮,就显示第二张卡片if(e.getSource()==jphy_jb2) {c1.show(this.getContentPane(), "2");} else if(e.getSource()==jpmsr_jb1) {c1.show(this.getContentPane(), "1");}}}package mon;import java.io.Serializable;/*** 发送的消息的类* */public class implements Serializable{private int mesType;//服务器返回的信息包:1代表用户验证成功,2代表用户验证失败,3代表其他信息包;private String sender;//发送消息的人private String getter;//接收消息的人private String context;//发送的消息private String time;//发送的时间public int getMesType() {return mesType;}public void setMesType(int mesType) {this.mesType = mesType;}public String getSender() {return sender;}public void setSender(String sender) {this.sender = sender;}public String getGetter() {return getter;}public void setGetter(String getter) {this.getter = getter;}public String getContext() {return context;}public void setContext(String context) { this.context = context;}public String getTime() {return time;}public void setTime(String time) {this.time = time;}}MessageType类:package mon;/*** 定义包的总类* */public interface MessageType {//表明登入成功的包int message_succeed = 1;//表明登入失败的包int message_login_fail = 2;//表明普通的包int message_common_mes = 3;//要求返回在线好友的包int message_get_onLineFriend = 4;//返回在线好友的包int message_ret_onLineFriend = 5; }package mon;import java.io.Serializable;/*** 用户类* */public class implements Serializable{ private String name;//用户名private String passWord;//密码public String getName() {return name;}public void setName(String name) { = name;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) { this.passWord = passWord;}}ManageClientThread类:package com.qq.server.model;import java.util.HashMap;import java.util.Iterator;import java.util.Map;/*** 这是一个管理服务器和客户端保持通讯的线程类* */public class ManageClientThread {public static Map map = new HashMap<String, SerConClientThread>();//向map中添加一个线程public static void addCilentThread(String userName, SerConClientThread sc) {map.put(userName, sc);}//根据userName取得一个线程public static SerConClientThread getCilentThread(String userName) {return (SerConClientThread) map.get(userName);}//返回当前在线的人的情况public static String getAllOnLineUser() {//使用迭代器完成Iterator it = map.keySet().iterator();String res = "";while(it.hasNext()) {res += it.next().toString() + " ";}return res;}}MyQqServer类:package com.qq.server.model;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import .ServerSocket;import .Socket;import mon.Message;import er;/*** 这是QQ服务器** */public class MyQqServer {public ServerSocket server;public static void main(String[] args) {new MyQqServer();}public MyQqServer() {try {System.out.println("在9999服务器监听.....");server = new ServerSocket(9999);//阻塞,等待某个客户端来连接while(true){Socket client = server.accept();//读取从客户端发来的消息ObjectInputStream ois = newObjectInputStream(client.getInputStream());User user = (User)ois.readObject();System.out.println("姓名是==="+user.getName()+"===密码是---"+user.getPassWord()+"---");ObjectOutputStream oos = newObjectOutputStream(client.getOutputStream());Message message = new Message();//只要密码是123456都让它登录成功if(user.getPassWord().equals("123456")) {message.setMesType(1);oos.writeObject(message);//登入成功,开启一个线程SerConClientThread sc = new SerConClientThread(client);//把该线程加入到map中ManageClientThread.addCilentThread(user.getName(), sc);//启动线程sc.start();//通知其他在线用户sc.notifyOther(user.getName());} else {//登录不成功时message.setMesType(2);oos.writeObject(message);client.close();}}} catch (Exception e) {e.printStackTrace();}}}QqServerUser类由于没写东西,所以不用创建也可以。
仿QQ界面代码
VERSION 5.00Begin VB.Form Form1Caption = "Form1"ClientHeight = 6645ClientLeft = 4695ClientTop = 2985ClientWidth = 9960LinkTopic = "Form1"ScaleHeight = 6645ScaleWidth = 9960Begin mandButton Command1 Caption = "Command1"Height = 1095Left = 120TabIndex = 0Top = 120Width = 1935EndBegin VB.Timer tmrMoveEnabled = 0 'FalseInterval = 1Left = 1620Top = 960EndBegin VB.Timer tmrCheckEnabled = 0 'FalseInterval = 50Left = 570Top = 720EndEndAttribute VB_Name = "Form1"Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = FalseAttribute VB_PredeclaredId = TrueAttribute VB_Exposed = FalseOption Explicit'//Download by '//本功能代码作者gvu'//子类化代码作者pctgl'//版权归作者所有'//转载请保留作者信息Private Const WM_NCLBUTTONDOWN = &HA1Private Const WM_EXITSIZEMOVE = &H232Private Const WM_MOVING = &H216Private Type RECTLeft As LongTop As LongRight As LongBottom As LongEnd TypePrivate Type POINTAPIX As LongY As LongEnd TypePrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)Private Declare Function PtInRect Lib "user32" (lpRect As RECT, ByVal X As Long, ByVal Y As Long) As LongPrivate Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As LongPrivate Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As LongPrivate WithEvents c_Subclass As iSubClassAttribute c_Subclass.VB_VarHelpID = -1Private Const SIZE_SHOW As Long = 60 '隐藏后留出来的宽度或高度,单位缇Private Const SHOWHIDE_SPEED As Long = 30 '(自动显示隐藏速度,单位缇)'显示标识'0 自动隐藏'1 自动显示Private m_ShowFlag As Long'显示方向'0 向左'1 向右'2 向上Private m_ShowOrient As Long'显示速度Private m_ShowSpeed As Long'是否已经启动自动隐藏(为了防止WM_MOVING调整窗口位置)Private m_MoveEnabled As Boolean'//下面是把窗口移动Top=0且Left=0或Right=Screen.Width的时候让窗口高度=屏幕高度'是否自动调整了大小Private m_AutoSize As BooleanPrivate m_OldHeight As LongPrivate Sub Command1_Click()Shell "C:\Program Files\yzwtools\清理影像系统缓存文件.bat"End SubPrivate Sub Form_Load()Set c_Subclass = New iSubClassc_Subclass.SetMsgHook Me.hWndForm1.Caption = "多功能小工具"Command1.Caption = "影像系统缓存清理"End SubPrivate Sub c_Subclass_GetWindowMessage(Result As Long, ByVal cHwnd As Long, ByVal Message As Long, ByVal wParam As Long, ByVal lParam As Long)Select Case MessageCase WM_NCLBUTTONDOWNConst HTCAPTION = 2If wParam = HTCAPTION Then'点击标题栏让所有Timer停止工作m_MoveEnabled = TruetmrCheck.Enabled = FalsetmrMove.Enabled = FalseEnd IfCase WM_MOVINGIf m_MoveEnabled = False Then Exit Sub'这里仅仅是为了不让窗口移出屏幕,可以忽略Dim rcMov As RECTDim rcWnd As RECTDim lScrW As Long'获取窗口矩形Call GetWindowRect(cHwnd, rcWnd)'//屏幕宽度lScrW = Screen.Width / Screen.TwipsPerPixelX'获取移动目标位置矩形Call CopyMemory(rcMov, ByVal lParam, Len(rcMov))With rcMovIf .Left < 0 Then.Left = 0.Right = rcWnd.Right - rcWnd.LeftEnd IfIf .Top < 0 Then.Top = 0.Bottom = rcWnd.Bottom - rcWnd.TopEnd IfIf .Right > lScrW Then.Left = lScrW - (rcWnd.Right - rcWnd.Left).Right = .Left + (rcWnd.Right - rcWnd.Left)End IfEnd With'//如果窗口的靠在右上角或左上角,则把高度设置为屏幕高度If rcMov.Top = 0 And (rcMov.Left = 0 Or rcMov.Right = Screen.Width / Screen.TwipsPerPixelX) ThenIf m_AutoSize = False Thenm_AutoSize = True'保存旧的高度m_OldHeight = rcMov.Bottom - rcMov.ToprcMov.Bottom = Screen.Height / Screen.TwipsPerPixelYEnd IfElseIf m_AutoSize Thenm_AutoSize = False'设置旧的高度rcMov.Bottom = rcMov.Top + m_OldHeightEnd IfEnd IfCall CopyMemory(ByVal lParam, rcMov, Len(rcMov))Case WM_EXITSIZEMOVEm_MoveEnabled = FalseCall GetWindowRect(cHwnd, rcWnd)If rcWnd.Left <= 0 Or rcWnd.Top <= 0 Or _rcWnd.Right >= Screen.Width / Screen.TwipsPerPixelX Then'如果窗口停靠在屏幕边缘'让检查鼠标位置的Timer工作'设置显示方向If rcWnd.Left = 0 Thenm_ShowOrient = 0ElseIf rcWnd.Right >= Screen.Width / Screen.TwipsPerPixelX Thenm_ShowOrient = 1ElseIf rcWnd.Top = 0 Thenm_ShowOrient = 2End IftmrCheck.Enabled = TrueEnd IfEnd SelectResult = c_Subclass.CallDefaultWindowProc(cHwnd, Message, wParam, lParam)End SubPrivate Sub tmrCheck_Timer()Dim pt As POINTAPIDim rc As RECTCall GetCursorPos(pt)Call GetWindowRect(Me.hWnd, rc)If PtInRect(rc, pt.X, pt.Y) Then'鼠标停留在窗口上If m_ShowFlag = 1 Then Exit Subm_ShowSpeed = SHOWHIDE_SPEEDm_ShowFlag = 1tmrMove.Enabled = TrueElse'鼠标不再窗口上If m_ShowFlag = 0 Then Exit Subm_ShowSpeed = SHOWHIDE_SPEEDm_ShowFlag = 0tmrMove.Enabled = TrueEnd IfEnd SubPrivate Sub tmrMove_Timer()Dim nTop As LongDim nLeft As Longm_ShowSpeed = m_ShowSpeed + SHOWHIDE_SPEED'如果大于300T则加快速度If m_ShowSpeed > 300 Then m_ShowSpeed = m_ShowSpeed + m_ShowSpeed * 0.2Select Case m_ShowOrientCase 0 '0 向左If m_ShowFlag = 0 ThennLeft = Me.Left - m_ShowSpeedIf nLeft < -Me.Width + SIZE_SHOW Then nLeft = -Me.Width + SIZE_SHOW: tmrMove.Enabled = FalseElsenLeft = Me.Left + m_ShowSpeedIf nLeft > -SIZE_SHOW Then nLeft = -SIZE_SHOW: tmrMove.Enabled = False End IfMe.Left = nLeftCase 1 '1 向右If m_ShowFlag = 0 ThennLeft = Me.Left + m_ShowSpeedIf nLeft > Screen.Width - SIZE_SHOW Then nLeft = Screen.Width - SIZE_SHOW:tmrMove.Enabled = FalseElsenLeft = Me.Left - m_ShowSpeedIf nLeft < Screen.Width - Me.Width + SIZE_SHOW Then nLeft = Screen.Width - Me.Width + SIZE_SHOW: tmrMove.Enabled = FalseEnd IfMe.Left = nLeftCase 2 '2 向上If m_ShowFlag = 0 ThennTop = Me.Top - m_ShowSpeedIf nTop < -Me.Height + SIZE_SHOW Then nTop = -Me.Height + SIZE_SHOW: tmrMove.Enabled = FalseElsenTop = Me.Top + m_ShowSpeedIf nTop > -SIZE_SHOW Then nTop = -SIZE_SHOW: tmrMove.Enabled = False End IfMe.Top = nTopEnd SelectEnd Sub。
北大青鸟:源代码清单
Load frmReminderPopUp
frmReminderPopUp.lblMessage.Caption = Adodc1.Recordset.Fields(2).Value
frmReminderPopUp.Show
Adodc2.RecordSource = "SELECT * FROM Task"
Adodc2.Refresh
If Me.Adodc2.Recordset.RecordCount > 0 Then
If Not Adodc2.Recordset.EOF Then Adodc2.Recordset.MoveLast
Exit Do
Else
TaskRecset.MoveNext
End If
End With
Loop
DBasecon.Close
Unload frmReminder
End Sub
Private Sub Cancel_Click()
Me.txtTime.Clear
Me.cboMonth.Clear
Me.cboDay.Clear
Me.txtScheduleDay.Enabled = False
End If
End Sub
Private Sub tlbMenu_ButtonClick(ByVal Button As MSComctlLib.Button)
Select Case Button.Key
Case "btnNew"
If tlbMenu.Buttons.Item(1).Caption = "New" Then
用C语言写聊天工具,类似于QQ
C 语言究竟能干什么序言鉴于现在已经大三了,很多同学很迷茫,自己学的东西到底能做什么,将来自己到底能干什么?我不想看着同学迷茫的面孔,特别是几个好兄弟,有几个想学习编程,但又苦苦找不到门路的兄弟,所以想写点东西,希望对大家又点略微的帮助,以尽兄弟我的微薄之力。
很多同学学了C语言之后,可能难免会有所感叹:这就是C语言!总是感觉C语言竟然能写出Windows、Linux?为了解除同学们的疑惑,也愿为同学们指点编程之道吧。
我写的这些东西采用C语言,计划通过编程实例来讲解C编程的一些知识,让大家对C能又更深一层的理解和认识。
当然,大家不要指望看了这些之后会写出一个操作系统来,但是我想,如果你认真看了的话,写一个类似与QQ的聊天程序应该不难。
本来书是假期里照顾妈妈时写的,原想是1、不让自己的水平停滞不前,温故知新(两个月的假期是很长的)2. 帮助一些同学,解决编程上的困惑3.希望妈妈快点康复4.让母亲和家里人知道自己一直都很努力,我是好样的但现在母亲已经能够不在了,所以第三点,就改为原母亲在天之灵得到慰藉,早日放下烦恼,不用惦记我们。
C语言的基本语法我是不打算再提了,很多C语言编程的书,就是将一些基本的数据类型、数据结构、语法,然后就是一些数值计算的实例,大多数都是雷同的,难免有抄袭之嫌,而且页没有多少实用价值。
本书以实用实例作为编程指导,指引大家编写真正实用的程序。
了解到大家对黑客程序、病毒、窗口类程序比较感兴趣,因此我就拿这些实例进行讲解。
基于大家基本都用Windows XP SP3,我也就在这个系统上把程序调试成功后再给大家讲解。
编程环境,我还是喜欢Visual C++ 6.0本书计划从四个大的方面来讲,这四个方面是:窗口类、文件操作类、网络类、数据库类。
都是时下流行的编程必备技术,也是软件开发者,必须掌握的技术。
中间以实例讲解,逐步学习,相信大家看完后会有很大的提高的。
第一章窗口类程序的编写这一章就先来讲解下窗口类程序的编写。
java_模拟qq聊天的源代码
客户端:package mutil;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .Socket;import javax.swing.JTextArea;public class ClienThread extends Thread{private Socket socket = null;private javax.swing.JTextArea jTextArea1;public ClienThread(JTextArea jTextArea1){this.jTextArea1 = jTextArea1;}public void run(){try{// 创建连接socket = new Socket("", 12344);String message = null;while (true){// 接受服务端请求message = receive();// 显示到消息接收框if (message != null && !message.equals("")){if (this.jTextArea1.getText() == null|| this.jTextArea1.getText().equals("")){this.jTextArea1.setText("服务端:" + message);} else{this.jTextArea1.setText(this.jTextArea1.getText()+ "\n服务端:" + message);}} else{message = "服务端以断开连接或未连接!";if (this.jTextArea1.getText() == null|| this.jTextArea1.getText().equals("")){this.jTextArea1.setText("服务端:" + message);} else{this.jTextArea1.setText(this.jTextArea1.getText()+ "\n服务端:" + message);}break;}}} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}/*** 向服务端发送消息*/public void send(String message){try{PrintWriter printWriter = new PrintWriter(socket.getOutputStream());printWriter.write(message + "\n");printWriter.flush();} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}/*** 接受服务端消息*/public String receive(){String message = "";try{BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));message = bufferedReader.readLine();} catch (IOException e){System.out.println("服务端已断开或未连接!");}return message;}}服务端:package mutil;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .ServerSocket;import .Socket;import javax.swing.JTextArea;public class ServerThread extends Thread{private Socket socket = null;private ServerSocket serverSocket = null;private javax.swing.JTextArea jTextArea1;public ServerThread(JTextArea jTextArea1){this.jTextArea1 = jTextArea1;}public void run(){try{// 创建连接serverSocket = new ServerSocket(12344);// 监听客户连接socket = serverSocket.accept();String message = null;while (true){// 接受客户请求message = receive(socket);if (message != null && !message.equals("")){// 显示到消息接收框if (this.jTextArea1.getText() == null|| this.jTextArea1.getText().equals("")){this.jTextArea1.setText("客户端:" + message);} else{this.jTextArea1.setText(this.jTextArea1.getText()+ "\n客户端:" + message);}} else{message = "客户端以断开连接或未连接!";if (this.jTextArea1.getText() == null|| this.jTextArea1.getText().equals("")){this.jTextArea1.setText("客户端:" + message);} else{this.jTextArea1.setText(this.jTextArea1.getText()+ "\n客户端:" + message);}break;}}} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}/*** 向客户端发送消息*/public void send(String message){try{PrintWriter printWriter = new PrintWriter(socket.getOutputStream());printWriter.write(message + "\n");printWriter.flush();} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}/*** 接受客户端消息*/public String receive(Socket socket){String message = "";try{BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));message = bufferedReader.readLine();} catch (IOException e){System.out.println("服务端已断开或未连接!");}return message;}}服务端界面:/** SereveFrame.java** Created on __DA TE__, __TIME__*/package com.insigma.frame;import mutil.ServerThread;/**** @author __USER__*/public class ServerFrame extends javax.swing.JFrame{private ServerThread serverThread;/** Creates new form SereveFrame */public ServerFrame(){initComponents();serverThread = new ServerThread(this.jTextArea1);serverThread.start();}/*** This method is called from within the constructor to initialize the form.* WARNING: Do NOT modify this code. The content of this method is always* regenerated by the Form Editor.*/// GEN-BEGIN:initComponents// <editor-fold defaultstate="collapsed" desc="Generated Code">private void initComponents(){jScrollPane1 = new javax.swing.JScrollPane();jTextArea1 = new javax.swing.JTextArea();jScrollPane2 = new javax.swing.JScrollPane();jTextArea2 = new javax.swing.JTextArea();jButton1 = new javax.swing.JButton();jButton2 = new javax.swing.JButton();setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);setTitle("\u670d\u52a1\u7aef");setBackground(new java.awt.Color(153, 153, 255));jTextArea1.setColumns(20);jTextArea1.setRows(5);jScrollPane1.setViewportView(jTextArea1);jTextArea2.setColumns(20);jTextArea2.setRows(5);jScrollPane2.setViewportView(jTextArea2);jButton1.setText("\u53d6\u6d88");jButton1.addActionListener(new java.awt.event.ActionListener(){public void actionPerformed(java.awt.event.ActionEvent evt){jButton1ActionPerformed(evt);}});jButton2.setText("\u53d1\u9001");jButton2.addActionListener(new java.awt.event.ActionListener(){public void actionPerformed(java.awt.event.ActionEvent evt){jButton2ActionPerformed(evt);}});javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());getContentPane().setLayout(layout);layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(javax.swing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup().addComponent(jButton1).addGap(18, 18,18).addComponent(jButton2).addGap(35, 35,35)).addGroup(layout.createSequentialGroup().addComponent( jScrollPane1,javax.swing.GroupLayout.PREFERRED_SIZE,377, javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_V ALUE)).addGroup(javax.swing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup().addComponent( jScrollPane2,javax.swing.GroupLayout.DEFAULT_SIZE,377, Short.MAX_V ALUE).addContainerGap()))));layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout.createSequentialGroup().addContainerGap().addComponent(jScrollPane1,javax.swing.GroupLayout.PREFERRED_SIZE,242,javax.swing.GroupLayout.PREFERRED_SIZE).addGap(18, 18, 18).addComponent(jScrollPane2,javax.swing.GroupLayout.PREFERRED_SIZE,javax.swing.GroupLayout.DEFAULT_SIZE,javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(ponentPlacement.RELATED).addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(jButton2).addComponent(jButton1)).addContainerGap()));pack();}// </editor-fold>// GEN-END:initComponents/*** 取消** @param evt*/private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){this.jTextArea2.setText("");}/*** 发送** @param evt*/private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){// 向客户端发消息String message = this.jTextArea2.getText();if (message != null && !message.equals("")){serverThread.send(message);// 清空消息输入框this.jTextArea2.setText("");// 显示到消息接收框if (this.jTextArea1.getText() == null|| this.jTextArea1.getText().equals("")){this.jTextArea1.setText("我说:" + message);} else{this.jTextArea1.setText(this.jTextArea1.getText() + "\n我说:"+ message);}}}/*** @param args* the command line arguments*/public static void main(String args[]){java.awt.EventQueue.invokeLater(new Runnable(){public void run(){new ServerFrame().setVisible(true);}});}// GEN-BEGIN:variables// Variables declaration - do not modifyprivate javax.swing.JButton jButton1;private javax.swing.JButton jButton2;private javax.swing.JScrollPane jScrollPane1;private javax.swing.JScrollPane jScrollPane2;private javax.swing.JTextArea jTextArea1;private javax.swing.JTextArea jTextArea2;// End of variables declaration//GEN-END:variables}客户端界面:/** ClienFrame.java** Created on __DA TE__, __TIME__*/package com.insigma.frame;import mutil.ClienThread;/**** @author __USER__*/public class ClienFrame extends javax.swing.JFrame{private ClienThread clienThread;/** Creates new form ClienFrame */public ClienFrame(){initComponents();clienThread = new ClienThread(this.jTextArea1);clienThread.start();}/*** This method is called from within the constructor to initialize the form.* WARNING: Do NOT modify this code. The content of this method is always* regenerated by the Form Editor.*/// GEN-BEGIN:initComponents// <editor-fold defaultstate="collapsed" desc="Generated Code">private void initComponents(){jScrollPane1 = new javax.swing.JScrollPane();jTextArea1 = new javax.swing.JTextArea();jScrollPane2 = new javax.swing.JScrollPane();jTextArea2 = new javax.swing.JTextArea();jButton1 = new javax.swing.JButton();jButton2 = new javax.swing.JButton();setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);setTitle("\u5ba2\u6237\u7aef");setBackground(new java.awt.Color(153, 153, 255));jTextArea1.setColumns(20);jTextArea1.setRows(5);jScrollPane1.setViewportView(jTextArea1);jTextArea2.setColumns(20);jTextArea2.setRows(5);jScrollPane2.setViewportView(jTextArea2);jButton1.setText("\u53d6\u6d88");jButton1.addActionListener(new java.awt.event.ActionListener(){public void actionPerformed(java.awt.event.ActionEvent evt){jButton1ActionPerformed(evt);}});jButton2.setText("\u53d1\u9001");jButton2.addActionListener(new java.awt.event.ActionListener(){public void actionPerformed(java.awt.event.ActionEvent evt){jButton2ActionPerformed(evt);}});javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());getContentPane().setLayout(layout);layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,376, Short.MAX_V ALUE).addGroup(javax.swing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup().addComponent(jButton1).addGap(18, 18,18).addComponent(jButton2).addGap(25, 25,25)).addComponent(jScrollPane2,javax.swing.GroupLayout.Alignment.TRAILING,javax.swing.GroupLayout.DEFAULT_SIZE,376, Short.MAX_V ALUE)).addContainerGap()));layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(javax.swing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup().addContainerGap().addComponent(jScrollPane1,javax.swing.GroupLayout.DEFAULT_SIZE,240, Short.MAX_V ALUE).addGap(18, 18, 18).addComponent(jScrollPane2,javax.swing.GroupLayout.PREFERRED_SIZE,javax.swing.GroupLayout.DEFAULT_SIZE,javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(ponentPlacement.RELATED).addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(jButton1).addComponent(jButton2)).addContainerGap()));pack();}// </editor-fold>// GEN-END:initComponents/*** 取消** @param evt*/private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){this.jTextArea2.setText("");}/*** 发送** @param evt*/private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){// 向服务端发消息String message = this.jTextArea2.getText();if (message != null && !message.equals("")){clienThread.send(message);// 清空消息输入框this.jTextArea2.setText("");// 显示到消息接收框if (this.jTextArea1.getText() == null|| this.jTextArea1.getText().equals("")){this.jTextArea1.setText("我说:" + message);} else{this.jTextArea1.setText(this.jTextArea1.getText() + "\n我说:"+ message);}}}/*** @param args* the command line arguments*/public static void main(String args[]){java.awt.EventQueue.invokeLater(new Runnable(){public void run(){new ClienFrame().setVisible(true);}});}// GEN-BEGIN:variables// Variables declaration - do not modifyprivate javax.swing.JButton jButton1;private javax.swing.JButton jButton2;private javax.swing.JScrollPane jScrollPane1;private javax.swing.JScrollPane jScrollPane2;private javax.swing.JTextArea jTextArea1;private javax.swing.JTextArea jTextArea2;// End of variables declaration//GEN-END:variables}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
需求分析——功能分析
主要功能:
注册与登录 好友管理 消息管理 个人设置
需求分析——界面分析
需要的界面:
注册界面 登录界面 登录后的主界面 查找/添加好友界面 聊天界面 系统消息界面 个人设置界面
头像列表界面
需求分析——辅助类分析
需要添加的辅助类:
DBHelper类 UserHelper 类
小组分工
4
4 4 4 4
软件开发流程
比尔盖子是一名建筑工人 起初只干一些比较简单的 建筑工作 凭个人技术和经验,不需要特 别设计,可以顺利完成
如同编写早期比较小的程序
软件开发流程
新任务:建造一间非常美 丽而完整的房间 工作变得复杂许多
像不断发展的软件,功能 越来越多,越来越复杂
软件开发流程
软件复杂性
图形用户界面 客户/服务器结构 分布式应用 数据通信 超大型关系型数据库
// 判断 ListView 中是否有选中的项 if (lvFaces.SelectedItems.Count == 0) { // … } // 获得选中的头像的索引 int faceId = lvFaces.SelectedItems[0].ImageIndex;
第四次集中编码:A任务
个人信息修改功能
第一次集中编码:难点分析
好友列表——第三方控件 SideBar
SbGroup 类型 Items 属性 Groups 属性 SbItem 类型
第一次集中编码:难点分析
SideBar
// 命名空间 using Aptech.UI; // 添加组 sbFriends.AddGroup("我的好友"); sbFriends.AddGroup("陌生人"); 显示的文字 // 添加项 SbItem item = new SbItem((string)dataReader["NickName"], (int)dataReader["FaceId"]); sbFriends.Groups[0].Items.Add(item); 显示的图像索引
大小头像切换—— SideBar 的 View 属性
// 小头像 sbFriends.View = SbView.SmallIcon;
总结及项目答辩
教员对项目完成情况作总结 学员以小组形式按要求答辩
Thank you
确定项目目的 了解系统中客户的期望 确定系统的规模 论证项目可行性
技术可行性 经济可行性 操作可行性 社会可行性
需求分析阶段
需求是产品的根源 需求工作的优劣对产品影响最大
获取需求 客户 同行、专家 已经存在的同类软件产品 行业标准、规则 Internet相关资料 可能遇到的问题 用户说不清楚需求 误解需求
分析需求
功能需求记录在客户需求说明书中
需求分析阶段
文档介绍
产品功能性需求
需求说明书
产品介绍
产品非功能性需求
产品应当遵循的标准和规范
其他需求
需求分析阶段
设计阶段
目的:根据用户的需要制定标准,划分并分配任务
构建原型 设计GUI标准
设计阶段涉及的活动
设计数据库
设计过程模块
分配任务和监督任务
设计编码标准
第四次集中编码:B任务
完善登录后主窗体:
扫描未读系统消息 右键菜单 工具条按钮功能
第四次集中编码:C任务
添加好友请求窗体设计及功能实现
第四次集中编码:难点分析
登录主窗体的右键菜单中
删除好友功能——从 SideBar 中移除一项
// 从SideBar中将选中的项移除 sbFriends.SeletedItem.Parent.Items.Remove( sbFriends.SeletedItem);
// 判断选中行的第一个单元格是否有值 if (dgvBasicResult.SelectedRows[0].Cells[0] != null) { // … } 表示空 // 获得选中行的第一个单元格的值 dgvBasicResult.SelectedRows[0].Cells[0].Value
第三次集中编码:A任务
开发阶段
开发阶段
对用户界面 进行最后的修改
构建数据库
通过添加代码 使其具备功能
评估/测试阶段
本阶段测试每个单元的功能
数据验证测试 单元测试 安全性测试
测试阶段涉及的活动
强度测试
集成测试
维护阶段
为客户提供故障诊断支持
网络 电话 上门
应用程序要求的任何软件升级
版本 补丁
软件开发过程
比尔通过类似软件瀑布模型的方 式成功完成了自己的建筑项目
WINDOWS 2000:
项目经理:250人 开发人员:1700人 测试人员:3200人
软件工程师的工作
项目设计与分析 编码 编写文档 测试 团队管理
软件工程师的素质
团队组织和管理能力
良好的编码能力 规范化编码习惯 具有软件工程的概念
规范意识 团队精神
求知欲、进取心 和学习总结的能力
软件开发过程
第二次集中编码:A任务
查找/添加好友窗体设计
第二次集中编码:B任务
查找/添加好友功能实现
第二次集中编码:C任务
聊天窗体设计及功能实现
第二次集中编码:难点分析
添加好友判断流程
第二次集中编码:难点分析
操作显示查询好友结果的 DataGridView
// 判断是否有单元格选中 if (dgvBasicResult.SelectedRows.Count == 0) { // … }
建库 建表
Users Friends FriendShipPolicy
建关系
项目准备阶段:C任务
建表
Star BloodType Messages MessageType
第一次集中编码:A任务
设计注册窗体界面 实现用户注册功能
第一次集中编码:B任务
设计登录后主窗体 显示好友列表
第一次集中编码:C任务
“这次不能盲目开工, 我们需要首先好好设 计一下!” 构想 分析 设计 构造 评估
软件的制作过程也非常相似
软件开发过程
建造房屋 构想 分析 设计 构造 评估 维护
软件开发 可行性研究与计划 需求分析 设计 开发 评估/测试 维护
软件开发过程模型
软件开发需要经历几个步骤 具体如何实施,具体项目不同,有所区别 软件开发过程模型:制作具体软件时,开发步骤的具体实 施方法
项目团队中的角色
比尔想到需要更多的人手帮他 终于组成了自己工作团队 就像软件中的项目团队
软件项目团队中的角色
项目团队
项目经理 技术负责人
软件架构师
分析师
设计人员 开发人员
测试人员
项目人员构成比例
例子: 微软 EXCHANGE 2000 SERVER 的开发:
项目经理:25人 开发人员:140人 测试人员:350人
MyQQ 聊天工具
组员 B
协助
组长 A
协助
组员 C
登 录 后 主 窗 体
查 找 / 添 加 好 友
注 册 窗 体
查 找 / 添 加 好 友
个 人 信 息 窗 体
辅 助 类
登 录 窗 体
聊 天 窗 体
头 像 列 表 窗 体
系 统 消 息 窗 体
查找/添加功能编码
界面设计、辅助功能
阶段划分
项目准备阶段 (2学时)
瀑布模型
瀑布模型
瀑布模型—— “线性顺序模型” 可行性研究报告 可行性研究与计划 将每个阶段都清楚定义了起止点 产生明确的交付成果 需求说明书 需求分析 阶段之间通过文档进行沟通 每个阶段都必需完成全部规定的任务(文档)后才能够进 设计文档 设计 入下一个阶段
开发 程序
测试
测试报告 维护
可行性研究与计划阶段
项目框架、建库、建表、提交计划
第一次集中编码 (4学时)
注册、登录功能
第二次集中编码 (4学时)
查找/添加好友、部分聊天功能
第三次集中编码 (4学时)
个人信息显示、完整聊天功能
第四次集中编码 (4学时)
个人信息修改、完善整个功能
项目答辩、总结(4学时)
项目准备阶段:A任务
搭建项目框架
提交小组计划
项目准备阶段:B任务
阶段项目 MyQQ
阶段项目简介
任务:MyQQ 聊天工具 系统结构:C/S,通过数据库交换聊天消息 小组形式完成 学时:24学时
项目实施和课程安排
课程进度 第一次课 项目讲解 项目准备阶段
描述
课时 2 2
第二次课
第三次课 第四次课 第五次课 第六次课
任务讲解
第一次集中编码 任务讲解 第二次集中编码 任务讲解 第三次集中编码 任务讲解 第四次集中编码 总结和答辩
设计登录窗体 实现登录功能
第一次集中编码:难点分析
注册功能难点
// 获取自动生成的Id值 // 查询新增加的记录的标识号的 SQL 语句 sql = "SELECT @@Identity FROM Users"; // …… // 执行查询语句 myQQNum = Convert.ToInt32(command.ExecuteScalar());
设计个人信息窗体 显示个人信息
第三次集中编码:B任务
完善登录后主窗体,扫描未读聊天消息
利用 Timer 实现
控制好友头像闪烁
来消息,头像闪烁
第三次集中编码:C任务
头像列表窗体设计及功能实现
第三次集中编码:难点分析
头像闪烁效果:
改变头像显示的图片,用Timer控制切换