// XTPHexEdit.cpp : implementation of the CXTPHexEdit class. // // This file is a part of the XTREME CONTROLS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "../Resource.h" #include "Common/XTPVC80Helpers.h" // Visual Studio 2005 helper functions #include "Common/XTPResourceManager.h" #include "Common/XTPColorManager.h" #include "Common/XTPDrawHelpers.h" #include "../Util/XTPFunctions.h" #include "XTPHexEdit.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static const CLIPFORMAT CF_BINARY = (CLIPFORMAT) ::RegisterClipboardFormat(_T("BinaryData")); static const BYTE chHexTable[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; #define TOHEX(a, b) {*b++ = chHexTable[a >> 4]; *b++ = chHexTable[a & 0xf];} ///////////////////////////////////////////////////////////////////////////// // CXTPHexEdit ///////////////////////////////////////////////////////////////////////////// CXTPHexEdit::CXTPHexEdit() { m_pData = NULL; m_nLength = 0; m_nTopIndex = 0; m_nCurrentAddress = 0; m_nSelStart = -1; m_nSelEnd = -1; m_nBytePerRow = 8; m_bDynamicBPR = FALSE; m_nLinesPerPage = 1; m_nLineHeight = 0; m_nNullWidth = 0; m_nOffHex = 0; m_nOffAscii = 0; m_nOffAddress = 0; m_bShowHex = TRUE; m_bShowAscii = TRUE; m_bShowAddress = TRUE; m_bAddressIsWide = TRUE; m_bShowCaret = TRUE; m_bUpdate = TRUE; m_bAllowDeletes = true; m_ptEditPos.x = 0; m_ptEditPos.y = 0; m_eEditMode = editNone; m_szCaret = CSize(0, 0); m_crBack = GetXtremeColor(COLOR_WINDOW); m_crText = GetXtremeColor(COLOR_WINDOWTEXT); m_crDisabledBack = GetXtremeColor(COLOR_3DFACE); m_crDisabledText = GetXtremeColor(COLOR_GRAYTEXT); m_crHighlightBack = GetXtremeColor(COLOR_HIGHLIGHT); m_crHighlightText = GetXtremeColor(COLOR_HIGHLIGHTTEXT); m_crDisabledHighlightText = GetXtremeColor(COLOR_HIGHLIGHTTEXT); m_crDisabledHighlightBack = GetXtremeColor(COLOR_3DSHADOW); m_nMaxLength = 0; m_dwBaseAddress = 0; _AFX_THREAD_STATE* pState = AfxGetThreadState(); if (!pState->m_bNeedTerm) { AfxOleInit(); } // create the default font used by the hex edit control. m_fontHex.CreateFont(-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _T("Courier New")); } CXTPHexEdit::~CXTPHexEdit() { if (m_fontHex.GetSafeHandle()) m_fontHex.DeleteObject(); if (m_pData) { free(m_pData); m_pData = NULL; } } IMPLEMENT_DYNAMIC(CXTPHexEdit, CWnd) BEGIN_MESSAGE_MAP(CXTPHexEdit, CXTPHexEditBase) //{{AFX_MSG_MAP(CXTPHexEdit) ON_WM_CHAR() ON_WM_KILLFOCUS() ON_WM_PAINT() ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient) ON_WM_SETFOCUS() ON_WM_SIZE() ON_WM_VSCROLL() ON_WM_HSCROLL() ON_WM_GETDLGCODE() ON_WM_ERASEBKGND() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONDBLCLK() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_WM_KEYDOWN() ON_WM_CONTEXTMENU() ON_COMMAND(ID_EDIT_CLEAR, OnEditClear) ON_COMMAND(ID_EDIT_COPY, OnEditCopy) ON_COMMAND(ID_EDIT_CUT, OnEditCut) ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) ON_WM_NCPAINT() ON_WM_MOUSEWHEEL() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CXTPHexEdit::RestoreDefaultFont() { if (m_fontHex.GetSafeHandle()) m_fontHex.DeleteObject(); // create the default font used by the hex edit control. m_fontHex.CreateFont(-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _T("Courier New")); } void CXTPHexEdit::SetHexFont(CFont* pFont) { ASSERT(pFont->GetSafeHandle()); if (pFont->GetSafeHandle()) { LOGFONT lf; pFont->GetLogFont(&lf); SetHexFont(&lf); } } void CXTPHexEdit::SetHexFont(LOGFONT* pLogFont) { ASSERT(pLogFont != NULL); if (m_fontHex.GetSafeHandle()) m_fontHex.DeleteObject(); m_fontHex.CreateFontIndirect(pLogFont); } COLORREF CXTPHexEdit::GetActualBackColor() { #ifdef _XTP_ACTIVEX if (!IsWindowEnabled()) #else if (IsReadOnly()) #endif { return m_crDisabledBack; } return m_crBack; } COLORREF CXTPHexEdit::GetActualTextColor() { if (!IsWindowEnabled()) { return m_crDisabledText; } return m_crText; } COLORREF CXTPHexEdit::GetActualHighlightBackColor() { if (!IsWindowEnabled()) { return m_crDisabledHighlightBack; } return m_crHighlightBack; } COLORREF CXTPHexEdit::GetActualHighlightTextColor() { if (!IsWindowEnabled()) { return m_crDisabledHighlightText; } return m_crHighlightText; } void CXTPHexEdit::OnPaint() { CPaintDC dc(this); // Paint to a memory device context to help // eliminate screen flicker. CXTPBufferDC memDC(dc); OnDraw(&memDC); } LRESULT CXTPHexEdit::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/) { CDC* pDC = CDC::FromHandle((HDC)wParam); if (pDC) { OnDraw(pDC); } return 1; } void CXTPHexEdit::OnDraw(CDC* pDC) { // Get the client rect. CXTPClientRect rectClient(this); pDC->FillSolidRect(rectClient, GetActualBackColor()); // Save the current device context, we will restore this just // before we loose scope. int nSavedDC = pDC->SaveDC(); ASSERT(m_nCurrentAddress >= 0); ASSERT(m_nTopIndex >= 0); pDC->SelectObject(&m_fontHex); int height = 0; int x = rectClient.TopLeft().x; int y = rectClient.TopLeft().y; TCHAR buf[256]; pDC->SetBoundsRect(&rectClient, DCB_DISABLE); pDC->SetTextColor(GetActualTextColor()); // Get char dimensions if (m_bUpdate) { const int h_delta = ::GetScrollPos(m_hWnd, SB_HORZ) * m_nNullWidth; pDC->GetCharWidth('0', '0', &m_nNullWidth); CSize sz = pDC->GetTextExtent(_T("0"), 1); m_nLineHeight = sz.cy; const int width_address = (m_bAddressIsWide ? 9 : 5) * m_nNullWidth; m_nOffHex = m_bShowAddress ? width_address : 0; m_nOffAscii = m_nOffHex; if (m_bShowHex) m_nOffAscii += m_nBytePerRow * 3 * m_nNullWidth; m_nOffAddress = -h_delta; m_nOffHex -= h_delta; m_nOffAscii -= h_delta; m_nLinesPerPage = rectClient.Height() / m_nLineHeight; m_bUpdate = FALSE; UpdateScrollbars(); } if (m_pData) { height = rectClient.Height() / m_nLineHeight; height *= m_nLineHeight; if (m_bShowAddress) { y = 0; CRect rcd = rectClient; rcd.left = m_nOffAddress; // draw address int i; for (i = m_nTopIndex; (i < (m_nLength + 1)) && (rcd.TopLeft().y < height); i += m_nBytePerRow) { const int width = m_bAddressIsWide ? 8 : 4; #if (_MSC_VER > 1310) // VS2005 _stprintf_s(buf, _countof(buf), _T("%0*lX"), width, m_dwBaseAddress + i); #else _stprintf(buf, _T("%0*lX"), width, m_dwBaseAddress + i); #endif pDC->DrawText(buf, width, rcd, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX); rcd.TopLeft().y += m_nLineHeight; } } if (m_bShowHex) { y = 0; CRect rcd = rectClient; rcd.left = x = m_nOffHex; if (m_nSelStart != -1 && (m_eEditMode == editHigh || m_eEditMode == editLow)) { int i; int n = 0; int selStart, selEnd; GetSel(selStart, selEnd); for (i = m_nTopIndex; (i < selStart) && (y < height); i++) { LPTSTR p = &buf[0]; TOHEX(m_pData[i], p); *p++ = ' '; pDC->TextOut(x, y, buf, 3); x += m_nNullWidth * 3; n++; if (n == m_nBytePerRow) { n = 0; x = m_nOffHex; y += m_nLineHeight; } } pDC->SetTextColor(GetActualHighlightTextColor()); pDC->SetBkColor(GetActualHighlightBackColor()); for (; (i < selEnd) && (i < m_nLength) && (y < height); i++) { LPTSTR p = &buf[0]; TOHEX(m_pData[i], p); *p++ = ' '; pDC->TextOut(x, y, buf, 3); x += m_nNullWidth * 3; n++; if (n == m_nBytePerRow) { n = 0; x = m_nOffHex; y += m_nLineHeight; } } pDC->SetTextColor(GetActualTextColor()); pDC->SetBkColor(GetActualBackColor()); for (; (i < m_nLength) && (y < height); i++) { LPTSTR p = &buf[0]; TOHEX(m_pData[i], p); *p++ = ' '; pDC->TextOut(x, y, buf, 3); x += m_nNullWidth * 3; n++; if (n == m_nBytePerRow) { n = 0; x = m_nOffHex; y += m_nLineHeight; } } } else { int i; for (i = m_nTopIndex; (i < m_nLength) && (rcd.TopLeft().y < height);) { LPTSTR p = &buf[0]; int n; for (n = 0; (n < m_nBytePerRow) && (i < m_nLength); n++) { TOHEX(m_pData[i], p); *p++ = ' '; i++; } while (n < m_nBytePerRow) { *p++ = ' '; *p++ = ' '; *p++ = ' '; n++; } pDC->DrawText(buf, m_nBytePerRow * 3, rcd, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX); rcd.TopLeft().y += m_nLineHeight; } } } if (m_bShowAscii) { y = 0; CRect rcd = rectClient; rcd.left = x = m_nOffAscii; if (m_nSelStart != -1 && m_eEditMode == editAscii) { int i; int n = 0; int selStart, selEnd; GetSel(selStart, selEnd); for (i = m_nTopIndex; (i < selStart) && (y < height); i++) { buf[0] = isprint(m_pData[i]) ? m_pData[i] : '.'; pDC->TextOut(x, y, buf, 1); x += m_nNullWidth; n++; if (n == m_nBytePerRow) { n = 0; x = m_nOffAscii; y += m_nLineHeight; } } pDC->SetTextColor(GetActualHighlightTextColor()); pDC->SetBkColor(GetActualHighlightBackColor()); for (; (i < selEnd) && (y < height); i++) { buf[0] = isprint(m_pData[i]) ? m_pData[i] : '.'; pDC->TextOut(x, y, buf, 1); x += m_nNullWidth; n++; if (n == m_nBytePerRow) { n = 0; x = m_nOffAscii; y += m_nLineHeight; } } pDC->SetTextColor(GetActualTextColor()); pDC->SetBkColor(GetActualBackColor()); for (; (i < m_nLength) && y < height; i++) { buf[0] = isprint(m_pData[i]) ? m_pData[i] : '.'; pDC->TextOut(x, y, buf, 1); x += m_nNullWidth; n++; if (n == m_nBytePerRow) { n = 0; x = m_nOffAscii; y += m_nLineHeight; } } } else { int i; for (i = m_nTopIndex; (i < m_nLength) && (rcd.top < height);) { LPTSTR p = &buf[0]; int n; for (n = 0; (n < m_nBytePerRow) && (i < m_nLength); n++) { *p++ = isprint(m_pData[i]) ? m_pData[i] : '.'; i++; } pDC->DrawText(buf, n, rcd, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX); rcd.top += m_nLineHeight; } } } } // Restore the device context. pDC->RestoreDC(nSavedDC); } void CXTPHexEdit::OnSetFocus(CWnd* pOldWnd) { CXTPHexEditBase::OnSetFocus(pOldWnd); if (m_pData && !IsSelected()) { if (m_ptEditPos.x == 0 && m_bShowAddress) { CreateAddressCaret(); } else { CreateEditCaret(); } RepositionCaret(m_nCurrentAddress); } } void CXTPHexEdit::OnKillFocus(CWnd* pNewWnd) { DestroyCaret(); CXTPHexEditBase::OnKillFocus(pNewWnd); } void CXTPHexEdit::OnVScroll(UINT nSBCode, UINT /*nPos*/, CScrollBar* /*pScrollBar*/) { DoVScroll(nSBCode, false); } void CXTPHexEdit::DoVScroll(UINT nSBCode, bool bMoveCaret) { if (!m_pData) { return; } BOOL bVisible = GetStyle() & WS_VISIBLE; // Turn off redraw while scrolling, this will cause paint problems // with our control because we are painting off screen to reduce // flicker. The default implementation assumes that WM_ERASEBKGND // has repainted the background, which in our case does not happen. if (bVisible) SetRedraw(FALSE); const int oa = m_nTopIndex; SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; if (GetStyle() & WS_VSCROLL) { VERIFY(::GetScrollInfo(m_hWnd, SB_VERT, &si)); } else { si.nPage = si.nPos = si.nMin = si.nMax = 0; } switch (nSBCode) { case SB_LINEDOWN: if (si.nPos < (si.nMax - (int)si.nPage + 1)) { m_nTopIndex += m_nBytePerRow; } break; case SB_LINEUP: if (m_nTopIndex > 0) { m_nTopIndex -= m_nBytePerRow; if (m_nTopIndex < 0) m_nTopIndex = 0; } break; case SB_PAGEDOWN: si.nPos += si.nPage; if (si.nPos >= si.nMax) si.nPos = si.nMax; m_nTopIndex = si.nPos * m_nBytePerRow; break; case SB_PAGEUP: if (oa == 0) { m_nCurrentAddress = 0; } else { m_nTopIndex -= m_nBytePerRow * m_nLinesPerPage; if (m_nTopIndex < 0) m_nTopIndex = 0; } break; case SB_THUMBTRACK: si.fMask = SIF_TRACKPOS; // Call GetScrollInfo to get current tracking // position in si.nTrackPos if (!::GetScrollInfo(m_hWnd, SB_VERT, &si)) { return ; // GetScrollInfo failed } m_nTopIndex = si.nTrackPos * m_nBytePerRow; break; } if (bMoveCaret) { m_nCurrentAddress += (m_nTopIndex - oa); } // bug fix by John M. Drescher jdrescher@geocities.com if (m_nCurrentAddress < 0) { m_nCurrentAddress = 0; } UpdateScrollbars(); RepositionCaret(m_nCurrentAddress); if (bVisible) SetRedraw(TRUE); // repaint the list box Invalidate(); UpdateWindow(); // repaint the scroll bar. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); } BOOL CXTPHexEdit::PreCreateWindow(CREATESTRUCT& cs) { if (!CXTPHexEditBase::PreCreateWindow(cs)) return FALSE; return TRUE; } BOOL CXTPHexEdit::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { return Create(_T("EDIT"), 0, dwStyle, rect, pParentWnd, nID); } BOOL CXTPHexEdit::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)) { TRACE0("Failed to create hex edit control.\n"); return FALSE; } CWnd::SetFont(&m_fontHex); return TRUE; } BOOL CXTPHexEdit::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } void CXTPHexEdit::OnLButtonDown(UINT nFlags, CPoint point) { SetFocus(); if (!m_pData) { return; } if (nFlags & MK_SHIFT) { m_nSelStart = m_nCurrentAddress; } CPoint pt = CalcPos(point.x, point.y); if (pt.x > -1) { m_ptEditPos = pt; pt.x *= m_nNullWidth; pt.y *= m_nLineHeight; if (pt.x == 0 && m_bShowAddress) { CreateAddressCaret(); } else { CreateEditCaret(); } SetCaretPos(pt); if (nFlags & MK_SHIFT) { m_nSelEnd = m_nCurrentAddress; if (m_eEditMode == editHigh || m_eEditMode == editLow) { m_nSelEnd++; } RedrawWindow(); } } if (!(nFlags & MK_SHIFT)) { if (::DragDetect(m_hWnd, point)) { m_nSelStart = m_nCurrentAddress; m_nSelEnd = m_nSelStart; SetCapture(); } else { BOOL bsel = m_nSelStart != -1; m_nSelStart = -1; m_nSelEnd = -1; if (bsel) { RedrawWindow(); } } } if (!IsSelected()) { if (m_bShowCaret) ShowCaret(); } } // in: pixels // out: character coordinates + change of m_nCurrrentAddress CPoint CXTPHexEdit::CalcPos(int x, int y) { if (y < 0 || x < 0) return CPoint(-1, -1); int lastVisRow = m_nLength / m_nBytePerRow - (m_nTopIndex / m_nBytePerRow); int row = y / m_nLineHeight; y = row + (m_nTopIndex / m_nBytePerRow); // x += (m_nNullWidth - 1); x /= m_nNullWidth; //In address area const int right_of_address = (m_nOffAddress / m_nNullWidth) + // one past last (!m_bShowAddress ? -1 : (m_bAddressIsWide ? 8 : 4)); if (x < right_of_address) { //Set first byte in line as current. m_nCurrentAddress = m_nTopIndex + (m_nBytePerRow * row); m_eEditMode = editNone; return CPoint(0, row); } //In hex area const int right_of_hex_area = right_of_address + (!m_bShowHex ? 0 : (m_nBytePerRow * 3)); //3 = 3 chars per byte (e.g. cc) if (m_bShowHex && x < right_of_hex_area) { if ((x % 3) == 2) { ++x; } const int col = (x - right_of_address) / 3; m_nCurrentAddress = m_nTopIndex + (m_nBytePerRow * row) + col; if (m_nCurrentAddress > m_nLength) // past end ? { x = m_nLength % m_nBytePerRow; row = lastVisRow; x *= 3; x += (right_of_address + 1); m_nCurrentAddress = m_nLength; } m_eEditMode = ((x % 3) == 0) ? editHigh : editLow; return CPoint(x, row); } const int right_of_ascii_area = right_of_hex_area + m_nBytePerRow + 1; if (m_bShowAscii && x < right_of_ascii_area) { if (x == right_of_hex_area) ++x; // advance from margin const int col = x - right_of_hex_area - 1; m_nCurrentAddress = m_nTopIndex + (m_nBytePerRow * row) + col; if (m_nCurrentAddress > m_nLength) // past end ? { x = m_nLength % m_nBytePerRow; row = lastVisRow; x += (right_of_hex_area + 1); m_nCurrentAddress = m_nLength; } m_eEditMode = editAscii; return CPoint(x, row); } return CPoint(-1, -1); } void CXTPHexEdit::CreateAddressCaret() { DestroyCaret(); m_szCaret = CSize(m_nNullWidth * (m_bAddressIsWide ? 8 : 4), m_nLineHeight); CreateSolidCaret(m_szCaret.cx, m_szCaret.cy); } void CXTPHexEdit::CreateEditCaret() { DestroyCaret(); m_szCaret = CSize(m_nNullWidth, m_nLineHeight); CreateSolidCaret(m_szCaret.cx, m_szCaret.cy); } void CXTPHexEdit::OnMouseMove(UINT nFlags, CPoint point) { if (!m_pData) { return; } if (nFlags & MK_LBUTTON && m_nSelStart != -1) { CRect rc; GetClientRect(&rc); if (!rc.PtInRect(point)) { if (point.y < 0) { DoVScroll(SB_LINEUP, true); point.y = 0; } else if (point.y > rc.Height()) { DoVScroll(SB_LINEDOWN, true); point.y = rc.Height() -1; } } // // we are selecting // int seo = m_nSelEnd; CPoint pt = CalcPos(point.x, point.y); if (pt.x > -1) { m_nSelEnd = m_nCurrentAddress; if (m_eEditMode == editHigh || m_eEditMode == editLow) { m_nSelEnd++; } } if (IsSelected()) { DestroyCaret(); } if (seo != m_nSelEnd) { RedrawWindow(); } } } void CXTPHexEdit::UpdateScrollbars() { DWORD dwStyle = GetStyle(); SCROLLINFO si; si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; if (dwStyle & WS_VSCROLL) { bool bDisable = false; si.nMin = 0; si.nMax = m_nLength / m_nBytePerRow - 1; // - m_nLinesPerPage + 1; if (si.nMax < m_nLinesPerPage - 1) { si.nMax = 1; si.nPage = 1; bDisable = true; if (m_nTopIndex) { m_nTopIndex = 0; RepositionCaret(m_nCurrentAddress); } } else { si.nPage = m_nLinesPerPage - 1; while (m_nTopIndex / m_nBytePerRow > (si.nMax - m_nLinesPerPage + 2) && m_nTopIndex > 0) { m_nTopIndex -= m_nBytePerRow; RepositionCaret(m_nCurrentAddress); } } if (m_nTopIndex < 0) m_nTopIndex = 0; si.nPos = m_nTopIndex / m_nBytePerRow; ModifyStyle(0, WS_VSCROLL); if (!bDisable) { SetScrollInfo(SB_VERT, &si, TRUE); EnableScrollBar(SB_VERT, ESB_ENABLE_BOTH); } else { si.nMax = si.nMin + 1; si.nPage = si.nPos = 0; SetScrollInfo(SB_VERT, &si, TRUE); EnableScrollBar(SB_VERT, ESB_DISABLE_BOTH); } } if (dwStyle & (WS_HSCROLL | ES_AUTOHSCROLL)) { CRect rc; GetClientRect(&rc); si.nMin = 0; si.nMax = ((m_bShowAddress ? (m_bAddressIsWide ? 9 : 5) : 0) + (m_bShowHex ? m_nBytePerRow * 3 : 0) + (m_bShowAscii ? m_nBytePerRow : 0)); si.nPage = m_nNullWidth == 0 ? 1 : __min(rc.Width() / m_nNullWidth, si.nMax); si.nPos = 0; BOOL bVisible = si.nMax * m_nNullWidth >= (int)rc.Width(); if (dwStyle & ES_AUTOHSCROLL) { ShowScrollBar(SB_HORZ, bVisible); } si.fMask &= ~SIF_POS; SetScrollInfo(SB_HORZ, &si, TRUE); if (bVisible && ((dwStyle & ES_AUTOHSCROLL) == 0)) { EnableScrollBar(SB_HORZ, ESB_ENABLE_BOTH); } } } void CXTPHexEdit::OnLButtonUp(UINT nFlags, CPoint point) { if (IsSelected()) { ReleaseCapture(); } CWnd::OnLButtonUp(nFlags, point); } BOOL CXTPHexEdit::IsReadOnly() const { if (!IsWindowEnabled() || (GetStyle() & ES_READONLY) == ES_READONLY) { return TRUE; } return FALSE; } void CXTPHexEdit::OnChar(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) { if (!m_pData) { return; } if (m_nCurrentAddress < 0) //Shouldn't happen { return; } if (nChar == '\t') { return; } if (::GetKeyState(VK_CONTROL) < 0) { switch (nChar) { case 0x03: if (IsSelected()) { OnEditCopy(); } return; case 0x16: OnEditPaste(); return; case 0x18: if (IsSelected()) { OnEditCut(); } return; case 0x1a: OnEditUndo(); return; } } if (IsReadOnly()) { return; } if (nChar == 0x08) // backspace { if (GetAllowDeletes()) { if (IsSelected()) { OnEditClear(); } else if (m_nCurrentAddress > 0) { m_nCurrentAddress--; SelDelete(m_nCurrentAddress, m_nCurrentAddress + 1); RepositionCaret(m_nCurrentAddress); RedrawWindow(); OnChange(); } else { MessageBeep(0); } } return; } // can't go past end of buffer if ((UINT)m_nCurrentAddress >= m_nMaxLength) { MessageBeep(0); return; } if (m_eEditMode != editNone) { // see if need to grow the buffer if (m_nCurrentAddress >= m_nLength) { int iNewLength = (m_nLength + 1); LPBYTE p = (LPBYTE) calloc(iNewLength, 1); MEMCPY_S(p, m_pData, m_nLength); free(m_pData); m_pData = p; SetSel(-1, -1); m_nLength = iNewLength; m_bUpdate = TRUE; } } SetSel(-1, -1); switch (m_eEditMode) { case editNone: return; case editHigh: case editLow: if (isxdigit(nChar)) { UINT b = 0; if (nChar >= 'a') b = 10 + nChar - 'a'; else if (nChar >= 'A') b = 10 + nChar - 'A'; else if (nChar >= '0') b = nChar - '0'; else break; if (b >= 16) break; if (m_eEditMode == editHigh) { m_pData[m_nCurrentAddress] = (unsigned char)((m_pData[m_nCurrentAddress] & 0x0f) | (b << 4)); } else { m_pData[m_nCurrentAddress] = (unsigned char)((m_pData[m_nCurrentAddress] & 0xf0) | b); } Move(1, 0); OnChange(); } break; case editAscii: m_pData[m_nCurrentAddress] = (unsigned char)nChar; Move(1, 0); OnChange(); break; } RedrawWindow(); } void CXTPHexEdit::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) { BOOL bShift = (::GetKeyState(VK_SHIFT) < 0); switch (nChar) { case VK_DOWN: if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } Move(0, 1); m_nSelEnd = m_nCurrentAddress; if (m_eEditMode == editHigh || m_eEditMode == editLow) { m_nSelEnd++; } RedrawWindow(); break; } else { SetSel(-1, -1); } Move(0, 1); break; case VK_UP: if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } Move(0, -1); m_nSelEnd = m_nCurrentAddress; RedrawWindow(); break; } else { SetSel(-1, -1); } Move(0, -1); break; case VK_LEFT: if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } Move(-1, 0); m_nSelEnd = m_nCurrentAddress; RedrawWindow(); break; } else { SetSel(-1, -1); } Move(-1, 0); break; case VK_RIGHT: if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } Move(1, 0); m_nSelEnd = m_nCurrentAddress; if (m_eEditMode == editHigh || m_eEditMode == editLow) { m_nSelEnd++; } RedrawWindow(); break; } else { SetSel(-1, -1); } Move(1, 0); break; case VK_PRIOR: if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } DoVScroll(SB_PAGEUP, true); Move(0, 0); m_nSelEnd = m_nCurrentAddress; RedrawWindow(); break; } else { SetSel(-1, -1); } DoVScroll(SB_PAGEUP, true); Move(0, 0); break; case VK_NEXT: if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } DoVScroll(SB_PAGEDOWN, true); Move(0, 0); m_nSelEnd = m_nCurrentAddress; RedrawWindow(); break; } else { SetSel(-1, -1); } DoVScroll(SB_PAGEDOWN, true); Move(0, 0); break; case VK_HOME: if (m_eEditMode == editLow) { m_eEditMode = editHigh; } if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } if (::GetKeyState(VK_CONTROL) < 0) { DoVScroll(SB_THUMBTRACK, true); Move(0, 0); } else { m_nCurrentAddress /= m_nBytePerRow; m_nCurrentAddress *= m_nBytePerRow; Move(0, 0); } m_nSelEnd = m_nCurrentAddress; RedrawWindow(); break; } else { SetSel(-1, -1); } if (::GetKeyState(VK_CONTROL) < 0) { m_nTopIndex = m_nCurrentAddress = 0; UpdateScrollbars(); RepositionCaret(m_nCurrentAddress); RedrawWindow(); } else { m_nCurrentAddress /= m_nBytePerRow; m_nCurrentAddress *= m_nBytePerRow; Move(0, 0); } break; case VK_END: if (m_eEditMode == editLow) { m_eEditMode = editHigh; } if (bShift) { if (!IsSelected()) { m_nSelStart = m_nCurrentAddress; } if (::GetKeyState(VK_CONTROL) < 0) { m_nCurrentAddress = m_nLength-1; DoVScroll(SB_PAGEDOWN, false); Move(0, 0); } else { m_nCurrentAddress /= m_nBytePerRow; m_nCurrentAddress *= m_nBytePerRow; m_nCurrentAddress += m_nBytePerRow - 1; if (m_nCurrentAddress > m_nLength) { m_nCurrentAddress = m_nLength; } Move(0, 0); } m_nSelEnd = m_nCurrentAddress; RedrawWindow(); break; } else { SetSel(-1, -1); } if (::GetKeyState(VK_CONTROL) < 0) { m_nCurrentAddress = m_nLength; DoVScroll(SB_PAGEDOWN, false); Move(0, 0); } else { m_nCurrentAddress /= m_nBytePerRow; m_nCurrentAddress *= m_nBytePerRow; m_nCurrentAddress += m_nBytePerRow - 1; if (m_nCurrentAddress > m_nLength) m_nCurrentAddress = m_nLength; Move(0, 0); } break; case VK_INSERT: if (IsReadOnly()) break; SelInsert(m_nCurrentAddress, __max(1, m_nSelEnd-m_nSelStart)); RepositionCaret(m_nCurrentAddress); OnChange(); RedrawWindow(); break; case VK_DELETE: if (IsReadOnly()) break; if (GetAllowDeletes()) { if (IsSelected()) { OnEditClear(); } else { if (m_nCurrentAddress < m_nLength) { SelDelete(m_nCurrentAddress, m_nCurrentAddress + 1); RedrawWindow(); OnChange(); } else { MessageBeep(0); } } } break; case VK_TAB: { int next_win_sel = 0; switch (m_eEditMode) { case editNone: m_eEditMode = editHigh; break; case editHigh: case editLow: if (bShift) { next_win_sel = GW_HWNDPREV; } else { m_eEditMode = editAscii; } break; case editAscii: if (bShift) { m_eEditMode = editHigh; } else { next_win_sel = GW_HWNDNEXT; } break; } if (next_win_sel) { CWnd *pWnd = this; for (;;) { pWnd = pWnd->GetNextWindow(next_win_sel); if (pWnd == this) { break; } if (pWnd == NULL) { if (next_win_sel == GW_HWNDNEXT) { pWnd = GetNextWindow(GW_HWNDFIRST); } else { pWnd = GetNextWindow(GW_HWNDLAST); } } if (pWnd->GetStyle() & WS_TABSTOP) { pWnd->SetFocus(); break; } if (pWnd == this) { m_eEditMode = editHigh; Move(0, 0); break; } } } else { Move(0, 0); } break; } } } void CXTPHexEdit::Move(int x, int y) { switch (m_eEditMode) { case editNone: return; case editHigh: if (x != 0) m_eEditMode = editLow; if (x == -1) m_nCurrentAddress--; m_nCurrentAddress += y * m_nBytePerRow; break; case editLow: if (x != 0) m_eEditMode = editHigh; if (x == 1) m_nCurrentAddress++; m_nCurrentAddress += y * m_nBytePerRow; break; case editAscii: { m_nCurrentAddress += x; m_nCurrentAddress += y * m_nBytePerRow; } break; } if (m_nCurrentAddress < 0) { m_nCurrentAddress = 0; } if (m_nCurrentAddress >= m_nLength) { m_nCurrentAddress = m_nLength; } if ((x | y) != 0 && m_nCurrentAddress < m_nTopIndex) { DoVScroll(SB_LINEUP, false); } if ((x | y) != 0 && m_nCurrentAddress >= m_nTopIndex + m_nLinesPerPage * m_nBytePerRow) { DoVScroll(SB_LINEDOWN, false); } //ScrollIntoView(m_nCurrentAddress); RepositionCaret(m_nCurrentAddress); } void CXTPHexEdit::SetSel(int nSelStart, int nSelEnd) { #ifdef _DEBUG _CrtCheckMemory(); #endif if (GetFocus() == this) DestroyCaret(); m_nSelStart = nSelStart; m_nSelEnd = nSelEnd; if (!IsWindow(m_hWnd)) return; RedrawWindow(); if (GetFocus() == this) { if (m_ptEditPos.x == 0 && m_bShowAddress) { CreateAddressCaret(); } else { CreateEditCaret(); } RepositionCaret(m_nCurrentAddress); if (m_bShowCaret) ShowCaret(); } } void CXTPHexEdit::RepositionCaret(int p) { if (GetFocus() != this) return; int x, y; y = (p - m_nTopIndex) / m_nBytePerRow; x = (p - m_nTopIndex) % m_nBytePerRow; switch (m_eEditMode) { case editNone: CreateAddressCaret(); x = m_nOffAddress; break; case editHigh: CreateEditCaret(); x *= m_nNullWidth * 3; x += m_nOffHex; break; case editLow: CreateEditCaret(); x *= m_nNullWidth * 3; x += m_nNullWidth; x += m_nOffHex; break; case editAscii: CreateEditCaret(); x *= m_nNullWidth; x += m_nOffAscii; break; } m_ptEditPos.x = x; m_ptEditPos.y = y*m_nLineHeight; CRect rc; GetClientRect(&rc); CRect rcCarret(m_ptEditPos, m_szCaret); CRect rcInt; rcInt.IntersectRect(rcCarret, rc); if (rcInt == rcCarret) { SetCaretPos(m_ptEditPos); if (m_bShowCaret) ShowCaret(); } } void CXTPHexEdit::ScrollIntoView(int p) { if (p < m_nTopIndex || p > m_nTopIndex + m_nLinesPerPage*m_nBytePerRow) { m_nTopIndex = (p/m_nBytePerRow) * m_nBytePerRow; m_nTopIndex -= (m_nLinesPerPage / 3) * m_nBytePerRow; if (m_nTopIndex < 0) { m_nTopIndex = 0; } UpdateScrollbars(); RedrawWindow(); } } void CXTPHexEdit::OnContextMenu(CWnd*, CPoint point) { if (point.x == -1 && point.y == -1) { //keystroke invocation CRect rect; GetClientRect(rect); ClientToScreen(rect); point = rect.TopLeft(); point.Offset(5, 5); } CMenu menu; XTPResourceManager()->LoadMenu(&menu, XTP_IDM_POPUP); CMenu* pPopup = menu.GetSubMenu(1); ASSERT(pPopup != NULL); if (!pPopup) return; const int DISABLE_FLAGS = MF_GRAYED | MF_DISABLED | MF_BYCOMMAND; pPopup->EnableMenuItem(ID_EDIT_UNDO, DISABLE_FLAGS); if (!GetAllowDeletes() || IsReadOnly()) { pPopup->EnableMenuItem(ID_EDIT_CLEAR, DISABLE_FLAGS); pPopup->EnableMenuItem(ID_EDIT_CUT, DISABLE_FLAGS); } if (!IsSelected()) { pPopup->EnableMenuItem(ID_EDIT_CLEAR, DISABLE_FLAGS); pPopup->EnableMenuItem(ID_EDIT_CUT, DISABLE_FLAGS); pPopup->EnableMenuItem(ID_EDIT_COPY, DISABLE_FLAGS); } if (IsReadOnly()) { pPopup->EnableMenuItem(ID_EDIT_PASTE, DISABLE_FLAGS); } else if (OpenClipboard()) { if (!IsClipboardFormatAvailable(CF_TEXT) && !IsClipboardFormatAvailable(CF_BINARY)) { pPopup->EnableMenuItem(ID_EDIT_PASTE, DISABLE_FLAGS); } ::CloseClipboard(); } XTPContextMenu(pPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, XTP_IDR_TBAR_HEXEDIT); } void CXTPHexEdit::OnEditClear() { if (IsReadOnly()) { return; } if (!GetAllowDeletes()) return; NormalizeSel(); m_nCurrentAddress = m_nSelStart; SelDelete(m_nSelStart, m_nSelEnd); RepositionCaret(m_nCurrentAddress); RedrawWindow(); OnChange(); } void CXTPHexEdit::OnEditCopy() { if (!OpenClipboard()) return; NormalizeSel(); ::EmptyClipboard(); const int dwLen = m_nSelEnd - m_nSelStart; HGLOBAL hMemb = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, dwLen); if (!hMemb) { CloseClipboard(); return; } // copy binary ASSERT(hMemb != NULL); LPBYTE p = (BYTE*)::GlobalLock(hMemb); if (!p) return; MEMCPY_S(p, m_pData + m_nSelStart, dwLen); ::GlobalUnlock(hMemb); HGLOBAL hMema = NULL; if (m_eEditMode != editAscii) { hMema = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, dwLen * 3 + 1); if (!hMema) { CloseClipboard(); return; } // copy ascii p = (BYTE*)::GlobalLock(hMema); if (!p) return; int i; for (i = 0; i < dwLen;) { TOHEX(m_pData[m_nSelStart + i], p); *p++ = ' '; i++; } ::GlobalUnlock(hMema); } else { hMema = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, dwLen + 1); if (!hMema) { CloseClipboard(); return; } // copy ascii p = (BYTE*)::GlobalLock(hMema); if (!p) return; MEMCPY_S(p, m_pData + m_nSelStart, dwLen); p[dwLen] = 0; for (int i = 0; i < dwLen; p++, i++) { if (!isprint(*p)) { *p = '.'; } } ::GlobalUnlock(hMema); } ::SetClipboardData(CF_TEXT, hMema); ::SetClipboardData(CF_BINARY, hMemb); VERIFY(CloseClipboard()); } void CXTPHexEdit::OnEditCut() { if (IsReadOnly()) return; OnEditCopy(); SelDelete(m_nSelStart, m_nSelEnd); RedrawWindow(); } void CXTPHexEdit::OnEditPaste() { if (IsReadOnly()) return; if (!OpenClipboard()) return; HGLOBAL hmem = NULL; LPBYTE p = NULL; DWORD dwLen = 0; if (::IsClipboardFormatAvailable(CF_BINARY)) { hmem = ::GetClipboardData(CF_BINARY); p = hmem ? (BYTE*)::GlobalLock(hmem) : NULL; dwLen = hmem ? (DWORD)::GlobalSize(hmem) : 0; } else if (::IsClipboardFormatAvailable(CF_TEXT)) { hmem = ::GetClipboardData(CF_TEXT); p = hmem ? (BYTE*)::GlobalLock(hmem) : NULL; dwLen = p ? (DWORD)strlen((char*)p) : 0; } if (p && dwLen > 0) { int insert; if (m_nCurrentAddress > m_nLength) m_nCurrentAddress = m_nLength; int oa = m_nCurrentAddress; NormalizeSel(); if (m_nSelStart == -1) { if (m_eEditMode == editLow) { m_nCurrentAddress++; } if (m_nCurrentAddress > m_nLength) { m_nCurrentAddress = m_nLength; } insert = m_nCurrentAddress; SelInsert(m_nCurrentAddress, dwLen); } else { insert = m_nSelStart; SelDelete(m_nSelStart, m_nSelEnd); SelInsert(insert, dwLen); SetSel(-1, -1); } if (insert + dwLen > m_nMaxLength) { dwLen = m_nMaxLength - insert; } MEMCPY_S(m_pData + insert, p, dwLen); #ifdef _DEBUG _CrtCheckMemory(); #endif OnChange(); m_nCurrentAddress = oa; RedrawWindow(); } if (hmem) { ::GlobalUnlock(hmem); } ::CloseClipboard(); } void CXTPHexEdit::OnEditSelectAll() { m_nSelStart = 0; m_nSelEnd = m_nLength; DestroyCaret(); RedrawWindow(); } void CXTPHexEdit::OnEditUndo() { } void CXTPHexEdit::NormalizeSel() { if (m_nSelStart > m_nSelEnd) { int nSelStart = m_nSelStart; m_nSelStart = m_nSelEnd; m_nSelEnd = nSelStart; } if (m_nSelStart > m_nLength) { m_nSelStart = m_nLength; } if (m_nSelEnd > m_nLength) { m_nSelEnd = m_nLength; } } void CXTPHexEdit::GetSel(int& nSelStart, int& nSelEnd) { nSelStart = m_nSelStart; nSelEnd = m_nSelEnd; if (nSelStart > nSelEnd) { nSelStart = m_nSelEnd; nSelEnd = m_nSelStart; } if (nSelStart > m_nLength) nSelStart = m_nLength; if (nSelEnd > m_nLength) nSelEnd = m_nLength; } void CXTPHexEdit::OnChange() { CWnd* pOwner = GetOwner(); ASSERT_VALID(pOwner); if (pOwner != NULL) { pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), EN_CHANGE), (LPARAM)m_hWnd); } } void CXTPHexEdit::SelDelete(int nSelStart, int nSelEnd) { if (!GetAllowDeletes()) return; #ifdef _DEBUG _CrtCheckMemory(); #endif if (nSelStart >= m_nLength) return; NormalizeSel(); const int nSelSize = (nSelEnd-nSelStart); const int newLength = m_nLength - nSelSize; if (newLength < 0) return; MEMMOVE_S(m_pData + nSelStart, m_pData + nSelEnd, m_nLength - nSelEnd); SetSel(-1, -1); m_nLength = newLength; if (m_nCurrentAddress > m_nLength) { m_nCurrentAddress = m_nLength; RepositionCaret(m_nCurrentAddress); } m_bUpdate = TRUE; } void CXTPHexEdit::SelInsert(int nSelStart, int nLength) { if ((UINT)(m_nLength + nLength) > m_nMaxLength) { nLength = (int)m_nMaxLength - m_nLength; } if (nLength <= 0) { MessageBeep(0); return; } if (nSelStart > m_nLength) { nSelStart = m_nLength; } LPBYTE p = (LPBYTE) calloc(m_nLength + nLength, 1); MEMCPY_S(p, m_pData, nSelStart); if (m_nLength > nSelStart) { MEMCPY_S(p + nSelStart + nLength, m_pData + nSelStart, (m_nLength - nSelStart)); } free(m_pData); m_pData = p; SetSel(-1, -1); m_nLength = m_nLength + nLength; m_bUpdate = TRUE; } void CXTPHexEdit::SetData(LPBYTE p, int nLength, int nMaxLength) { if (m_pData) free(m_pData); m_pData = (LPBYTE) malloc(nLength); MEMCPY_S(m_pData, p, nLength); SetSel(-1, -1); m_nMaxLength = nMaxLength < 0 ? -1 : __max(nMaxLength, nLength); m_nLength = nLength; m_nCurrentAddress = 0; m_ptEditPos.x = m_ptEditPos.y = 0; m_eEditMode = editHigh; m_nTopIndex = 0; m_bUpdate = TRUE; if (m_hWnd) { UpdateScrollbars(); RepositionCaret(m_nCurrentAddress); RedrawWindow(); // this will force the scroll bars to update if this is before the // initial update if (GetStyle() & WS_VSCROLL) { PostMessage(WM_VSCROLL, (WPARAM)-1, 0); } } } void CXTPHexEdit::OnHScroll(UINT nSBCode, UINT /*nPos*/, CScrollBar* /*pScrollBar*/) { SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS | SIF_TRACKPOS; VERIFY(::GetScrollInfo(m_hWnd, SB_HORZ, &si)); int newpos = si.nPos; switch (nSBCode) { case SB_LINELEFT: --newpos; break; case SB_LINERIGHT: ++newpos; break; case SB_PAGELEFT: newpos -= si.nPage; break; case SB_PAGERIGHT: newpos += si.nPage; break; case SB_THUMBTRACK: newpos = si.nTrackPos; break; } if (newpos < 0) { newpos = 0; } else if (newpos > si.nMax) { newpos = si.nMax; } if (newpos != si.nPos) { m_bUpdate = true; ::SetScrollPos(m_hWnd, SB_HORZ, newpos, TRUE); RedrawWindow(); RepositionCaret(m_nCurrentAddress); } } void CXTPHexEdit::OnLButtonDblClk(UINT /*nFlags*/, CPoint /*point*/) { } DWORD CXTPHexEdit::SetAddressBase(DWORD dwBase) { DWORD dwOldAddress = m_dwBaseAddress; m_dwBaseAddress = dwBase; m_bUpdate = TRUE; return dwOldAddress; } void CXTPHexEdit::OnSize(UINT nType, int cx, int cy) { BOOL bVisible = GetStyle() & WS_VISIBLE; if (bVisible) SetRedraw(FALSE); CXTPHexEditBase::OnSize(nType, cx, cy); if (m_bDynamicBPR) { RecalcBPR(); } m_bUpdate = TRUE; UpdateScrollbars(); if (bVisible) { SetRedraw(TRUE); Invalidate(); UpdateWindow(); } } void CXTPHexEdit::RecalcBPR() { CDC* dc = GetDC(); HGDIOBJ hOldFont = dc->SelectObject(&m_fontHex); dc->GetCharWidth('0', '0', &m_nNullWidth); CRect rc; GetClientRect(rc); int cx = rc.Width(); if (m_bShowAddress) cx -= m_nOffHex; if (m_bShowAscii && m_bShowHex) { m_nBytePerRow = ((cx * 2) / 3) / (3 * m_nNullWidth); // 2/3rd is hex, 1/3rd is ascii } else if (m_bShowHex) { m_nBytePerRow = cx / (3 * m_nNullWidth); } else if (m_bShowAscii) { m_nBytePerRow = cx / m_nNullWidth; } m_bUpdate = TRUE; if (m_nBytePerRow <= 0) m_nBytePerRow = 1; dc->SelectObject(hOldFont); ReleaseDC(dc); } void CXTPHexEdit::OnNcPaint() { // Use the OnNcPaint() handler to prevent the caret // from being shown when the control is first displayed CXTPHexEditBase::OnNcPaint(); // Be sure and call the parent class //HideCaret(); // Hide the caret } BOOL CXTPHexEdit::OnMouseWheel(UINT /*nFlags*/, short zDelta, CPoint /*pt*/) { OnVScroll(zDelta < 0 ? SB_LINEDOWN : SB_LINEUP, 0, NULL); return TRUE; } void CXTPHexEdit::EnableScrollBars(bool /*bVertical*/, bool /*bHorizontal*/) { XTP_ERROR_MSG( "CXTPHexEdit::EnableScrollBars has been deprecated.\n" "\n" "You should now set scroll bars for the control through WS_HSCROLL/WS_VSCROLL and/or the resource editor." ); } int CXTPHexEdit::GetData(LPBYTE pData, int nLength) { MEMCPY_S(pData, m_pData, __min(nLength, m_nLength)); return m_nLength; }