winform项目——仿QQ即时通讯程序15:接收验证消息的反馈

编程项目2019/12/26 11:33:58阅读:903

上一篇文章我们完成了验证消息的接收和存储,并且在会话列表当中显示出验证消息会话。用户接收到验证消息以后,是需要对验证消息进行一个反馈的,在这里我们只做用户同意之后的反馈,忽略和拒绝反馈暂时就不做了。那么本篇文章将实现接收验证消息的反馈,并且实现互相添加为好友的操作以及在会话列表当中显示出用户会话。如下图所示:

效果图

验证消息的反馈

首先我们应该分析按了同意按钮之后要做什么。

第一步应该是在界面上进行修改,这个操作我们在上一篇文章已经完成了。

第二步应该是对数据进行修改。首先修改的应该是储存会话列表文件当中的状态,将该条会话消息的状态改成1即可表示已经同意了。

紧接着应该对数据库进行修改,在数据库的好友表当中,新增两条记录,这样就能够互相成为好友。具体操作请看同意按钮的点击事件中的代码。


紧接着我们应该向对方发送一条消息,告诉对方我们已经同意了他的验证请求,这条消息的格式也需要单独来设计,这样客户端在接收到消息的时候才能够识别出这是验证消息的反馈,这个步骤在上一篇文章我们也已经做过。

接着我们还要在双方客户端上的会话列表当中生成和对方的会话,同时刷新双方的好友列表。

我们需要在验证消息窗体对同意按钮的点击事件继续补充:

private void Agree_btn_MouseClick(object sender, MouseEventArgs e)
{
string account = ((Button)sender).Name.Substring(9);
Control.ControlCollection cc = ((Button)sender).Parent.Controls;
foreach (Control c in cc)
{
if (c is Button)
{
c.Visible = false;
}
if (c is Label)
{
if (c.Name == "state_lbl")
{
c.Text = "已同意";
c.Visible = true;

//修改本地文件中的state
updateFileConfirmState(account, 1);
//修改数据库好友表,添加两条记录,这样就互相成为好友了
SqlHelper.ExecuteSql("insert into Friends (MyAccount,FriendAccount) values ('"+Common.Account+"','"+account+"')");
SqlHelper.ExecuteSql("insert into Friends (MyAccount,FriendAccount) values ('" + account + "','" + Common.Account + "')");
//发送消息给对方
//第二段内容格式固定,接收时截取出同意,如果是“同意”
//就说明是验证消息的反馈
Common.sandMsg(account + Common.splitFlag + "~~~" + "同" + "~~~" + "意");
//加载和对方的会话
//在主界面中的会话列表加载和对方的会话
TalkMessage tm = new TalkMessage();
tm.Account = account;
tm.NickName = Common.majorForm.getNickName(account);
tm.SubMessage = "你已和" + tm.Account + "成为好友"; ;
Common.existedTalk.Add(tm.Account,Common.majorForm.loadtalk(0,tm));
Common.majorForm.refreshTalkList();
Common.majorForm.initFriendList();
}
}
}
}

这些代码是我经优化过的代码,在编码的过程当中,肯定会遇到一些问题,这些都是宝贵的经验。下面我就说一个特别重要的问题。

点击同意按钮之后,本地的客户端能够刷新好友列表,但是接收反馈的客户端并不能刷新会话列表,但是此时查看数据库好友表当中是有记录的。客户端退出重新登陆后也能够刷新出好友列表,为了解决这个问题,打了好几个断点,最终在程序运行的状态下一直没有解决掉这个问题。最后我突然想到,要刷新好友列表,必须根据数据库中的数据来进行刷新,我就使用断点在读取数据库的时候进行检查,发现点击同意按钮之后,对方的客户端在数据库当中根本就没有查询到好友记录,但是事实上数据库当中是有数据记录的,读取数据库的代码肯定没有问题,那么就只有一个原因了,就是因为延迟的问题。


点击同意按钮之后,我是先发送的验证消息,然后再对数据库进行了修改,对方接收到验证消息之后,立刻在数据库当中进行读取,然而此时数据库根本就没有执行好插入语句,记录当然是不存在的。因此我将数据库操作和发送验证消息操作调换了一下位置,变成了先改变数据库,然后发送验证消息。果然问题就解决掉了。由此可见在编程当中需要考虑到的事情真的是非常多。

修改本地文件中验证状态的方法在上一篇文章中已经贴出来了,下面是初始化好友列表的方法:

public void initFriendList()
{
List list = loadFriendList();
loadFriends(list.Count,list);
}

该方法不止在这里调用,在Major主窗体的load事件中也要调用,记得加上。还有,这个方法是Major窗体中的,通过Common类中定义的Major静态字段进行调用。

加下来是loadFriends方法:

private void loadFriends(int FriendsNum,List friendsList)
{
//不写这个会报错线程间操作控件错误
if (this.InvokeRequired)
{
getLoadFriends a = loadFriends;
this.Invoke(a, FriendsNum, friendsList);
return;//一定要记得return或者else啊啊啊!!!!!!
}
rightPanel.Controls.Clear();
for (int i = 0; i < FriendsNum; i++)
{
Panel FriendPanel = new Panel();
FriendPanel.Name = friendsList[i].Account;
FriendPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
FriendPanel.Size = new Size(346, 50);
FriendPanel.Location = new Point(3, i * 50);
FriendPanel.MouseEnter += FriendPanel_MouseEnter;
FriendPanel.MouseLeave += FriendPanel_MouseLeave;
FriendPanel.MouseDoubleClick += FriendPanel_MouseDoubleClick;
//头像
PictureBox pb = new PictureBox();
pb.Size = new Size(30, 30);
pb.Location = new Point(11, 11);
pb.Image = Properties.Resources.知了;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.MouseEnter += FriendPanel_MouseEnter;
pb.MouseLeave += FriendPanel_MouseLeave;
pb.MouseDoubleClick += FriendPanel_MouseDoubleClick;
FriendPanel.Controls.Add(pb);
//昵称
Label nickname = new Label();
nickname.AutoSize = true;
nickname.Font = new Font("微软雅黑", 12F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(134)));
nickname.Location = new Point(47, 14);
nickname.Text = friendsList[i].NickName;
nickname.MouseEnter += FriendPanel_MouseEnter;
nickname.MouseLeave += FriendPanel_MouseLeave;
nickname.MouseDoubleClick += FriendPanel_MouseDoubleClick;
FriendPanel.Controls.Add(nickname);
//个性签名
Label signName = new Label();
signName.AutoSize = true;
signName.ForeColor = SystemColors.ControlDarkDark;
signName.Location = new Point(125, 22);
signName.Size = new Size(277, 15);
signName.Text = friendsList[i].SignName;
signName.MouseEnter += FriendPanel_MouseEnter;
signName.MouseLeave += FriendPanel_MouseLeave;
signName.MouseDoubleClick += FriendPanel_MouseDoubleClick;
FriendPanel.Controls.Add(signName);


rightPanel.Controls.Add(FriendPanel);
}

}

该方法在主界面搭建的时候已经贴出一次,这次是进行了一些修改。

Confirm窗体的任务目前为止就已经完成了,现在移步Major主窗体的接收验证消息的反馈方法这里。

private void receiveMsg()
{
//死循环保证能一直接收消息
while (true)
{
byte[] buffer = new byte[1024];
int len = Common.socket.Receive(buffer);
//该msg可以是普通消息,也可以是验证消息
string msg = Encoding.UTF8.GetString(buffer, 0, len);
//通过split将msg中的数据拆分出来
string[] msgarr = msg.Split(new string[] {Common.splitFlag }, StringSplitOptions.None);
//通过判断拆分后包含几段来区分是普通消息还是验证消息
if(msgarr.Length == 3)
{//是普通消息 先不做
MessageBox.Show("1");//测试用
}
else if(msgarr.Length ==2)
{//是验证消息
//判断是否是验证消息的反馈,暂时只识别“同意”反馈
string[] text = msgarr[1].Split(new string[] {"~~~" }, StringSplitOptions.None);
if (text.Length == 3&&text[0] == "" && text[1] == "同"&& text[2]=="意")
{//说明是验证消息的反馈
//加载和对方的会话
TalkMessage tm = new TalkMessage();
tm.Account = msgarr[0];
tm.SubMessage = "你已和"+tm.Account+"成为好友";
//geiNickName是之前写好的函数
tm.NickName = getNickName(tm.Account);
//之前写好的loadtalk方法
//获取返回值的目的是为了后面判断该会话是否存在
Panel talkpanel = loadtalk(0,tm);
Common.existedTalk.Add(tm.Account, talkpanel);
//刷新会话列表界面
refreshTalkList();
//初始化好友列表
initFriendList();
}
else
{//普通验证消息
//1.会话列表出现验证消息会话
//判断界面上是否有了验证消息会话 有就修改,没有就添加
if (!Common.existedTalk.ContainsKey("验证消息"))
{
//不包含就添加到会话列表
TalkMessage tm = new TalkMessage();
tm.NickName = "验证消息";
tm.SubMessage = msgarr[0] + "请求添加你为好友";
tm.Account = "验证消息";
Panel talkpanle = loadConfirmTalk(tm);
Common.existedTalk.Add(tm.Account, talkpanle);
//刷新会话列表界面
refreshTalkList();
}
else
{
//已经存在会话列表中了,就修改上面的提示消息
Panel talkpanel = Common.existedTalk["验证消息"];
foreach (Control c in talkpanel.Controls)
{
if (c is Label)
{
if (((Label)c).Name == "messageName")
{
((Label)c).Text = msgarr[0] + "请求添加你为好友";
}
}
}
//刷新会话列表界面
refreshTalkList();
}
//2.将消息保存到本地文件中,需要保存对方的账号、昵称、附加消息和状态
//为了存取方便,将四种数据存在文本文件的一行,一行就表示一个验证消息记录
Thread t = new Thread(saveConfirmMsg);
t.IsBackground = true;
//线程中方法传参,参数类型必须为object
object m = msgarr;
t.Start(m);
}
}
}
}

这个receiveMsg方法中就包含了接收验证消息反馈的逻辑,和昨天贴的代码就一个差别,增加了接收验证消息反馈的刷新好友列表方法。

好了,到目前为止,接收验证消息也已经完成了。效果还是不错的。到这里,CIM项目其实已经完成的差不多了,只要添加好友能完成,基本上核心内容就做完了一大半。下一篇文章将实现好友间互发消息。


本文系小博客网站原创,转载请注明文章链接地址