27.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-数据推测功能的实现

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

如果看不懂、不知道现在做的什么,那就跟着做完看效果

内容参考于: 易道云信息技术研究院VIP课

上一个内容:26.实现生成日志文件的功能

码云地址(master 分支):https://gitee.com/dye_your_fingers/titan

码云版本号:13a407b03922897a3453674a43c10e9eb617b18a

代码下载地址,在 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的分享

26.实现生成日志文件的功能 它的代码为基础进行修改

首先创建一个Dialog

添加一个编辑框控件:

然后添加一个类:

编辑框添加变量:

给数据包列表添加一个鼠标左键事件处理程序

效果图:选择文字可以弹出选择的文字,后面改成其它弹框,不会弹MessageBox

DataAnlyDlg.cpp文件的修改:修改了 OnInitDialog函数、LoadConfig函数(上一个内容中写错了默认配置文件取值字段),新加 OnNMClickList1函数(列表鼠标左键单击事件处理函数)


// DataAnlyDlg.cpp: 实现文件
//#include "pch.h"
#include "framework.h"
#include "DataAnly.h"
#include "DataAnlyDlg.h"
#include "afxdialogex.h"
#include "extern_all.h"
#include <fstream> // 引入io流,用于写文件#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx
{
public:CAboutDlg();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_ABOUTBOX };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CDataAnlyDlg 对话框CDataAnlyDlg::CDataAnlyDlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_DATAANLY_DIALOG, pParent), Pause(FALSE)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CDataAnlyDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_LIST1, lstView);DDX_Check(pDX, IDC_CHECK1, Pause);
}BEGIN_MESSAGE_MAP(CDataAnlyDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDOK, &CDataAnlyDlg::OnBnClickedOk)ON_WM_COPYDATA()ON_BN_CLICKED(IDC_CHECK1, &CDataAnlyDlg::OnBnClickedCheck1)ON_BN_CLICKED(IDC_BUTTON1, &CDataAnlyDlg::OnBnClickedButton1)ON_BN_CLICKED(IDC_BUTTON4, &CDataAnlyDlg::OnBnClickedButton4)ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST1, &CDataAnlyDlg::OnNMCustomdrawList1)ON_BN_CLICKED(IDC_BUTTON5, &CDataAnlyDlg::OnBnClickedButton5)ON_NOTIFY(NM_CLICK, IDC_LIST1, &CDataAnlyDlg::OnNMClickList1)
END_MESSAGE_MAP()// CDataAnlyDlg 消息处理程序BOOL CDataAnlyDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != nullptr){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// ShowWindow(SW_MAXIMIZE); // 设置最大号启动// TODO: 在此添加额外的初始化代码SetListView(&lstView);wchar_t buff[0xFF];/*获取当前程序名,这个名字是全路径,不只有程序名字(就是.exe文件的名字)它还可以获取别人的名字详细看微软的MSDN里的说明(百度搜索 “GetModuleFileName msdn” 关键字,就可以搜索出微软MSDN的说明)*/ GetModuleFileName(0, buff, sizeof(buff));int i;for (i = 0xFF - 1; buff[i] != L'\\'; i--);buff[++i] = 0;AppPath.Format(L"%s", buff);// AfxMessageBox(AppPath);ConfigPath = AppPath + L"Config\\";DataPath = AppPath + L"Datas\\";DefConfigIni = ConfigPath + L"titan.ini";SetIni = AppPath + L"Set.ini";/*读取一个Set.ini文件Set.ini文件目前存放了,当程序启动时默认加载什么配置文件的数据*/GetPrivateProfileString(L"main", L"defPro", L"", buff, 0xFF, SetIni);// 获取配置文件,也就是现在的titan.ini这个文件DefConfigIni = AppPath + L"Config\\" + buff + L".ini";LoadConfig(DefConfigIni);/*lstView.InsertColumn(0, L"消息类型", 0, 70);lstView.InsertColumn(1, L"数据类型", 0, 70);lstView.InsertColumn(2, L"内容", 0, 700);lstView.InsertColumn(3, L"长度", 0, 50);lstView.InsertColumn(4, L"时间", 0, 130);这几行代码意思是设置表头*/lstView.InsertColumn(0, L"消息类型", 0, 70);lstView.InsertColumn(1, L"数据类型", 0, 70);lstView.InsertColumn(2, L"内容", 0, 700);lstView.InsertColumn(3, L"长度", 0, 50);lstView.InsertColumn(4, L"时间", 0, 130);struct tm newtiem {};time_t t;time(&t);localtime_s(&newtiem, &t); // 获取时间LogName.Format(L"%.4d-%.2d-%.2d %.2d-%.2d-%.2d.log", newtiem.tm_year + 1900, newtiem.tm_mon+1, newtiem.tm_mday, newtiem.tm_hour, newtiem.tm_min, newtiem.tm_sec);wndSet.Create(IDD_SET);wndData.Create(IDD_DIALOG1);return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}void CDataAnlyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。void CDataAnlyDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDataAnlyDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CDataAnlyDlg::OnBnClickedOk()
{wchar_t buff[]{ L"我爱阿民" };COPYDATASTRUCT copydata{};/*这里的0表示字符串0具体是什么要看 WM_COPYDATA消息处理函数怎样写的*/copydata.dwData = 0;copydata.cbData = sizeof(buff);copydata.lpData = buff;SendMessage(WM_COPYDATA, 0, (LPARAM)&copydata);
}BOOL CDataAnlyDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* p)
{UpdateData(true);if (Pause)return CDialogEx::OnCopyData(pWnd, p);PCOPYDATA pdata = (PCOPYDATA)p->lpData;struct tm newtiem {};localtime_s(&newtiem, &pdata->ltime); // 获取时间int type = p->dwData;if (type < MAX_MSG) {CString _result;CString _time;_time.Format(L"%.2d-%.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);// 0数据包 1 char 2 wchar_tif (_MsgPtr[type].Type == 0) { // 数据包// 转换为buffunsigned char* buff = (unsigned char*)pdata->buff;CString _tmp;for (int i = 0; i < pdata->len; i++) {_tmp.Format(L"%.2X", buff[i]);_result = _result + L" " + _tmp;}}CString wlen;PDATA _data = _MsgPtr[type].GetData(pdata->MsgType);bool Show = true;CString txtDetails;if (_data){Show = _data->IsUi;txtDetails.Format(L"%s(%X)", _data->Name, pdata->MsgType);}else {txtDetails.Format(L"%X", pdata->MsgType);}if (Show) {lstView.InsertItem(0, _MsgPtr[type].txtName);lstView.SetItemData(0, (DWORD_PTR)_data);lstView.SetItemText(0, 1, txtDetails);lstView.SetItemText(0, 2, _result);lstView.SetItemText(0, 4, _time);wlen.Format(L"%d", pdata->len);lstView.SetItemText(0, 3, wlen);}CString _log;CString _logfile;_log.Format(L"[%s][%s][%d][%s][%s]", _MsgPtr[type].txtName, _time.GetBuffer(), pdata->len, txtDetails, _result);_logfile = DataPath + productName + L"\\" + LogName;if(_MsgPtr[type].IsTxt) Savelog(_log.GetBuffer(), _logfile.GetBuffer()); // 写到文件if ((_data)&&(_data->IsTxt)) { // 所有这里存放所有类型的数据包_logfile.Format(L"%s%s\\%s.log", DataPath, productName, _MsgPtr[type].txtDefine);Savelog(_log.GetBuffer(), _logfile.GetBuffer());}if ((_data) && (_data->IsTxtAlone)) { // 单独输出,也就是相同类型的数据包放到一个文件中_logfile.Format(L"%s%s\\%s\\%X.log", DataPath, productName, _MsgPtr[type].txtDefine, _data->Id);Savelog(_log.GetBuffer(), _logfile.GetBuffer());}}else {AfxMessageBox(L"接收到无法识别的数据,需要重新根据配置生成头文件!");}	return CDialogEx::OnCopyData(pWnd, p);
}void CDataAnlyDlg::OnBnClickedCheck1()
{
}void CDataAnlyDlg::OnBnClickedButton1()
{lstView.DeleteAllItems();
}void CDataAnlyDlg::OnBnClickedButton4()
{wndSet.ShowWindow(TRUE);wndSet.LoadConfig(DefConfigIni, productName);
}void CDataAnlyDlg::LoadConfig(CString inifile) {/*从配置文件中读取一个数据,意思是从main下的count读取一个数字int类型的数字GetPrivateProfileInt用来获取.ini文件里的内容,最后的Int表示读取的数据类型Int就表示读取int类型,String表示读取String类型,也就是一个字符串GetPrivateProfileString(L"main", L"title", L"", buff, 0xFF, inifile);里的L""是默认值GetPrivateProfileInt(L"main", L"count", 0, inifile);里的0是默认值默认值的意思,如果读取不到数据就把默认值返回给我们*/int icount = GetPrivateProfileInt(L"main", L"count", 0, inifile);if (_MsgPtr) delete[] _MsgPtr;if (icount < 1) return;MAX_MSG = icount;_MsgPtr = new MSG_DEC[icount];lstView.DeleteAllItems();wchar_t buff[0xFF];GetPrivateProfileString(L"main", L"title", L"", buff, 0xFF, inifile);this->SetWindowText(buff);GetPrivateProfileString(L"main", L"name", L"", buff, 0xFF, inifile);productName = buff;WritePrivateProfileString(L"main", L"defPro", productName, SetIni);/*CString App;CString AppData;CString _Name;它是用来初始化字符串的,利用 Foramt 函数把从.ini文件里获取的数据全部转成字符串*/CString App;CString AppData;CString _Name;for (int i = 0; i < icount; i++){App.Format(L"Message_%d", i);GetPrivateProfileString(App, L"name", L"", _MsgPtr[i].txtName, 0xFF, inifile);_Name.Format(L"%s", _MsgPtr[i].txtName);GetPrivateProfileString(App, L"define", L"", _MsgPtr[i].txtDefine, 0xFF, inifile);GetPrivateProfileString(App, L"type", L"", buff, 0xFF, inifile);_MsgPtr[i].Type = TxtToType(buff);GetPrivateProfileString(App, L"istxt", L"", buff, 0xFF, inifile);_MsgPtr[i].IsTxt = TxtToBool(buff);;int lcount = GetPrivateProfileInt(App, L"count", 0, inifile);_MsgPtr[i].Datas = new DATA_DEC[lcount];_MsgPtr[i].DataCount = lcount;for (int j = 0; j < lcount; j++){AppData.Format(L"%s_%d", _Name.GetBuffer(), j);PDATA dataDec = &(_MsgPtr[i].Datas[j]);dataDec->Msg = &(_MsgPtr[i]);GetPrivateProfileString(AppData, L"id", L"0", buff, 0xFF, inifile);dataDec->Id = _wtoi(buff);GetPrivateProfileString(AppData, L"name", L"0", dataDec->Name, 0xFF, inifile);GetPrivateProfileString(AppData, L"backcolor", L"0", buff, 0xFF, inifile);dataDec->BackColor = TxtToColor(buff);GetPrivateProfileString(AppData, L"fontcolor", L"0", buff, 0xFF, inifile);dataDec->FontColor = TxtToColor(buff);GetPrivateProfileString(AppData, L"isui", L"0", buff, 0xFF, inifile);dataDec->IsUi = TxtToBool(buff);GetPrivateProfileString(AppData, L"istxt", L"0", buff, 0xFF, inifile);dataDec->IsTxt = TxtToBool(buff);GetPrivateProfileString(AppData, L"istxtalone", L"0", buff, 0xFF, inifile);dataDec->IsTxtAlone = TxtToBool(buff);}}/*要做一个数据包保存到硬盘功能mainlog = DataPath + productName; 是用来获取保存到什么文件的也就是一个文件的绝对路径,这个文件用来保存数据包*/mainlog = DataPath + productName; 
}void CDataAnlyDlg::OnNMCustomdrawList1(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码*pResult = 0;NMLVCUSTOMDRAW* lp = (NMLVCUSTOMDRAW*)pNMHDR;NMCUSTOMDRAW& ncmd = lp->nmcd;switch (ncmd.dwDrawStage){case CDDS_PREPAINT: {*pResult = CDRF_NOTIFYITEMDRAW;break;}case CDDS_ITEMPREPAINT: {PDATA _data = (PDATA)lstView.GetItemData(ncmd.dwItemSpec);if (_data) {lp->clrTextBk = _data->BackColor;lp->clrText = _data->FontColor;*pResult = CDRF_DODEFAULT;}break;}}}void CDataAnlyDlg::Savelog(const wchar_t* logs, const wchar_t* file)
{// 设置追加写入文件std::wofstream ofs(file, std::ios::app);// 设置语言集,防止写中文出错ofs.imbue(std::locale("chs")); if (ofs.bad())return;ofs << logs << std::endl;ofs.close();
}// 加载按钮
void CDataAnlyDlg::OnBnClickedButton5()
{LoadConfig(DefConfigIni);
}void CDataAnlyDlg::OnNMClickList1(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);// TODO: 在此添加控件通知处理程序代码*pResult = 0;NM_LISTVIEW* p = (NM_LISTVIEW*)pNMHDR;if (p->iItem != -1) {wndData.ShowWindow(TRUE);wndData.m_Edit.SetWindowTextW(lstView.GetItemText(p->iItem,2));}
}

DataAnlyDlg.cpp文件的修改:新加 OnNMClickList1函数(列表鼠标左键单击事件处理函数)


// DataAnlyDlg.h: 头文件
//#pragma once
#include "CSet.h"
#include "MSG_DEC.h"
#include "CWndData.h"typedef struct COPY_DATA {time_t ltime; // 时间unsigned MsgType; // 数据类型unsigned len; // 数据长度char buff[0x2000]; // 数据
}*PCOPYDATA;// CDataAnlyDlg 对话框
class CDataAnlyDlg : public CDialogEx
{
// 构造
public:CDataAnlyDlg(CWnd* pParent = nullptr);	// 标准构造函数// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_DATAANLY_DIALOG };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持// 实现
protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
public:CListCtrl lstView;afx_msg void OnBnClickedOk();afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);BOOL Pause;afx_msg void OnBnClickedCheck1();afx_msg void OnBnClickedButton1();CSet wndSet;CWndData wndData;afx_msg void OnBnClickedButton4();void CDataAnlyDlg::LoadConfig(CString inifile);afx_msg void OnNMCustomdrawList1(NMHDR* pNMHDR, LRESULT* pResult);CString LogName; // 数据包写到硬盘上的文件名CString mainlog; // 数据包保存目录CString productName; // 当前titlevoid Savelog(const wchar_t* logs, const wchar_t* file);afx_msg void OnBnClickedButton5();afx_msg void OnNMClickList1(NMHDR* pNMHDR, LRESULT* pResult);
};

新加CWndData.h文件:

#pragma once// CWndData 对话框class CWndData : public CDialogEx
{DECLARE_DYNAMIC(CWndData)public:CWndData(CWnd* pParent = nullptr);   // 标准构造函数virtual ~CWndData();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_DIALOG1 };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持DECLARE_MESSAGE_MAP()
public:CEdit m_Edit;HWND hTips;virtual BOOL OnInitDialog();void loops(HWND, UINT, CWndData* _this, DWORD);void ShowTips();CString lastTxt;
};

新加CWndData.cpp文件

// CWndData.cpp: 实现文件
//#include "pch.h"
#include "DataAnly.h"
#include "CWndData.h"
#include "afxdialogex.h"// CWndData 对话框IMPLEMENT_DYNAMIC(CWndData, CDialogEx)CWndData::CWndData(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_DIALOG1, pParent)
{}CWndData::~CWndData()
{
}void CWndData::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_EDIT1, m_Edit);
}BOOL CWndData::OnInitDialog()
{/*为了处理数据方便,我要给定时器一个成员函数然后成员函数它不满足 TIMERPROC 这个类型,编译器也不让我们强制转换所以要用一个联合体封装一下,联合体里的变量都共用一个内存内存大小由联合体里最大的变量决定*/union {TIMERPROC _address;void (CWndData::* _classProc)(HWND, UINT, CWndData*, DWORD);}v;v._classProc = &CWndData::loops;CDialogEx::OnInitDialog();/*定时器执行的函数stdcall,让它调用的函数是类的成员函数定时器调用的时候可能不会有this(也就是ecx的值不是类对象地址)所以这里要手动的把this传递过去这样可以方便在函数里对数据进行操作*/ ::SetTimer(m_hWnd, (UINT_PTR)this, 100, v._address);return TRUE;
}void CWndData::loops(HWND, UINT, CWndData* _this, DWORD)
{int nstart = 0;// 选中的内容起始下标int nend = 0; // 选中的内容结束下标_this->m_Edit.GetSel(nstart, nend); // 获取选中的文字int ncount = nend - nstart;if (ncount > 1) {CString txt;CString tmp;_this->m_Edit.GetWindowText(txt); // 获取编辑框里的内容tmp = txt.Mid(nstart, ncount);tmp.Replace(L" ", L""); // 把空格替换成空字符if (_this->lastTxt != tmp) {int lenth = tmp.GetLength();if (lenth % 2 == 0) { // 必须是2的倍数,如果不是就说明没有选择全_this->lastTxt = tmp;_this->ShowTips();}}}
}void CWndData::ShowTips()
{AfxMessageBox(lastTxt);
}BEGIN_MESSAGE_MAP(CWndData, CDialogEx)
END_MESSAGE_MAP()// CWndData 消息处理程序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/749270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java手写简易数据库--持续更新中

MYDB 0. 项目结构0.1 引用计数缓存框架为什么不使用LRU引用计数缓存缓存框架实现 0.2 共享内存数组 1. 事务管理器--TM1.1 XID 文件XID 规则XID 文件结构读取方式事务状态 1.2 代码实现 2. 数据管理器--DM2.1 页面缓存页面结构页面缓存数据页管理第一页普通页 2.2 日志文件 3. …

MQ 延迟队列

MQ 延迟队列 1. 前言 延迟队列是我们日常开发过程中&#xff0c;经常接触并需要使用到的一种技术方案。前些时间在开发业务需求时&#xff0c;我也遇到了一个需要使用到延迟消息队列的需求场景&#xff0c;因此我也在网上调研了一系列不同的延迟队列的实现方案&#xff0c;在…

【Linux】信号量和线程池

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【Linux】进程通信——共享内存消息队列信号量 目录 &#x1f449;&#x1f3fb;信号量&#x1f449;&#x1f…

微信小程序原生<map>地图实现标记多个位置以及map 组件 callout 自定义气泡

老规矩先上效果图: 1 、在pages文件夹下新建image文件夹用来存放标记的图片。 2、代码片段 也可以参考小程序文档:https://developers.weixin.qq.com/miniprogram/dev/component/map.html index.wxml代码 <mapid="map"style="width: 100%; height:100%;&…

mybatis源码阅读系列(二)

前言 上一篇文章mybatis源码阅读系列&#xff08;一&#xff09;介绍了mybatis和原生jdbc的区别&#xff0c;并通过代码展示了两者的运行过程和结果&#xff0c;下面让我们继续详细了解下mybatis的执行过程&#xff1b; package com.wyl.mybatis.service;import com.wyl.mybat…

openCV实现拖拽虚拟方块

一、项目效果&#xff1a; 二、核心流程&#xff1a; openCV读取视频流、在每一帧图片上画一个矩形。使用mediapipe获取手指关键点坐标。根据手指坐标位置和矩形的坐标位置&#xff0c;判断手指点是否在矩形上&#xff0c;如果在则矩形跟随手指移动。 三、代码流程&#xff1…

【系统架构师】-第3章-信息系统基础知识

1、信息系统的基本功能 输入&#xff1a;决定于系统所要达到的目的及系统的能力和信息环境的许可存储&#xff1a;存储各种信息资料和数据的能力处理&#xff1a;数据处理工具&#xff0c;利用OLAP、DM&#xff08;数据挖掘&#xff09;技术输出&#xff1a;保证最终实现最佳的…

AI人员入侵识别摄像机

AI人员入侵识别摄像机是一种智能监控设备&#xff0c;利用人工智能技术辨认并报警可能的入侵行为。这种摄像机利用深度学习算法实时分析监控画面&#xff0c;识别出普通行人和潜在入侵者之间的差异&#xff0c;从而更准确地预警可能发生的安全事件。 该摄像机通过对比数据库中存…

springboot项目学习-瑞吉外卖(1)

第一天任务如下&#xff1a; 建立基本架构完成登录、退出功能 注意&#xff1a;本博客没有使用网上教程里的mybatis-plus&#xff0c;使用的是mybatis&#xff1b;数据库连接池也没有使用教程里的druid&#xff0c;使用的是spring自带的连接池 基本架构 common包&#xff1a;存…

【Linux进程状态】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、直接谈论Linux的进程状态 看看Linux内核源代码怎么说 1.1、R状态 -----> 进程运行的状态 1.2、S状态 -----> 休眠状态(进程在等待“资源”就绪) 1.3、T状…

奇怪的比赛(Python,递归,状态压缩动态规划dp)

目录 前言&#xff1a;题目&#xff1a;思路&#xff1a;递归&#xff1a;代码及详细注释&#xff1a; 状态压缩dp&#xff1a;代码及详细注释&#xff1a; 总结&#xff1a; 前言&#xff1a; 这道题原本是蓝桥上的题&#xff0c;现在搜不到了&#xff0c;网上关于此题的讲解…

Python爬虫:原理与实战

引言 在当今的信息时代&#xff0c;互联网上的数据如同浩瀚的海洋&#xff0c;充满了无尽的宝藏。Python爬虫作为一种高效的数据抓取工具&#xff0c;能够帮助我们轻松地获取这些数据&#xff0c;并进行后续的分析和处理。本文将深入探讨Python爬虫的原理&#xff0c;并结合实战…

kkview远程控制: 内网远程桌面控制软件

内网远程桌面控制软件&#xff1a;高效、安全的远程管理方案 在信息技术日新月异的今天&#xff0c;内网远程桌面控制软件已成为许多企业和个人用户不可或缺的工具。这类软件允许用户通过内部网络&#xff0c;实现对其他计算机的远程访问和控制&#xff0c;从而大大提高工作效…

[Windows] Win11 常用快捷键

文章目录 &#x1f680; [Windows] Win11 常用快捷键&#x1f310; Windows 操作系统&#x1f525; Windows 11 &#x1f310; Windows 11 快捷键概览&#x1f525; 基本快捷键&#x1f525; 窗口快捷键&#x1f525; 功能快捷键 &#x1f4dd; 小结 &#x1f680; [Windows] W…

“技多不压身”是什么意思?看完这篇文章你会明白:有了手艺,走遍天下都不怕!

“技多不压身”是什么意思&#xff1f;看完这篇文章你会明白&#xff1a;有了手艺&#xff0c;走遍天下都不怕&#xff01; 咱们的老祖宗流传一句话&#xff1a;“一招鲜&#xff0c;吃遍天。”这话说得直白&#xff0c;却道出了学一门手艺或技术对于人生的重要性。“李秘书讲…

使用Loadrunner进行性能测试

一、确定性能测试的范围、要求、配置、工具等 明确测试的系统&#xff1a; 本文档主要指的是web应用。 明确测试要求&#xff1a; 用户提出性能测试&#xff0c;例如&#xff0c;网站首页页面响应时间在3S之内&#xff0c;主要的业务操作时间小于10s&#xff0c;支持300用户在…

Android Studio实现内容丰富的安卓宠物用品商店管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号128 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.系统公告 3.宠物社区&#xff08;可发布宠物帖子&#…

this是什么?为什么要改变this?怎么改变 this 指向?

目录 this 是什么&#xff1f; 箭头函数中的 this 为什么要改变 this 指向&#xff1f; 改变 this 指向的三种方法 call(无数个参数) apply(两个参数) bind(无数个参数) this 是什么&#xff1f; 在对象方法中&#xff0c;this 指的是所有者对象&#xff08;方法的拥有者…

提升口才表达能力的重要性与途径

提升口才表达能力的重要性与途径 口才表达能力&#xff0c;即一个人通过口头语言准确、流畅、生动地传达思想、情感和观点的能力&#xff0c;是现代社会中不可或缺的一项基本技能。无论是在职场沟通、人际交往还是公共场合发言&#xff0c;优秀的口才表达能力都能为我们带来诸…

力扣hot100:416.分割等和子集(组合/动态规划/STL问题)

组合数问题 我们思考一下&#xff0c;如果要把数组分割成两个子集&#xff0c;并且两个子集的元素和相等&#xff0c;是否等价于在数组中寻找若干个数使之和等于所有数的一半&#xff1f;是的&#xff01; 因此我们可以想到&#xff0c;两种方式&#xff1a; ①回溯的方式找到t…