📄 hexview.c
字号:
}
VOID HV_OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PHEXVIEW pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
int i;
NMHDR n;
if (pHex->NoCursor == TRUE)
{
switch ((TCHAR)wParam)
{
case VK_UP:
if (pHex->PageOffset > 0)
pHex->PageOffset -= pHex->LineWidth;
break;
case VK_DOWN:
if (pHex->PageLength >= pHex->LineWidth)
pHex->PageOffset += pHex->LineWidth;
break;
}
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
}
else
{
switch ((TCHAR)wParam)
{
case VK_UP:
i = HV_MoveCursor(pHex, 0, -1);
break;
case VK_DOWN:
i = HV_MoveCursor(pHex, 0, 1);
break;
case VK_LEFT:
i = HV_MoveCursor(pHex, -1, 0);
break;
case VK_RIGHT:
i = HV_MoveCursor(pHex, 1, 0);
break;
default:
return;
}
pHex->SelEnd = -1;
HV_UpdatePage(hWnd, i);
n.code = HV_EN_SELCHANGE;
n.idFrom = GetDlgCtrlID(hWnd);
n.hwndFrom = hWnd;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&n);
}
}
VOID HV_MouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PHEXVIEW pHex;
ULONG i;
INT TopPos, BottomPos;
NMHDR n;
if (wParam & MK_LBUTTON)
{
pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
TopPos = pHex->CharHeight;
BottomPos = (pHex->PageMaxLength / pHex->LineWidth) * pHex->CharHeight;
if ((short)HIWORD(lParam) < TopPos)
{
HV_OnVscroll(hWnd, SB_LINEUP, 0);
//SendMessage(hWnd, WM_MOUSEMOVE, wParam, lParam);
}
if ((short)HIWORD(lParam) >= BottomPos)
{
HV_OnVscroll(hWnd, SB_LINEDOWN, 0);
//SendMessage(hWnd, WM_MOUSEMOVE, wParam, lParam);
}
i = HV_GetCurrentCursor(pHex, LOWORD(lParam), HIWORD(lParam), NULL);
pHex->SelEnd = i;
pHex->Cursor = i;
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
n.code = HV_EN_SELCHANGE;
n.idFrom = GetDlgCtrlID(hWnd);
n.hwndFrom = hWnd;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&n);
}
}
VOID HV_ResetSize(HWND hWnd)
{
HDC hDC;
HFONT hFont, hOldFont;
SIZE charSize;
RECT rect;
UINT nWndHeight;
PHEXVIEW pHex;
SCROLLINFO si;
pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
hFont = CreateFont(-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New");
hDC = GetDC(hWnd);
hOldFont = SelectObject(hDC, hFont);
GetTextExtentPoint32(hDC, "0", 1, &charSize);
pHex->CharWidth = charSize.cx;
pHex->CharHeight = charSize.cy;
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
ReleaseDC(hWnd, hDC);
GetClientRect(hWnd, &rect);
nWndHeight = rect.bottom - rect.top;
pHex->PageMaxLength = (nWndHeight / pHex->CharHeight - 1) * pHex->LineWidth;
pHex->PageLength = MIN(pHex->Length - pHex->PageOffset, pHex->PageMaxLength);
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = pHex->Length / pHex->LineWidth +
(pHex->Length % pHex->LineWidth == 0 ? 0 : 1);
si.nPage = pHex->PageMaxLength / pHex->LineWidth + 1;
si.nPos = 0;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
if (pHex->Length > pHex->PageMaxLength)
{
EnableScrollBar(hWnd, SB_VERT, ESB_ENABLE_BOTH);
}
else
{
EnableScrollBar(hWnd, SB_VERT, ESB_DISABLE_BOTH);
}
}
int HV_FindText(HWND hWnd, PHV_FIND hv_find)
{
PBYTE p1, p2, pp;
DWORD i, n, count;
PHEXVIEW pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
NMHDR nm;
if (hv_find->nLen > 0x8000)
return -1;
if (pHex->Length == 0)
return -1;
if (hv_find->dwFlags & ~HV_FIND_MATCHCASE)
{
n = MIN(pHex->Length, 0x10000);
p1 = VirtualAlloc( NULL,
n + hv_find->nLen,
MEM_COMMIT,
PAGE_READWRITE);
if (p1 == NULL)
return -1;
p2 = p1 + n;
pp = hv_find->pMem;
for (i = 0; i < hv_find->nLen; i++)
{
if (pp[i] >= 'a' && pp[i] <= 'z')
p2[i] = pp[i] - 'a' + 'A';
else
p2[i] = pp[i];
}
}
else
{
n = MIN(pHex->Length, 0x10000);
p1 = VirtualAlloc( NULL,
n,
MEM_COMMIT,
PAGE_READWRITE);
if (p1 == NULL)
return -1;
p2 = hv_find->pMem;
}
for (count = hv_find->cpMin;;)
{
n = MIN(pHex->Length - count, 0x10000);
HV_GetModifyData(&pHex->hv_modl, count, p1, n);
if (hv_find->dwFlags & ~HV_FIND_MATCHCASE)
{
for (i = 0; i < n; i++)
{
if (p1[i] >= 'a' && p1[i] <= 'z')
p1[i] -= 'a' - 'A';
}
}
pp = HV_MemSearchR(p1, n, p2, hv_find->nLen);
if (pp != NULL)
{
n = pp - p1 + count;
pHex->SelStart = n;
pHex->SelEnd = n + hv_find->nLen - 1;
pHex->Cursor = n;
if (n >= pHex->PageOffset + pHex->PageLength)
{
n /= pHex->LineWidth;
n -= pHex->PageMaxLength / pHex->LineWidth - 1;
pHex->PageOffset = n * pHex->LineWidth;
pHex->PageLength = MIN(pHex->PageMaxLength, pHex->Length - pHex->PageOffset);
HV_UpdatePage(hWnd, n);
}
else if (n < pHex->PageOffset)
{
n /= pHex->LineWidth;
pHex->PageOffset = n * pHex->LineWidth;
pHex->PageLength = MIN(pHex->PageMaxLength, pHex->Length - pHex->PageOffset);
HV_UpdatePage(hWnd, n);
}
nm.code = HV_EN_SELCHANGE;
nm.idFrom = GetDlgCtrlID(hWnd);
nm.hwndFrom = hWnd;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&nm);
break;
}
if (pHex->Length - i > 0x10000)
{
i += 0x10000 - hv_find->nLen;
}
else
break;
}
VirtualFree(p1, 0, MEM_RELEASE);
return 0;
}
LRESULT CALLBACK HV_HexViewProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PHEXVIEW p;
HGLOBAL hGlobal;
PBYTE pGlobal, pSource;
LONG i, SelLength, MemSize;
NMHDR n;
switch (uMsg)
{
case WM_MOUSEMOVE:
HV_MouseMove(hWnd, wParam, lParam);
break;
case WM_LBUTTONDOWN:
SetCapture(hWnd);
SetFocus(hWnd);
HV_LButtonDown(hWnd, wParam, lParam);
break;
case WM_LBUTTONUP:
ReleaseCapture();
break;
case WM_VSCROLL:
HV_OnVscroll(hWnd, wParam, lParam);
break;
case WM_MOUSEWHEEL:
if ((short)HIWORD(wParam) > 0)
{
HV_OnVscroll(hWnd, SB_LINEUP, 0);
}
else
{
HV_OnVscroll(hWnd, SB_LINEDOWN, 0);
}
break;
case WM_PAINT:
HV_OnPaint(hWnd);
break;
case WM_CHAR:
HV_OnChar(hWnd, wParam);
break;
case WM_KEYDOWN:
HV_OnKeyDown(hWnd, wParam, lParam);
break;
case WM_SETFOCUS:
SetTimer(hWnd, WM_TIMER, 500, HV_TimerProc);
break;
case WM_KILLFOCUS:
KillTimer(hWnd, WM_TIMER);
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
break;
case WM_SIZE:
HV_ResetSize(hWnd);
break;
case HV_SETHANDLE:
if ((ULONG)wParam < 512 * 1024 * 1024)
{
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
p->Buffer = (LPSTR)lParam;
p->Length = (ULONG)wParam;
p->PageOffset = 0;
p->SelEnd = -1;
p->Cursor = 0;
p->EditMode = EM_HEX_HIGH;
HV_ResetModifyLog(&p->hv_modl, p->Buffer, p->Length);
HV_AddModifyLog(&p->hv_modl, 39, 3, "324");
HV_AddModifyLog(&p->hv_modl, 41, 7, "abcdefg");
HV_AddModifyLog(&p->hv_modl, 22, 14, "happy new year");
p->hv_modl.nLog = 0;
HV_ResetSize(hWnd);
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
n.code = HV_EN_CHANGE;
n.idFrom = GetDlgCtrlID(hWnd);
n.hwndFrom = hWnd;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&n);
n.code = HV_EN_SELCHANGE;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&n);
}
break;
case HV_CANUNDO:
return HV_LogUndo(hWnd, TRUE);
case HV_CANREDO:
return HV_LogRedo(hWnd, TRUE);
case HV_UNDO:
return HV_LogUndo(hWnd, FALSE);
case HV_REDO:
return HV_LogRedo(hWnd, FALSE);
case HV_GETSEL:
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
*(DWORD *)wParam = p->SelStart;
*(DWORD *)lParam = p->SelEnd;
break;
case HV_SETSEL:
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
p->SelStart = (DWORD)wParam;
p->SelEnd = (DWORD)lParam;
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
n.code = HV_EN_SELCHANGE;
n.idFrom = GetDlgCtrlID(hWnd);
n.hwndFrom = hWnd;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&n);
break;
case HV_SELALL:
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
p->SelStart = 0;
p->SelEnd = p->Length;
p->Cursor = (p->Length << 1) - 1;
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
n.code = HV_EN_SELCHANGE;
n.idFrom = GetDlgCtrlID(hWnd);
n.hwndFrom = hWnd;
SendMessage(GetParent(hWnd), WM_NOTIFY, GetDlgCtrlID(hWnd), (LPARAM)&n);
break;
case HV_COPY:
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
SelLength = p->SelEnd - p->SelStart;
SelLength = MAX(SelLength, -SelLength) + 1;
hGlobal = GlobalAlloc(GHND | GMEM_SHARE, SelLength + 1);
if (hGlobal == NULL)
break;
pGlobal = GlobalLock(hGlobal);
pSource = p->Buffer + MIN(p->SelEnd, p->SelStart);
strncpy(pGlobal, pSource, SelLength);
GlobalUnlock(hGlobal);
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobal);
CloseClipboard();
break;
case HV_COPYHEX:
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
SelLength = p->SelEnd - p->SelStart;
SelLength = MAX(SelLength, -SelLength) + 1;
MemSize = SelLength * 3 + SelLength / 16;
hGlobal = GlobalAlloc(GHND | GMEM_SHARE, MemSize + 1);
if (hGlobal == NULL)
break;
pGlobal = GlobalLock(hGlobal);
pSource = p->Buffer + MIN(p->SelEnd, p->SelStart);
for (i = 0; i < SelLength;)
{
*pGlobal++ = "0123456789ABCDEF"[pSource[i] >> 4];
*pGlobal++ = "0123456789ABCDEF"[pSource[i] & 15];
*pGlobal++ = ' ';
if (!(++i & 15))
{
*(pGlobal - 1) = '\r';
*pGlobal++ = '\n';
}
}
*pGlobal = '\0';
GlobalUnlock(hGlobal);
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobal);
CloseClipboard();
break;
case HV_SETCOLOR:
if ((DWORD)wParam < 10)
{
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
p->color[(DWORD)wParam] = lParam;
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
}
break;
case HV_APPLYMODIFY:
p = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
HV_ApplyModifyLog(&p->hv_modl, (PBYTE)lParam);
if ((PBYTE)lParam != NULL) p->Buffer = (PBYTE)lParam;
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
break;
case HV_FINDTEXT:
HV_FindText(hWnd, (PHV_FIND)lParam);
break;
case WM_CREATE:
p = xmalloc(sizeof(HEXVIEW));
p->NoCursor = FALSE;
p->ReadOnly = TRUE;
p->BaseAddress = 0;
p->PageOffset = 0;
p->Length = 0;
p->Buffer = NULL;
p->AddressWidth = 4;
p->LineWidth = 16;
p->SelStart = 0;
p->SelEnd = -1;
p->color[HV_COLOR_BG0] = RGB(255, 255, 255);
p->color[HV_COLOR_BG1] = RGB(192, 192, 192);
p->color[HV_COLOR_ADDR] = RGB(0, 0, 255);
p->color[HV_COLOR_HEX] = RGB(0, 0, 0);
p->color[HV_COLOR_TEXT] = RGB(0, 0, 0);
p->color[HV_COLOR_MODIFY] = RGB(255, 0, 0);
SetWindowLong(hWnd, GWL_HEXINFO, (LONG)p);
HV_ResetSize(hWnd);
HV_InitModifyLog(&p->hv_modl, p->Buffer, p->Length);
break;
case WM_DESTROY:
p = (void *)GetWindowLong(hWnd, GWL_HEXINFO);
HV_FreeModifyLog(&p->hv_modl);
xfree(p);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
BOOL InitHexViewClass(VOID)
{
LPSTR lpClass = "HexView";
WNDCLASS wc;
HINSTANCE hInstance;
hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = (WNDPROC)HV_HexViewProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(void *);
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = lpClass;
if (!RegisterClass(&wc))
{
if (!GetClassInfo(hInstance, lpClass, &wc))
return FALSE;
if (wc.lpfnWndProc != (WNDPROC)HV_HexViewProc)
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -