免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
如果看不懂、不知道现在做的什么,那就跟着做完看效果
现在的代码都是依据数据包来写的,如果看不懂代码,就说明没看懂数据包
内容参考于: 易道云信息技术研究院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_TIME
enum { IDD = IDD_MAIN };
#endif
protected:
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;
};