📄 hexeditview.cpp
字号:
////////////////////////////////////////////////////////////////////////////
// File: HexEditView.cpp
// Version: 1.0.0.0
// Created: 17-Oct-2003
//
// Author: Cuick
// E-mail: Cuick@163.net
//
// You are free to use or modify this code .
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "二进制编辑.h"
#include "HexEditView.h"
#include "二进制编辑Doc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CHexEditView
IMPLEMENT_DYNCREATE(CHexEditView, CView)
CHexEditView::CHexEditView()
{
m_text = NULL;
}
CHexEditView::~CHexEditView()
{
}
BEGIN_MESSAGE_MAP(CHexEditView, CView)
//{{AFX_MSG_MAP(CHexEditView)
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
ON_WM_MOUSEWHEEL()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_CHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHexEditView drawing
void CHexEditView::OnDraw(CDC* pDC)
{
CRect rc;
GetClientRect(rc);
if(m_text == NULL)
{
pDC->FillRect(rc, &CBrush(RGB(255,255,255)));
return;
}
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap bm;
bm.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
dc.SelectObject(bm);
dc.SetBoundsRect(&rc, DCB_DISABLE);
CFont font;
font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 );
CFont* oldFont = dc.SelectObject ( &font );
CBrush bkBrush(RGB(255,255,255));
dc.FillRect(rc, &bkBrush);
UINT lineCY, lineCX;
UINT dwPos;
char currentchar[20];
UCHAR text[17];
int lineBeginPos;
m_HexStart = m_CharWidth * (14 - m_LeftChar); //计算二进制显示开始位置
m_TextStart = m_HexStart + m_CharWidth * 50; //计算ASCII码显示开始位置
for(UINT i = 0; i < m_PageRows; i++) //按行显示数据
{
lineBeginPos = (m_TopLine+i-1)*16; //计算当前行开始字符相对于总缓冲区的位置
lineCY = i * m_LineHeight; //当前行的Y坐标
sprintf(currentchar, "%08Xh:", lineBeginPos);
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(RGB(255,255,255));
dc.TextOut (m_CharWidth*(2-m_LeftChar), lineCY, currentchar); //显示地址基值
memcpy(text,&m_text[lineBeginPos],16); //取当前行数据
text[16] = '\0';
for(int l = 0; l < 16; l++)
{
if(text[l] < 32)
text[l] = 46; //不可见ASCII字符用.表示
}
if(lineBeginPos+16 > m_CharCount)
{
text[m_CharCount%16] = '\0'; //最后的数据不满一行时
}
dc.TextOut (m_TextStart, lineCY, text);//显示右面的ASCII字符
//被选中时反色显示右面的ASCII字符
int selStart = (m_SelStart - lineBeginPos)<0? 0:(m_SelStart - lineBeginPos);
int selEnd = (m_SelEnd - lineBeginPos)>15? 15:(m_SelEnd - lineBeginPos);
if(selStart <= 15 && selEnd >= 0)
{
dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));
dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));
text[selEnd+1]='\0';
dc.TextOut (m_TextStart+selStart*m_CharWidth, lineCY, &text[selStart]);
}
else
{
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(RGB(255,255,255));
}
for(UINT j = 0; j < 16; j++)
{
dwPos = j + lineBeginPos;
if(dwPos > (m_CharCount-1))
goto bitblt; //显示完最后一行退出
if(dwPos >= m_SelStart && dwPos <= m_SelEnd)
{
dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));
dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));
}
else
{
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(RGB(255,255,255));
}
lineCX = m_HexStart + j * m_CharWidth *3 ; //计算当前要显示的二进制字符的位置
sprintf(currentchar, "%02X", ((UCHAR *)m_text)[dwPos]);
dc.TextOut (lineCX, lineCY, currentchar); //显示二进制字符
if(dwPos == m_SelEnd) //选中单个字符的显示
{
dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
dc.SetBkColor(RGB(255,0,0));
UCHAR cHex = m_text[dwPos];
if(m_bFirst)//二进制字符的高四位选中
{
cHex = cHex & 0xf0;
cHex = cHex >> 4;
sprintf(currentchar, "%X", cHex);
dc.TextOut (lineCX, lineCY, currentchar);
}
else
{
lineCX = m_HexStart + j * m_CharWidth *3 + m_CharWidth;
cHex = cHex & 0x0f;
sprintf(currentchar, "%X", cHex);
dc.TextOut (lineCX, lineCY, currentchar);
}
}
}
}
bitblt:
pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &dc, 0, 0, SRCCOPY);
dc.DeleteDC ();
}
/////////////////////////////////////////////////////////////////////////////
// CHexEditView diagnostics
#ifdef _DEBUG
void CHexEditView::AssertValid() const
{
CView::AssertValid();
}
void CHexEditView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CHexEditView message handlers
void CHexEditView::SetText(char *input, int len)
{
m_text = input;
m_CharCount = len;
m_Rows = m_CharCount/16;
m_TopLine = 1;
m_LeftChar = 0;
m_SelStart = 0;
m_SelEnd = 0;
m_StartDrag = FALSE;
m_bFirst = TRUE;
CFont font;
m_LineHeight = 16;
font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 );
CFont* oldFont = GetDC()->SelectObject ( &font );
CSize size = GetDC()->GetTextExtent ("A");
m_LineHeight = size.cy;
m_CharWidth = size.cx ;
GetPageRowCols();
SetVertScrollBar();
SetHorzScrollBar();
}
void CHexEditView::OnSetFocus(CWnd* pOldWnd)
{
CView::OnSetFocus(pOldWnd);
m_bFocused = TRUE;
}
void CHexEditView::OnKillFocus(CWnd* pNewWnd)
{
CView::OnKillFocus(pNewWnd);
m_bFocused = FALSE;
}
void CHexEditView::OnLButtonDown(UINT nFlags, CPoint point)
{
CView::OnLButtonDown(nFlags, point);
m_StartDrag = TRUE;
m_bFirst = TRUE;
m_oriStart = m_SelStart = m_SelEnd = Point2Pos(point);
Invalidate(FALSE);
}
void CHexEditView::OnLButtonUp(UINT nFlags, CPoint point)
{
CView::OnLButtonUp(nFlags, point);
if(m_StartDrag)
{
m_SelEnd = Point2Pos(point);
if(m_SelEnd < m_oriStart)
{
m_SelStart = m_SelEnd;
m_SelEnd = m_oriStart;
}
else
{
m_SelStart = m_oriStart;
}
Invalidate(FALSE);
m_StartDrag = FALSE;
}
}
void CHexEditView::OnMouseMove(UINT nFlags, CPoint point)
{
CView::OnMouseMove(nFlags, point);
if(m_StartDrag)
{
m_SelEnd = Point2Pos(point);
if(m_SelEnd < m_oriStart) //反向选择
{
m_SelStart = m_SelEnd;
m_SelEnd = m_oriStart;
}
else
{
m_SelStart = m_oriStart;
}
Invalidate(FALSE);
}
}
//根据鼠标位置求鼠标当前指向的字符
UINT CHexEditView::Point2Pos(CPoint point)
{
if(m_text == NULL)
return 0;
UINT line = m_TopLine + point.y / m_LineHeight - 1;//鼠标所在的行
UINT charset;
if(point.x < m_HexStart)
charset = 0;
else if(point.x < m_HexStart + m_CharWidth * 48)
charset = (point.x - m_HexStart)/(m_CharWidth*3);
else if(point.x < m_TextStart + 16 * m_CharWidth)
charset = (point.x - m_TextStart)/m_CharWidth;
else
charset = 15;
return ((line * 16 + charset)>m_CharCount?m_CharCount-1:(line * 16 + charset));
}
void CHexEditView::OnInitialUpdate()
{
CView::OnInitialUpdate();
}
void CHexEditView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
GetPageRowCols();
SetVertScrollBar();
SetHorzScrollBar();
}
//设置滚动条
void CHexEditView::SetVertScrollBar()
{
if((m_Rows - m_TopLine + 2) < m_PageRows) m_TopLine = 1;
SCROLLINFO si;
ZeroMemory(&si,sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = 0;
si.nMax = m_Rows;
si.nPage = m_PageRows;
si.nPos = m_TopLine-1;
VERIFY(SetScrollInfo(SB_VERT, &si, TRUE));
Invalidate(FALSE);
}
void CHexEditView::SetHorzScrollBar()
{
if((80 - m_LeftChar + 2) < m_PageCols) m_LeftChar = 0;
SCROLLINFO si;
ZeroMemory(&si,sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = 0;
si.nMax = 80;
si.nPage = m_PageCols;
si.nPos = m_LeftChar;
VERIFY(SetScrollInfo(SB_HORZ, &si, TRUE));
Invalidate(FALSE);
}
BOOL CHexEditView::PreCreateWindow(CREATESTRUCT& cs)
{
CWnd *pParentWnd = CWnd::FromHandlePermanent(cs.hwndParent);
if (pParentWnd == NULL || ! pParentWnd->IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
{
// View must always create its own scrollbars,
// if only it's not used within splitter
cs.style |= (WS_HSCROLL | WS_VSCROLL);
}
cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS);
return CView::PreCreateWindow(cs);
}
BOOL CHexEditView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if(zDelta > 0)
{
m_TopLine = --m_TopLine < 1 ? 1 : m_TopLine;
}
else
{
if((m_TopLine + m_PageRows -2) < m_Rows)
m_TopLine+=1;
}
SetVertScrollBar();
SetHorzScrollBar();
return CView::OnMouseWheel(nFlags, zDelta, pt);
}
//计算一页能够显示的字符的行数和列数
void CHexEditView::GetPageRowCols()
{
CRect rc;
GetClientRect(rc);
m_PageRows = rc.Height ()/m_LineHeight;
m_PageCols = rc.Width ()/m_CharWidth;
}
//处理滚动条消息
void CHexEditView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CView::OnHScroll(nSBCode, nPos, pScrollBar);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
VERIFY(GetScrollInfo(SB_HORZ, &si));
switch (nSBCode)
{
case SB_LEFT:
m_LeftChar = 0;
break;
case SB_BOTTOM:
m_LeftChar = 80 - m_PageCols + 1;
break;
case SB_LINEUP:
m_LeftChar = m_LeftChar - 1;
break;
case SB_LINEDOWN:
m_LeftChar = m_LeftChar + 1;
break;
case SB_PAGEUP:
m_LeftChar = m_LeftChar - si.nPage + 1;
break;
case SB_PAGEDOWN:
m_LeftChar = m_LeftChar + si.nPage - 1;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_LeftChar = si.nTrackPos;
break;
default:
return;
}
if((m_LeftChar + m_PageCols - 2) > 80) m_LeftChar = 80 - m_PageCols +2;
if(m_LeftChar < 0) m_LeftChar = 0;
SetHorzScrollBar();
}
void CHexEditView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CView::OnVScroll(nSBCode, nPos, pScrollBar);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
VERIFY(GetScrollInfo(SB_VERT, &si));
switch (nSBCode)
{
case SB_TOP:
m_TopLine = 0;
break;
case SB_BOTTOM:
m_TopLine = m_Rows - m_PageRows + 1;
break;
case SB_LINEUP:
m_TopLine = m_TopLine - 1;
break;
case SB_LINEDOWN:
m_TopLine = m_TopLine + 1;
break;
case SB_PAGEUP:
m_TopLine = m_TopLine - si.nPage + 1;
break;
case SB_PAGEDOWN:
m_TopLine = m_TopLine + si.nPage - 1;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_TopLine = si.nTrackPos+1;
break;
default:
return;
}
if((m_TopLine + m_PageRows -2) > m_Rows) m_TopLine = m_Rows - m_PageRows + 2;
if(m_TopLine < 1) m_TopLine = 1;
SetVertScrollBar();
}
//输入字符转换成二进制数据
void CHexEditView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CView::OnChar(nChar, nRepCnt, nFlags);
UINT input;
UCHAR cHex = m_text[m_SelEnd];
if(nChar > 47 && nChar < 58)
{
input = nChar - 48;
}
else if (nChar > 64 && nChar < 71)
{
input = nChar - 64 + 9;
}
else if (nChar > 96 && nChar < 103)
{
input = nChar - 96 + 9;
}
else
{
return;
}
if(m_bFirst)
{
input = input << 4;
cHex = cHex & 0x0f;
cHex = cHex | input;
m_bFirst = FALSE;
m_text[m_SelEnd] = cHex;
}
else
{
cHex = cHex & 0xf0;
cHex = cHex | input;
m_bFirst = TRUE;
m_text[m_SelEnd] = cHex;
m_SelEnd ++;
}
if(m_SelEnd == m_CharCount)
{
m_CharCount = m_SelEnd + 1;
m_Rows = m_CharCount/16;
}
m_text = ((CMyDoc*)GetDocument ())->JudgeMem (m_CharCount + 100);
m_SelStart = m_SelEnd;
ChangeTop();
ChangeLeft();
Invalidate(FALSE);
}
//键盘的上下左右键处理
BOOL CHexEditView::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
switch (LOWORD(pMsg->wParam))
{
case VK_LEFT:
OnCharLeft();
break;
case VK_RIGHT:
OnCharRight();
break;
case VK_UP:
OnLineUp();
break;
case VK_DOWN:
OnLineDown();
break;
default:
break;
}
}
return CView::PreTranslateMessage(pMsg);
}
void CHexEditView::OnCharLeft()
{
if(m_bFirst && m_SelEnd > 0)
{
m_SelEnd --;
m_bFirst = FALSE;
}
else
{
m_bFirst = TRUE;
}
ChangeTop();
ChangeLeft();
m_SelStart = m_SelEnd;
Invalidate(FALSE);
}
void CHexEditView::OnCharRight()
{
if(m_bFirst)
{
m_bFirst = FALSE;
}
else if( m_SelEnd < m_CharCount-1)
{
m_bFirst = TRUE;
m_SelEnd++;
}
ChangeTop();
ChangeLeft();
m_SelStart = m_SelEnd;
Invalidate(FALSE);
}
void CHexEditView::OnLineUp()
{
if(m_SelEnd > 15)
m_SelEnd = m_SelEnd - 16;
ChangeTop();
ChangeLeft();
m_SelStart = m_SelEnd;
Invalidate(FALSE);
}
void CHexEditView::OnLineDown()
{
if(m_SelEnd + 16 < m_CharCount)
m_SelEnd = m_SelEnd + 16;
else
m_SelEnd = m_CharCount-1;
ChangeTop();
ChangeLeft();
m_SelStart = m_SelEnd;
Invalidate(FALSE);
}
//计算顶行
void CHexEditView::ChangeTop()
{
int newtop = m_TopLine;
if((m_SelEnd/16 + 1) < m_TopLine)
{
newtop = m_SelEnd/16 + 1;
}
if((m_SelEnd/16 + 2) > m_TopLine+m_PageRows)
{
newtop = m_SelEnd/16 + 2 - m_PageRows;
}
if(newtop != m_TopLine)
{
m_TopLine = newtop;
SetVertScrollBar();
}
}
//计算左列
void CHexEditView::ChangeLeft()
{
int currentcol = m_SelEnd%16;
if(currentcol*3 + 14 < m_LeftChar)
{
m_LeftChar = currentcol*3 + 14;
SetHorzScrollBar();
}
if(currentcol*3 + 14 - m_LeftChar+1 > m_PageCols)
{
m_LeftChar = currentcol*3 + 14 - m_PageCols +2;
SetHorzScrollBar();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -