欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > MFC 自定义十六进制显示控件

MFC 自定义十六进制显示控件

2025/2/22 2:23:17 来源:https://blog.csdn.net/qq_42877866/article/details/145647807  浏览:    关键词:MFC 自定义十六进制显示控件
//MyHexView.h
#pragma once
class CMyHexView : public CWnd
{DECLARE_DYNAMIC(CMyHexView)public:CMyHexView();virtual ~CMyHexView();void SetData(const CByteArray& data);  // 设置数据const CByteArray& GetData() const;    // 获取数据protected:afx_msg void OnKillFocus(CWnd* pNewWnd); // 处理失去焦点事件DECLARE_MESSAGE_MAP()private:CByteArray m_data;          // 存储数据的字节数组int m_nScrollPos;           // 滚动位置int m_nLinesPerPage;        // 每页显示的行数int m_nSelectedByte;        // 当前选中的字节索引bool m_bEditing;            // 是否正在编辑void DrawHexView(CDC* pDC); // 绘制十六进制视图void UpdateScrollBar();     // 更新滚动条void UpdateSelection();     // 更新选中状态void StartEditing();        // 开始编辑void EndEditing();          // 结束编辑public:afx_msg void OnPaint();afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);afx_msg void OnLButtonDown(UINT nFlags, CPoint point); // 处理鼠标点击afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); // 处理键盘输入
};
//MyHexView.cpp
#include "stdafx.h"
#include "MyHexView.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// CMyHexViewIMPLEMENT_DYNAMIC(CMyHexView, CWnd)CMyHexView::CMyHexView(): m_nScrollPos(0), m_nLinesPerPage(0)
{
}CMyHexView::~CMyHexView()
{
}BEGIN_MESSAGE_MAP(CMyHexView, CWnd)ON_WM_PAINT()ON_WM_VSCROLL()ON_WM_MOUSEWHEEL()ON_WM_LBUTTONDOWN()ON_WM_CHAR()ON_WM_KILLFOCUS() // 添加失去焦点的消息处理
END_MESSAGE_MAP()// CMyHexView 消息处理程序void CMyHexView::SetData(const CByteArray& data)
{m_data.Copy(data);  // 使用 Copy 方法复制数据,而不是直接赋值m_nScrollPos = 0;UpdateScrollBar();Invalidate();
}const CByteArray& CMyHexView::GetData() const
{return m_data;  // 返回 const 引用
}void CMyHexView::OnPaint()
{CPaintDC dc(this); // 用于绘制的设备上下文CRect rect;GetClientRect(&rect);CDC memDC;memDC.CreateCompatibleDC(&dc);CBitmap memBitmap;memBitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());CBitmap* pOldBitmap = memDC.SelectObject(&memBitmap);memDC.FillSolidRect(&rect, RGB(255, 255, 255));DrawHexView(&memDC);dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);memDC.SelectObject(pOldBitmap);
}void CMyHexView::DrawHexView(CDC* pDC)
{CRect rect;GetClientRect(&rect);CFont font;font.CreatePointFont(100, _T("Courier New"));CFont* pOldFont = pDC->SelectObject(&font);int nLineHeight = pDC->GetTextExtent(_T("X")).cy;m_nLinesPerPage = rect.Height() / nLineHeight;int nLines = (m_data.GetSize() + 15) / 16;int nStartLine = m_nScrollPos;int nEndLine = min(nStartLine + m_nLinesPerPage, nLines);for (int i = nStartLine; i < nEndLine; ++i){CString strLine;strLine.Format(_T("%08X  "), i * 16);for (int j = 0; j < 16; ++j){int nIndex = i * 16 + j;if (nIndex < m_data.GetSize()){if (nIndex == m_nSelectedByte && m_bEditing){pDC->SetTextColor(RGB(255, 0, 0)); // 选中字节高亮显示}else{pDC->SetTextColor(RGB(0, 0, 0));}strLine.AppendFormat(_T("%02X "), m_data[nIndex]);}else{strLine += _T("   ");}}strLine += _T(" ");for (int j = 0; j < 16; ++j){int nIndex = i * 16 + j;if (nIndex < m_data.GetSize()){BYTE b = m_data[nIndex];if (b >= 32 && b <= 126){strLine += (TCHAR)b;}else{strLine += _T(".");}}else{strLine += _T(" ");}}pDC->TextOut(10, (i - nStartLine) * nLineHeight, strLine);}pDC->SelectObject(pOldFont);
}
void CMyHexView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{int nScrollPos = m_nScrollPos;switch (nSBCode){case SB_LINEUP:nScrollPos -= 1;break;case SB_LINEDOWN:nScrollPos += 1;break;case SB_PAGEUP:nScrollPos -= m_nLinesPerPage;break;case SB_PAGEDOWN:nScrollPos += m_nLinesPerPage;break;case SB_THUMBTRACK:nScrollPos = nPos;break;}int nLines = (m_data.GetSize() + 15) / 16;nScrollPos = max(0, min(nScrollPos, nLines - m_nLinesPerPage));if (nScrollPos != m_nScrollPos){m_nScrollPos = nScrollPos;UpdateScrollBar();Invalidate();}
}BOOL CMyHexView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{int nScrollPos = m_nScrollPos - zDelta / WHEEL_DELTA;int nLines = (m_data.GetSize() + 15) / 16;nScrollPos = max(0, min(nScrollPos, nLines - m_nLinesPerPage));if (nScrollPos != m_nScrollPos){m_nScrollPos = nScrollPos;UpdateScrollBar();Invalidate();}return TRUE;
}void CMyHexView::UpdateScrollBar()
{SCROLLINFO si;si.cbSize = sizeof(SCROLLINFO);si.fMask = SIF_ALL;si.nMin = 0;si.nMax = (m_data.GetSize() + 15) / 16 - 1;si.nPage = m_nLinesPerPage;si.nPos = m_nScrollPos;SetScrollInfo(SB_VERT, &si, TRUE);
}
void CMyHexView::OnLButtonDown(UINT nFlags, CPoint point)
{// 计算点击的字节索引CRect rect;GetClientRect(&rect);CDC* pDC = GetDC();CFont font;font.CreatePointFont(100, _T("Courier New"));CFont* pOldFont = pDC->SelectObject(&font);int nLineHeight = pDC->GetTextExtent(_T("X")).cy;int nCharWidth = pDC->GetTextExtent(_T("X")).cx;int nLine = (point.y / nLineHeight) + m_nScrollPos;int nColumn = (point.x - 10) / (3 * nCharWidth); // 每个字节占 3 个字符宽度if (nColumn >= 0 && nColumn < 16 && nLine >= 0 && nLine < (m_data.GetSize() + 15) / 16){m_nSelectedByte = nLine * 16 + nColumn;if (m_nSelectedByte >= m_data.GetSize()){m_nSelectedByte = -1;}else{StartEditing();}}else{m_nSelectedByte = -1;}pDC->SelectObject(pOldFont);ReleaseDC(pDC);UpdateSelection();CWnd::OnLButtonDown(nFlags, point);
}void CMyHexView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{if (m_bEditing && m_nSelectedByte >= 0){// 只允许输入十六进制字符 (0-9, A-F, a-f)if ((nChar >= '0' && nChar <= '9') || (nChar >= 'A' && nChar <= 'F') || (nChar >= 'a' && nChar <= 'f')){// 将字符转换为十六进制值BYTE b = 0;if (nChar >= '0' && nChar <= '9'){b = nChar - '0';}else if (nChar >= 'A' && nChar <= 'F'){b = nChar - 'A' + 10;}else if (nChar >= 'a' && nChar <= 'f'){b = nChar - 'a' + 10;}// 更新数据if (m_bEditing){m_data[m_nSelectedByte] = (m_data[m_nSelectedByte] << 4) | b;Invalidate(); // 刷新显示}}}CWnd::OnChar(nChar, nRepCnt, nFlags);
}void CMyHexView::StartEditing()
{m_bEditing = true;Invalidate();
}void CMyHexView::EndEditing()
{m_bEditing = false;m_nSelectedByte = -1;Invalidate(); // 刷新显示
}void CMyHexView::UpdateSelection()
{Invalidate();
}
void CMyHexView::OnKillFocus(CWnd* pNewWnd)
{if (m_bEditing){EndEditing(); // 结束编辑}CWnd::OnKillFocus(pNewWnd);
}
//主类中
int C改变Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CDialogEx::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  在此添加您专用的创建代码WNDCLASS wc;memset(&wc, 0, sizeof(WNDCLASS));wc.lpfnWndProc = ::DefWindowProc; // 使用默认窗口过程wc.hInstance = AfxGetInstanceHandle();wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);wc.lpszClassName = _T("CMyHexView"); // 类名必须与控件类名一致if (!AfxRegisterClass(&wc)){AfxMessageBox(_T("Failed to register custom control class!"));return FALSE;}return 0;
}
BOOL C改变Dlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// TODO: 在此添加额外的初始化代码if (!m_hexView.SubclassDlgItem(IDC_CUSTOM2, this)){AfxMessageBox(_T("Failed to subclass custom control!"));return FALSE;}CFile file;if (file.Open(_T("D:\\miniout.txt"), CFile::modeRead)){CByteArray data;data.SetSize(file.GetLength());file.Read(data.GetData(), file.GetLength());file.Close();m_hexView.SetData(data);  // 传递 CByteArray 的引用}return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

细节配置
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词