📄 hexview.c
字号:
bHighLight = FALSE;
if (selEnd != -1)
{
if (j + startAddr < selStart)
{
k = MIN((DWORD)k, selStart - (j + startAddr));
bHighLight = FALSE;
}
else if ((DWORD)j + startAddr == selStart)
{
k = MIN((DWORD)k, selEnd - (j + startAddr) + 1);
bHighLight = TRUE;
}
else if ((DWORD)j + startAddr <= selEnd)
{
k = MIN((DWORD)k, selEnd - (j + startAddr) + 1);
bHighLight = TRUE;
}
}
hv_pfmt = (PHV_PRINTFMT)buf; //输出十六进制
hv_pfmt->x = (1 + 8 + 1 + j * 3);
hv_pfmt->y = i;
hv_pfmt->color = bModify ? HV_COLOR_MODIFY : HV_COLOR_HEX;
hv_pfmt->highlight = bHighLight ? 1 : 0;
hv_pfmt->len = k * 3;
buf += sizeof(HV_PRINTFMT);
for (l = 0; l < k; l++)
{
*buf++ = "0123456789ABCDEF"[(text[i * lineWidth + j + l] >> 4) & 15];
*buf++ = "0123456789ABCDEF"[(text[i * lineWidth + j + l] >> 0) & 15];
*buf++ = ' ';
}
if (j + k >= lineWidth - 1 || (bHighLight && j + startAddr + k == selEnd + 1))
{
hv_pfmt->len -= 1;
buf--;
}
hv_pfmt = (PHV_PRINTFMT)buf; //输出文本
hv_pfmt->x = (1 + 8 + lineWidth * 3 + 4 + j);
hv_pfmt->y = i;
hv_pfmt->color = bModify ? HV_COLOR_MODIFY : HV_COLOR_TEXT;
hv_pfmt->highlight = bHighLight ? 1 : 0;
hv_pfmt->len = k;
buf += sizeof(HV_PRINTFMT) + hv_pfmt->len;
for (l = 0; l < k; l++)
hv_pfmt->data[l] = text[i * lineWidth + j + l] < 0x20 ? '.' : text[i * lineWidth + j + l];
}
startAddr += lineWidth;
}
hv_pfmt = (PHV_PRINTFMT)buf; //输出结束
hv_pfmt->x = 0;
hv_pfmt->y = 0;
hv_pfmt->color = 0;
hv_pfmt->len = 0;
}
VOID HV_PrintHexView(HDC hDC, PHEXVIEW pHex, DWORD nWidth, DWORD nHeight)
{
TCHAR HexTitle[] = " OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F ";
HFONT hFont, hOldFont;
HBRUSH hbr;
PHV_PRINTFMT hv_pfmt;
DWORD lastBgColor = -1, lastColor = -1;
UINT nCharWidth, nCharHeight;
PVOID fmt;
RECT rc;
LONG SelStart, SelEnd;
hFont = CreateFont(-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New");
hOldFont = SelectObject(hDC, hFont);
nCharWidth = pHex->CharWidth;
nCharHeight = pHex->CharHeight;
rc.top = 0;
rc.left = 0;
rc.bottom = nHeight;
rc.right = nWidth;
hbr = CreateSolidBrush(pHex->color[HV_COLOR_BG0]);
FillRect(hDC, &rc, hbr);
DeleteObject(hbr);
SetBkColor(hDC, RGB(0, 255, 255));
TextOut(hDC, nCharWidth, 0, HexTitle, 9 + pHex->LineWidth * 3);
fmt = VirtualAlloc(NULL, 0x5000, MEM_COMMIT, PAGE_READWRITE);
if (fmt == NULL)
return;
SelStart = MIN(pHex->SelStart, pHex->SelEnd);
SelEnd = MAX(pHex->SelStart, pHex->SelEnd);
HV_FormatForPrint( pHex->LineWidth,
nHeight / nCharHeight - 1,
pHex->PageOffset,
&pHex->hv_modl,
pHex->Buffer,
SelStart,
SelEnd,
fmt);
do
{
hv_pfmt = (PHV_PRINTFMT)fmt;
(PBYTE)fmt += sizeof(HV_PRINTFMT) + hv_pfmt->len;
if (hv_pfmt->len == 0)
break;
if (pHex->color[hv_pfmt->color] != lastColor)
{
SetTextColor(hDC, pHex->color[hv_pfmt->color]);
lastColor = pHex->color[hv_pfmt->color];
}
if (pHex->color[hv_pfmt->highlight] != lastBgColor)
{
SetBkColor(hDC, pHex->color[hv_pfmt->highlight]);
lastBgColor = pHex->color[hv_pfmt->highlight];
}
TextOut( hDC,
hv_pfmt->x * nCharWidth,
hv_pfmt->y * nCharHeight + nCharHeight,
hv_pfmt->data,
hv_pfmt->len);
} while (1);
VirtualFree(fmt, 0, MEM_RELEASE);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
}
ULONG HV_GetCurrentCursor(PHEXVIEW pHex, short x, short y, PDWORD pEditMode)
{
UINT nCharWidth, nCharHeight;
int lenHex, lenAscii;
int bx, by, mx, my, middle;
DWORD dwEditMode;
nCharWidth = pHex->CharWidth;
nCharHeight = pHex->CharHeight;
bx = x / (int)nCharWidth;
by = y / (int)nCharHeight - 1;
bx -= pHex->AddressWidth * 2 + 2;
middle = pHex->LineWidth * 3 + 1;
lenHex = pHex->LineWidth * 3 - 1;
lenAscii = pHex->LineWidth;
mx = pHex->PageLength % pHex->LineWidth;
my = pHex->PageLength / pHex->LineWidth;
mx = pHex->LineWidth - mx;
if (by < 0)
by = 0;
if (by > my)
by = my;
if (mx != 0 && by == my)
{
lenHex -= mx * 3;
lenAscii -= mx;
}
if (bx >= middle)
{
bx -= middle + 2;
if (bx < 0)
{
bx = 0;
}
else if (bx >= lenAscii)
{
bx = lenAscii - 1;
}
dwEditMode = EM_TEXT;
}
else
{
if (bx < 0)
{
bx = 0;
}
if ((bx + 1) % 3 == 0)
{
if (x % nCharWidth < nCharWidth / 2)
{
bx--;
}
else
{
bx++;
}
}
if (bx >= lenHex)
{
bx = lenHex - 1;
}
if ((bx + 1) % 3 == 1)
dwEditMode = EM_HEX_HIGH;
else
dwEditMode = EM_HEX_LOW;
bx = (bx + 1) / 3;
}
if (pEditMode != NULL)
*pEditMode = dwEditMode;
return bx + by * pHex->LineWidth + pHex->PageOffset;
}
VOID HV_OnPaint(HWND hWnd)
{
UINT nWndWidth, nWndHeight;
HDC hDC, hMemDC;
HBITMAP hBitmap;
RECT rect;
PAINTSTRUCT ps;
GetClientRect(hWnd, &rect);
nWndWidth = rect.right - rect.left;
nWndHeight = rect.bottom - rect.top;
hDC = BeginPaint(hWnd, &ps);
hMemDC = CreateCompatibleDC(hDC);
hBitmap = CreateCompatibleBitmap(hDC, nWndWidth, nWndHeight);
SelectObject(hMemDC, hBitmap);
HV_PrintHexView( hMemDC,
(PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO),
nWndWidth,
nWndHeight);
BitBlt(hDC, 0, 0, nWndWidth, nWndHeight, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
DeleteObject(hBitmap);
EndPaint(hWnd, &ps);
}
int HV_MoveCursor(PHEXVIEW pHex, int lx, int ly)
{
if (lx != 0)
{
switch (pHex->EditMode)
{
case EM_TEXT:
pHex->Cursor += lx;
break;
case EM_HEX_HIGH:
if (lx > 0)
{
pHex->EditMode = lx & 1 ? EM_HEX_LOW : EM_HEX_HIGH;
pHex->Cursor += lx / 2;
}
else
{
pHex->EditMode = lx & 1 ? EM_HEX_LOW : EM_HEX_HIGH;
pHex->Cursor += (lx - 1) / 2;
}
break;
case EM_HEX_LOW:
if (lx > 0)
{
pHex->EditMode = lx & 1 ? EM_HEX_HIGH : EM_HEX_LOW;
pHex->Cursor += (lx + 1) / 2;
}
else
{
pHex->EditMode = lx & 1 ? EM_HEX_HIGH : EM_HEX_LOW;
pHex->Cursor += lx / 2;
}
break;
}
}
pHex->Cursor += ly * pHex->LineWidth;
if (pHex->Cursor >= (int)(pHex->Length))
{
pHex->Cursor = pHex->Length - 1;
pHex->EditMode = pHex->EditMode == EM_TEXT ? EM_TEXT : EM_HEX_LOW;
}
else if (pHex->Cursor < 0)
{
pHex->Cursor = 0;
pHex->EditMode = pHex->EditMode == EM_TEXT ? EM_TEXT : EM_HEX_HIGH;
}
if (pHex->Cursor >= (int)(pHex->PageOffset + pHex->PageLength))
{
int n = pHex->Cursor / pHex->LineWidth;
n -= pHex->PageMaxLength / pHex->LineWidth - 1;
pHex->PageOffset = n * pHex->LineWidth;
pHex->PageLength = MIN(pHex->PageMaxLength, pHex->Length - pHex->PageOffset);
return n;
}
else if (pHex->Cursor < (int)pHex->PageOffset)
{
int n = pHex->Cursor / pHex->LineWidth;
pHex->PageOffset = n * pHex->LineWidth;
pHex->PageLength = MIN(pHex->PageMaxLength, pHex->Length - pHex->PageOffset);
return n;
}
return -1;
}
VOID HV_UpdatePage(HWND hWnd, int n)
{
SCROLLINFO si;
if (n != -1)
{
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
SetScrollPos(hWnd, SB_VERT, n, TRUE);
}
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
}
VOID HV_OnChar(HWND hWnd, WPARAM wParam)
{
char ch = (char)wParam, ch1;
PHEXVIEW pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
DWORD off = pHex->Cursor;
int i;
NMHDR n;
if (pHex->EditMode == EM_TEXT)
{
HV_AddModifyLog(&pHex->hv_modl, off, 1, &ch);
i = HV_MoveCursor(pHex, 1, 0);
HV_UpdatePage(hWnd, i);
}
else
{
switch (ch = toupper(ch))
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ch -= '0';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
ch -= 'A' - 0x0a;
break;
default:
return;
}
HV_GetModifyData(&pHex->hv_modl, off, &ch1, 1);
if (pHex->EditMode != EM_HEX_HIGH)
{
if (ch != (ch1 & 0x0f))
{
ch |= ch1 & 0xf0;
HV_AddModifyLog(&pHex->hv_modl, off, 1, &ch);
}
}
else
{
ch <<= 4;
if (ch != (ch1 & 0xf0))
{
ch |= ch1 & 0x0f;
HV_AddModifyLog(&pHex->hv_modl, off, 1, &ch);
}
}
i = HV_MoveCursor(pHex, 1, 0);
HV_UpdatePage(hWnd, i);
}
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);
}
VOID CALLBACK HV_TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
int t, x, y, w, h;
HDC hDC;
PHEXVIEW pHex;
pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
w = pHex->CharWidth;
h = pHex->CharHeight;
if (pHex->NoCursor == TRUE)
return;
t = pHex->Cursor - pHex->PageOffset;
if (t < 0 || t >= (int)pHex->PageLength)
return;
switch (pHex->EditMode)
{
case EM_TEXT:
x = t % pHex->LineWidth;
x += pHex->AddressWidth * 2 + pHex->LineWidth * 3 + 3 + 2;
break;
case EM_HEX_HIGH:
x = t % pHex->LineWidth * 3;
x += pHex->AddressWidth * 2 + 2;
break;
case EM_HEX_LOW:
x = t % pHex->LineWidth * 3 + 1;
x += pHex->AddressWidth * 2 + 2;
break;
}
x *= pHex->CharWidth;
y = (t / pHex->LineWidth + 1) * pHex->CharHeight;
hDC = GetDC(hWnd);
BitBlt(hDC, x, y, w, h, NULL, 0, 0, DSTINVERT);
ReleaseDC(hWnd, hDC);
}
VOID HV_LButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PHEXVIEW pHex;
ULONG i;
NMHDR n;
pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
i = HV_GetCurrentCursor(pHex, LOWORD(lParam), HIWORD(lParam), &pHex->EditMode);
pHex->SelStart = i;
pHex->SelEnd = -1;
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_OnVscroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PHEXVIEW pHex;
int i;
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
GetScrollInfo(hWnd, SB_VERT, &si);
pHex = (PHEXVIEW)GetWindowLong(hWnd, GWL_HEXINFO);
switch (LOWORD(wParam))
{
case SB_LINEUP:
i = si.nPos - 1;
break;
case SB_LINEDOWN:
i = si.nPos + 1;
break;
case SB_PAGEUP:
i = si.nPos - si.nPage;
break;
case SB_PAGEDOWN:
i = si.nPos + si.nPage;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
i = HIWORD(wParam);
break;
default:
return;
}
i = MAX(i, si.nMin);
i = MIN(i, MAX(0, (int)(si.nMax - si.nPage + 1)));
pHex->PageOffset = pHex->LineWidth * i;
pHex->PageLength = MIN(pHex->Length - pHex->PageOffset, pHex->PageMaxLength);
SetScrollPos(hWnd, SB_VERT, i, TRUE);
RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -