hexdisp.cpp
来自「IO函数调用测试」· C++ 代码 · 共 509 行
CPP
509 行
// HexDisp.cpp : implementation file
//
#include "stdafx.h"
#include "DataArray.h"
#include "HexDisp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CHexDisplay
CHexDisplay::CHexDisplay()
{
inHex = FALSE;
}
CHexDisplay::~CHexDisplay()
{
}
BEGIN_MESSAGE_MAP(CHexDisplay, CEdit)
//{{AFX_MSG_MAP(CHexDisplay)
ON_WM_DESTROY()
ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
ON_WM_CHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHexDisplay message handlers
/****************************************************************************
* CHexDisp::SetWindowTextHexMaybe
* Inputs:
* LPCSTR s: Pointer to string possibly containing NUL bytes
* DWORD len: Length of buffer
* Result: BOOL
* TRUE if input string contains NUL bytes and mode was set to hex
* or if the mode is already hex
* FALSE if input string is pure ascii; mode left unchanged
* Effect:
* Stores the bytes of the string and if there are embedded NUL bytes
* changes the mode to hex. The caller must determine if any hex
* controls need to be set on to indicate this
****************************************************************************/
BOOL CHexDisplay::SetWindowTextHexMaybe(LPBYTE s, DWORD len)
{
BOOL hex = FALSE;
for(DWORD i = 0; i < len; i++)
if(s[i] == '\0')
{ /* hex it */
hex = TRUE;
break;
} /* hex it */
if(!hex)
{ /* ascii */
SetWindowTextA((LPCSTR)s);
return inHex; // return current mode
} /* ascii */
// It requires hex mode for proper display
rawData.SetSize(len);
CopyMemory(&rawData.ElementAt(0), s, len);
CEdit::SetWindowText(makeHex(rawData));
inHex = TRUE;
return TRUE;
}
/****************************************************************************
* CHexDisplay::GetWindowText
* Inputs:
* CDataArray & b: Place to put bytes
* Result: void
*
* Effect:
* Copies the rawData to the byte array
****************************************************************************/
void CHexDisplay::GetWindowText(CDataArray & b)
{
b.Copy(rawData);
}
/****************************************************************************
* CHexDisplay::SetWindowText
* Inputs:
* LPCSTR s: text to store, 8-bit bytes
* Result: void
*
* Effect:
* Stores the text in the window. If the GWL_USERDATA field is 0,
* stores it as ASCII text. If the GWL_USERDATA field is nonzero,
* stores the text in the GWL_USERDATA field and stores a hex
* representation in the window
****************************************************************************/
void CHexDisplay::SetWindowTextA(LPCSTR s)
{
if(!inHex)
{ /* store ascii */
CEdit::SetWindowTextA(s);
return;
} /* store ascii */
rawData.SetSize(lstrlen(s));
CopyMemory(&rawData.ElementAt(0), s, lstrlen(s));
CString text = makeHex(rawData);
CEdit::SetWindowText(text);
}
void CHexDisplay::OnDestroy()
{
CEdit::OnDestroy();
}
/****************************************************************************
* CHexDisplay::makeHex
* Inputs:
* CDataArray & b: input string
* Result: CString
* String converted to hex
* Effect:
* Allocates a CString
****************************************************************************/
CString CHexDisplay::makeHex(CDataArray & b)
{
CString text;
TCHAR hex[10];
for(int i = 0; i < b.GetSize(); i++)
{ /* scan each */
wsprintf(hex, _T("%02x "), b[i]);
text += hex;
} /* scan each */
return text;
}
/****************************************************************************
* CHexDisplay::toHex
* Result: BOOL
* TRUE if the display was in ascii mode and now is in hex
* FALSE if the display was already in hex mode
* Effect:
* Converts the ascii display to a hex display
****************************************************************************/
BOOL CHexDisplay::toHex()
{
if(inHex)
return FALSE; // already in hex mode
CEdit::SetWindowText(makeHex(rawData));
inHex = TRUE;
return TRUE;
}
/****************************************************************************
* CHexDisplay::toAscii
* Result: BOOL
* TRUE if hex value is replaced by ASCII value
* FALSE if already in ASCII
* Effect:
* If in hex, converts the display to ASCII
****************************************************************************/
BOOL CHexDisplay::toAscii()
{
if(!inHex)
return FALSE; // already in ASCII mode
if(!canAscii())
return FALSE; // can't convert to ASCII (NUL bytes!)
if(rawData.GetSize() > 0)
{ /* store it */
CString s( (LPCSTR)&rawData.ElementAt(0), rawData.GetSize());
CEdit::SetWindowText(s);
} /* store it */
inHex = FALSE;
return TRUE;
}
/****************************************************************************
* CHexDisplay::isHex
* Result: BOOL
* TRUE if display is in hex
* FALSE if display is in ASCII
****************************************************************************/
BOOL CHexDisplay::isHex()
{
return inHex;
}
/****************************************************************************
* CHexDisplay::SetWindowTextAscii
* Inputs:
* LPCSTR s: String to set (8-bit)
* Result: void
*
* Effect:
* Sets the text unconditionally in ASCII.
****************************************************************************/
void CHexDisplay::SetWindowTextAscii(LPCSTR s)
{
rawData.SetSize(lstrlen(s));
CopyMemory(&rawData.ElementAt(0), s, lstrlenA(s));
CEdit::SetWindowTextA(s);
}
/****************************************************************************
* CHexDisplay::SetWindowTextHex
* Inputs:
* LPCSTR s: String to be stored as hex (8-bit)
* Result: void
*
* Effect:
* Stores the string as both hidden ASCII and visible hex data
****************************************************************************/
void CHexDisplay::SetWindowTextHex(LPCSTR s)
{
rawData.SetSize(lstrlenA(s));
CopyMemory(&rawData.ElementAt(0), s, lstrlenA(s));
CEdit::SetWindowText(makeHex(rawData));
}
/****************************************************************************
* CHexDisplay::GetWindowText
* Inputs:
* LPTSTR s: String location to store data
* int count: Maximum count
* Result: int
* Number of characters stored
* Effect:
* Copies the ascii data to the string
****************************************************************************/
int CHexDisplay::GetWindowTextA(LPSTR str, int count)
{
if(!inHex)
return CEdit::GetWindowText(str, count);
LPTSTR d = str;
int c = min(count - 1, rawData.GetSize());
CopyMemory(str, &rawData.ElementAt(0), c);
str[c + 1] = '\0';
return count - c;
}
/****************************************************************************
* CHexDisplay::GetWindowText
* Inputs:
* CString & str: Place to put result
* Result: void
*
* Effect:
* Copies the ASCII data from the window to the string
****************************************************************************/
void CHexDisplay::GetWindowText(CString &str)
{
str = CString(rawData.ElementAt(0), rawData.GetSize());
}
/****************************************************************************
* CHexDisplay::OnUpdate
* Result: void
*
* Effect:
* Handles change in the hex data
****************************************************************************/
void CHexDisplay::OnUpdate()
{
if(!inHex)
{ /* ascii mode */
CString s;
CEdit::GetWindowTextA(s);
rawData.SetSize(s.GetLength());
if(rawData.GetSize() > 0)
CopyMemory(&rawData.ElementAt(0), (LPCSTR)s, s.GetLength());
return;
} /* ascii mode */
CString s;
CEdit::GetWindowText(s);
// format is xx xx xx xx x xx xx x xxxxxx x xxx xxx xx xx xx
#define STATE_S0 0 // expecting hex digit
#define STATE_S1 1 // expecting second hex digit or space
#define STATE_S2 2 // expecting space
int state = STATE_S0;
BYTE ch = 0;
CDataArray data;
int pos = 0; // place to put next byte
for(int i = 0; i < s.GetLength(); i++)
{ /* scan */
switch(state)
{ /* state */
case STATE_S0:
if(s[i] == _T(' '))
break;
if(!isHexDigit(s[i]))
break;
ch = hexToBinary(s[i]);
state = STATE_S1;
break;
case STATE_S1:
if(ch == _T(' '))
{ /* end of char */
data.SetAtGrow(pos, ch);
ch = 0;
pos++;
state = STATE_S0;
break;
} /* end of char */
ch = (ch << 4) | hexToBinary(s[i]);
data.SetAtGrow(pos, ch);
pos++;
state = STATE_S2;
break;
case STATE_S2:
if(ch == _T(' '))
{ /* end of char */
state = STATE_S0;
break;
} /* end of char */
// Else we have hex digit string w/no spaces
if(!isHexDigit(s[i]))
break;
ch = hexToBinary(s[i]);
state = STATE_S1;
break;
} /* state */
} /* scan */
// We left in some parse state. We may have one last char to append
switch(state)
{ /* state end */
case STATE_S0:
break; // nothing pending
case STATE_S1:
data.SetAtGrow(pos, ch); // partial character pending
break;
case STATE_S2:
break; // no character pending
} /* state end */
// We've now parsed the text. Set it as the ASCII data value
rawData.Copy(data);
}
/****************************************************************************
* CHexDisplay::canAscii
* Result: BOOL
* TRUE if we can convert the text to ASCII (no embedded NUL bytes)
* FALSE if string has any embedded NUL bytes
****************************************************************************/
BOOL CHexDisplay::canAscii()
{
if(!inHex)
return TRUE; // already in ASCII mode, conversion self-evident
// It is in hex mode. Make sure there are no NUL bytes
for(int i = 0; i < rawData.GetSize(); i++)
if(rawData[i] == '\0')
return FALSE;
return TRUE;
}
void CHexDisplay::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(!isHex() || nChar == _T(' ') || nChar == _T('\b'))
{ /* normal char */
CEdit::OnChar(nChar, nRepCnt, nFlags);
return;
} /* normal char */
if(isHexDigit(nChar))
CEdit::OnChar(nChar, nRepCnt, nFlags);
else
MessageBeep(MB_ICONERROR);
}
/****************************************************************************
* CHexDisplay::isHexDigit
* Inputs:
* TCHAR ch: Character code
* Result: BOOL
* TRUE if character is hex digit
* FALSE otherwise
****************************************************************************/
BOOL CHexDisplay::isHexDigit(TCHAR ch)
{
switch(ch)
{ /* ch */
case _T('0'):
case _T('1'):
case _T('2'):
case _T('3'):
case _T('4'):
case _T('5'):
case _T('6'):
case _T('7'):
case _T('8'):
case _T('9'):
case _T('A'):
case _T('B'):
case _T('C'):
case _T('D'):
case _T('E'):
case _T('F'):
case _T('a'):
case _T('b'):
case _T('c'):
case _T('d'):
case _T('e'):
case _T('f'):
return TRUE;
default:
return FALSE;
} /* ch */
}
/****************************************************************************
* CHexDisplay::hexToBinary
* Inputs:
* TCHAR ch: Character to convert
* Result: UINT
* Binary representation of character
* Notes:
* returns 0 for non-hex digit (use isHexDigit to verify before calling)
****************************************************************************/
UINT CHexDisplay::hexToBinary(TCHAR ch)
{
switch(ch)
{ /* ch */
case _T('0'):
case _T('1'):
case _T('2'):
case _T('3'):
case _T('4'):
case _T('5'):
case _T('6'):
case _T('7'):
case _T('8'):
case _T('9'):
return ch - _T('0');
case _T('A'):
case _T('B'):
case _T('C'):
case _T('D'):
case _T('E'):
case _T('F'):
return ch - _T('A') + 10;
case _T('a'):
case _T('b'):
case _T('c'):
case _T('d'):
case _T('e'):
case _T('f'):
return ch - _T('a') + 10;
} /* ch */
return 0;
}
/****************************************************************************
* CHexDisplay::GetWindowTextLength
* Result: int
* Length of window text, as ASCII text
****************************************************************************/
int CHexDisplay::GetWindowTextLength()
{
return rawData.GetSize();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?