工控编程吧
标题:
上位机MFC实现十六进制编辑框
[打印本页]
作者:
qq263946146
时间:
2019-7-5 16:37
标题:
上位机MFC实现十六进制编辑框
效果演示
(, 下载次数: 0)
上传
点击文件名下载附件
例程实现在编辑框中添加十六进制和ASCII文本,可以通过单选框选择是否显示。
地址也可以通过选择设置,效果如上图。
例程使用的两文件可以在帖子底部使用或直接下载工程源代码使用:
(, 下载次数: 0)
上传
点击文件名下载附件
实现过程
1.同样也是新建一个工程,这里建立基于对话框的工程,
按照上图添加单选框,编辑框,与滑块控件,并进行界面排序。
2.复制例程目录两文件HEXEDITCTRL.CPP,HEXEDITCTRL.H到自己工程根目录中,
并导入到工程,两文件源代码可以在帖子底部复制使用。
操作之后,自己的工程目录内就多出了一个集成类CHexEdit,如下图:
(, 下载次数: 0)
上传
点击文件名下载附件
3.紧接着就产类的使用。
在主对话框头文件内包含#include "hexeditctrl.h"
并添加变量
//{{AFX_DATA(CCtestDlg)
enum { IDD = IDD_CTEST_DIALOG };
CSliderCtrl m_slider;
CHexEdit m_Edit;
//}}AFX_DATA
void CCtestDlg:
oDataExchange(CDataExchange* pDX)
{
CDialog:
oDataExchange(pDX);
DDX_Control(pDX, IDC_SLIDER1, m_slider);
DDX_Control(pDX, IDC_HEXEDIT1, m_Edit);
//}}AFX_DATA_MAP
}
并初始化变量
m_slider.SetRange(1, 16);
m_slider.SetPos(8);
编译时会提示少一个菜单ID,CG_IDR_POPUP_HEX_EDIT,
添加或从例程复制使用。
4.添加几个单选框的点击处理函数
void CHexEditDlg::OnCheck1()
{
UpdateData(TRUE);
m_Edit.SetOptions(m_address, m_hex, m_ascii, m_48);
m_Edit.RedrawWindow();
}
void CHexEditDlg::OnCheck2()
{
UpdateData(TRUE);
m_Edit.SetOptions(m_address, m_hex, m_ascii, m_48);
m_Edit.RedrawWindow();
}
void CHexEditDlg::OnCheck3()
{
UpdateData(TRUE);
m_Edit.SetOptions(m_address, m_hex, m_ascii, m_48);
m_Edit.RedrawWindow();
}
void CHexEditDlg::OnCheck4()
{
UpdateData(TRUE);
m_Edit.SetOptions(m_address, m_hex, m_ascii, m_48);
m_Edit.RedrawWindow();
}
复制代码
运行程序,就可以点击界面的几个单选框查看效果,
编辑框自带的文本可以通过去除集成类头文件的#define DEMO 1,去除。
5.最后就滑块功能的实现,在主对话框添加对消息WM_HSCROLL的处理便可:
void CCtestDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
m_Edit.SetBPR(m_slider.GetPos());
m_Edit.RedrawWindow();
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
下面是两个文件的源代码:
/////////////////////////////////////////////////////////////////////////////
// CHexEdit window
class CHexEdit : public CEdit
{
// Construction
public:
CHexEdit();
enum EDITMODE{
EDIT_NONE,
EDIT_ASCII,
EDIT_HIGH,
EDIT_LOW
} ;
// Attributes
public:
LPBYTE m_pData; // pointer to data
int m_length; // length of data
int m_topindex; // offset of first visible byte on screen
int m_currentAddress; // address under cursor
EDITMODE m_currentMode; // current editing mode: address/hex/ascii
int m_selStart; // start address of selection
int m_selEnd; // end address of selection
int m_bpr; // byte per row
int m_lpp; // lines per page
BOOL m_bShowAddress;
BOOL m_bShowAscii;
BOOL m_bShowHex;
BOOL m_bAddressIsWide;
BOOL m_bNoAddressChange; // internally used
BOOL m_bHalfPage;
CFont m_Font;
int m_lineHeight;
int m_nullWidth;
BOOL m_bUpdate;
int m_offHex,
m_offAscii,
m_offAddress;
CPoint m_editPos;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHexEdit)
public:
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
public:
int GetData(LPBYTE p, int len);
void SetData(LPBYTE p, int len);
CSize GetSel(void);
void SetSel(int s, int e);
void SetBPR(int bpr);
void SetOptions(BOOL a, BOOL h, BOOL c, BOOL w);
virtual ~CHexEdit();
// Generated message map functions
protected:
void ScrollIntoView(int p);
void RepositionCaret(int p);
void Move(int x, int y);
inline BOOL IsSelected(void);
void UpdateScrollbars(void);
void CreateEditCaret(void);
void CreateAddressCaret(void);
CPoint CalcPos(int x, int y);
void SelInsert(int s, int l);
void SelDelete(int s, int e);
inline void NormalizeSel(void);
afx_msg void OnContextMenu(CWnd*, CPoint point);
//{{AFX_MSG(CHexEdit)
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnPaint();
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg UINT OnGetDlgCode();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnEditClear();
afx_msg void OnEditCopy();
afx_msg void OnEditCut();
afx_msg void OnEditPaste();
afx_msg void OnEditSelectAll();
afx_msg void OnEditUndo();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
复制代码
// HexEdit.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "HexEditCtrl.h"
#include <ctype.h>
#include <afxole.h>
#include <afxdisp.h>
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
char hextable[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
#define TOHEX(a, b) {*b++ = hextable[a >> 4];*b++ = hextable[a&0xf];}
/////////////////////////////////////////////////////////////////////////////
// CHexEdit
#define DEMO 1
CHexEdit::CHexEdit()
{
#if !defined(DEMO)
m_pData = NULL; // pointer to data
m_length = 0; // length of data
#else
m_pData = (LPBYTE)malloc(0x40);
for(int i = 0; i < 0x40; i++)
m_pData[i] = i;
#endif
m_length = 0x40;
m_topindex = 0;
m_bpr = 8; // byte per row
m_lpp = 1;
m_bShowHex = TRUE;
m_bShowAscii = TRUE;
m_bShowAddress = TRUE;
m_bAddressIsWide= TRUE; // 4/8 byte address
m_offAddress = 0;
m_offHex = 0;
m_offAscii = 0;
m_bUpdate = TRUE; // update font info
m_bNoAddressChange = FALSE;
m_currentMode = EDIT_NONE;
m_editPos.x = m_editPos.y = 0;
m_currentAddress = 0;
m_bHalfPage = TRUE;
m_selStart = 0xffffffff;
m_selEnd = 0xffffffff;
m_Font.CreateFont(-12, 0,0,0,0,0,0,0,0,0,0,0,0, "Courier New");
AfxOleInit();
}
CHexEdit::~CHexEdit()
{
}
BEGIN_MESSAGE_MAP(CHexEdit, CEdit)
ON_WM_CONTEXTMENU()
//{{AFX_MSG_MAP(CHexEdit)
ON_WM_CHAR()
ON_WM_KILLFOCUS()
ON_WM_PAINT()
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_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)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHexEdit message handlers
void CHexEdit::OnPaint()
{
CPaintDC pdc(this); // device context for painting
CRect rc;
GetClientRect(rc);
CDC dc;
dc.CreateCompatibleDC(CDC::FromHandle(pdc.m_ps.hdc));
CBitmap bm;
bm.CreateCompatibleBitmap(CDC::FromHandle(pdc.m_ps.hdc), rc.Width(), rc.Height());
dc.SelectObject(bm);
CBrush b;
b.CreateSolidBrush(RGB(0xff,0xff,0xff));
dc.FillRect(rc, &b);
ASSERT(m_currentAddress >= 0);
ASSERT(m_topindex >= 0);
dc.SelectObject(m_Font);
int height = 0;
int x,y;
char buf[256];
x = rc.TopLeft().x;
y = rc.TopLeft().y;
dc.SetBoundsRect(&rc, DCB_DISABLE);
if(m_pData)
{
//
// get char dimensions
//
if(m_bUpdate)
{
dc.GetCharWidth('0', '0', &m_nullWidth);
CSize sz = dc.GetTextExtent("0", 1);
m_lineHeight = sz.cy;
m_offHex = m_bShowAddress ? (m_bAddressIsWide ? m_nullWidth * 9 : m_nullWidth * 5) : 0;
m_offAscii = m_bShowAddress ? (m_bAddressIsWide ? m_nullWidth * 9 : m_nullWidth * 5) : 0;
m_offAscii += m_bShowHex ? (m_bpr * 3 * m_nullWidth) : 0;
m_lpp = rc.Height() / m_lineHeight;
m_bHalfPage = FALSE;
if(m_lpp * m_bpr > m_length)
{
m_lpp = (m_length + (m_bpr/2)) / m_bpr ;
if(m_length % m_bpr != 0)
{
m_bHalfPage = TRUE;
m_lpp++;
}
}
m_bUpdate = FALSE;
UpdateScrollbars();
}
TRACE("%i %i\n", m_topindex, m_selStart);
height = rc.Height() / m_lineHeight;
height *= m_lineHeight;
if(m_bShowAddress)
{
char fmt[8] = {'%','0','8','l','X'};
fmt[2] = m_bAddressIsWide ? '8' : '4';
int w = m_bAddressIsWide ? 8 : 4;
y = 0;
CRect rcd = rc;
rcd.TopLeft().x = m_offAddress;
for(int i = m_topindex; (i < m_length) && (rcd.TopLeft().y < height); i+= m_bpr)
{
sprintf(buf, fmt, i);
dc.DrawText(buf, w, rcd, DT_LEFT|DT_TOP|DT_SINGLELINE|DT_NOPREFIX);
rcd.TopLeft().y += m_lineHeight;
}
}
if(m_bShowHex)
{
y = 0;
CRect rcd = rc;
rcd.TopLeft().x = x = m_offHex;
if(m_selStart != 0xffffffff && (m_currentMode == EDIT_HIGH || m_currentMode == EDIT_LOW))
{
int i;
int n = 0;
int selStart = m_selStart, selEnd = m_selEnd;
if(selStart > selEnd)
selStart ^= selEnd ^= selStart ^= selEnd;
for(i = m_topindex; (i < selStart) && (y < height); i++)
{
char* p = &buf[0];
TOHEX(m_pData[i], p);
*p++ = ' ';
dc.TextOut(x, y, buf, 3);
x += m_nullWidth * 3;
n++;
if(n == m_bpr)
{
n = 0;
x = m_offHex;
y += m_lineHeight;
}
}
dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
dc.SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
for(; (i < selEnd) && (i < m_length) && (y < height); i++)
{
char* p = &buf[0];
TOHEX(m_pData[i], p);
*p++ = ' ';
dc.TextOut(x, y, buf, 3);
x += m_nullWidth * 3;
n++;
if(n == m_bpr)
{
n = 0;
x = m_offHex;
y += m_lineHeight;
}
}
dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(GetSysColor(COLOR_WINDOW));
for(; (i < m_length) && (y < height); i++)
{
char* p = &buf[0];
TOHEX(m_pData[i], p);
*p++ = ' ';
dc.TextOut(x, y, buf, 3);
x += m_nullWidth * 3;
n++;
if(n == m_bpr)
{
n = 0;
x = m_offHex;
y += m_lineHeight;
}
}
}
else
{
for(int i = m_topindex; (i < m_length) && (rcd.TopLeft().y < height);)
{
char* p = &buf[0];
for(int n = 0; (n < m_bpr) && (i < m_length); n++)
{
TOHEX(m_pData[i], p);
*p++ = ' ';
i++;
}
while(n < m_bpr)
{
*p++ = ' '; *p++ = ' '; *p++ = ' ';
n++;
}
dc.DrawText(buf, m_bpr*3, rcd, DT_LEFT|DT_TOP|DT_SINGLELINE|DT_NOPREFIX);
rcd.TopLeft().y += m_lineHeight;
}
}
}
if(m_bShowAscii)
{
y = 0;
CRect rcd = rc;
rcd.TopLeft().x = x = m_offAscii;
if(m_selStart != 0xffffffff && m_currentMode == EDIT_ASCII)
{
int i;
int n = 0;
int selStart = m_selStart, selEnd = m_selEnd;
if(selStart > selEnd)
selStart ^= selEnd ^= selStart ^= selEnd;
for(i = m_topindex; (i < selStart) && (y < height); i++)
{
buf[0] = isprint(m_pData[i]) ? m_pData[i] : '.';
dc.TextOut(x, y, buf, 1);
x += m_nullWidth;
n++;
if(n == m_bpr)
{
n = 0;
x = m_offAscii;
y += m_lineHeight;
}
}
dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
dc.SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
for(; (i < selEnd) && (y < height); i++)
{
buf[0] = isprint(m_pData[i]) ? m_pData[i] : '.';
dc.TextOut(x, y, buf, 1);
x += m_nullWidth;
n++;
if(n == m_bpr)
{
n = 0;
x = m_offAscii;
y += m_lineHeight;
}
}
dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(GetSysColor(COLOR_WINDOW));
for(; (i < m_length) && y < height; i++)
{
buf[0] = isprint(m_pData[i]) ? m_pData[i] : '.';
dc.TextOut(x, y, buf, 1);
x += m_nullWidth;
n++;
if(n == m_bpr)
{
n = 0;
x = m_offAscii;
y += m_lineHeight;
}
}
}
else
{
for(int i = m_topindex; (i < m_length) && (rcd.TopLeft().y < height);)
{
char* p = &buf[0];
for(int n = 0; (n < m_bpr) && (i < m_length); n++)
{
*p++ = isprint(m_pData[i]) ? m_pData[i] : '.';
i++;
}
dc.DrawText(buf, n, rcd, DT_LEFT|DT_TOP|DT_SINGLELINE|DT_NOPREFIX);
rcd.TopLeft().y += m_lineHeight;
}
}
}
}
pdc.BitBlt(0, 0, rc.Width(), rc.Height(), &dc, 0, 0, SRCCOPY);
}
void CHexEdit::OnSetFocus(CWnd* pOldWnd)
{
if(m_pData && !IsSelected())
{
if(m_editPos.x == 0 && m_bShowAddress)
CreateAddressCaret();
else
CreateEditCaret();
SetCaretPos(m_editPos);
ShowCaret();
}
CWnd::OnSetFocus(pOldWnd);
}
void CHexEdit::OnKillFocus(CWnd* pNewWnd)
{
DestroyCaret();
CWnd::OnKillFocus(pNewWnd);
}
void CHexEdit::OnSize(UINT nType, int cx, int cy)
{
CEdit::OnSize(nType, cx, cy);
}
void CHexEdit::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
pScrollBar;
if(!m_pData)
return;
int oa = m_topindex;
switch(nSBCode)
{
case SB_LINEDOWN:
if(m_topindex < m_length - m_lpp*m_bpr)
{
//ScrollWindow(0, -m_lineHeight, rc);
m_topindex += m_bpr;
RedrawWindow();
}
break;
case SB_LINEUP:
if(m_topindex > 0)
{
//ScrollWindow(0, m_lineHeight, rc);
m_topindex -= m_bpr;
RedrawWindow();
}
break;
case SB_PAGEDOWN:
if(m_topindex < m_length - m_lpp*m_bpr)
{
m_topindex += m_bpr * m_lpp;
if(m_topindex > m_length - m_lpp*m_bpr)
m_topindex = m_length - m_lpp*m_bpr;
RedrawWindow();
}
break;
case SB_PAGEUP:
if(m_topindex > 0)
{
m_topindex -= m_bpr * m_lpp;
if(m_topindex < 0)
m_topindex = 0;
RedrawWindow();
}
break;
case SB_THUMBTRACK:
m_topindex = nPos * m_bpr;
RedrawWindow();
break;
}
::SetScrollPos(this->m_hWnd, SB_VERT, m_topindex / m_bpr, TRUE);
if(!m_bNoAddressChange)
m_currentAddress += (m_topindex - oa);
RepositionCaret(m_currentAddress);
}
void CHexEdit::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
nSBCode;nPos; pScrollBar;
}
UINT CHexEdit::OnGetDlgCode()
{
return DLGC_WANTALLKEYS;
}
BOOL CHexEdit::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_HSCROLL|WS_VSCROLL;
return CEdit::PreCreateWindow(cs);
}
BOOL CHexEdit::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
dwStyle |= WS_HSCROLL|WS_VSCROLL;
BOOL bRet = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
if(bRet)
SetFont(&m_Font);
return bRet;
}
BOOL CHexEdit::OnEraseBkgnd(CDC* pDC)
{
pDC;
return TRUE;
}
void CHexEdit::SetOptions(BOOL a, BOOL h, BOOL c, BOOL w)
{
m_bShowHex = h;
m_bShowAscii = c;
m_bShowAddress = a;
m_bAddressIsWide= w; // 4/8 byte address
m_bUpdate = TRUE;
}
void CHexEdit::SetBPR(int bpr)
{
m_bpr = bpr;
m_bUpdate = TRUE;
}
void CHexEdit::OnLButtonDown(UINT nFlags, CPoint point)
{
SetFocus();
if(!m_pData)
return;
if(nFlags & MK_SHIFT)
{
m_selStart = m_currentAddress;
}
CPoint pt = CalcPos(point.x, point.y);
if(pt.x > -1)
{
m_editPos = pt;
pt.x *= m_nullWidth;
pt.y *= m_lineHeight;
if(pt.x == 0 && m_bShowAddress)
CreateAddressCaret();
else
CreateEditCaret();
SetCaretPos(pt);
if(nFlags & MK_SHIFT)
{
m_selEnd = m_currentAddress;
if(m_currentMode == EDIT_HIGH || m_currentMode == EDIT_LOW)
m_selEnd++;
RedrawWindow();
}
}
if(!(nFlags & MK_SHIFT))
{
if(DragDetect(this->m_hWnd, point))
{
m_selStart = m_currentAddress;
m_selEnd = m_selStart;
SetCapture();
}
else
{
BOOL bsel = m_selStart != 0xffffffff;
m_selStart = 0xffffffff;
m_selEnd = 0xffffffff;
if(bsel)
RedrawWindow();
}
}
if(!IsSelected())
{
ShowCaret();
}
}
void CHexEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
{
nFlags; point;
}
复制代码
欢迎光临 工控编程吧 (https://www.gkbc8.com/)
Powered by Discuz! X3.4