免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
如果看不懂、不知道现在做的什么,那就跟着做完看效果
现在的代码都是依据数据包来写的,如果看不懂代码,就说明没看懂数据包
内容参考于: 易道云信息技术研究院VIP课
上一个内容:99.角色信息显示的界面与功能
码云版本号:29bc3dcda440ed9313ce135d7cdf2d475f81431d
代码下载地址,在 titan 目录下,文件名为:titan-聊天功能的界面与设计.zip
链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg
提取码:q9n5
--来自百度网盘超级会员V4的分享
HOOK引擎,文件名为:黑兔sdk升级版.zip
链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw
提取码:78h8
--来自百度网盘超级会员V4的分享
以 99.角色信息显示的界面与功能 它的代码为基础进行修改
上一个内容把角色的基础信息给显示了出来,然后现在把游戏聊天的功能界面给实现了,然后就能在我们的界面中跟游戏中的玩家进行聊天了
效果图:
聊天数据包的分析,传送门:56.聊天数据的截取与模拟
然后给别人发私信,服务端会给我一个103的数据,用来表示发送的私信
新加组件
属性,除了下图的下拉框属性有修改其它两个(输入框)属性都是默认的,但是这个输入框不知怎么回事没法写中文(中文乱码)
添加的变量,下图是下拉框的
添加的变量,下图的指向的输入框是私聊的时候写对方角色名的
添加的变量,用来写发送内容的
CUI.cpp文件的修改:修改了 OnInitDialog函数、OnTimer函数,重写 OnSvrChat函数,新加 OnBnClickedButton1函数
// CUI.cpp: 实现文件
//#include "pch.h"
#include "htdMfcDll.h"
#include "CUI.h"
#include "afxdialogex.h"
#include "extern_all.h"
// CUI 对话框IMPLEMENT_DYNAMIC(CUI, CDialogEx)CUI::CUI(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_MAIN, pParent), txtDetails(_T("")), txtChat(_T("")), txtChatName(_T(""))
{}CUI::~CUI()
{
}void CUI::SetListView(CListCtrl* lst)
{auto lStyle = GetWindowLongPtr(lst->m_hWnd, GWL_STYLE); // 获取窗口样式lStyle |= LVS_REPORT; // 设置为报表模式SetWindowLongPtr(lst->m_hWnd, GWL_STYLE, lStyle);// 给窗口设置样式auto dStyle = lst->GetExtendedStyle(); // 获取扩展样式dStyle |= LVS_EX_FULLROWSELECT; // 设置选择时选择一行dStyle |= LVS_EX_GRIDLINES; // 画网格线lst->SetExtendedStyle(dStyle); // 设置扩展样式
}void CUI::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_TAB1, mTab);DDX_Control(pDX, IDC_LIST1, lstlog);DDX_Text(pDX, IDC_EDIT1, txtDetails);DDX_Text(pDX, IDC_EDIT3, txtChat);DDX_Text(pDX, IDC_EDIT2, txtChatName);DDX_Control(pDX, IDC_COMBO2, cmbChat);
}BOOL CUI::OnInitDialog()
{CDialogEx::OnInitDialog();SetListView(&lstlog);InstallPage(new CUIWnd_0(this), IDD_PAGE_0, L"角色", TRUE);InstallPage(new CUIWnd_1(this), IDD_PAGE_1, L"信息");lstlog.InsertColumn(0, L"消息", 0, 70);lstlog.InsertColumn(1, L"内容", 0, 700);lstlog.InsertColumn(2, L"时间", 0, 200);//PageINJ.Init(wAppPath);//PageRAN.SetAppPath(wAppPath);for (CString & txt : ChatPdName){cmbChat.AddString(txt);}cmbChat.SetCurSel(0);return TRUE;
}bool CUI::InstallPage(CDialogEx* wnd, int IDD_WND, CString&& _Name, BOOL IsShow)
{if (CurPage >= (sizeof(WNDS) / sizeof(CDialogEx*))) return false;Pages[CurPage] = wnd;Pages[CurPage]->Create(IDD_WND, this);//Pages[CurPage]->SetParent(this);Pages[CurPage]->ShowWindow(IsShow);CRect rect;mTab.GetClientRect(&rect);rect.top += 32;rect.left += 5;rect.bottom -= 4;rect.right -= 5;Pages[CurPage]->MoveWindow(&rect);mTab.InsertItem(CurPage, _Name);CurPage++;return true;
}BEGIN_MESSAGE_MAP(CUI, CDialogEx)ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, &CUI::OnTcnSelchangeTab1)ON_WM_TIMER()ON_BN_CLICKED(IDC_BUTTON1, &CUI::OnBnClickedButton1)
END_MESSAGE_MAP()// CUI 消息处理程序void CUI::OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
{// TODO: 在此添加控件通知处理程序代码*pResult = 0;int n = mTab.GetCurSel();for (int i = 0; i < CurPage; i++){Pages[i]->ShowWindow(i == n);}
}PTextManger CUI::getTxtManger()
{if (!txtManger)txtManger = new TextManger("F:\\语言包.txt");return txtManger;
}void CUI::loginok(ROLE_DATA* _roles, int count)
{PushLog(LOGTYPE::SYS, L"账号登录成功");NetClient::loginok(_roles, count);wnds.wndRole->lstRole.DeleteAllItems();CString txtInfos;for (int i = 0; i < count; i++){txtInfos = _roles[i].infos.value();txtInfos = txtInfos + L";";CString txtIndex, txtSex, txtMap, txtJob, txtCamp, txtRace, txtLv;CStringA stxtMap, stxtJob, stxtCamp, stxtRace;txtSex = ReadValue(txtInfos, L"1,", L";");txtMap = ReadValue(txtInfos, L"56,", L";");txtJob = L"job_" + ReadValue(txtInfos, L"37,", L";");txtCamp = L"camp_" + ReadValue(txtInfos, L"35,", L";");txtRace = L"race_" + ReadValue(txtInfos, L"36,", L";");txtLv = ReadValue(txtInfos, L"38,", L";");txtIndex.Format(L"%d", _roles[i].index.value());stxtMap = txtMap;stxtJob = txtJob;stxtCamp = txtCamp;stxtRace = txtRace;txtSex = SexName[txtSex == L"1"];wnds.wndRole->lstRole.InsertItem(0, txtIndex);wnds.wndRole->lstRole.SetItemText(0, 1, _roles[i].name);wnds.wndRole->lstRole.SetItemText(0, 2, txtLv);wnds.wndRole->lstRole.SetItemText(0, 3, txtSex);wnds.wndRole->lstRole.SetItemText(0, 4, getTxtManger()->ReadTextById(stxtCamp.GetBuffer()));wnds.wndRole->lstRole.SetItemText(0, 5, getTxtManger()->ReadTextById(stxtMap.GetBuffer()));wnds.wndRole->lstRole.SetItemText(0, 6, getTxtManger()->ReadTextById(stxtRace.GetBuffer()));wnds.wndRole->lstRole.SetItemText(0, 7, getTxtManger()->ReadTextById(stxtJob.GetBuffer()));}
}bool CUI::Tips(int code)
{CString logName;logName.Format(L"服务器提示:%d", code);PushLog(LOGTYPE::TIPS, logName.GetBuffer());// NetClient::Tips(code);return true;
}bool CUI::OnInited()
{SetTimer(0x10001, 50, NULL);return true;
}bool CUI::OnSvrChat(PCHAT_PRV _coder)
{CString txt;CString txtPd;CString txtName = _coder->name;CString txtInfo = _coder->txt;txt.Format(L"%d", _coder->ChartId.value());AfxMessageBox(txt);switch (_coder->ChartId){case 1:// 附近频道txtPd = L"附近";break;case 2:// 区域频道txtPd = L"区域";break;case 3:// 私聊txtPd = L"接收的私聊";// return OnChatPrivate((PCHAT_PRV)_coder);break;case 6:// 公会频道txtPd = L"公会";break;case 9:// 阵营频道txtPd = L"阵营";break;case 21:// 喊话频道txtPd = L"喊话";// return OnChatPublic((PCHAT_PUB)_coder);break;case 103:// 喊话频道txtPd = L"发送的私信";// return OnChatPublic((PCHAT_PUB)_coder);break;}txt.Format(L"[%s][%s][%s]", txtPd, txtInfo, txtName);PushLog(LOGTYPE::CHAT, txt.GetBuffer());return true;
}CString CUI::ReadValue(CString& txt, wchar_t* key, wchar_t* endStr)
{CString result = L"";int iStart = txt.Find(key);if (iStart > -1) {iStart = iStart + wcslen(key);int iend = txt.Find(endStr, iStart);if (iend > -1)result = txt.Mid(iStart, iend - iStart);}return result;
}void CUI::PushLog(LOGTYPE type, wchar_t* txt)
{struct tm newtiem {};time_t t;time(&t);localtime_s(&newtiem, &t); // 获取时间CString logName;logName.Format(L"%.4d-%.2d-%.2d %.2d:%.2d:%.2d", newtiem.tm_year + 1900, newtiem.tm_mon + 1, newtiem.tm_mday, newtiem.tm_hour, newtiem.tm_min, newtiem.tm_sec);lstlog.InsertItem(0, MsgName[(int)type]);lstlog.SetItemText(0, 1, txt);lstlog.SetItemText(0, 2, logName);
}void CUI::OnTimer(UINT_PTR nIDEvent)
{CStringA tmp;tmp.Format("%d", Player.CurArea);txtDetails.Format(L"lv.%d.%s 生命值[%d/%d] 经验值[%d/%d] 当前所在场景[%s](%.2f|%.2f|%.2f)", Player.Level, Player.Name, Player.HP, Player.MaxHP + Player.MaxHPAdd, Player.PlayerExp, Player.PlayerUpgradeExp, getTxtManger()->ReadTextById(tmp.GetBuffer()), Player.x, Player.h, Player.y);SetDlgItemText(IDC_EDIT1, txtDetails.GetBuffer());// UpdateData(FALSE);__super::OnTimer(nIDEvent);
}void CUI::OnBnClickedButton1()
{int nsel = cmbChat.GetCurSel();UpdateData(TRUE);if (nsel > -1) {if (ChatPdId[nsel] != -1) {Talk(txtChat.GetBuffer(), ChatPdId[nsel]);}else {TalkTo(txtChatName.GetBuffer(), txtChat.GetBuffer());}txtChat = L"";}SetDlgItemText(IDC_EDIT3, txtChat.GetBuffer());}
CUI.h文件的修改:修改了 LOGTYPE枚举、MsgName数组、新加 ChatPdName数组、ChatPdId数组,重写 OnSvrChat函数,新加 OnBnClickedButton1函数(发送按钮的点击事件处理函数)
#pragma once
#include "afxdialogex.h"
#include "NetClient.h"
#include "TextManger.h"
//增加页面头文件
#include "CUIWnd_0.h"
#include "CUIWnd_1.h"
//游戏辅助UI类
// CUI 对话框enum class LOGTYPE {TIPS = 0,SYS = 1,CHAT = 2,MAX
};typedef struct WNDS {CUIWnd_0* wndRole;CUIWnd_1* wndInfo;
};// #define MAX_PAGE_MAIN 3// 这里用了多重继承,这回有一个问题,函数名一样的会发生冲突
// 所以在继承的时候要注意函数名
class CUI : public CDialogEx,public NetClient
{DECLARE_DYNAMIC(CUI)public:CUI(CWnd* pParent = nullptr); // 标准构造函数virtual ~CUI();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_MAIN };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持DECLARE_MESSAGE_MAP()union {CDialogEx* Pages[sizeof(WNDS)/sizeof(CDialogEx*)];WNDS wnds;};short CurPage = 0;
public:CTabCtrl mTab;virtual BOOL OnInitDialog();bool InstallPage(CDialogEx* wnd, int IDD_WND, CString&& _Name, BOOL IsShow=FALSE);afx_msg void OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);
public:void SetListView(CListCtrl* lst);PTextManger getTxtManger();CListCtrl lstlog;
protected:CString MsgName[(unsigned int)LOGTYPE::MAX]{L"错误",L"系统",L"聊天"};CString SexName[2]{L"男",L"女"};CString ChatPdName[6]{L"附近",L"区域",L"公会",L"阵营",L"喊话",L"私信"};int ChatPdId[6]{1, 2, 6, 9, 21, -1};void PushLog(LOGTYPE type, wchar_t* txt);
protected:void virtual loginok(ROLE_DATA* _roles, int count);bool virtual Tips(int code);bool virtual OnInited();bool virtual OnSvrChat(PCHAT_PRV _coder);// 解析角色的信息,性别、种族、阵营等CString ReadValue(CString&txt, wchar_t* key, wchar_t* endStr);
public:CString txtDetails;afx_msg void OnTimer(UINT_PTR nIDEvent);CString txtChat;CString txtChatName;afx_msg void OnBnClickedButton1();CComboBox cmbChat;
};