📄 hexedit.cpp
字号:
RepositionCaret(m_currentAddress);
RedrawWindow();
}
return;
}
SetSel(-1, -1);
switch(m_currentMode)
{
case EDIT_NONE:
return;
case EDIT_HIGH:
case EDIT_LOW:
if((nChar >= '0' && nChar <= '9') || (nChar >= 'a' && nChar <= 'f'))
{
UINT b = nChar - '0';
if(b > 9)
b = 10 + nChar - 'a';
if(m_currentMode == EDIT_HIGH)
{
m_pData[m_currentAddress] = (unsigned char)((m_pData[m_currentAddress] & 0x0f) | (b << 4));
}
else
{
m_pData[m_currentAddress] = (unsigned char)((m_pData[m_currentAddress] & 0xf0) | b);
}
Move(1,0);
}
break;
case EDIT_ASCII:
m_pData[m_currentAddress] = (unsigned char)nChar;
Move(1,0);
break;
}
RedrawWindow();
}
void CHexEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
nFlags; nRepCnt;
BOOL bShift = GetKeyState(VK_SHIFT) & 0x80000000;
BOOL bac = m_bNoAddressChange;
m_bNoAddressChange = TRUE;
switch(nChar)
{
case VK_DOWN:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
Move(0,1);
m_selEnd = m_currentAddress;
if(m_currentMode == EDIT_HIGH || m_currentMode == EDIT_LOW)
m_selEnd++;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
Move(0,1);
break;
case VK_UP:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
Move(0,-1);
m_selEnd = m_currentAddress;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
Move(0,-1);
break;
case VK_LEFT:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
Move(-1,0);
m_selEnd = m_currentAddress;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
Move(-1,0);
break;
case VK_RIGHT:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
Move(1,0);
m_selEnd = m_currentAddress;
if(m_currentMode == EDIT_HIGH || m_currentMode == EDIT_LOW)
m_selEnd++;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
Move(1,0);
break;
case VK_PRIOR:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
OnVScroll(SB_PAGEUP, 0, NULL);
Move(0,0);
m_selEnd = m_currentAddress;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
OnVScroll(SB_PAGEUP, 0, NULL);
Move(0,0);
break;
case VK_NEXT:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
OnVScroll(SB_PAGEDOWN, 0, NULL);
Move(0,0);
m_selEnd = m_currentAddress;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
OnVScroll(SB_PAGEDOWN, 0, NULL);
Move(0,0);
break;
case VK_HOME:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
if(GetKeyState(VK_CONTROL) & 0x80000000)
{
OnVScroll(SB_THUMBTRACK, 0, NULL);
Move(0,0);
}
else
{
m_currentAddress /= m_bpr;
m_currentAddress *= m_bpr;
Move(0,0);
}
m_selEnd = m_currentAddress;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
if(GetKeyState(VK_CONTROL) & 0x80000000)
{
OnVScroll(SB_THUMBTRACK, 0, NULL);
m_currentAddress = 0;
Move(0,0);
}
else
{
m_currentAddress /= m_bpr;
m_currentAddress *= m_bpr;
Move(0,0);
}
break;
case VK_END:
if(bShift)
{
if(!IsSelected())
{
m_selStart = m_currentAddress;
}
if(GetKeyState(VK_CONTROL) & 0x80000000)
{
m_currentAddress = m_length-1;
OnVScroll(SB_THUMBTRACK, ((m_length+(m_bpr/2)) / m_bpr) - m_lpp, NULL);
Move(0,0);
}
else
{
m_currentAddress /= m_bpr;
m_currentAddress *= m_bpr;
m_currentAddress += m_bpr - 1;
if(m_currentAddress > m_length)
m_currentAddress = m_length-1;
Move(0,0);
}
m_selEnd = m_currentAddress;
RedrawWindow();
break;
}
else
SetSel(-1, -1);
if(GetKeyState(VK_CONTROL) & 0x80000000)
{
m_currentAddress = m_length-1;
if(m_bHalfPage)
OnVScroll(SB_THUMBTRACK, 0, NULL);
else
OnVScroll(SB_THUMBTRACK, ((m_length+(m_bpr/2)) / m_bpr) - m_lpp, NULL);
Move(0,0);
}
else
{
m_currentAddress /= m_bpr;
m_currentAddress *= m_bpr;
m_currentAddress += m_bpr - 1;
if(m_currentAddress > m_length)
m_currentAddress = m_length-1;
Move(0,0);
}
break;
case VK_INSERT:
SelInsert(m_currentAddress, max(1, m_selEnd-m_selStart));
RedrawWindow();
break;
case VK_DELETE:
if(IsSelected())
{
OnEditClear();
}
else
{
SelDelete(m_currentAddress, m_currentAddress+1);
RedrawWindow();
}
break;
case '\t':
switch(m_currentMode)
{
case EDIT_NONE:
m_currentMode = EDIT_HIGH;
break;
case EDIT_HIGH:
case EDIT_LOW:
m_currentMode = EDIT_ASCII;
break;
case EDIT_ASCII:
m_currentMode = EDIT_HIGH;
break;
}
Move(0,0);
break;
}
m_bNoAddressChange = bac;
}
void CHexEdit::Move(int x, int y)
{
switch(m_currentMode)
{
case EDIT_NONE:
return;
case EDIT_HIGH:
if(x != 0)
m_currentMode = EDIT_LOW;
if(x == -1)
m_currentAddress --;
m_currentAddress += y* m_bpr;
break;
case EDIT_LOW:
if(x != 0)
m_currentMode = EDIT_HIGH;
if(x == 1)
m_currentAddress++;
m_currentAddress += y* m_bpr;
break;
case EDIT_ASCII:
{
m_currentAddress += x;
m_currentAddress += y*m_bpr;
}
break;
}
if(m_currentAddress < 0)
m_currentAddress = 0;
if(m_currentAddress >= m_length)
{
m_currentAddress -= x;
m_currentAddress -= y*m_bpr;
}
m_bNoAddressChange = TRUE;
if(m_currentAddress < m_topindex)
{
OnVScroll(SB_LINEUP, 0, NULL);
}
if(m_currentAddress >= m_topindex + m_lpp*m_bpr)
{
OnVScroll(SB_LINEDOWN, 0, NULL);
}
m_bNoAddressChange = FALSE;
// ScrollIntoView(m_currentAddress);
RepositionCaret(m_currentAddress);
}
void CHexEdit::SetSel(int s, int e)
{
DestroyCaret();
m_selStart = s;
m_selEnd = e;
RedrawWindow();
if(m_editPos.x == 0 && m_bShowAddress)
CreateAddressCaret();
else
CreateEditCaret();
SetCaretPos(m_editPos);
ShowCaret();
}
void CHexEdit::RepositionCaret(int p)
{
int x, y;
y = (p - m_topindex) / m_bpr;
x = (p - m_topindex) % m_bpr;
switch(m_currentMode)
{
case EDIT_NONE:
CreateAddressCaret();
x = 0;
break;
case EDIT_HIGH:
CreateEditCaret();
x *= m_nullWidth*3;
x += m_offHex;
break;
case EDIT_LOW:
CreateEditCaret();
x *= m_nullWidth*3;
x += m_nullWidth;
x += m_offHex;
break;
case EDIT_ASCII:
CreateEditCaret();
x *= m_nullWidth;
x += m_offAscii;
break;
}
m_editPos.x = x;
m_editPos.y = y*m_lineHeight;
CRect rc;
GetClientRect(&rc);
if(rc.PtInRect(m_editPos))
{
SetCaretPos(m_editPos);
ShowCaret();
}
}
void CHexEdit::ScrollIntoView(int p)
{
if(p < m_topindex || p > m_topindex + m_lpp*m_bpr)
{
m_topindex = (p/m_bpr) * m_bpr;
m_topindex -= (m_lpp / 3) * m_bpr;
if(m_topindex < 0)
m_topindex = 0;
UpdateScrollbars();
RedrawWindow();
}
}
void CHexEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
// CG: This block was added by the Pop-up Menu component
{
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
CMenu menu;
VERIFY(menu.LoadMenu(CG_IDR_POPUP_HEX_EDIT));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
pPopup->EnableMenuItem(ID_EDIT_UNDO, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
if(!IsSelected())
{
pPopup->EnableMenuItem(ID_EDIT_CLEAR, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(ID_EDIT_CUT, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(ID_EDIT_COPY, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
}
{
COleDataObject obj;
if (obj.AttachClipboard())
{
if(!obj.IsDataAvailable(CF_TEXT) && !obj.IsDataAvailable(RegisterClipboardFormat("BinaryData")))
pPopup->EnableMenuItem(ID_EDIT_PASTE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
}
}
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
this);
}
}
void CHexEdit::OnEditClear()
{
m_currentAddress = m_selStart;
SelDelete(m_selStart, m_selEnd);
RepositionCaret(m_currentAddress);
RedrawWindow();
}
void CHexEdit::OnEditCopy()
{
COleDataSource* pSource = new COleDataSource();
EmptyClipboard();
if(m_currentMode != EDIT_ASCII)
{
int dwLen = (m_selEnd-m_selStart);
HGLOBAL hMemb = ::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT, m_selEnd-m_selStart);
HGLOBAL hMema = ::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT, (dwLen) * 3);
if (!hMema)
return;
// copy binary
LPBYTE p = (BYTE*)::GlobalLock(hMemb);
memcpy(p, m_pData+m_selStart, dwLen);
::GlobalUnlock(hMemb);
// copy ascii
p = (BYTE*)::GlobalLock(hMema);
for(int i = 0; i < dwLen;)
{
TOHEX(m_pData[m_selStart+i], p);
*p++ = ' ';
i++;
}
::GlobalUnlock(hMema);
pSource->CacheGlobalData(RegisterClipboardFormat("BinaryData"), hMemb);
pSource->CacheGlobalData(CF_TEXT, hMema);
}
else
{
HGLOBAL hMemb = ::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT, m_selEnd-m_selStart);
HGLOBAL hMema = ::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT, m_selEnd-m_selStart);
if (!hMemb || !hMema)
return;
// copy binary
LPBYTE p = (BYTE*)::GlobalLock(hMemb);
int dwLen = m_selEnd-m_selStart;
memcpy(p, m_pData+m_selStart, dwLen);
::GlobalUnlock(hMemb);
// copy ascii
p = (BYTE*)::GlobalLock(hMema);
memcpy(p, m_pData+m_selStart, dwLen);
for(int i = 0; i < dwLen; p++, i++)
if(!isprint(*p))
*p = '.';
::GlobalUnlock(hMema);
pSource->CacheGlobalData(RegisterClipboardFormat("BinaryData"), hMemb);
pSource->CacheGlobalData(CF_TEXT, hMema);
}
pSource->SetClipboard();
}
void CHexEdit::OnEditCut()
{
OnEditCopy();
SelDelete(m_selStart, m_selEnd);
RedrawWindow();
}
void CHexEdit::OnEditPaste()
{
COleDataObject obj;
if (obj.AttachClipboard())
{
HGLOBAL hmem = NULL;
if (obj.IsDataAvailable(RegisterClipboardFormat("BinaryData")))
{
hmem = obj.GetGlobalData(RegisterClipboardFormat("BinaryData"));
}
else if (obj.IsDataAvailable(CF_TEXT))
{
hmem = obj.GetGlobalData(CF_TEXT);
}
if(hmem)
{
LPBYTE p = (BYTE*)::GlobalLock(hmem);
DWORD dwLen = ::GlobalSize(hmem);
int insert;
int oa = m_currentAddress;
NormalizeSel();
if(m_selStart == 0xffffffff)
{
if(m_currentMode == EDIT_LOW)
m_currentAddress++;
insert = m_currentAddress;
SelInsert(m_currentAddress, dwLen);
}
else
{
insert = m_selStart;
SelDelete(m_selStart, m_selEnd);
SelInsert(insert, dwLen);
SetSel(-1, -1);
}
memcpy(m_pData+insert, p, dwLen);
m_currentAddress = oa;
RedrawWindow();
::GlobalUnlock(hmem);
}
}
}
void CHexEdit::OnEditSelectAll()
{
m_selStart = 0;
m_selEnd = m_length;
DestroyCaret();
RedrawWindow();
}
void CHexEdit::OnEditUndo()
{
//DEL // TODO: Add your command handler code here
//DEL
}
void CHexEdit::NormalizeSel()
{
if(m_selStart > m_selEnd)
m_selStart ^= m_selEnd ^= m_selStart ^= m_selEnd;
}
void CHexEdit::SelDelete(int s, int e)
{
LPBYTE p = (LPBYTE) malloc(m_length - (e-s)+1);
memcpy(p, m_pData, s);
if(s < m_length-(e-s))
memcpy(p+s, m_pData+e, (m_length -e));
free(m_pData);
SetSel(-1, -1);
m_pData = p;
m_length = m_length-(e-s);
if(m_currentAddress > m_length)
{
m_currentAddress = m_length;
RepositionCaret(m_currentAddress);
}
m_bUpdate = TRUE;
}
void CHexEdit::SelInsert(int s, int l)
{
LPBYTE p = (LPBYTE) calloc(m_length + l, 1);
memcpy(p, m_pData, s);
memcpy(p+s+l, m_pData+s, (m_length-s));
free(m_pData);
SetSel(-1, -1);
m_pData = p;
m_length = m_length+l;
m_bUpdate = TRUE;
}
CSize CHexEdit::GetSel()
{
return CSize(m_selStart, m_selEnd);
}
void CHexEdit::SetData(LPBYTE p, int len)
{
free(m_pData);
m_pData = (LPBYTE) malloc(len);
memcpy(m_pData, p, len);
SetSel(-1, -1);
m_length = len;
m_currentAddress = 0;
m_editPos.x = m_editPos.y = 0;
m_currentMode = EDIT_HIGH;
m_topindex = 0;
m_bUpdate = TRUE;
}
int CHexEdit::GetData(LPBYTE p, int len)
{
memcpy(p, m_pData, min(len, m_length));
return m_length;
}
void CHexEdit::AppendData(LPBYTE p, int addlen)
{
LPBYTE oldData=m_pData;
int oldlen=m_length;
m_pData = (LPBYTE) malloc(oldlen+addlen);
m_length = oldlen+addlen;
memcpy(m_pData, oldData, oldlen);
free(oldData);
memcpy(m_pData+oldlen,p,addlen);
SetSel(oldlen, m_length);
m_currentAddress = oldlen;
m_editPos.x = m_editPos.y = 0;
m_currentMode = EDIT_HIGH;
m_topindex = 0;
m_bUpdate = TRUE;
}
void CHexEdit::Clear()
{
free(m_pData);
m_pData = NULL; // pointer to data
m_length = 0;
m_selStart = 0xffffffff;
m_selEnd = 0xffffffff;
m_bUpdate=TRUE;
}
BOOL CHexEdit::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return CEdit::OnEraseBkgnd(pDC);
}
void CHexEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// CEdit::OnLButtonDblClk(nFlags, point);
}
void CHexEdit::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CEdit::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CHexEdit::OnSize(UINT nType, int cx, int cy)
{
CEdit::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -