// YQPackageCaptureDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "YQPackageCapture.h"
#include "YQPackageCaptureDlg.h"
#include "afxdialogex.h"
#include <pcap.h>
#include <vector>
#include <afxwin.h>
using namespace std;
#pragma warning(disable:4996)
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/*_____________________________________________结构体_________________________________________*/
/* 4字节的IP地址 */
typedef struct ip_address
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
} ip_address;
/* IPv4 首部 */ //Internet Protocol version 4
typedef struct ip_header
{
u_char ver_ihl; // 版本 (4 bits) + 首部长度 (4 bits)
u_char tos; // 服务类型(Type of service)
u_short tlen; // 总长(Total length)
u_short identification; // 标识(Identification)
u_short flags_fo; // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)
u_char ttl; // 存活时间(Time to live)
u_char proto; // 协议(Protocol)
u_short crc; // 首部校验和(Header checksum)
ip_address saddr; // 源地址(Source address)
ip_address daddr; // 目的地址(Destination address)
u_int op_pad; // 选项与填充(Option + Padding)
} ip_header;
/* UDP 首部*/
/*UDP 是User Datagram Protocol的简称,
中文名是用户数据报协议,
是OSI(Open System Interconnection,开放式系统互联)参考模型中一种无连接的传输层协议*/
typedef struct udp_header
{
u_short sport; // 源端口(Source port)
u_short dport; // 目的端口(Destination port)
u_short len; // UDP数据包长度(Datagram length)
u_short crc; // 校验和(Checksum)
} udp_header;
/*TCP头部*/
typedef struct tcp_header
{
short m_sSourPort; // 源端口号16bit
short m_sDestPort; // 目的端口号16bit
unsigned int m_uiSequNum; // 序列号32bit
unsigned int m_uiAcknowledgeNum; // 确认号32bit
short m_sHeaderLenAndFlag; // 前4位:TCP头长度;中6位:保留;后6位:标志位
short m_sWindowSize; // 窗口大小16bit
short m_sCheckSum; // 检验和16bit
short m_surgentPointer; // 紧急数据偏移量16bit
}tcp_header;
typedef struct ip_flow
{
ip_address ipaddr; // 源地址(Source address)
float flow; //该源地址的流量
}ip_flow;
typedef struct package_info
{
u_char *package; // 源地址(Source address)
short len; //该源地址的流量
}package_info;
/*_____________________________________________全局变量_________________________________________*/
int no = 0;
LARGE_INTEGER m_nFreq; //内部计时器的时钟周期,用于计时
LARGE_INTEGER m_nBeginTime; //开始捕获时,计时器的值,用于计时
vector<package_info> package_vec;
vector<ip_flow>ip_flow_vec;
CListCtrl CYQPackageCaptureDlg::list_package;
CListCtrl CYQPackageCaptureDlg::list_flow;
pcap_t *adhandle; //网卡句柄
pcap_if_t *alldevs;
pcap_if_t *d;
int stopNow=0; //是否现在要停止捕获
/*______________________________ 回调函数原型 ______________________________________________*/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
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()
// CYQPackageCaptureDlg 对话框
CYQPackageCaptureDlg::CYQPackageCaptureDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_YQPACKAGECAPTURE_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CYQPackageCaptureDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO_ADAPTER, com_adapter);
DDX_Control(pDX, IDC_LIST_PACKAGES, list_package);
DDX_Control(pDX, IDC_LIST_FLOW, list_flow);
}
BEGIN_MESSAGE_MAP(CYQPackageCaptureDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_START_CAP, &CYQPackageCaptureDlg::OnBnClickedButtonStartCap)
ON_CBN_SELCHANGE(IDC_COMBO_ADAPTER, &CYQPackageCaptureDlg::OnCbnSelchangeComboAdapter)
ON_EN_CHANGE(IDC_EDIT_DESCRIPTION, &CYQPackageCaptureDlg::OnEnChangeEditDescription)
ON_BN_CLICKED(IDC_BUTTON_STOP_CAP, &CYQPackageCaptureDlg::OnBnClickedButtonStopCap)
ON_EN_CHANGE(IDC_EDIT_ASCII, &CYQPackageCaptureDlg::OnEnChangeEditAscii)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PACKAGES, &CYQPackageCaptureDlg::OnLvnItemchangedListPackages)
END_MESSAGE_MAP()
// CYQPackageCaptureDlg 消息处理程序
BOOL CYQPackageCaptureDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
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); // 设置小图标
// TODO: 在此添加额外的初始化代码
/***________________________显示可选的网卡__________________________***/
//pcap_if_t *alldevs;
//pcap_if_t *d;
int inum;
int adapter_counter = 0; //网卡数目
//pcap_t *adhandle; //网卡句柄
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "ip and tcp or udp"; //程序最终可以得到IPV4,udp和tcp的数据包,并把它们复制给应用程序
struct bpf_program fcode; //伯克利封包过滤器(Berkeley Packet Filter,缩写 BPF)
//printf("%d\n", sizeof(u_char));
/* 获得设备列表 */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* 显示网卡 */
//为组合框控件的列表框添加列表项
for (d = alldevs; d; d = d->next)
{
CString name(d->name);
com_adapter.InsertString(adapter_counter++, name);
//adapter_counter++;
}
if (adapter_counter == 0)
{
AfxMessageBox(L"\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}
// 默认选择第一项
com_adapter.SetCurSel(0);
/* 跳转到已选设备 */
inum = com_adapter.GetCurSel();
int i;
for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
//显示网卡描述
CString description_str(d->description);
SetDlgItemText(IDC_EDIT_DESCRIPTION, description_str);
///* 释放设备列表 */
//pcap_freealldevs(alldevs);
/*____________显示control list package 的基本信息_______________________*/
CRect rect;
list_package.GetClientRect(&rect); //获得客户区
list_package.SetExtendedStyle(list_package.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); //设置风格,LVS_EX_FULLROWSELECT是有线条,后面那个是充满
//插入列:
list_package.InsertColumn(0, _T("NO."), LVCFMT_CENTER, rect.Width() /14, 0);
list_package.InsertColumn(1, _T("Time"), LVCFMT_CENTER, rect.Width() / 7, 1);
list_package.InsertColumn(2, _T("Source"), LVCFMT_CENTER, rect.Width() / 7, 2);
list_package.InsertColumn(3, _T("Destination"), LVCFMT_CENTER, rect.Width() / 7, 3);
list_package.InsertColumn(4, _T("Protocol"), LVCFMT_CENTER, rect.Width() /14, 4);
list_package.InsertColumn(5, _T("Length"), LVCFMT_CENTER, rect.Width() / 14, 5);
list_package.InsertColumn(6, _T("Info"), LVCFMT_CENTER, 5*rect.Width() /14, 6);
list_flow.GetClientRect(&rect); //获得客户区
list_flow.SetExtendedStyle(list_package.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); //设置风格,LVS_EX_FULLROWSELECT是有线条,后面那个是充满
//插入列:
list_flow.InsertColumn(0, _T("源IP地址"), LVCFMT_CENTER, rect.Width() / 2, 0);
list_flow.InsertColumn(1, _T("流量"), LVCFMT_CENTER, rect.Width() / 2, 1);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CYQPackageCaptureDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CYQPackageCaptureDlg::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 CYQPackageCaptureDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
/*开始捕获按钮*/
void CYQPackageCaptureDlg::OnBnClickedButtonStartCap()
{
// TODO: 在此添加控件通知处理程序代码
//pcap_if_t *alldevs;
//pcap_if_t *d;
int inum;
int adapter_counter = 0;
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "ip and tcp or udp"; //程序最终可以得到IPV4,udp和tcp的数据包,并把它们复制给应用程序
struct bpf_program fcode; //伯克利封包过滤器(Berkeley Packet Filter,缩写 BPF)
//printf("%d\n", sizeof(u_char));
/* 跳转到已选设备 */
inum= com_adapter.GetCurSel();
int i;
for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
/* 打开适配器 */
if ((adhandle = pcap_open(d->name, // 设备名
65536, // 要捕捉的数据包的部分
// 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式
1000, // 读取超时时间
NULL, // 远程机器验证
errbuf // 错误缓冲池
)) == NULL)
{
AfxMessageBox(L"\nUnable to open the adapter. %s is not supported by WinPcap\n");
fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return ;
}
/* 检查数据链路层,为了简单,我们只考虑以太网 */
/*返回链路层的类型,链路层的类型包括:
DLT_NULL: BSD回路封装;链路层协议头是一个4字节的域,……
DLT_EN10MB: 以太网(10Mb, 100Mb, 1000Mb, 或者更高)。
DLT_IEEE802: IEEE802.5令牌环网。
……
*/
if (pcap_datalink(adhandle) != DLT_EN10MB) //如果不是以太网就不处理了
{
AfxMessageBox(L"\nThis program works only on Ethernet networks.\n");
fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return ;
}
/*类型 格式 默认子网掩码
A 网络 节点 节点 节点 255.0.0.0
B 网络 网络 节点 节点 255.255.0.0
C 网络 网络 网络 节点 255.255.255.0*/
if (d->addresses != NULL)
/* 获得接口第一个地址的掩码 */
netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
/* 如果接口没有地址,那么我们假设一个C类的掩码 */
netmask = 0xffffff;
//编译过滤器pcap_compile
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0)
{
AfxMessageBox(L"\nUnable to compile the packet filter. Check the syntax.\n");
fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
getchar();
return ;
}
//设置过滤器pcap_setfilter
if (pcap_setfilter(adhandle, &fcode)<0)
{
AfxMessageBox(L"\nError setting the filter.\n");
fprintf(stderr, "\nError setting the filter.\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
getchar();
return ;
}
printf("\nlistening on %s...\n", d->description);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
/* 开始捕捉并计时 */
QueryPerformanceFrequency(&m_nFreq); // 获取时钟周期
QueryPerformanceCounter(&m_nBeginTime);//获取开始捕获时,计时器的值
pcap_loop(adhandle, 0, packet_handler, NULL);
}
void CYQPackageCaptureDlg::OnCbnSelchangeComboAdapter()
{
// TODO: 在此添加控件通知处理程序代码
/* 跳转到已选设备 */
int inum = com_adapter.GetCurSel();
int i;
for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
//显示网卡描述
CString description_str(d->description);
SetDlgItemText(IDC_EDIT_DESCRIPTION, description_str);
//SetDlgItemText(IDC_EDIT_DESCRIPTION, L"change my friend!!");
}
/****************************回调函数***********************************/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
//NO. Time Source Destination Protocol Length Info 十六进制 ASCII码 流量统计
//AfxMessageBox(L"抓到包了!");
struct tm ltime;
char timestr[16];
ip_header *ih;
udp_header *uh;
tcp_header *th;
u_int ip_len;
time_t local_tv_sec;
struct timeval tv_capPackage;
/* 获得IP数据包头部的位置 */
/*因为我们需要解析IP数据包,
从IP数据包的首部解析到源IP地址和目的IP地址,
而IP数据包的首部位于MAC首部的后面,所以我们需要跳过MAC首部。
对于以太网而言MAC首部长度为14位*/
ih = (ip_header *)(pkt_data +
14); //以太网头部长度 固定14位
ip_len = (ih->ver_ihl & 0xf) * 4; //ip首部有多少字节(取低四位,得到首部有多少个双字;乘4得到字节数)
/*************** 显示每个包的PCI ****************************************/
CString noStr;
noStr.Format(_T("%d"), no+1);
////插入该包数据,第0列(no)内容为1
CYQPackageCaptureDlg::list_package.InsertItem(no, noStr);
//Time
LARGE_INTEGER m_nTime;
QueryPerformanceCounter(&m_nTime);//获取当前时间
long long sec, next, time; //从开始捕获,到捕获到当前包,时间差的秒,及其剩下的0.1秒;整个以微妙表示
time = (m_nTime.QuadPart - m_nBeginTime.QuadPart) * 1000000 / m_nFreq.QuadPart;
sec = time / 1000000;
next = time - time / 1000000 * 1000000;
//printf("Time:%lld.%.6lld \n", sec, next);
CString timeStr;
timeStr.Format(_T("%lld.%.6lld \n"), sec, next);
//设置该包第1列(time)内容
CYQPackageCaptureDlg::list_package.SetItemText(no , 1,timeStr);
//Source
CString sourceStr;
sourceStr.Format(_T("%d.%d.%d.%d\n"),
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4);
//设置该包第2列(source)内容
CYQPackageCaptureDlg::list_package.SetItemText(no, 2,sourceStr);
//Destination
CString desStr;
desStr.Format(_T("%d.%d.%d.%d\n"),
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
//设置该包第3列(Destination)内容
CYQPackageCaptureDlg::list_package.SetItemText(no, 3, desStr);
//Protocol
/*协议字段:占8比特。指明IP层所封装的上层协议类型,
如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)、EIGRP(88)、OSPF(89)等。*/
CString protocolStr = NULL;
CString Str;
switch (ih->proto)
{
case 1:protocolStr = "ICMP"; break;
case 2:protocolStr = "IGMP"; break;
case 6:protocolStr = "TCP"; break;
case 17:protocolStr = "UDP"; break;
case 20:protocolStr = "HMP"; break;
case 88:protocolStr = "EIGRP"; break;
case 89:protocolStr = "OSPF"; break;
default: protocolStr.Format(_T("%d", ih->proto));
}
CYQPackageCaptureDlg::list_package.SetItemText(no, 4,protocolStr);
//printf("Protocol:%s\n", protocol);
//Length
CString lenStr;
int wholeLen = ntohs(ih->tlen) + 14; //将网络字节序列转换成主机字节序列,加上以太网包头的长度
lenStr.Format(_T("%d"), wholeLen);
CYQPackageCaptureDlg::list_package.SetItemText(no, 5, lenStr);
//Info
CString infoStr;
//UDP
//printf("Info:\n");
if (protocolStr == "UDP")
{
/* 获得UDP首部的位置 */
uh = (udp_header *)((u_char*)ih + ip_len);
infoStr.Format(_T("%d -> %d, Len=%d\n\n"), ntohs(uh->sport), ntohs(uh->dport), ntohs(uh->len));
}
else if (protocolStr == "TCP")
{
/* 获得TCP首部的位置 */
th = (tcp_header *)((u_char*)ih + ip_len);
infoStr.Format(_T("%d -> %d, Seq=%u, Ack=%u, Win=%d "),
ntohs(th->m_sSourPort),
ntohs(th->m_sDestPort),
ntohl(th->m_uiSequNum),
ntohl(th->m_uiAcknowledgeNum),
ntohs(th->m_sWindowSize)
);
}
CYQPackageCaptureDlg::list_package.SetItemText(no, 6, infoStr);
int list_item_count = CYQPackageCaptureDlg::list_package.GetItemCount();
if (list_item_count > 0)
CYQPackageCaptureDlg::list_package.EnsureVisible(list_item_count - 1, FALSE);
//十六进制
CString hexStr,tempStr;
u_char *temp = (u_char *)pkt_data;
for (int i = 0; i < wholeLen; i++)
{
tempStr.Format(_T("%x "), *(temp++));
hexStr += tempStr;
}
SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_EDIT_HEX,hexStr);
//ASCII码
CString asciiStr;
temp = (u_char *)pkt_data;
for (int i = 0; i < wholeLen; i++)
{
tempStr.Format(_T("%c "), *(temp++));
asciiStr += tempStr;
}
SetDlgItemText(AfxGetMainWnd()->m_hWnd, IDC_EDIT_ASCII, asciiStr);
//统计流量:
int ip_count = size(ip_flow_vec); //已经统计过的ip源地址
int isNew = 1; //之前没出现过该ip源地址
ip_flow new_ip_flow;
CString flowStr;
for (int i = 0; i < ip_count; i++)
{
//如果该ip地址已经出现过
if (ih->saddr.byte1 == ip_flow_vec[i].ipaddr.byte1
&&ih->saddr.byte2 == ip_flow_vec[i].ipaddr.byte2
&&ih->saddr.byte3 == ip_flow_vec[i].ipaddr.byte3
&&ih->saddr.byte4 == ip_flow_vec[i].ipaddr.byte4)
{
ip_flow_vec[i].flow += (double)wholeLen / 1024; //单位为KB
isNew = 0;
flowStr.Format(_T("%.2f KB"), ip_flow_vec[i].flow);
CYQPackageCaptureDlg::list_flow.SetItemText(i, 1, flowStr);
break;
}
}
//如果该ip地址此前没有出现过
if (isNew == 1)
{
new_ip_flow.ipaddr = ih->saddr;
new_ip_flow.flow = (double)wholeLen / 1024;
ip_flow_vec.push_back(new_ip_flow);
flowStr.Format(_T("%.2f KB"),new_ip_flow.flow);
//插入该IP地址,显示ip地址
CYQPackageCaptureDlg::list_flow.InsertItem(ip_count, sourceStr);
//显示流量
CYQPackageCaptureDlg::list_flow.SetItemText(ip_count, 1, flowStr);
}
list_item_count = CYQPackageCaptureDlg::list_flow.GetItemCount();
if (list_item_count > 0)
CYQPackageCaptureDlg::list_flow.EnsureVisible(list_item_count - 1, FALSE);
/*把包的内容存入package_vec*/
temp = (u_char *)pkt_data;
package_info new_package_info;
new_package_info.package = temp;
new_package_info.len = wholeLen;
package_vec.push_back(new_package_info);
//包的个数+1
no++;
//实时显示
UpdateWindow(AfxGetMainWnd()->m_hWnd);
//CString mess;
//mess.Format(_T("%d"), adhandle);
//AfxMessageBox(mess);
//判断是否停止
AfxGetApp()->PumpMessage();
if (stopNow == 1)
{
pcap_breakloop(adhandle); ///right here ahandle turned into 0
}
}
void CYQPackageCaptureDlg::OnEnChangeEditDescription()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CYQPackageCaptureDlg::OnBnClickedButtonStopCap()
{
// TODO: 在此添加控件通知处理程序代码
stopNow = 1;
}
void CYQPackageCaptureDlg::OnEnChangeEditAscii()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CYQPackageCaptureDlg::OnLvnItemchangedListPackages(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
NMLISTVIEW *pnml = (NMLISTVIEW*)pNMHDR;//新建一个指针
if (-1 != pnml->iItem)//如果指针无误
{
CString pac_no_str;
int pac_no;
pac_no_str = list_package.GetItemText(pnml->iItem, 0);//如果鼠标选中了某行,将选中的行的第0列赋给str
pac_no = _ttoi(pac_no_str)-1;
CString hexStr, tempStr;
u_char *temp = (u_char *)package_vec[pac_no].package;
for (int i = 0; i < package_vec[pac_no].len; i++)
{
tempStr.Format(_T("%x "), *(temp++));
hexStr += tempStr;
}
//CString len;
//len.Format(_T("%d"), wholeLen);
//AfxMessageBox(len);
//SetDlgItemText(IDC_EDIT_HEX, L"exm");
SetDlgItemText(IDC_EDIT_HEX, hexStr);
//ASCII码
CString asciiStr;
temp = (u_char *)package_vec[pac_no].package;
for (int i = 0; i < package_vec[pac_no].len; i++)
{
tempStr.Format(_T("%c "), *(temp++));
asciiStr += tempStr;
}
//SetDlgItemText(IDC_EDIT_ASCII, L"exm");
SetDlgItemText(IDC_EDIT_ASCII, asciiStr);
}
*pResult = 0;
}
原文地址:https://www.cnblogs.com/YuQiao0303/p/8886172.html
时间: 2024-10-13 17:23:26