📄 hexeditbase.cpp
字号:
CRect cRect(m_tPaintDetails.cPaintingRect);
cRect.left-=2;
cRect.right+=2;
cRegn.CreateRectRgnIndirect((LPCRECT)cRect);
cMemDC.SelectClipRgn(&cRegn);
if(m_bShowAddress) {
PaintAddresses(cMemDC);
}
PaintHexData(cMemDC);
if(m_bShowAscii) {
PaintAsciiData(cMemDC);
}
cPaintDC.BitBlt(0, 0, cClientRect.right, cClientRect.bottom, &cMemDC, 0, 0, SRCCOPY);
if(pOldFont != NULL) {
cMemDC.SelectObject(pOldFont);
}
if(pOldBitmap != NULL) {
cMemDC.SelectObject(pOldBitmap);
}
}
void CHexEditBase::MakeVisible(UINT nBegin, UINT nEnd, bool bUpdate)
{
ASSERT(nBegin<=nEnd);
UINT nAdrBeg = m_nScrollPostionY * m_tPaintDetails.nBytesPerRow;
UINT nFullBytesPerScreen = m_tPaintDetails.nFullVisibleLines * m_tPaintDetails.nBytesPerRow;
UINT nAdrEnd = nAdrBeg + nFullBytesPerScreen;
UINT nLength = nEnd - nBegin;
if( (nBegin > nAdrBeg) || (nEnd < nAdrEnd) ) {
// don't do anything when it's simply not possible to see everything and
// we already see one ful page.
if(nLength > nFullBytesPerScreen) {
if(nAdrBeg < nBegin) {
SetScrollPositionY(nBegin/m_tPaintDetails.nBytesPerRow, false);
} else if (nAdrEnd > nEnd) {
SetScrollPositionY((nEnd-nFullBytesPerScreen+m_tPaintDetails.nBytesPerRow)/m_tPaintDetails.nBytesPerRow, false);
}
} else {
if(nAdrBeg > nBegin) {
SetScrollPositionY(nBegin/m_tPaintDetails.nBytesPerRow, false);
} else if (nAdrEnd < nEnd) {
SetScrollPositionY((nEnd-nFullBytesPerScreen+m_tPaintDetails.nBytesPerRow)/m_tPaintDetails.nBytesPerRow, false);
}
}
}
int iLineX = (int)((nBegin%m_tPaintDetails.nBytesPerRow)*3*m_tPaintDetails.nCharacterWidth + m_tPaintDetails.nHexPos + m_tPaintDetails.cPaintingRect.left) - (int)m_nScrollPostionX;
int iLineX2 = (int)((2+(nEnd%m_tPaintDetails.nBytesPerRow)*3)*m_tPaintDetails.nCharacterWidth + m_tPaintDetails.nHexPos + m_tPaintDetails.cPaintingRect.left) - (int)m_nScrollPostionX;
if(iLineX > iLineX2) {
int iTemp = iLineX;
iLineX = iLineX2;
iLineX2 = iTemp;
}
if( (iLineX <= m_tPaintDetails.cPaintingRect.left) && (iLineX2 >= m_tPaintDetails.cPaintingRect.right) ) {
// nothing to do here...
} else if(iLineX < m_tPaintDetails.cPaintingRect.left) {
SetScrollPositionX(m_nScrollPostionX + iLineX - m_tPaintDetails.cPaintingRect.left, false);
} else if(iLineX2 >= m_tPaintDetails.cPaintingRect.right) {
SetScrollPositionX(m_nScrollPostionX + iLineX2 - m_tPaintDetails.cPaintingRect.Width(), false);
}
if(bUpdate && ::IsWindow(m_hWnd)) {
Invalidate();
}
}
void CHexEditBase::SetScrollbarRanges()
{
if(!(GetStyle() & ES_MULTILINE)) {
return;
}
SCROLLINFO tScrollInfo;
memset(&tScrollInfo, 0, sizeof(SCROLLINFO));
tScrollInfo.cbSize = sizeof(SCROLLINFO);
if(m_nScrollRangeY > 0) {
ShowScrollBar(SB_VERT, TRUE);
EnableScrollBar(SB_VERT);
tScrollInfo.fMask = SIF_ALL ;
tScrollInfo.nPage = m_tPaintDetails.nFullVisibleLines;
tScrollInfo.nMax = m_nScrollRangeY + tScrollInfo.nPage - 1;
if(m_nScrollPostionY > m_nScrollRangeY) {
m_nScrollPostionY = m_nScrollRangeY;
}
tScrollInfo.nPos = m_nScrollPostionY;
SetScrollInfo(SB_VERT, &tScrollInfo, TRUE);
} else {
ShowScrollBar(SB_VERT, FALSE);
}
if(m_nScrollRangeX > 0) {
EnableScrollBar(SB_HORZ);
ShowScrollBar(SB_HORZ, TRUE);
tScrollInfo.fMask = SIF_ALL ;
tScrollInfo.nPage = m_tPaintDetails.cPaintingRect.Width();
tScrollInfo.nMax = m_nScrollRangeX + tScrollInfo.nPage - 1;
if(m_nScrollPostionX > m_nScrollRangeX) {
m_nScrollPostionX = m_nScrollRangeX;
}
tScrollInfo.nPos = m_nScrollPostionX;
SetScrollInfo(SB_HORZ, &tScrollInfo, TRUE);
} else {
ShowScrollBar(SB_HORZ, FALSE);
}
}
void CHexEditBase::OnSetFocus(CWnd*)
{
if(m_pData != NULL) {
SetEditCaretPos(m_nCurrentAddress, m_bHighBits);
Invalidate();
}
}
void CHexEditBase::OnKillFocus(CWnd* pNewWnd)
{
DestoyEditCaret();
CWnd::OnKillFocus(pNewWnd);
Invalidate();
}
void CHexEditBase::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
CalculatePaintingDetails(CClientDC(this));
SetEditCaretPos(m_nCurrentAddress, m_bHighBits);
SetScrollbarRanges();
}
void CHexEditBase::MoveScrollPostionY(int iDelta, bool bUpdate)
{
if(iDelta > 0) {
SetScrollPositionY(m_nScrollPostionY+iDelta, bUpdate);
} else {
int iPositon = (int)m_nScrollPostionY;
iPositon -= (-iDelta);
if(iPositon < 0) {
iPositon = 0;
}
SetScrollPositionY((UINT)iPositon, bUpdate);
}
}
void CHexEditBase::MoveScrollPostionX(int iDelta, bool bUpdate)
{
if(iDelta > 0) {
SetScrollPositionX(m_nScrollPostionX+iDelta, bUpdate);
} else {
int iPositon = (int)m_nScrollPostionX;
iPositon -= (-iDelta);
if(iPositon < 0) {
iPositon = 0;
}
SetScrollPositionX((UINT)iPositon, bUpdate);
}
}
void CHexEditBase::GetAddressFromPoint(const CPoint& cPt, UINT& nAddress, bool& bHighBits)
{
CPoint cPoint(cPt);
cPoint.x += m_nScrollPostionX;
cPoint.y -= m_tPaintDetails.cPaintingRect.top;
if((GetStyle() & ES_MULTILINE)) {
cPoint.x += (m_tPaintDetails.nCharacterWidth>>1) - CONTROL_BORDER_SPACE ;
} else {
cPoint.x += (m_tPaintDetails.nCharacterWidth>>1);
}
if(cPoint.y < 0) {
cPoint.y = 0;
} else if(cPoint.y > (int)(m_tPaintDetails.nVisibleLines*m_tPaintDetails.nLineHeight)) {
cPoint.y = m_tPaintDetails.nVisibleLines*m_tPaintDetails.nLineHeight;
}
if((int)cPoint.x < (int)m_tPaintDetails.nHexPos) {
cPoint.x = m_tPaintDetails.nHexPos;
} else if(cPoint.x > (int)(m_tPaintDetails.nHexPos + m_tPaintDetails.nHexLen - DATA_ASCII_SPACE)) {
cPoint.x = m_tPaintDetails.nHexPos + m_tPaintDetails.nHexLen - DATA_ASCII_SPACE;
}
cPoint.x -= m_tPaintDetails.nHexPos;
UINT nRow = cPoint.y / m_tPaintDetails.nLineHeight;
UINT nCharColumn = cPoint.x / m_tPaintDetails.nCharacterWidth;
UINT nColumn = nCharColumn / 3;
bHighBits = nCharColumn % 3 == 0;
nAddress = nColumn + (nRow + m_nScrollPostionY) * m_tPaintDetails.nBytesPerRow;
if(nAddress >= m_nLength) {
nAddress = m_nLength - 1;
bHighBits = false;
}
}
BOOL CHexEditBase::OnMouseWheel(UINT nFlags, short zDelta, CPoint)
{
MoveScrollPostionY(-(zDelta/WHEEL_DELTA), true);
return TRUE;
}
void CHexEditBase::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*)
{
if(m_pData == NULL) {
return;
}
switch(nSBCode) {
case SB_LINEDOWN:
MoveScrollPostionY(1, true);
break;
case SB_LINEUP:
MoveScrollPostionY(-1, true);
break;
case SB_PAGEDOWN:
MoveScrollPostionY(m_tPaintDetails.nFullVisibleLines, true);
break;
case SB_PAGEUP:
MoveScrollPostionY(-(int)m_tPaintDetails.nFullVisibleLines, true);
break;
case SB_THUMBTRACK:
// Windows only allows 16Bit track-positions in the callback message.
// MFC hides this by providing a 32-bit value (nobody expects to
// be an invalid value) which is unfortunately casted from a 16Bit value.
// -- MSDN gives a hint (in the API-documentation) about this problem
// -- and a solution as well. We should use GetScrollInfo here to receive
// -- the correct 32-Bit value when our scrollrange exceeds the 16bit range
// -- to keep it simple, I decided to always do it like this
SCROLLINFO tScrollInfo;
memset(&tScrollInfo, 0, sizeof(SCROLLINFO));
if(GetScrollInfo(SB_VERT, &tScrollInfo, SIF_TRACKPOS)) {
SetScrollPositionY(tScrollInfo.nTrackPos, true);
}
#ifdef _DEBUG
else {
TRACE("CHexEditBase::OnVScroll: Error receiving trackposition while thumbtracking\n");
}
#endif
break;
}
}
void CHexEditBase::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*)
{
if(m_pData == NULL) {
return;
}
switch(nSBCode) {
case SB_LINEDOWN:
MoveScrollPostionX(m_tPaintDetails.nCharacterWidth, true);
break;
case SB_LINEUP:
MoveScrollPostionX(-(int)m_tPaintDetails.nCharacterWidth, true);
break;
case SB_PAGEDOWN:
MoveScrollPostionX(m_tPaintDetails.cPaintingRect.Width(), true);
break;
case SB_PAGEUP:
MoveScrollPostionX(-(int)m_tPaintDetails.cPaintingRect.Width(), true);
break;
case SB_THUMBTRACK:
SetScrollPositionX(nPos, true);
break;
}
}
void CHexEditBase::SetEditCaretPos(UINT nOffset, bool bHighBits)
{
ASSERT(::IsWindow(m_hWnd));
m_nCurrentAddress = nOffset;
m_bHighBits = bHighBits;
if((m_pData == NULL) || (m_nLength == NULL) ) {
return;
}
if(m_bRecalc) {
CalculatePaintingDetails(CClientDC(this));
}
if(m_nCurrentAddress < m_nScrollPostionY*m_tPaintDetails.nBytesPerRow
|| (m_nCurrentAddress >= (m_nScrollPostionY + m_tPaintDetails.nVisibleLines)*m_tPaintDetails.nBytesPerRow) ) {
// not in the visible range
DestoyEditCaret();
return;
}
if(GetFocus() != this) {
// in case we missed once something...
DestoyEditCaret();
return;
}
UINT nRelAdr = m_nCurrentAddress - m_nScrollPostionY*m_tPaintDetails.nBytesPerRow;
UINT nRow = nRelAdr / m_tPaintDetails.nBytesPerRow;
UINT nColumn = nRelAdr % m_tPaintDetails.nBytesPerRow;
UINT nCarretHeight;
UINT nCarretWidth = m_tPaintDetails.nCharacterWidth;
if(nRow == m_tPaintDetails.nVisibleLines-1) {
// last row can be only half visible
nCarretHeight = m_tPaintDetails.nLastLineHeight;
} else {
nCarretHeight = m_tPaintDetails.nLineHeight;
}
CPoint cCarretPoint(m_tPaintDetails.cPaintingRect.left
- m_nScrollPostionX + m_tPaintDetails.nHexPos
+ (nColumn * 3 + (bHighBits ? 0 : 1)) * m_tPaintDetails.nCharacterWidth,
m_tPaintDetails.cPaintingRect.top + 1 + nRow * m_tPaintDetails.nLineHeight);
if( (cCarretPoint.x + (short)m_tPaintDetails.nCharacterWidth <= m_tPaintDetails.cPaintingRect.left-2 )
|| (cCarretPoint.x > m_tPaintDetails.cPaintingRect.right) ) {
// we can't see it
DestoyEditCaret();
return;
}
if(cCarretPoint.x < m_tPaintDetails.cPaintingRect.left-2) {
nCarretWidth -= m_tPaintDetails.cPaintingRect.left-2 - cCarretPoint.x;
cCarretPoint.x = m_tPaintDetails.cPaintingRect.left-2;
}
if(cCarretPoint.x + (int)nCarretWidth > (int)m_tPaintDetails.cPaintingRect.right+2) {
nCarretWidth = m_tPaintDetails.cPaintingRect.right + 2 - cCarretPoint.x;
}
CreateEditCaret(nCarretHeight-1, nCarretWidth);
SetCaretPos(cCarretPoint);
ShowCaret();
}
void CHexEditBase::CreateEditCaret(UINT nCaretHeight, UINT nCaretWidth)
{
if(!m_bHasCaret || (nCaretHeight != m_nCurCaretHeight)
|| (nCaretWidth != m_nCurCaretWidth) ) {
m_bHasCaret = true;
m_nCurCaretHeight = nCaretHeight;
m_nCurCaretWidth = nCaretWidth;
CreateSolidCaret(m_nCurCaretWidth, m_nCurCaretHeight);
}
}
void CHexEditBase::DestoyEditCaret() {
m_bHasCaret = false;
DestroyCaret();
}
UINT CHexEditBase::OnGetDlgCode()
{
return DLGC_WANTALLKEYS;
}
BOOL CHexEditBase::PreCreateWindow(CREATESTRUCT& cs)
{
return CWnd::PreCreateWindow(cs);
}
BOOL CHexEditBase::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
if(!CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext)) {
return FALSE;
}
return TRUE;
}
BOOL CHexEditBase::OnEraseBkgnd(CDC*)
{
return TRUE;
}
void CHexEditBase::OnLButtonDown(UINT, CPoint point)
{
SetFocus();
if(m_pData == NULL) {
return;
}
GetAddressFromPoint(point, m_nCurrentAddress, m_bHighBits);
SetEditCaretPos(m_nCurrentAddress, m_bHighBits);
int iDragCX = GetSystemMetrics(SM_CXDRAG);
int iDragCY = GetSystemMetrics(SM_CYDRAG);
m_cDragRect = CRect(point.x - (iDragCX>>1), point.y - (iDragCY>>1),
point.x + (iDragCX>>1) + (iDragCX&1), //(we don't want to loose a pixel, when it's so small)
point.y + (iDragCY>>1) + (iDragCY&1));
m_nSelectingEnd = NOSECTION_VAL;
m_nSelectionBegin = NOSECTION_VAL;
m_nSelectingEnd = NOSECTION_VAL;
m_nSelectingBeg = m_nCurrentAddress;
SetCapture();
}
void CHexEditBase::OnLButtonUp(UINT, CPoint)
{
if(GetCapture() == this) {
ReleaseCapture();
}
StopMouseRepeat(); // in case it's started, otherwise it doesn't matter either
Invalidate();
}
void CHexEditBase::OnLButtonDblClk(UINT, CPoint point)
{
SetFocus();
if(m_pData == NULL) {
return;
}
GetAddressFromPoint(point, m_nCurrentAddress, m_bHighBits);
SetEditCaretPos(m_nCurrentAddress, m_bHighBits);
if( (m_nHighlightedBegin <= m_nCurrentAddress)
&& (m_nHighlightedEnd >= m_nCurrentAddress) ) {
// well it's christmas and we can doubleclick the highlighted section ;)
m_nSelectionEnd = m_nHighlightedEnd;
m_nSelectionBegin = m_nHighlightedBegin;
} else {
// or just a whole byte
m_nSelectionEnd = m_nCurrentAddress;
m_nSelectionBegin = m_nCurrentAddress;
}
Invalidate();
}
void CHexEditBase::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_pData == NULL) {
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -