📄 datashowview.cpp
字号:
// DataShowView.cpp : implementation of the CDataShowView class
//
#include "stdafx.h"
#include "DataShowView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDataShowView
IMPLEMENT_DYNCREATE(CDataShowView, CView)
CDataShowView::CDataShowView()
{
m_bufferbytes=1000;//表示缓冲的大小
m_bmousedown=FALSE;//鼠标左键是否按下
m_selfrom=-1;//表示选中的范围,m_selfrom为-1表示未选中
m_selto=0;
m_firstsel=-1;//表示选中的起始位置
m_bfrozen=FALSE;//表示是否冻结屏幕
m_btimer=0;//当鼠标位于窗口上方和下方时,屏幕自动向上向下卷屏的定时器;2为上,1为下
m_specialbyte=(BYTE)0x01;//表示以特殊颜色显示的字符
m_bpointing=FALSE;//表示正在指定特殊字符
m_oldcharpos=-1;//上指向的字符位置
}
CDataShowView::~CDataShowView()
{
}
BEGIN_MESSAGE_MAP(CDataShowView,CView )
//{{AFX_MSG_MAP(CDataShowView)
ON_WM_SIZE()
ON_WM_DESTROY()
ON_WM_CREATE()
ON_WM_VSCROLL()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_RBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
ON_COMMAND(1001, OnFreezeScreen)
ON_COMMAND(1003, OnCopyData)
ON_COMMAND(1002, OnCopyDisp)
ON_COMMAND(1004, OnSelectAll)
ON_COMMAND(1005, OnSetSpByte)
ON_COMMAND(1006, OnClearWindow)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDataShowView message handlers
BOOL CDataShowView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CView::PreCreateWindow(cs))
return FALSE;
// cs.dwExStyle |= WS_EX_CLIENTEDGE;
cs.style|=WS_VSCROLL;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_IBEAM),HBRUSH(COLOR_WINDOW+1), NULL);//HBRUSH(COLOR_WINDOW+1)
return TRUE;
}
///////////////////////////////////////////////////
//函数OnSize,在本函数中,确定窗口中显示的字符行数
//和每行字符的显示个数,另外设置滚动轴的范围和位置
//////////////////////////////////////////////////
void CDataShowView::OnSize(UINT nType, int cx, int cy)
{
//*weiyi begin
m_bytesperline=(cx/8-2)/4;
// weiyi end 在窗口中只显示16进制格式的数据*/
// m_bytesperline=cx/24;
m_linesshown=cy/15;
if(m_bytesperline<1)
m_bytesperline=1;
// if(m_linesshown<0)
// m_linesshown=0;
CView ::OnSize(nType, cx, cy);
if(cx!=0 && cy!=0)
{
int size=m_bytes.GetSize()/m_bytesperline;
if(m_bytes.GetSize()%m_bytesperline ==0)
size--;
if(size<=0)
size=1;
SetScrollRange(SB_VERT,0,size);
if(size==1)
SetScrollPos(SB_VERT,0);
else
SetScrollPos(SB_VERT,size);
}
// TODO: Add your message handler code here
}
/////////////////////////////////////////////////////
//函数:ShowData,功能是将一些字符放入显示缓冲区,并且
//在窗口中滚动显示出来。需要控制缓冲区的大小和滚动条的
//范围和位置。
//////////////////////////////////////////////////////
void CDataShowView::ShowData(BYTE *pbyte, int nlen)
{
if(m_bfrozen)
return;
//将对m_bytes的操作作为临界区,使用临界区操作命令
//进入临界区,如果已经有线程在临界区里了,则等待,
//一直到没有线程在临界区里
EnterCriticalSection(&cs);
for(int i=0;i<nlen;i++)
m_bytes.Add(pbyte[i]);
int oldpos=GetScrollPos(SB_VERT);
int removed=0;
if(m_bytes.GetSize()>m_bufferbytes)
{
//保证每次竖直滚动,即每次从缓冲区刷出的字符为每行字符个数的倍数
removed=(m_bytes.GetSize()-m_bufferbytes)/m_bytesperline*m_bytesperline;
m_bytes.RemoveAt(0,removed);
if(m_selfrom!=-1)
{//由于缓冲区内容改变了,那么已经选中的范围也相应的改变
m_selfrom-=removed;
m_selto-=removed;
if(m_selfrom<0)
m_selfrom=0;
if(m_selto<0)
m_selfrom=-1;
}
}
//离开临界区
LeaveCriticalSection(&cs);
//下面是对新数据的显示操作,包含滚动条的处理
int size=m_bytes.GetSize()/m_bytesperline;
if(m_bytes.GetSize()%m_bytesperline==0)
size--;
/*SetScrollRange(SB_VERT,0,size);
SetScrollPos(SB_VERT,size);
int line=size-oldpos+removed/m_bytesperline;
if(m_bufferbytes<m_bytesperline*m_linesshown)
{//如果所有的字符在一个屏幕以内就可以显示的话,则需要全屏刷新
Invalidate();
}
else
{//否则将屏幕向上滚动line行,然后刷新添入的一部分
ScrollWindow(0,-15*line);
RECT rect;
GetClientRect(&rect);
rect.top=rect.bottom-15*(line+1);
rect.bottom=rect.top+15;
InvalidateRect(&rect);
}*/
SetScrollRange(SB_VERT,0,size);
SetScrollPos(SB_VERT,size);
int line=size-oldpos+removed/m_bytesperline;
if(m_bufferbytes<m_bytesperline*m_linesshown)
{//如果所有的字符在一个屏幕以内就可以显示的话,则需要全屏刷新
Invalidate();
}
else
{//否则将屏幕向上滚动line行,然后刷新添入的一部分
//RECT rect;
//GetClientRect(&rect);
//rect.top=rect.bottom-15;
//InvalidateRect(&rect);
ScrollWindow(0,15);
ScrollWindow(0,-15*line-15);
}
}
///////////////////////////////////////////////////////////
//函数:OnDestroy,销毁窗口,释放空间,停止定时器
//////////////////////////////////////////////////////////
void CDataShowView::OnDestroy()
{
CView ::OnDestroy();
// TODO: Add your message handler code here
m_bytes.RemoveAll();
if(m_btimer)
KillTimer(1111);
DeleteCriticalSection(&cs);
}
///////////////////////////////////////////////////////////
//函数:OnCreate; 进行窗口的初始化
///////////////////////////////////////////////////////////
int CDataShowView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView ::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//设置显示字体
LOGFONT logfont;
memset(&logfont, 0, sizeof logfont);
logfont.lfHeight = 16;
logfont.lfWidth=8;
logfont.lfWeight=FW_NORMAL;
logfont.lfCharSet=DEFAULT_CHARSET;
lstrcpy(logfont.lfFaceName, _T("宋体"));
m_font.CreateFontIndirect(&logfont);
SetFont(&m_font);
m_color_normaltext=RGB(0,0,0);//正常颜色
m_color_normalback=RGB(255,255,255);
m_color_selecttext=RGB(255,255,255);//选中颜色
m_color_selectback=RGB(0,0,0);
//m_color_keywordtext=RGB(0,220,100);//特殊字符颜色
m_color_keywordtext=RGB(255,0,0);//特殊字符颜色
InitializeCriticalSection(&cs);//初始化临界区控制
return 0;
}
/////////////////////////////////////////////////////////
//函数:OnVScroll;功能是处理滚动轴消息
/////////////////////////////////////////////////////////
void CDataShowView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
int min,max;
GetScrollRange(SB_VERT,&min,&max);
int pos=GetScrollPos(SB_VERT);
switch(nSBCode)
{
case SB_LINEUP://向上滚动一行
if(pos<=min)
return;
SetScrollPos(SB_VERT,pos-1);
ScrollWindow(0,15);
// UpdateWindow();
break;
case SB_LINEDOWN://向下滚动一行
if(pos>=max)
return;
SetScrollPos(SB_VERT,pos+1);
ScrollWindow(0,-15);
// UpdateWindow();
break;
case SB_PAGEDOWN://向下翻页
{
int scrolls;
if(pos>=max)
return;
if(pos+m_linesshown>max)
scrolls=max-pos;
else
scrolls=m_linesshown;
SetScrollPos(SB_VERT,pos+m_linesshown);
ScrollWindow(0,-15*scrolls);
}
break;
case SB_PAGEUP://向上翻页
{
int scrolls;
if(pos<=min)
return;
if(pos-m_linesshown<min)
scrolls=pos-min;
else
scrolls=m_linesshown;
SetScrollPos(SB_VERT,pos-m_linesshown);
ScrollWindow(0,15*scrolls);
}
break;
case SB_BOTTOM://滚动到最下
if(pos>=max)
return;
SetScrollPos(SB_VERT,max);
ScrollWindow(0,-15*(max-pos));
break;
case SB_TOP://滚动到最上
if(pos<=min)
return;
SetScrollPos(SB_VERT,min);
ScrollWindow(0,15*(pos-min));
break;
case SB_THUMBPOSITION://拖动滚动轴
// SetScrollPos(SB_VERT,nPos);
// ScrollWindow(0,15*(pos-nPos));
// break;
case SB_THUMBTRACK:
SetScrollPos(SB_VERT,nPos);
ScrollWindow(0,15*(pos-nPos));
break;
}
// Invalidate();
CView ::OnVScroll(nSBCode, nPos, pScrollBar);
}
////////////////////////////////////////////////////////
//函数:OnLButtonDown;功能,处理鼠标左键点下的操作,包括:
//选中特殊字符,选择字符范围等
//////////////////////////////////////////////////////////
void CDataShowView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_bpointing)
{//如果正在选择特殊字符,鼠标左键点下后,就确定了当前指向的字符为需要
//特殊显示的字符
// ReleaseCapture();
SetClassLong(m_hWnd,GCL_HCURSOR,(long)(::LoadCursor(NULL,IDC_IBEAM)));
m_bpointing=FALSE;
RECT rect1;
GetClientRect(&rect1);
int curline=(rect1.bottom-point.y)/15;//(point.y+10)/15;
curline=GetScrollPos(SB_VERT)-curline;
if(curline<0)
curline=0;
int curchar=point.x>=m_bytesperline*24?m_bytesperline-1:point.x/24;
curchar+=curline*m_bytesperline;
if(curchar>=m_bytes.GetSize())
curchar=m_bytes.GetSize()-1;
Invalidate();
if(curchar>=0 && m_bytes.GetSize()>0)
m_specialbyte=m_bytes[curchar];
m_oldcharpos=-1;
CView::OnLButtonDown(nFlags,point);
return;
}
//这是选择字符范围的开始,点下后就确认了选中的开始位置
m_bmousedown=TRUE;
SetCapture();
m_oldpoint=point;
RECT rect1;
GetClientRect(&rect1);
int curline=(rect1.bottom-point.y)/15;//(point.y+10)/15;
curline=GetScrollPos(SB_VERT)-curline;
if(curline<0)
curline=0;
int curchar=point.x>=m_bytesperline*24?m_bytesperline:(point.x+8)/24;
curchar+=curline*m_bytesperline;
m_firstsel=curchar;
//如果以前已经有选择的范围,则将选择范围取消
if(m_selfrom!=-1)
{
RECT rect;
GetClientRect(&rect);
//rect.top=m_selfrom/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT)-1;
//rect.top*=15;
//rect.bottom=m_selto/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT);
//rect.bottom*=15;
rect.top=rect1.bottom-(GetScrollPos(SB_VERT)-m_selfrom/m_bytesperline+1)*15;
rect.bottom=rect1.bottom-(GetScrollPos(SB_VERT)-m_selto/m_bytesperline)*15;
rect.bottom++;
m_selfrom=-1;
InvalidateRect(&rect);
}
CView ::OnLButtonDown(nFlags, point);
}
///////////////////////////////////////////////////////////
//函数:OnLButtonUp,功能确认选择范围,如果鼠标左键点下和弹起的
//位置在一个范围以内,则认为没有选中任何范围
/////////////////////////////////////////////////////////////
void CDataShowView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(!m_bmousedown )
return;
m_bmousedown=FALSE;
ReleaseCapture();
RECT rect1;
GetClientRect(&rect1);
//如果鼠标左键点下和弹起的位置在一个范围-直径10象素的矩形以内,则认为没有选中任何范围
if(abs(point.x-m_oldpoint.x)<5 && abs(point.y-m_oldpoint.y)<5)
{
if(m_selfrom!=-1)
{
RECT rect;
GetClientRect(&rect);
//rect.top=m_selfrom/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT)-1;
//rect.top*=15;
//rect.bottom=m_selto/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT);
//rect.bottom*=15;
rect.top=rect1.bottom-(GetScrollPos(SB_VERT)-m_selfrom/m_bytesperline+1)*15;
rect.bottom=rect1.bottom-(GetScrollPos(SB_VERT)-m_selto/m_bytesperline)*15;
m_selfrom=-1;
InvalidateRect(&rect);
}
CView ::OnLButtonUp(nFlags, point);
return;
}
//确认选中范围
int curline=(rect1.bottom-point.y)/15;//(point.y+10)/15;
curline=GetScrollPos(SB_VERT)-curline;
if(curline<0)
curline=0;
int curchar=point.x>=m_bytesperline*24?m_bytesperline:point.x/24;
curchar+=curline*m_bytesperline;
int oldfrom=m_selfrom,oldto=m_selto;
if(m_firstsel>=curchar)
{
m_selfrom=curchar;
m_selto=m_firstsel;
}
else
{
m_selfrom=m_firstsel;
m_selto=curchar;
}
// if(oldfrom>m_selfrom)
// oldfrom=m_selfrom;
// if(oldto<m_selto)
// oldto=m_selto;
if(oldfrom!=m_selfrom)
{
if(oldfrom>m_selfrom)
{
oldto=oldfrom;
oldfrom=m_selfrom;
}
else
oldto=m_selfrom;
}
else
{
if(oldto<m_selto)
{
oldfrom=oldto;
oldto=m_selto;
}
else
oldfrom=m_selto;
}
// Invalidate();
RECT rect;
GetClientRect(&rect);
//rect.top=oldfrom/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT)-1;
//rect.top*=15;
//rect.bottom=oldto/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT);
//rect.bottom*=15;
rect.top=rect1.bottom-(GetScrollPos(SB_VERT)-oldfrom/m_bytesperline+1)*15;
rect.bottom=rect1.bottom-(GetScrollPos(SB_VERT)-oldto/m_bytesperline)*15;
rect.bottom++;
InvalidateRect(&rect);
//KillTimer(1111);
//如果自动滚动定时器在运行,停止该定时器
if(m_btimer)
{
m_btimer=0;
KillTimer(1111);
}
CView ::OnLButtonUp(nFlags, point);
}
///////////////////////////////////////////////////////
//函数:OnRButtonUp,功能,取消选择特殊字符操作或显示
//辅助菜单
////////////////////////////////////////////////////////
void CDataShowView::OnRButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_bpointing)
{//停止选择特殊字符
m_bpointing=FALSE;
// ReleaseCapture();
//设置默认鼠标
SetClassLong(m_hWnd,GCL_HCURSOR,(long)(::LoadCursor(NULL,IDC_IBEAM)));
RECT rect1;
GetClientRect(&rect1);
int curline=(rect1.bottom-point.y)/15;//(point.y+10)/15;
curline=GetScrollPos(SB_VERT)-curline;
if(curline<0)
curline=0;
int curchar=point.x>=m_bytesperline*24?m_bytesperline-1:point.x/24;
curchar+=curline*m_bytesperline;
if(curchar>=m_bytes.GetSize())
curchar=m_bytes.GetSize()-1;
RECT rect;
rect.left=(curchar%m_bytesperline)*24;
rect.right=rect.left+16;
//rect.top=curchar/m_bytesperline+m_linesshown-GetScrollPos(SB_VERT)-1;
rect.top=rect1.bottom-(GetScrollPos(SB_VERT)-curchar/m_bytesperline+1)*15;
//rect.top*=15;
rect.bottom=rect.top+15;
rect.left--;
rect.top--;
rect.bottom++;
rect.right++;
InvalidateRect(&rect);
m_oldcharpos=-1;
CView::OnRButtonUp(nFlags,point);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -