MFC读取文件并将其显示为十六进制(hexdump)
我需要读取二进制文件并以一定的偏移量显示字节,这样我就可以更改这些字节,然后保存更新的文件。我真的不明白我怎样才能做到这一点。我使用的是MFC/VS2008 所以,我正在使用WinApi打开文件,并将其内容放入字节缓冲区。但我不确定如何将数据以一定的偏移量打印到(例如)编辑框和主问题-如何编辑这些数据(如在十六进制编辑器中)并保存更新的文件MFC读取文件并将其显示为十六进制(hexdump),mfc,hexdump,Mfc,Hexdump,我需要读取二进制文件并以一定的偏移量显示字节,这样我就可以更改这些字节,然后保存更新的文件。我真的不明白我怎样才能做到这一点。我使用的是MFC/VS2008 所以,我正在使用WinApi打开文件,并将其内容放入字节缓冲区。但我不确定如何将数据以一定的偏移量打印到(例如)编辑框和主问题-如何编辑这些数据(如在十六进制编辑器中)并保存更新的文件 CFileDialog FileDlg(TRUE, "*", "*", OFN_FILEMUSTEXIST); if(FileDlg.DoModa
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;
}
下面是一个具有所有者绘制列表框的解决方案(大小=固定大小,排序=false)
类clistEx:公共CListBox
{
公众:
向量缓冲区;
正确的保存项;
CEdit编辑;
整数指数;
无效设置()
{
if(Edit.m_-hWnd&&IsWindow(Edit.m_-hWnd))
返回;
编辑.创建(WS|u CHILD | WS|u BORDER | ES|u CENTER,CRect(0,0,0),this,1);
Edit.SetFont(GetFont());
编辑.SetLimitText(2);
SetItemHeight(0,21);
}
无效读取()
{
HANDLE hfile=CreateFile(L“in.txt”,通用\u READ,NULL,NULL,OPEN\u EXISTING,FILE\u ATTRIBUTE\u NORMAL,NULL);
如果(hfile!=无效的句柄值)//****已更改****
{
DWORD size=GetFileSize(hfile,NULL);
调整缓冲区大小(大小);
读取文件(hfile,&缓冲区[0],大小,0,空);
闭合手柄(hfile);
对于(int i=0;i rcItem;
正确的r=di->rcItem;
r、 右=右左+右宽度()/16;
HBRUSH笔刷=(HBRUSH)选择对象(di->hDC,GetStockObject(白色笔刷));
FillRect(di->hDC,&di->rcItem,画笔);
对于(int i=0;i<16;i++)
{
无符号int cursor=di->itemID*16+i;
如果(游标>=Buffer.size())
打破
csts;
s、 格式(L“%02X”,缓冲区[光标];
DrawText(di->hDC,s,s.GetLength(),r,DT_EDITCONTROL | DT|u CENTER | DT|u VCENTER | DT|u SINGLELINE);
}
}
仅无效按钮向下(UINT f,CPP点)
{
CListBox::OnLButtonDown(f,p);
设置();
int w=SaveItemRect.Width()/16;
正确的r=SaveItemRect;
r、 右=右+左+西;
对于(int i=0;i<16;i++)
{
如果(r.p.删除(p))
{
unsigned int index=GetCurSel()*16+i;
如果(索引>=Buffer.size())
返回;
指数=指数;
GetParent()->SetRedraw(0);
csts;
s、 格式(L“%02X”,缓冲区[索引]);
编辑.SetWindowText;
编辑.SetWindowPos(0,右左,右上,右宽(),右高(),SWP_NOZORDER | SWP_NOREDRAW | SWP_SHOWWINDOW);
Edit.SetFocus();
GetParent()->SetRedraw(1);
打破
}
r、 偏距(w,0);
}
}
//******已更改******
void MeasureItem(LPMEASUREITEMSTRUCT m){m->itemHeight=21;}
int CompareItem(LPCOMPAREITEMSTRUCT){返回0;}
//******已更改******
声明消息映射()
};
开始消息映射(ClisEx、ClisBox)
关于WM_LBUTTONDOWN()
结束消息映射()
另外,
- 您可以为
CEdit
- 重写
以关闭编辑框CMyEdit::OnKillFocus()
- 重写
以仅接受十六进制字符CMyEdit::OnChar
- 读取编辑字符串,然后转换为
,并将其分配给无符号字符
缓冲区[索引]
- 覆盖
以关闭编辑框clisEx::OnVScroll
list.Create(WS_VSCROLL | WS|u BORDER | WS|u CHILD | WS|u VISIBLE | LBS|USETABSTOPS | LBS|OWNERDRAWFIXED,CRect(10,10,450,350),this,1001);
list.read();
请稍等,我将修正我的问题,使其更加精确。至少显示用于打开文件的代码。若要将字节转换为十六进制表示形式,请使用sprintf(displaybuf,“%02X”,byte)
其中byte是char
或unsigned char
谢谢,但是如何用这些数据填充editbox并使其像在Hexdump中一样可编辑呢?谢谢,我尝试了第一个带有滚动的多行编辑框的代码片段,现在我看到了文件的十六进制表示形式。现在我将尝试将所有内容放在一起,并使其在我需要的方式。@Barmak Shemirani,当然,我想看看。我更改了答案,旧答案仍然在这里:(滚动到底部查看第一次修订)奇怪的是,我添加了一个列表框,将类声明添加到.h文件,将消息映射添加到.cpp文件(还有用于读写过程的按钮)但当我试图读取文件时,我在void AFXAPI AfxUnlockGlobals(int nLockType)上遇到了调试器错误。这可能是什么?我不确定那是什么错误。我在代码中有几个错误,我应该使用无效句柄值
检查文件的创建情况(请参阅更新的答案)。还可以尝试使用create手动创建列表框
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()