📄 hexeditview.cpp
字号:
// HexEditView.cpp : 实现文件
//
#include "stdafx.h"
#include "GameMaster.h"
#include "HexEditView.h"
#include "GameMasterDoc.h"
#include ".\hexeditview.h"
const int block = 1024 * 4;
static int block_num = 1;
// CHexEditView
IMPLEMENT_DYNCREATE(CHexEditView, CView)
CHexEditView::CHexEditView()
{
m_nTopLine = 0;
m_nLeftChar = 0;
strText = NULL;
m_bFirst = TRUE;
m_bStartDrag = FALSE;
////////////////此部分关于动态获得文件长度和字体高度尚未解决/////////////////////
//m_nRows = 100;
//m_nLineHeight = 16;
////////////////此部分关于动态获得文件长度和字体高度尚未解决/////////////////////
}
CHexEditView::~CHexEditView()
{
if(strText!=NULL)
{
delete strText;
strText = NULL;
}
}
BEGIN_MESSAGE_MAP(CHexEditView, CView)
ON_WM_SIZE()
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_MOUSEWHEEL()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_CHAR()
END_MESSAGE_MAP()
// CHexEditView 绘图
void CHexEditView::OnDraw(CDC* pDC)
{
CGameMasterDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: 在此添加绘制代码
//获取客户区大小
CRect rectClient;
GetClientRect(&rectClient);
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap bm;
bm.CreateCompatibleBitmap(pDC, rectClient.Width(), rectClient.Height());
dc.SelectObject(bm);
dc.SetBoundsRect(&rectClient, DCB_DISABLE);
//将字体选入设备上下文
CFont* pOldFont = dc.SelectObject (&font);
CBrush bkBrush(RGB(255,255,255));
dc.FillRect(rectClient, &bkBrush);
//////显示数据////////////////////////////////////////////////////////////////////
UINT lineCY, lineCX;
UINT dwPos;
char currentchar[20];
char text[17];
int lineBeginPos;
DWORD showAddress = startAddress;
m_nHexStart = m_nCharWidth * (14 - m_nLeftChar); //计算二进制显示开始位置
m_nTextStart = m_nHexStart + m_nCharWidth * 50; //计算ASCII码显示开始位置
for(UINT i = 0; i < m_nPageRows; i++) //按行显示数据
{
lineBeginPos = (m_nTopLine+i)*16; //计算当前行开始字符相对于总缓冲区的位置
lineCY = i * m_nLineHeight; //当前行的Y坐标
sprintf(currentchar, "%08X:", showAddress);
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(RGB(255,255,255));
dc.TextOut (m_nCharWidth*(2-m_nLeftChar), lineCY, currentchar); //显示地址基值
memcpy(text,&strText[lineBeginPos],16); //取当前行数据
text[16] = '\0';
for(int l = 0; l < 16; l++)
{
if(text[l] < 32)
text[l] = 46; //不可见ASCII字符用.表示
}
if(lineBeginPos+16 > m_nCharCount)
{
text[m_nCharCount%16] = '\0'; //最后的数据不满一行时
}
dc.TextOut (m_nTextStart, lineCY, text);//显示右面的ASCII字符
//被选中时反色显示右面的ASCII字符
int s = m_nSelStart - lineBeginPos;
int e = m_nSelEnd - lineBeginPos;
int selStart = s < 0 ? 0:(m_nSelStart - lineBeginPos);
int selEnd = e > 15 ? 15:(m_nSelEnd - lineBeginPos);
if(selStart <= 15 && selEnd >= 0)
{
dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));
dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));
text[selEnd+1]='\0';
dc.TextOut(m_nTextStart+selStart*m_nCharWidth, 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((int)dwPos > (m_nCharCount-1))
goto bitblt; //显示完最后一行退出
if(dwPos >= m_nSelStart && dwPos <= m_nSelEnd)
{
dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));
dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));
}
else
{
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(RGB(255,255,255));
}
lineCX = m_nHexStart + j * m_nCharWidth *3 ; //计算当前要显示的二进制字符的位置
sprintf(currentchar, "%02X", ((UCHAR *)strText)[dwPos]);
dc.TextOut (lineCX, lineCY, currentchar); //显示二进制字符
if(dwPos == m_nSelEnd) //选中单个字符的显示
{
dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
dc.SetBkColor(RGB(255,0,0));
UCHAR cHex = strText[dwPos];
if(m_bFirst)//二进制字符的高四位选中
{
cHex = cHex & 0xf0;
cHex = cHex >> 4;
sprintf(currentchar, "%X", cHex);
dc.TextOut (lineCX, lineCY, currentchar);
}
else
{
lineCX = m_nHexStart + j * m_nCharWidth *3 + m_nCharWidth;
cHex = cHex & 0x0f;
sprintf(currentchar, "%X", cHex);
dc.TextOut (lineCX, lineCY, currentchar);
}
}
}
showAddress += 16;
}
bitblt:
pDC->BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &dc, 0, 0, SRCCOPY);
dc.DeleteDC ();
// strText[m_nCharCount] = '\0';
// pDoc->m_strline = strText;
}
// CHexEditView 诊断
#ifdef _DEBUG
void CHexEditView::AssertValid() const
{
CView::AssertValid();
}
void CHexEditView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CGameMasterDoc* CHexEditView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGameMasterDoc)));
return (CGameMasterDoc*)m_pDocument;
}
#endif //_DEBUG
//自定义函数
void CHexEditView::SetView(DWORD dwAddress,char *text,int nDocChars,LOGFONT lf)
{
//获取起始地址
startAddress = dwAddress;
//获取文件总字节数
m_nCharCount = nDocChars;
//获取总行数
m_nRows = nDocChars/16;
//获取文件内容
strText = text;
block_num = m_nCharCount / block + 1;
strText = (char *)realloc(strText,block*block_num);
//设置视图显示字体
font.CreateFontIndirect(&lf);
GetDC()->SelectObject(&font);
CSize size = GetDC()->GetTextExtent("A");
//设置行高
m_nLineHeight = size.cy;
//设置列宽
m_nCharWidth = size.cx;
m_nSelStart = m_nSelEnd = 0;
//获取客户区信息
GetClientInfo();
SetVertScrollBar();
SetHorzScrollBar();
}
void CHexEditView::GetClientInfo()
{
//获取一页的行数和列数
CRect rc;
GetClientRect(rc);
m_nPageRows = rc.Height()/m_nLineHeight+1;
m_nPageCols = rc.Width()/m_nCharWidth;
}
//设置滚动条
void CHexEditView::SetVertScrollBar()
{
if((m_nRows - m_nTopLine + 2) < m_nPageRows)
m_nTopLine = 0;
SCROLLINFO si;
ZeroMemory(&si,sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = -1;
si.nMax = m_nRows;
si.nPage = m_nPageRows;
si.nPos = m_nTopLine-1;
VERIFY(SetScrollInfo(SB_VERT, &si, TRUE));
Invalidate(FALSE);
}
void CHexEditView::SetHorzScrollBar()
{
if((80 - ((UINT)m_nLeftChar) + 2) < m_nPageCols)
m_nLeftChar = 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_nPageCols;
si.nPos = m_nLeftChar;
VERIFY(SetScrollInfo(SB_HORZ, &si, TRUE));
Invalidate(FALSE);
}
//根据鼠标位置求鼠标当前指向的字符
UINT CHexEditView::PointPos(CPoint point)
{
UINT line = m_nTopLine + point.y / m_nLineHeight;//鼠标所在的行
if(line > m_nRows)
line = m_nRows;
// int liney = line*m_nLineHeight;//行纵坐标
UINT charset;
if(point.x < m_nHexStart)
charset = 0;
else if(point.x < m_nTextStart-m_nCharWidth)
charset = (point.x-m_nHexStart)/(m_nCharWidth*3);
// else if(point.x==m_nTextStart-m_nCharWidth)
// charset = (point.x-m_nTextStart)/m_nCharWidth+1;
else if(point.x < m_nTextStart + 16*m_nCharWidth)
charset = (point.x-m_nTextStart)/m_nCharWidth;
else
charset = 15;
//comSel = charset;
//SelectPoint[0] = CPoint(m_nHexStart+charset*m_nCharWidth*3,liney);
//SelectPoint[1] = CPoint(m_nTextStart+charset*m_nCharWidth,liney);
return ((line * 16 + charset)>(UINT)m_nCharCount?(UINT)m_nCharCount-1:(line * 16 + charset));
}
//计算顶行
void CHexEditView::ChangeTop()
{
int newtop = m_nTopLine;
if(((int)m_nSelEnd/16 + 1) < m_nTopLine)
{
newtop = m_nSelEnd/16 + 1;
}
if((m_nSelEnd/16 + 2) > m_nTopLine+m_nPageRows)
{
newtop = m_nSelEnd/16 + 2 - m_nPageRows;
}
if(newtop != m_nTopLine)
{
m_nTopLine = newtop;
SetVertScrollBar();
}
}
//计算左列
void CHexEditView::ChangeLeft()
{
int currentcol = m_nSelEnd%16;
if(currentcol*3 + 14 < m_nLeftChar)
{
m_nLeftChar = currentcol*3 + 14;
SetHorzScrollBar();
}
if(currentcol*3 + 14 - m_nLeftChar+1 >(int)m_nPageCols)
{
m_nLeftChar = currentcol*3 + 14 - m_nPageCols +2;
SetHorzScrollBar();
}
}
// CHexEditView 消息处理程序
void CHexEditView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
GetClientInfo();
SetVertScrollBar();
SetHorzScrollBar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -