MFC 读取文件并将其显示为 HEX (hexdump)
MFC read file and display it as HEX (hexdump)
我需要读取二进制文件并显示特定偏移量的字节,以便我可以更改该字节然后保存更新的文件。我真的不明白我怎么能做到这一点。我正在使用 MFC/VS 2008
所以,我正在使用 WinApi 打开文件并将其内容获取到 BYTE 缓冲区。但我不确定如何以特定偏移量将数据打印到(例如)编辑框和主要问题 - 如何编辑此数据(如在 HEX 编辑器中)并保存更新的文件。
CFileDialog FileDlg(TRUE, "*", "*", OFN_FILEMUSTEXIST);
if(FileDlg.DoModal() == IDOK)
{
CString pathName = FileDlg.GetPathName();
//MessageBox(pathName, NULL, MB_OK);
// Implement opening and reading file in here.
//Change the window's title to the opened file's title.
//CString fileName = FileDlg.GetFileTitle();
//SetWindowText(fileName);
HANDLE hFile = CreateFile(pathName.GetString(), GENERIC_READ | GENERIC_WRITE, NULL,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if(!hFile)
return;
DWORD dwSize = GetFileSize(hFile, NULL);
BYTE *Content = (BYTE *)malloc(dwSize);
DWORD dwRead;
if(!ReadFile(hFile, Content, dwSize, &dwRead, NULL))
return;
}
这是一个所有者绘制 ListBox 的解决方案(大小=固定大小,排序=假)
class CListHex : public CListBox
{
public:
std::vector<BYTE> Buffer;
CRect SaveItemRect;
CEdit Edit;
int Index;
void setup()
{
if (Edit.m_hWnd && IsWindow(Edit.m_hWnd))
return;
Edit.Create(WS_CHILD | WS_BORDER | ES_CENTER, CRect(0, 0, 0, 0), this, 1);
Edit.SetFont(GetFont());
Edit.SetLimitText(2);
SetItemHeight(0, 21);
}
void read()
{
HANDLE hfile = CreateFile(L"in.txt", GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile != INVALID_HANDLE_VALUE) //****CHANGED****
{
DWORD size = GetFileSize(hfile, NULL);
Buffer.resize(size);
ReadFile(hfile, &Buffer[0], size, 0, NULL);
CloseHandle(hfile);
for (int i = 0; i <= (int)Buffer.size() / 16; i++)
AddString(0);
}
else
{
MessageBox(L"error");
}
}
void write()
{
HANDLE hFile = CreateFile(L"out.txt", GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile != INVALID_HANDLE_VALUE) //****CHANGED****
{
WriteFile(hFile, &Buffer[0], Buffer.size(), 0, 0);
CloseHandle(hFile);
}
else
{
MessageBox(L"error");
}
}
void DrawItem(LPDRAWITEMSTRUCT di)
{
SaveItemRect = di->rcItem;
CRect r = di->rcItem;
r.right = r.left + r.Width() / 16;
HBRUSH brush = (HBRUSH)SelectObject(di->hDC, GetStockObject(WHITE_BRUSH));
FillRect(di->hDC, &di->rcItem, brush);
for (int i = 0; i < 16; i++)
{
unsigned int cursor = di->itemID * 16 + i;
if (cursor >= Buffer.size())
break;
CString s;
s.Format(L"%02X", Buffer[cursor]);
DrawText(di->hDC, s, s.GetLength(), r, DT_EDITCONTROL|DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
}
void OnLButtonDown(UINT f, CPoint p)
{
CListBox::OnLButtonDown(f, p);
setup();
int w = SaveItemRect.Width() / 16;
CRect r = SaveItemRect;
r.right = r.left + w;
for (int i = 0; i < 16; i++)
{
if (r.PtInRect(p))
{
unsigned int index = GetCurSel() * 16 + i;
if (index >= Buffer.size())
return;
Index = index;
GetParent()->SetRedraw(0);
CString s;
s.Format(L"%02X", Buffer[Index]);
Edit.SetWindowText(s);
Edit.SetWindowPos(0, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER | SWP_NOREDRAW | SWP_SHOWWINDOW);
Edit.SetFocus();
GetParent()->SetRedraw(1);
break;
}
r.OffsetRect(w, 0);
}
}
//******CHANGED******
void MeasureItem(LPMEASUREITEMSTRUCT m) { m->itemHeight=21; }
int CompareItem(LPCOMPAREITEMSTRUCT) { return 0; }
//******CHANGED******
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CListHex, CListBox)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
此外,
- 您可以为
CEdit
添加子类
- 重写
CMyEdit::OnKillFocus()
以关闭编辑框
- 覆盖
CMyEdit::OnChar
以仅接受十六进制字符
- 读取编辑字符串然后转换为
unsigned char
并将其分配给 Buffer[Index]
。
- 重写
CListHex::OnVScroll
以关闭编辑框
//已更改:
要创建函数,请尝试手动执行,以确保它获得正确的标志:
list.Create(WS_VSCROLL | WS_BORDER | WS_CHILD | WS_VISIBLE | LBS_USETABSTOPS | LBS_OWNERDRAWFIXED , CRect(10, 10, 450, 350), this, 1001);
list.read();
我需要读取二进制文件并显示特定偏移量的字节,以便我可以更改该字节然后保存更新的文件。我真的不明白我怎么能做到这一点。我正在使用 MFC/VS 2008
所以,我正在使用 WinApi 打开文件并将其内容获取到 BYTE 缓冲区。但我不确定如何以特定偏移量将数据打印到(例如)编辑框和主要问题 - 如何编辑此数据(如在 HEX 编辑器中)并保存更新的文件。
CFileDialog FileDlg(TRUE, "*", "*", OFN_FILEMUSTEXIST);
if(FileDlg.DoModal() == IDOK)
{
CString pathName = FileDlg.GetPathName();
//MessageBox(pathName, NULL, MB_OK);
// Implement opening and reading file in here.
//Change the window's title to the opened file's title.
//CString fileName = FileDlg.GetFileTitle();
//SetWindowText(fileName);
HANDLE hFile = CreateFile(pathName.GetString(), GENERIC_READ | GENERIC_WRITE, NULL,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if(!hFile)
return;
DWORD dwSize = GetFileSize(hFile, NULL);
BYTE *Content = (BYTE *)malloc(dwSize);
DWORD dwRead;
if(!ReadFile(hFile, Content, dwSize, &dwRead, NULL))
return;
}
这是一个所有者绘制 ListBox 的解决方案(大小=固定大小,排序=假)
class CListHex : public CListBox
{
public:
std::vector<BYTE> Buffer;
CRect SaveItemRect;
CEdit Edit;
int Index;
void setup()
{
if (Edit.m_hWnd && IsWindow(Edit.m_hWnd))
return;
Edit.Create(WS_CHILD | WS_BORDER | ES_CENTER, CRect(0, 0, 0, 0), this, 1);
Edit.SetFont(GetFont());
Edit.SetLimitText(2);
SetItemHeight(0, 21);
}
void read()
{
HANDLE hfile = CreateFile(L"in.txt", GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile != INVALID_HANDLE_VALUE) //****CHANGED****
{
DWORD size = GetFileSize(hfile, NULL);
Buffer.resize(size);
ReadFile(hfile, &Buffer[0], size, 0, NULL);
CloseHandle(hfile);
for (int i = 0; i <= (int)Buffer.size() / 16; i++)
AddString(0);
}
else
{
MessageBox(L"error");
}
}
void write()
{
HANDLE hFile = CreateFile(L"out.txt", GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile != INVALID_HANDLE_VALUE) //****CHANGED****
{
WriteFile(hFile, &Buffer[0], Buffer.size(), 0, 0);
CloseHandle(hFile);
}
else
{
MessageBox(L"error");
}
}
void DrawItem(LPDRAWITEMSTRUCT di)
{
SaveItemRect = di->rcItem;
CRect r = di->rcItem;
r.right = r.left + r.Width() / 16;
HBRUSH brush = (HBRUSH)SelectObject(di->hDC, GetStockObject(WHITE_BRUSH));
FillRect(di->hDC, &di->rcItem, brush);
for (int i = 0; i < 16; i++)
{
unsigned int cursor = di->itemID * 16 + i;
if (cursor >= Buffer.size())
break;
CString s;
s.Format(L"%02X", Buffer[cursor]);
DrawText(di->hDC, s, s.GetLength(), r, DT_EDITCONTROL|DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
}
void OnLButtonDown(UINT f, CPoint p)
{
CListBox::OnLButtonDown(f, p);
setup();
int w = SaveItemRect.Width() / 16;
CRect r = SaveItemRect;
r.right = r.left + w;
for (int i = 0; i < 16; i++)
{
if (r.PtInRect(p))
{
unsigned int index = GetCurSel() * 16 + i;
if (index >= Buffer.size())
return;
Index = index;
GetParent()->SetRedraw(0);
CString s;
s.Format(L"%02X", Buffer[Index]);
Edit.SetWindowText(s);
Edit.SetWindowPos(0, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER | SWP_NOREDRAW | SWP_SHOWWINDOW);
Edit.SetFocus();
GetParent()->SetRedraw(1);
break;
}
r.OffsetRect(w, 0);
}
}
//******CHANGED******
void MeasureItem(LPMEASUREITEMSTRUCT m) { m->itemHeight=21; }
int CompareItem(LPCOMPAREITEMSTRUCT) { return 0; }
//******CHANGED******
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CListHex, CListBox)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
此外,
- 您可以为
CEdit
添加子类
- 重写
CMyEdit::OnKillFocus()
以关闭编辑框 - 覆盖
CMyEdit::OnChar
以仅接受十六进制字符 - 读取编辑字符串然后转换为
unsigned char
并将其分配给Buffer[Index]
。 - 重写
CListHex::OnVScroll
以关闭编辑框
//已更改:
要创建函数,请尝试手动执行,以确保它获得正确的标志:
list.Create(WS_VSCROLL | WS_BORDER | WS_CHILD | WS_VISIBLE | LBS_USETABSTOPS | LBS_OWNERDRAWFIXED , CRect(10, 10, 450, 350), this, 1001);
list.read();