免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了
内容参考于:易道云信息技术研究院
上一个内容:105.处理装备与技能数据的创建
码云版本号:a715264dcde99ef2789e15577a69513e4574255d
代码下载地址,在 titan 目录下,文件名为:titan-在UI中显示装备与技能信息.zip
链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg
提取码:q9n5
--来自百度网盘超级会员V4的分享
HOOK引擎,文件名为:黑兔sdk升级版.zip
链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw
提取码:78h8
--来自百度网盘超级会员V4的分享
以 105.处理装备与技能数据的创建 它的代码为基础进行修改
效果图:
装备
物品
坐骑
扩展包
技能
上一个内容里,把装备、技能相关的结构体、数据包拦截函数(NetClient.h里面的OnSvrGameBaseReset函数)都已经搞好了,本次就是要把这些信息在ui界面中显示出来
上一个内容中的代码有一个问题
下图中15 03 00 05 00,也就是18 03数据包最大有5个,但是18 03这个数据包的序号是从1开始,这就会导致超出数组长度访问一个不确定的内存导致程序崩溃,所以数组长度我们要进行加1
新加一个Dialog
它的属性
添加一个类
类名,如果点了确定出现 COM组件的调用返回了错误HRESULT E_FAIL 98节里有解决方式,由中文目录引起的
给控件添加变量
控件的属性
变量名、变量类型
上方是物品相关的界面,下方是技能相关的界面
新加Dialog
Dialog属性
用到的控件
控件的属性
新加类
类名,CWndSkill
List控件添加变量
变量名,lstSkill
新加CWndSkill.cpp文件,技能窗口类
// CWndSkill.cpp: 实现文件
//
#include "pch.h"
#include "CWndSkill.h"
#include "resource.h"
#include "CUI.h"
#include "extern_all.h"
// CWndSkill 对话框
IMPLEMENT_DYNAMIC(CWndSkill, CDialogEx)
CWndSkill::CWndSkill(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_PAGE_4, pParent)
{
}
CWndSkill::~CWndSkill()
{
}
void CWndSkill::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, lstSkill);
}
BOOL CWndSkill::OnInitDialog()
{
CDialogEx::OnInitDialog();
CUI* ui = (CUI*)Client;
ui->SetListView(&lstSkill);
lstSkill.InsertColumn(0, L"名称", 0, 100);
lstSkill.InsertColumn(1, L"冷却时间", 0, 100);
return TRUE;
}
BEGIN_MESSAGE_MAP(CWndSkill, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &CWndSkill::OnBnClickedButton1)
END_MESSAGE_MAP()
// CWndSkill 消息处理程序
void CWndSkill::OnBnClickedButton1()
{
lstSkill.DeleteAllItems();
CString txt;
float coolDown;
int index = 0;
for (int i = 0; i < Client->SkillMax; i++)
{
if (!Client->Skill[i].Isfree) {
coolDown = Client->Skill[i].CoolDownTime / 1000;
lstSkill.InsertItem(index, Client->Skill[i].Name);
txt.Format(L"%.2f秒", coolDown);
lstSkill.SetItemText(index++, 1, txt);
}
}
}
新加CWndSkill.h文件,技能窗口类
#pragma once
#include "afxdialogex.h"
// CWndSkill 对话框
class CWndSkill : public CDialogEx
{
DECLARE_DYNAMIC(CWndSkill)
public:
CWndSkill(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CWndSkill();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_PAGE_4 };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CListCtrl lstSkill;
afx_msg void OnBnClickedButton1();
};
新加CWndItem.cpp文件,物品窗口类
// CWndItem.cpp: 实现文件
//
#include "pch.h"
#include "CWndItem.h"
#include "resource.h"
#include "extern_all.h"
#include "CUI.h"
// CWndItem 对话框
IMPLEMENT_DYNAMIC(CWndItem, CDialogEx)
CWndItem::CWndItem(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_PAGE_3, pParent)
{
}
CWndItem::~CWndItem()
{
}
void CWndItem::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, lstItem);
}
BOOL CWndItem::OnInitDialog()
{
CDialogEx::OnInitDialog();
CUI* ui = (CUI*)Client;
ui->SetListView(&lstItem);
lstItem.InsertColumn(0, L"名称",0, 100);
lstItem.InsertColumn(1, L"数量",0, 100);
return TRUE;
}
BEGIN_MESSAGE_MAP(CWndItem, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &CWndItem::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON4, &CWndItem::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CWndItem::OnBnClickedButton5)
ON_BN_CLICKED(IDC_BUTTON6, &CWndItem::OnBnClickedButton6)
END_MESSAGE_MAP()
// CWndItem 消息处理程序
void CWndItem::OnBnClickedButton1()
{
lstItem.DeleteAllItems();
CString txt;
int index = 0;
for (int i = 0; i < Client->EquipMax; i++)
{
if (!Client->Equip[i].Isfree) {
lstItem.InsertItem(index, Client->Equip[i].Name);
txt.Format(L"%d/%d", Client->Equip[i].Amount, Client->Equip[i].MaxAmount);
lstItem.SetItemText(index++, 1, txt);
}
}
}
void CWndItem::OnBnClickedButton4()
{
lstItem.DeleteAllItems();
CString txt;
int index = 0;
for (int i = 0; i < Client->ItemMax; i++)
{
if (!Client->ItemBag[i].Isfree) {
lstItem.InsertItem(index, Client->ItemBag[i].Name);
txt.Format(L"%d/%d", Client->ItemBag[i].Amount, Client->ItemBag[i].MaxAmount);
lstItem.SetItemText(index++, 1, txt);
}
}
}
void CWndItem::OnBnClickedButton5()
{
lstItem.DeleteAllItems();
CString txt;
int index = 0;
for (int i = 0; i < Client->MountMax; i++)
{
if (!Client->MountBag[i].Isfree) {
lstItem.InsertItem(index, Client->MountBag[i].Name);
txt.Format(L"%d/%d", Client->MountBag[i].Amount, Client->MountBag[i].MaxAmount);
lstItem.SetItemText(index++, 1, txt);
}
}
}
void CWndItem::OnBnClickedButton6()
{
lstItem.DeleteAllItems();
CString txt;
int index = 0;
for (int i = 0; i < Client->ItemExMax; i++)
{
if (!Client->ItemEx[i].Isfree) {
lstItem.InsertItem(index, Client->ItemEx[i].Name);
txt.Format(L"%d/%d", Client->ItemEx[i].Amount, Client->ItemEx[i].MaxAmount);
lstItem.SetItemText(index++, 1, txt);
}
}
}
新加CWndItem.h文件,物品窗口类
#pragma once
#include "afxdialogex.h"
// CWndItem 对话框
class CWndItem : public CDialogEx
{
DECLARE_DYNAMIC(CWndItem)
public:
CWndItem(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CWndItem();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_PAGE_3 };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CListCtrl lstItem;
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton4();
afx_msg void OnBnClickedButton5();
afx_msg void OnBnClickedButton6();
};
SKILL.cpp文件的修改:修改了 SetConfigID函数
#include "pch.h"
#include "SKILL.h"
#include "extern_all.h"
void SKILL::SetConfigID(char*& buffStart)
{
GAMEOBJECT::SetConfigID(buffStart);
CStringA txt;
txt.Format("desc_%s_1", ConfigID);
Name = txtManger->ReadTextById(txt.GetBuffer());
if (Name.IsEmpty()) {
Name = ConfigID;
}
}
NetClient.h文件的修改:新加 EquipMax变量、MountMax变量、ItemMax变量、SkillMax变量
#pragma once
#include "NetClass.h"
#include "GameWinSock.h"
#include "AIM.h"
#include "ITEM.h"
#include "SKILL.h"
#define CAMP_NAME_QH "xuanrenQH"
#define CAMP_NAME_ZE "xuanrenZQ"
#define MAX_AIM 0x200
class NetClient // 监视客户端每一个操作
{
typedef bool (NetClient::* DATAPROC)(char*&, unsigned&);
public:
AIM Player; // 玩家角色
/*
怪物列表,最好排序,使用lId排序,然后使用二分查找实现快速查询
结构用链表或者数组都可以
怪物或附近玩家这种东西不可能会很多
如果太多电脑处理不过来,所以数组设置为0x100大小差不多够用
*/
PAIM Aimlst[MAX_AIM]{};
// 用来控制飞天
bool HideMode;
/*
18 01 是装备
18 02 是角色背包
18 03 是扩展背包
18 08 是坐骑背包
18 31 是攻击技能
18 28 是移动类型技能
*/
PITEM Equip = nullptr; // 装备栏,18 01 是装备
PITEM MountBag = nullptr; // 坐骑栏,18 08 是坐骑背包
PITEM ItemBag = nullptr; // 物品栏,18 02 是角色背包
PITEM ItemEx = nullptr; // 扩展栏,18 03 是扩展背包
PSKILL Skill = nullptr; // 技能栏,18 28 是技能信息
short EquipMax = 0; // 装备栏数据个数
short MountMax = 0; // 坐骑栏数据个数
short ItemMax = 0; // 物品栏数据个数
short ItemExMax = 0; // 扩展栏数据个数
short SkillMax = 0; // 技能栏数据个数
protected:
PSTRUCT_DESC StructTable = nullptr;
char* StructTxt = nullptr;
POBJ_DESC ObjectTable = nullptr;// 游戏的数据类型表
char* ObjectTxt = nullptr;
DATAPROC SendProc[0x100];
DATAPROC RecvProc[0x100];
bool DefaultProc(char*&, unsigned&);
protected: // 消息处理函数-SEND
bool OnClientlogin(char*& buff, unsigned& len); // 登录数据包的处理 I_LOGIN
bool OnClientStartCreateRole(char*& buff, unsigned& len); // 申请进入创建角色界面 I_CREATEROLE_START
bool OnClientDelRole(char*& buff, unsigned& len);
bool OnClientSendCustom(char*& buff, unsigned& len);
bool OnClientCreateRole(char*& buff, unsigned& len);
bool OnClientSelectRole(char*& buff, unsigned& len);
protected: // 消息处理函数-RECV
bool OnSvrTips(char*& buff, unsigned& len);
bool OnSvrloginOk(char*& buff, unsigned& len);
bool OnSvrStartCreateRole(char*& buff, unsigned& len);
bool OnSverNotice(char*& buff, unsigned& len);
bool OnSverObject(char*& buff, unsigned& len);
bool OnSverStruct(char*& buff, unsigned& len);
bool OnSvrObjectInit(char*& buff, unsigned& len);
bool OnSvrObjectInitEx(char*& buff, unsigned& len);
bool OnSvrUpdateCord(char*& buff, unsigned& len);
bool OnSvrUpdateProperty(char*& buff, unsigned& len);
bool OnSvrUpdatePropertyMu(char*& buff, unsigned& len);
bool OnSvrRemoveObjectMu(char*& buff, unsigned& len);
bool OnSvrUpdateCordEx(char*& buff, unsigned& len);
bool OnSvrGameBase(char*& buff, unsigned& len);
bool OnSvrGameBaseReset(char*& buff, unsigned& len);
public:
PROLEDATA roles;
unsigned rolecount;
bool logined = false;
private:
GameWinSock* WinSock;
bool DelRole(const wchar_t* rolename, unsigned _len);
PAIM GetAimById(long long lId);
PAIM CreateAim(long long lId);
void RemoveAimById(long long lId);
POBJECTBASE GetGameOBJECT(short MainIndex, short Index);// 获取一个物品或技能
void ReSetGameOBJECT(short MainIndex, short max);
public:
// 通过角色名获取附近角色的信息
PAIM GetAimByName(const wchar_t* name);
// 获取面向
float GetFace(float x, float y, float targetX, float targetY);
// 通过附近角色名获取它的信息,然后通过它的信息里的坐标,再通过我们角色坐标计算面向,效果就是面向 GetAimByName(name); 这个角色
void FaceTo(const wchar_t* name);
public:
void virtual Init(GameWinSock * _winSock);
// 模拟接收的数据包
bool SetCoord(long long lId, float x, float h, float y, float face);
bool SetProperty(long long lId, int ProType, void* value);
/*
模拟登陆的方法
Id是账号
Pass是密码
它要基于发送的方法实现,因为我们没有连接socket的操作
*/
bool login(const char* Id, const char* Pass);
bool DelRole(const wchar_t* rolename);
bool StartCreateRole();// 用于创建角色
bool SelectCamp(const char* _campname);// 选择阵营
/*
性别 0 男 1 女
阵营 1 艾森赫特 2 格兰蒂尔
种族 1 布冯特人 3 格洛玛人 4 尤恩图人 6 喀什人
职业 1 仲裁者 3秘法师 6 猎魔人 8 元素法师
脸型 0 1 2 3
*/
bool CreateRole(wchar_t* name,double sex, double camp, double face, double occu, const char* photo, const char*infos, const char* txt, double faceShape);// 角色创建
// 选择角色并且登录进游戏
bool SelectRole(const wchar_t* rolename);
// 坠落
bool Fall();
// 瞬移
void Teleport(float x, float h, float y, float face);
// 模拟停止
bool MoveStop(float x, float h, float y, float face);
// 原地跳
bool MoveJump(float x, float h, float y, float face, float oldy, float xNext, float yNext);
// 移动开始
bool MoveWalk(float x, float h, float y, float face, float oldy, float xNext, float yNext);
// 应该是移动时跳跃
bool MoveWJump(float x, float h, float y, float face, float oldy, float xNext, float yNext);
// 使用技能
bool UseSkill(const char* _skillName, float x, float h, float y, float face, float xTarget = 0, float hTarget = 0, float yTarget = 0, int rInt1 = 0, int rInt2 = 0, int rInt3 = 0);
// 根据角色名字获取一个登录成功数据包(选择角色列表里的一个数据)
PROLEDATA GetRoleByName(const wchar_t* rolename);
bool Talk(wchar_t* txt, int PdId = 1, double un = 0.0);
bool TalkTo(wchar_t* name, wchar_t* txt, double un = 0.0);
bool HeartBeep();// 心跳数据包(5秒)
bool HeartLoop();// 延迟心跳数据包(20秒)
bool Backtoroles(); // 返回到选择角色界面
public:
// 用于拦截游戏删除角色功能
bool virtual OnDelRole(wchar_t* rolename, unsigned _len);
// 用于拦截游戏登录功能
void virtual Onlogin(const char* Id, const char*Pass);
// 用于拦截游戏创建角色功能
bool virtual OnStartCreateRole(int code);
// 拦截创建角色
bool virtual OnCreateRole(PNS_CREATEROLE _header, PCREATE_ROLE_DATAS _body);
// opcode意思是操作码,count意思是数量,buffStart意思是解码的内容开始,buffend意思是解码的内容结束,buffer是原始的数据,len是原始数据的长度
// char& buffer, int& len这俩参数带&的原因是,在 OnSendCustom 里进行修改之后,通过&的方式传递回去
bool virtual OnSendCustom(PNET_SEND_CHEAD _coder, char*& buffer, unsigned& len);// 拦截0xA开头发送的数据包
bool virtual OnSelectRole(wchar_t* rolename);
public:
// 针对SendCustom的单独处理
bool virtual OnChooseCamp(PNS_CHOOSECAMP _coder);
bool virtual OnChat(PCHAT_DATA _coder);
bool virtual OnChatPublic(PCHAT_PUB _coder);
bool virtual OnChatPrivate(PCHAT_PRV _coder);
bool virtual OnHeartBeep(PHEART_BEEP _coder);
bool virtual OnHeartLoop(PHEART_LOOP _coder);
// 分发移动处理函数
bool virtual OnMove(PMOVE_DATA _coder);
// 移动中处理函数
bool virtual OnMoveWalk(PMOVE_DATA_WALK _coder);
// 停止移动处理函数
bool virtual OnMoveStop(PMOVE_DATA_STOP _coder);
// 跳跃处理函数
bool virtual OnMoveJump(PMOVE_DATA_JUMP _coder);
// 移动时跳跃
bool virtual OnMoveWJump(PMOVE_DATA_WJUMP _coder);
// 分发坠落函数
bool virtual OnFall(PFALL_DATA_START _coder);
// 针对Notice的单独处理
bool virtual OnSvrChat(PCHAT_PRV _coder);
bool virtual OnUseSkill(PUSESKILL _coder);
bool virtual OnInited(); // 发送完了964数据包,表示角色上线
public:
// 处理失败,参数是错误码
bool virtual Tips(int code);
void virtual loginok(ROLE_DATA* _roles, int count);
bool virtual OnScrStartCreateRole(short code,wchar_t* _txt);
bool virtual OnSvrNotice(PNET_SEND_CHEAD _coder, int count, char*& buffer, unsigned& len);
public:
bool virtual OnRecvData(char*& buff, unsigned& len);
bool virtual OnSendData(char*& buff, unsigned& len);
bool virtual OnConnect(char*& ip, unsigned& port);
};
CUI.cpp文件的修改:修改了 OnInitDialog函数
// 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"周围");
InstallPage(new CWndSet(), IDD_PAGE_2, L"设置");
InstallPage(new CWndItem(), IDD_PAGE_3, L"装备");
InstallPage(new CWndSkill(), IDD_PAGE_4, 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;
}
bool CUI::OnFall(PFALL_DATA_START _coder)
{
NetClient::OnFall(_coder);
return !wnds.wndSet->setValue[(unsigned)SETNAME::NeverFall];
}
bool CUI::OnMoveWalk(PMOVE_DATA_WALK _coder)
{
if (wnds.wndSet->setValue[(unsigned)SETNAME::AddSpeed])
{
float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;
MoveSpeed[0] = wnds.wndSet->OldSpeed;
}
return true;
}
bool CUI::OnMoveJump(PMOVE_DATA_JUMP _coder)
{
if (wnds.wndSet->setValue[(unsigned)SETNAME::AddSpeed])
{
float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;
MoveSpeed[0] = wnds.wndSet->OldSpeed;
}
return true;
}
bool CUI::OnMoveWJump(PMOVE_DATA_WJUMP _coder)
{
if (wnds.wndSet->setValue[(unsigned)SETNAME::AddSpeed])
{
float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;
MoveSpeed[0] = wnds.wndSet->OldSpeed;
}
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)
{
// wnds.wndAIM->UI();
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文件的修改:新加 CWndItem.h头文件、CWndSkill.h头文件,修改了 WNDS结构体
#pragma once
#include "afxdialogex.h"
#include "NetClient.h"
#include "TextManger.h"
//增加页面头文件
#include "CUIWnd_0.h"
#include "CUIWnd_1.h"
#include "CWndSet.h"
#include "CWndItem.h"
#include "CWndSkill.h"
//游戏辅助UI类
// CUI 对话框
enum class LOGTYPE {
TIPS = 0,
SYS = 1,
CHAT = 2,
MAX
};
typedef struct WNDS {
CUIWnd_0* wndRole;
CUIWnd_1* wndAIM;
CWndSet* wndSet;
CWndItem* wndItem;
CWndSkill* wndSkill;
}*PWNDS;
// #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);
// 分发坠落函数
bool virtual OnFall(PFALL_DATA_START _coder);
// 移动中处理函数
bool virtual OnMoveWalk(PMOVE_DATA_WALK _coder);
// 跳跃处理函数
bool virtual OnMoveJump(PMOVE_DATA_JUMP _coder);
// 移动时跳跃
bool virtual OnMoveWJump(PMOVE_DATA_WJUMP _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;
};