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 + -
显示快捷键?