} }
m_hostList.SetColWidth (0, 100); m_hostList.SetColWidth (1, 130); m_hostList.SetColWidth (2, 50); m_hostList.SetColWidth (3, 55); m_hostList.SetColWidth (4, 70);
m_hostList.SetText (0,0,\地址\ m_hostList.SetText (0,1,\地址\ m_hostList.SetText (0,2,\ m_hostList.SetText (0,3,\欺骗\ m_hostList.SetText (0,4,\报告IP冲突\
m_packetList.Create(CRect(444,26,768,466),this, 1000); m_packetList.SetCols (6); m_packetList.SetRows (31); for (i = 0; i < 30; i ++) {
m_packetList.SetRowHeight (i, 13); for(int j =0;j<6;j++) {
m_packetList.SetAlignment(i,j,DT_CENTER); } }
m_packetList.SetRowHeight (i, 47);
m_packetList.SetColWidth (0, 75); m_packetList.SetColWidth (1, 75); m_packetList.SetColWidth (2, 32); m_packetList.SetColWidth (3, 45); m_packetList.SetColWidth (4, 55); m_packetList.SetColWidth (5, 40); m_packetList.SetText (0,0,\源IP\ m_packetList.SetText (0,1,\目的IP\ m_packetList.SetText (0,2,\协议\ m_packetList.SetText (0,3,\源端口\ m_packetList.SetText (0,4,\目的端口\ m_packetList.SetText (0,5,\长度\ m_packetList.JoinCells (30,0,30,5);
mailDlg = this;
return TRUE; // return TRUE unless you set the focus to a control
}
右边表格中最后的一行是多列合并的结果,完成此合并的代码为:
int XTable::JoinCells (int startRow, int startCol, int endRow, int endCol) {
if (startRow < 0 || startRow >= rows) return -1; if (endRow < 0 || startRow >= rows) return -1;
if (startCol < 0 || startCol >= cols) return -1; if (endCol < 0 || endCol >= cols) return -1;
if (startRow > endRow || startCol > endCol) return -1;
for (int i = startRow; i <= endRow; i++) {
for (int j = startCol; j <=endCol; j++) {
cells [i * cols + j].SetSpan(0,0); } }
cells [startRow * cols + startCol].SetSpan(endRow - startRow+1, endCol - startCol+1); return 0; }
其\反函数\为:
int XTable::UnjoinCells (int row, int col) {
if (row < 0 || row >= this->rows) return -1; if (col < 0 || col >= this->cols) return -1;
if (cells [row * cols + col].rowSpan <= 1 && cells [row * cols + col].colSpan <= 1 ) return -1;
for (int i = row; i <= row + cells [row * cols + col].rowSpan; i++) {
for (int j = col; j <= cells [row * cols + col].colSpan; j++) {
cells[i*cols+j] = defaultCell; cells [i * cols + j].SetSpan(1,1); } } return 0;
}
程序中的IDC_ADAPTERLIST_COMBO控件用于提供用户选择本地适配器,获得本地适配器列表的代码如下(也处于对话框的初始化函数中):
char errbuf[PCAP_ERRBUF_SIZE]; /* 取得列表 */
if (pcap_findalldevs(&alldevs, errbuf) == - 1) {
AfxMessageBox(\获得网卡列表失败!\\n\
GetDlgItem(IDC_STARTSTOP_BUTTON)->EnableWindow(FALSE); }
/* 输出列表 */
for (d = alldevs; d; d = d->next) {
CString str(d->name);
if (str.Find(\ m_adapterList.AddString(str); }
给监控IP地址范围内的主机发送ARP请求包并获取反馈,即可获得监控范围内活动机器的IP地址和MAC地址,以进行进一步地管理。
发送ARP请求的函数代码:
void SendArpReq(unsigned long srcIp,unsigned long desIp,UCHAR * srcMac) {
char sendbuf[1024]; ETHDR eth; ARPHDR arp;
memcpy(eth.eh_src,mmac,6); eth.eh_type=htons(ETH_ARP);
arp.arp_hdr=htons(ARP_HARDWARE); arp.arp_pro=htons(ETH_IP); arp.arp_hln=6; arp.arp_pln=4;
arp.arp_opt=htons(ARP_REQUEST); arp.arp_spa=htonl(srcIp); arp.arp_tpa=htonl(desIp); memcpy(arp.arp_sha,srcMac,6);
for(int i=0;i<6;i++) {
eth.eh_dst[i]=0xff; arp.arp_tha[i]=0x00; }
memset(sendbuf,0,sizeof(sendbuf)); memcpy(sendbuf,ð,sizeof(eth));
memcpy(sendbuf+sizeof(eth),&arp,sizeof(arp));
PacketInitPacket(lppackets,sendbuf,sizeof(eth)+sizeof(arp)); if(PacketSendPacket(lpadapter,lppackets,TRUE)==FALSE) {
AfxMessageBox(\ } }
双击表格中控制Sniffer、ARP欺骗和IP地址重复的栏目,需要变换其中的显示内容,要么从\到\,要么从\到\(当然,主机数据结构中的控制属性也要随之而改变),相关的代码为:
void XTable::OnLButtonDblClk(UINT nFlags, CPoint point) {
HitTest(point, focusRow, focusCol);
SetFocus();
CString str = GetText(focusRow, focusCol); if (str == \ {
SetText(focusRow, focusCol, \ switch (focusCol) { case 2:
oldHostList[focusRow - 1+nVWndPos / 13].sniffer = 0; break; case 3:
oldHostList[focusRow - 1+nVWndPos / 13].arpCheat = 0; break; case 4:
oldHostList[focusRow - 1+nVWndPos / 13].ipConflict = 0; break; default: break; } }
else if (str == \ {
SetText(focusRow, focusCol, \ switch (focusCol) { case 2:
oldHostList[focusRow - 1+nVWndPos / 13].sniffer = 1; break; case 3:
oldHostList[focusRow - 1+nVWndPos / 13].arpCheat = 1; break; case 4:
oldHostList[focusRow - 1+nVWndPos / 13].ipConflict = 1; break; default: break; } }
Invalidate();
CWnd::OnLButtonDblClk(nFlags, point); }
上述代码中的HitTest()调用比较关键,用于获得当前选中的行和列,我们来看看相关的代码:
bool XTable::HitTest(CPoint point, int &row, int &col) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j++) {
RECT rect = GetRect(i, j);
if (rect.top <= point.y && rect.bottom > point.y && rect.left <= point.x && rect.right > point.x) { row = i; col = j; return true; } } }
return false; }
在表格的某一格处于焦点时,我们应给其画一个矩形边框: