📄 hexeditwnd.cpp
字号:
void HexEditWnd::InitGotoDlg(HWND hDlg)
{
// hook editbox proc
HookHexEditbox( GetDlgItem(hDlg, GO_OFFSET) );
// limit text len
SendDlgItemMessage(hDlg, GO_OFFSET, EM_SETLIMITTEXT, 8, 0);
return;
}
BOOL HexEditWnd::GDHandleWM_COMMAND(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DWORD dwNewOff;
char cBuff[9];
switch(LOWORD(wParam))
{
case GO_OFFSET:
if (HIWORD(wParam) != NM_HEXEDITENTER)
return FALSE;
case GO_OK:
// get off
GetDlgItemText(hDlg, GO_OFFSET, cBuff, sizeof(cBuff));
HexStrToInt(cBuff, &dwNewOff);
if (!IsOutOfRange(dwNewOff))
{
KillSelection();
SetCaretPosData(dwNewOff);
SendMessage(hDlg, WM_CLOSE, 1, 0);
}
else
ErrMsg(hDlg, "Out of range !");
return TRUE;
case GO_CANCEL:
SendMessage(hDlg, WM_CLOSE, 0, 0);
return TRUE;
}
return FALSE;
}
void HexEditWnd::ErrMsg(HWND hWnd, char* szText)
{
MessageBox(hWnd, szText, "ERROR", MB_ICONERROR);
return;
}
//
// overloaded
//
void HexEditWnd::ErrMsg(char* szText)
{
MessageBox(hMainWnd, szText, "ERROR", MB_ICONERROR);
return;
}
//
// overloaded
//
void HexEditWnd::ErrMsg(HWND hWnd, char* szText, char* szCaption)
{
MessageBox(hWnd, szText, szCaption, MB_ICONERROR);
return;
}
BOOL HexEditWnd::IsOutOfRange(DWORD dwOffset)
{
return (dwOffset >= diData.dwSize) ? TRUE : FALSE;
}
//
// overloaded
//
BOOL HexEditWnd::IsOutOfRange(PHE_POS ppos)
{
return (ppos->dwOffset >= diData.dwSize) ? TRUE : FALSE;
}
//
// simply fills the HE_POS struct of the caret
//
void HexEditWnd::SetCaretPosData(PHE_POS ppos)
{
memcpy(
&stat.posCaret,
ppos,
sizeof(HE_POS));
stat.bCaretPosValid = TRUE;
return;
}
//
// overloaded
//
void HexEditWnd::SetCaretPosData(DWORD dwOffset)
{
HE_POS posNew;
posNew.bHiword = TRUE;
posNew.bTextSection = FALSE;
posNew.dwOffset = dwOffset;
SetCaretPosData(&posNew);
return;
}
//
// returns:
// 0 - if the message was processed
//
LRESULT HexEditWnd::HEHandleWM_CHAR(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BYTE byNew, byMask;
// caret set ?
if (!stat.bCaretVisible ||
!stat.bCaretPosValid)
return 1; // ERR
// skip key combinations (STR + Z, ...)
if (wParam < 0x20)
return 1; // ERR
if (IsReadOnly())
{
Beep();
return 1; // ERR
}
//
// process HE change
//
if (stat.posCaret.bTextSection)
{
*(BYTE*)((DWORD)diData.pDataBuff + stat.posCaret.dwOffset) = (BYTE)wParam;
}
else
{
// build new byte
if (wParam >= '0' && wParam <= '9')
byMask = wParam - 0x30;
else if (wParam >= 'a' && wParam <= 'f')
byMask = wParam - 87;
else if (wParam >= 'A' && wParam <= 'F')
byMask = wParam - 55;
else
return 1; // ERR
byNew = *(BYTE*)((DWORD)diData.pDataBuff + stat.posCaret.dwOffset);
if (stat.posCaret.bHiword)
byNew = (byNew & 0x0F) + byMask * 16;
else
byNew = (byNew & 0xF0) + byMask;
*(BYTE*)((DWORD)diData.pDataBuff + stat.posCaret.dwOffset) = byNew;
}
//
// reset caret
//
if (stat.posCaret.bTextSection)
{
++stat.posCaret.dwOffset;
}
else
{
if (!stat.posCaret.bHiword)
++stat.posCaret.dwOffset;
stat.posCaret.bHiword ^= 1;
}
stat.bChanges = TRUE;
ConfigureTB();
ValidatePos(&stat.posCaret);
SetCaret();
return 0; // OK
}
//
// enables/disables toolbar buttons
//
void HexEditWnd::ConfigureTB()
{
BOOL bEnabled;
// save button
bEnabled = !IsReadOnly() && stat.bChanges;
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_SAVE,
bEnabled ? 2 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_SAVE,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
// undo button
bEnabled = !IsReadOnly() && stat.bChanges;
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_UNDO,
bEnabled ? 14 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_UNDO,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
// top button
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_WIN2TOP,
bHEOnTop ? 5 : 6);
// search buttons
bEnabled = search.bInited;
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_SEARCHDOWN,
bEnabled ? 13 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_SEARCHDOWN,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_SEARCHUP,
bEnabled ? 12 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_SEARCHUP,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
// cut button
bEnabled = stat.bSel && !IsReadOnly() && IsResizingAllowed();
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_CUT,
bEnabled ? 9 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_CUT,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
// copy button
bEnabled = stat.bSel;
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_COPY,
bEnabled ? 10 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_COPY,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
// paste button
bEnabled = !IsReadOnly() && IsResizingAllowed();
SendMessage(hTB,
TB_CHANGEBITMAP,
TB_PASTE,
bEnabled ? 11 : 4);
SendMessage(hTB,
TB_SETSTATE,
TB_PASTE,
bEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
return;
}
BOOL HexEditWnd::SaveChanges()
{
BOOL bRet = FALSE;
void* pNewOrgMem;
HE_ACTION act;
// valid?
if (IsReadOnly() ||
!stat.bChanges)
goto Exit; // ERR
SetStatusText("Saving...");
RepaintClientAreaNow();
//
// save changes to buffer (and to disk)
//
if (fInput.GetMapPtr())
{
// alloc more mem if needed
if (diOrgData.dwSize < diData.dwSize)
{
pNewOrgMem = realloc(diOrgData.pDataBuff, diData.dwSize);
if (!pNewOrgMem)
{
ErrMsg("Not enough memory available to update the buffer with the original data !");
goto SkipOrgBuffUpdate;
}
else
diOrgData.pDataBuff = pNewOrgMem;
}
memcpy(
diOrgData.pDataBuff,
diData.pDataBuff,
diData.dwSize);
// set vars
diOrgData.dwSize = diData.dwSize;
fInput.SetMapPtrSize(diOrgData.pDataBuff, diOrgData.dwSize);
SkipOrgBuffUpdate:
fInput.FlushFileMap();
}
else
{
// current working memory buffer greater than org mem buffer ?
if (diData.dwSize > diOrgData.dwSize)
{
diData.pDataBuff = realloc(diData.pDataBuff, diOrgData.dwSize);
diData.dwSize = diOrgData.dwSize;
}
memcpy(
diOrgData.pDataBuff,
diData.pDataBuff,
diData.dwSize);
}
//
// repaint
//
stat.bChanges = FALSE;
SetCaretSelInfoToStatus();
RepaintClientArea();
ConfigureTB();
//
// inform about HE_ACTION_SAVED
//
if (pActionHandler)
{
ZERO(act);
act.dwNewSize = diData.dwSize;
act.dwActionCode = HE_ACTION_SAVED;
pActionHandler(&act);
}
bRet = TRUE;
Exit:
return bRet;
}
void HexEditWnd::SetHEWndCaption()
{
char cCaption[400];
if (!diOrgData.dwSize)
SetWindowText(hMainWnd, HEDIT_WND_TITLE);
// build str
lstrcpy(cCaption, HEDIT_WND_TITLE);
lstrcat(cCaption, " - \"");
if (fInput.GetMapPtr())
lstrcat(cCaption, fInput.GetFilePath());
else
lstrcat(cCaption, szMemoryBuff);
lstrcat(cCaption, "\" ");
if (IsReadOnly())
lstrcat(cCaption, "[READONLY]");
else
lstrcat(cCaption, "[READWRITE]");
// set
SetWindowText(hMainWnd, cCaption);
return;
}
void HexEditWnd::SetStatusText(char *szFormat, ...)
{
va_list args;
va_start(args, szFormat);
wvsprintf(cSBText, szFormat, args);
va_end(args);
return;
}
BOOL HexEditWnd::IsReadOnly()
{
return diOrgData.bReadOnly;
}
//
// selects a block
//
BOOL HexEditWnd::SetSelection(DWORD dwOffStart, DWORD dwOffEnd)
{
// input valid?
if (IsOutOfRange(dwOffStart) ||
IsOutOfRange(dwOffEnd))
return FALSE; // ERR
// set sel vars
stat.dwOffSelStart = __min(dwOffStart, dwOffEnd);
stat.dwOffSelEnd = __max(dwOffStart, dwOffEnd);
stat.bSel = TRUE;
// set caret vars
if (stat.bCaretVisible)
{
HideCaret(hMainWnd);
stat.bCaretVisible = FALSE;
}
if (dwOffEnd > dwOffStart)
{
stat.posCaret.bHiword = FALSE;
stat.posCaret.dwOffset = dwOffEnd;
}
else
{
stat.posCaret.bHiword = TRUE;
stat.posCaret.dwOffset = dwOffEnd;
}
// make caret pos valid
if (!stat.bCaretPosValid)
{
stat.posCaret.bTextSection = FALSE;
stat.bCaretPosValid = TRUE;
}
// setup TB
ConfigureTB();
// repaint
SetCaretSelInfoToStatus();
RepaintClientArea();
return TRUE; // OK
}
//
// returns:
// whether there was a selection before
//
BOOL HexEditWnd::KillSelection()
{
if (stat.bSel)
{
stat.bSel = FALSE;
// setup TB
ConfigureTB();
return TRUE;
}
else
return FALSE;
}
//
// args:
// ppClient - x and y position in client coordinates
//
// returns:
// whether the the input changed the selection
//
BOOL HexEditWnd::Point2Selection(LPPOINT ppClient)
{
HE_POS pos, *pposLast;
if (!stat.bLastLBDownPos)
return FALSE; //ERR
if (!PointToPos(ppClient, &pos))
return FALSE; // ERR
// mouse moved since last button down ?
pposLast = &stat.posLastLButtonDown;
if (pos.bTextSection == pposLast->bTextSection)
{
if ((pos.dwOffset != pposLast->dwOffset) ||
((pos.dwOffset == pposLast->dwOffset) && pos.bHiword != pposLast->bHiword))
{
SetSelection(pposLast->dwOffset, pos.dwOffset);
RepaintClientArea();
return TRUE; // OK
}
}
return FALSE; // ERR
}
//
// Args:
// hWnd - can be the window handle of the main window or of the TB
//
BOOL HexEditWnd::HEHandleWM_MOUSEMOVE(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
POINT poi;
BOOL bRet;
//
// handle selection
//
if ( !TESTBIT(wParam, MK_LBUTTON) )
return FALSE; // ERR
poi.x = LOWORD(lParam);
poi.y = HIWORD(lParam);
// cursor not in text/hex region ?
if ((DWORD)poi.x > PAIRS_X
&& (DWORD)poi.x < CHARS_X + 16*uFontWidth
&& stat.bMouseSelecting)
if ((DWORD)poi.y > iyHETop + uMaxLines*uFontHeight) // under ?
{
// scroll down
stat.posCaret.dwOffset += 2*16;
ValidatePos( &stat.posCaret );
MakeCaretVisible();
if (stat.posCaret.bTextSection)
poi.x = CHARS_X + 15*uFontWidth;
else
poi.x = PAIRS_X + 15*DIGIT_PAIR_WIDTH;
poi.y = iyHETop + uFontHeight * (uMaxLines-1);
}
else if ((DWORD)poi.y < iyHETop) // over ?
{
// scroll up
stat.posCaret.dwOffset -= 2*16;
ValidatePos( &stat.posCaret );
MakeCaretVisible();
if (stat.posCaret.bTextSection)
poi.x = CHARS_X;
else
poi.x = PAIRS_X;
poi.y = iyHETop;
}
bRet = Point2Selection(&poi);
return bRet; // RET
}
UINT HexEditWnd::GetCurrentLine()
{
return (UINT)(stat.dwCurOffset / 16);
}
//
// same as "SetTopLine" but fails if "iLine" is invalid
//
BOOL HexEditWnd::SetCurrentLine(UINT iLine)
{
if ((int)iLine < 0)
return FALSE; // ERR
if (iLine > GetTotalLineNum())
return FALSE; // ERR
SetTopLine((int)iLine);
return TRUE;
}
//
// returns:
// whether sth was fixed
//
BOOL HexEditWnd::ValidateLine(int *piLine)
{
int iLastLine = GetTotalLineNum();
if (*piLine < 0)
{
*piLine = 0;
return TRUE; // OK
}
else if (*piLine > iLastLine)
{
*piLine = iLastLine;
return TRUE; // OK
}
else
return FALSE; // ERR
}
//
// returns:
// whether the last state
//
BOOL HexEditWnd::SetHEWnd2Top(BOOL bTop)
{
RECT rect;
BOOL bBefore;
// set wnd state
GetWindowRect(hMainWnd, &rect);
SetWindowPos(
hMainWnd,
bTop ? HWND_TOPMOST : HWND_NOTOPMOST,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
SWP_SHOWWINDOW);
// handle vars
bBefore = bHEOnTop;
bHEOnTop = bTop;
return bBefore;
}
void HexEditWnd::InitSelBlockDlg(HWND hDlg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -