winform項目——仿QQ即時通訊程序17:互發消息及消息的本地存儲

上一篇文章我們實現了會話列表的存儲,本篇文章將實現最後的功能:好友間互發消息及本地消息記錄的存儲。這是CIM項目系列的最後一篇文章,因為實現這個功能之後整個項目基本上就算完成了。

首先,我們需要在Chat聊天窗體中進行用戶初始化。

我們雙擊會話或者好友列表中的panel的時候,彈出Chat聊天窗體,同時利用控件的tag屬性將對方賬號傳了過去。窗體上方有一個現實用戶暱稱的label需要初始化。

private void Chat_Load(object sender, EventArgs e)
{
//上方的暱稱標籤
lbl_nickName.Text = Common.majorForm.getNickName(this.Tag.ToString());
//消息記錄文件的路徑 以賬號為唯一標識符
msgFilePath = "record_"+this.Tag.ToString()+".db";
//初始化聊天記錄
initChatRecord();
//讓輸入框獲取焦點
tb_content.Focus();
}

這是最終的代碼,先不用管其餘的代碼,後面會用到。

winform項目——仿QQ即時通訊程序17:互發消息及消息的本地存儲


其次,我們實現發送按鈕的點擊事件:

private string msgFilePath;
private void btn_send_Click(object sender, EventArgs e)
{
//1.簡單的輸入驗證
if (tb_content.Text == "")
{
MessageBox.Show("請先輸入要發送的內容");
return;
}
if (tb_content.Text.Length > 1000)
{
MessageBox.Show("輸入的內容太多啦~");
return;
}
//2.發送消息
string time = DateTime.Now.ToString();
Common.sandMsg(this.Tag.ToString() + Common.splitFlag + tb_content.Text + Common.splitFlag + time);
//3.保存消息記錄到文件 路徑、暱稱、時間、內容
//按行保存
saveChatRecordToFile(msgFilePath, Common.majorForm.lbl_NickName.Text, time, tb_content.Text);
//刷新聊天窗體
refreshChatForm(Common.majorForm.lbl_NickName.Text,time,tb_content.Text);

//4.在會話類別中生成和對方的會話
if (!Common.existedTalk.ContainsKey(this.Tag.ToString()))
{
//加載和對方的會話
TalkMessage tm = new TalkMessage();
tm.Account = this.Tag.ToString();
if (tb_content.Text.Length > 10)
{
tm.SubMessage = tb_content.Text.Substring(0, 10) + "...";
}
else


{
tm.SubMessage = tb_content.Text;
}
tm.Time = time;
//geiNickName是之前寫好的函數
tm.NickName = lbl_nickName.Text;
//之前寫好的loadtalk方法
//獲取返回值的目的是為了後面判斷該會話是否存在
Panel talkpanel = Common.majorForm.loadtalk(0, tm);
Common.existedTalk.Add(tm.Account, talkpanel);
//將會話列表保存到文件中
Common.majorForm.saveTalkPanelToFile(tm);
//刷新會話列表界面
Common.majorForm.refreshTalkList();
}
else
{
Panel talkpanel = Common.existedTalk[this.Tag.ToString()];
foreach (Control c in talkpanel.Controls)
{
if (c is Label)
{
if (((Label)c).Name == "messageName")
{
if (tb_content.Text.Length > 10)
{
((Label)c).Text = tb_content.Text.Substring(0, 10) + "...";
}
else
{
((Label)c).Text = tb_content.Text;
}
}
if (((Label)c).Name == "lbl_time")
{
((Label)c).Text = time;
}
}
}
}
//5.將發送框中的內容清空
tb_content.Clear();
}

我將要處理的事情分成5個過程,這5點是必須要考慮到的。按照上面的註釋理解就可以了。

在這裡說一下實現本地存儲消息記錄的邏輯。網上查了下,人家是用的結構化存儲技術,只是這個技術就非常龐大了。因此我們放棄使用複雜的存儲方式。我們還是利用文本文件進行存儲,消息記錄存儲在和用戶賬號相關的一個文件中,每一條記錄佔用一行,讀取的時候也挺方便的。主要就是效率不夠高。因此我們將一個用戶就生成一個消息記錄文件,這樣既避免的訪問衝突,也提高了一點效率。

winform項目——仿QQ即時通訊程序17:互發消息及消息的本地存儲


接下來我們要繼續修改Major主界面中的接收消息部分。下面是核心代碼:

if(msgarr.Length == 3)
{//是普通消息
//判斷會話列表上是否有和對方的會話
string tempNickName = "";
if (!Common.existedTalk.ContainsKey(msgarr[0]))
{
//加載和對方的會話
TalkMessage tm = new TalkMessage();
tm.Account = msgarr[0];
if (msgarr[1].Length > 10)
{
tm.SubMessage = msgarr[1].Substring(0, 10)+"...";
}
else
{
tm.SubMessage = msgarr[1];
}
tm.Time = msgarr[2];
//geiNickName是之前寫好的函數
tempNickName = getNickName(tm.Account);
tm.NickName = tempNickName;
//之前寫好的loadtalk方法
//獲取返回值的目的是為了後面判斷該會話是否存在
Panel talkpanel = loadtalk(0, tm);
Common.existedTalk.Add(tm.Account, talkpanel);
//將會話列表保存到文件中
saveTalkPanelToFile(tm);
//刷新會話列表界面
refreshTalkList();
}
else
{


//已經存在會話列表中了,就修改上面的提示消息
Panel talkpanel = Common.existedTalk[msgarr[0]];
string temp = "";
foreach (Control c in talkpanel.Controls)
{
if (c is Label)
{
if (((Label)c).Name == "messageName")
{
if (msgarr[1].Length > 10)
{
((Label)c).Text = msgarr[1].Substring(0, 10)+"...";
}
else
{
((Label)c).Text = msgarr[1];
}
temp = ((Label)c).Text;
}
if(((Label)c).Name == "lbl_time")
{
((Label)c).Text = msgarr[2];
}
if (((Label)c).Name == "lbl_nickName")
{
tempNickName = ((Label)c).Text;
}
}
}
//刷新會話列表界面
refreshTalkList();
}
//判斷聊天窗口是否已經打開
if (!Common.existedChatForm.ContainsKey(msgarr[0]))
{//沒有打開聊天窗體
//啥也不做
}
else
{
Common.existedChatForm[msgarr[0]].refreshChatForm(tempNickName,msgarr[2],msgarr[1]);
}
//將聊天消息保存到本地文件中
saveChatRecordToFile("record_"+msgarr[0]+".db",tempNickName,msgarr[2],msgarr[1]);
}

這裡最下面多了一個判斷聊天窗體是否已經打開的邏輯,用到了Common類中定義的字典:existedChatForm,之前定義的List集合,注意要改成字典,鍵是string類型,值是Chat類型。如果窗體已經打開了,就將消息顯示聊天窗體裡面。這個字典還有一個用處,在雙擊會話列表或者好友列表的時候,會直接彈出聊天窗體,我們需要驗證一下該窗體是否已經存在了,如果存在就讓它顯示即可。

winform項目——仿QQ即時通訊程序17:互發消息及消息的本地存儲


我們需要修改動態生成的會話和好友列表中的雙擊事件:

private void FriendPanel_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (sender is Panel)
{
string account = ((Panel)sender).Name;
if (Common.existedChatForm.ContainsKey(account))
{
//存在就顯示出來
Common.existedChatForm[account].WindowState = FormWindowState.Normal;
}
else
{
//不存在就new出來
Chat c = new Chat();
//new出chat窗體 需要傳遞一個對方賬號過去
c.Tag = account;
Common.existedChatForm.Add(c.Tag.ToString(), c);
c.Show();
}
}
else
{
string account = ((Control)sender).Parent.Name;
//也new出chat窗體
//new出chat窗體 需要傳遞一個對方賬號過去
if (Common.existedChatForm.ContainsKey(account))
{
Common.existedChatForm[account].WindowState = FormWindowState.Normal;
}
else
{
Chat c = new Chat();
c.Tag = account;
Common.existedChatForm.Add(c.Tag.ToString(), c);
c.Show();
}
}
}

這裡是好友列表panel修改後的雙擊事件,會話列表的雙擊事件和這個類似,就不貼出來了。

好了,到這裡,項目規劃中所有的功能全部實現,至此,winform的CIM仿QQ即時通訊項目正式結束。

剩下的需要優化的部分需要在實際使用過程中逐漸優化。

很多同學學了編程語言,卻很難自己做項目。缺乏真正獨立的思考或者不知道如何下手。希望本系列文章能夠為初學者提供做項目的參考,將編程應用到實際。

本文系小博客網站原創,轉載請註明文章鏈接地址


分享到:


相關文章: