⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hexedit.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Hex editor control
 *
 * Copyright (C) 2004 Thomas Weidenmueller <w3seek@reactos.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <regedit.h>
typedef struct
{
  HWND hWndSelf;
  HWND hWndParent;
  HLOCAL hBuffer;
  DWORD style;
  DWORD MaxBuffer;
  INT ColumnsPerLine;
  INT nLines;
  INT nVisibleLinesComplete;
  INT nVisibleLines;
  INT Position;
  INT LineHeight;
  INT CharWidth;
  HFONT hFont;
  BOOL SbVisible;

  INT LeftMargin;
  INT AddressSpacing;
  INT SplitSpacing;

  BOOL EditingField;
  INT CaretCol;
  INT CaretLine;
} HEXEDIT_DATA, *PHEXEDIT_DATA;

/* hit test codes */
#define HEHT_LEFTMARGIN	(0x1)
#define HEHT_ADDRESS	(0x2)
#define HEHT_ADDRESSSPACING	(0x3)
#define HEHT_HEXDUMP	(0x4)
#define HEHT_HEXDUMPSPACING	(0x5)
#define HEHT_ASCIIDUMP	(0x6)
#define HEHT_RIGHTMARGIN	(0x7)

INT_PTR CALLBACK HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

ATOM
STDCALL
RegisterHexEditorClass(HINSTANCE hInstance)
{
  WNDCLASSEX WndClass;

  ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
  WndClass.cbSize = sizeof(WNDCLASSEX);
  WndClass.style = CS_DBLCLKS;
  WndClass.lpfnWndProc = (WNDPROC)HexEditWndProc;
  WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA);
  WndClass.hInstance = hInstance;
  WndClass.hCursor = LoadCursor(0, IDC_IBEAM);
  WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  WndClass.lpszClassName = HEX_EDIT_CLASS_NAME;

  return RegisterClassEx(&WndClass);
}

BOOL
STDCALL
UnregisterHexEditorClass(HINSTANCE hInstance)
{
  return UnregisterClass(HEX_EDIT_CLASS_NAME, hInstance);
}

/*** Helper functions *********************************************************/

static VOID
HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, BOOL Scroll)
{
  SCROLLINFO si;

  si.cbSize = sizeof(SCROLLINFO);
  si.fMask = SIF_POS;
  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);

  if(Scroll)
  {
    if(si.nPos > hed->CaretLine)
    {
      si.nPos = hed->CaretLine;
      SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
      GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
      InvalidateRect(hed->hWndSelf, NULL, TRUE);
    }
    else if(hed->CaretLine >= (hed->nVisibleLinesComplete + si.nPos))
    {
      si.nPos = hed->CaretLine - hed->nVisibleLinesComplete + 1;
      SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
      GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
      InvalidateRect(hed->hWndSelf, NULL, TRUE);
    }
  }

  if(hed->EditingField)
    SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + (3 * hed->CaretCol)) * hed->CharWidth) - 1, (hed->CaretLine - si.nPos) * hed->LineHeight);
  else
    SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine) + hed->CaretCol) * hed->CharWidth) - 2, (hed->CaretLine - si.nPos) * hed->LineHeight);
}

static VOID
HEXEDIT_Update(PHEXEDIT_DATA hed)
{
  SCROLLINFO si;
  RECT rcClient;
  BOOL SbVisible;
  INT bufsize, cvislines;

  GetClientRect(hed->hWndSelf, &rcClient);
  hed->style = GetWindowLong(hed->hWndSelf, GWL_STYLE);

  bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0);
  hed->nLines = max(bufsize / hed->ColumnsPerLine, 1);
  if(bufsize > hed->ColumnsPerLine && (bufsize % hed->ColumnsPerLine) > 0)
  {
    hed->nLines++;
  }

  if(hed->LineHeight > 0)
  {
    hed->nVisibleLinesComplete = cvislines = rcClient.bottom / hed->LineHeight;
    hed->nVisibleLines = hed->nVisibleLinesComplete;
    if(rcClient.bottom % hed->LineHeight)
    {
      hed->nVisibleLines++;
    }
  }
  else
  {
    hed->nVisibleLines = cvislines = 0;
  }

  SbVisible = bufsize > 0 && cvislines < hed->nLines;
  ShowScrollBar(hed->hWndSelf, SB_VERT, SbVisible);

  /* update scrollbar */
  si.cbSize = sizeof(SCROLLINFO);
  si.fMask = SIF_RANGE | SIF_PAGE;
  si.nMin = 0;
  si.nMax = ((bufsize > 0) ? hed->nLines - 1 : 0);
  si.nPage = ((hed->LineHeight > 0) ? rcClient.bottom / hed->LineHeight : 0);
  SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);

  if(IsWindowVisible(hed->hWndSelf) && SbVisible != hed->SbVisible)
  {
    InvalidateRect(hed->hWndSelf, NULL, TRUE);
  }

  hed->SbVisible = SbVisible;
}

static HFONT
HEXEDIT_GetFixedFont(VOID)
{
  LOGFONT lf;
  GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
  return CreateFontIndirect(&lf);
}

static VOID
HEXEDIT_PaintLines(PHEXEDIT_DATA hed, HDC hDC, DWORD ScrollPos, DWORD First, DWORD Last, RECT *rc)
{
  DWORD dx, dy, linestart;
  INT x;
  PBYTE buf, current, end, line;
  size_t bufsize;
  TCHAR hex[3], addr[17];
  RECT rct;

  FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1));

  if(hed->hBuffer)
  {
    bufsize = LocalSize(hed->hBuffer);
    buf = LocalLock(hed->hBuffer);
  }
  else
  {
    buf = NULL;
    bufsize = 0;

    if(ScrollPos + First == 0)
    {
      /* draw address */
      _stprintf(addr, _T("%04X"), 0);
      TextOut(hDC, hed->LeftMargin, First * hed->LineHeight, addr, 4);
    }
  }

  if(buf)
  {
    end = buf + bufsize;
    dy = First * hed->LineHeight;
    linestart = (ScrollPos + First) * hed->ColumnsPerLine;
    current = buf + linestart;
    Last = min(hed->nLines - ScrollPos, Last);

    while(First <= Last && current < end)
    {
      DWORD dh;

      dx = hed->LeftMargin;

      /* draw address */
      _stprintf(addr, _T("%04lX"), linestart);
      TextOut(hDC, dx, dy, addr, 4);

      dx += ((4 + hed->AddressSpacing) * hed->CharWidth);
      dh = (3 * hed->CharWidth);

      rct.left = dx;
      rct.top = dy;
      rct.right = rct.left + dh;
      rct.bottom = dy + hed->LineHeight;

      /* draw hex map */
      dx += (hed->CharWidth / 2);
      line = current;
      for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
      {
        rct.left += dh;
        rct.right += dh;

	_stprintf(hex, _T("%02X"), *(current++));
	ExtTextOut(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL);
	dx += dh;
      }

      /* draw ascii map */
      dx = ((4 + hed->AddressSpacing + hed->SplitSpacing + (hed->ColumnsPerLine * 3)) * hed->CharWidth);
      current = line;
      for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
      {
	_stprintf(hex, _T("%C"), *(current++));
	hex[0] = ((hex[0] & _T('\x007f')) >= _T(' ') ? hex[0] : _T('.'));
	TextOut(hDC, dx, dy, hex, 1);
	dx += hed->CharWidth;
      }

      dy += hed->LineHeight;
      linestart += hed->ColumnsPerLine;
      First++;
    }
  }

  LocalUnlock(hed->hBuffer);
}

static DWORD
HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed, POINTS pt)
{
  int d;

  if(pt.x <= hed->LeftMargin)
  {
    return HEHT_LEFTMARGIN;
  }

  pt.x -= hed->LeftMargin;
  d = (4 * hed->CharWidth);
  if(pt.x <= d)
  {
    return HEHT_ADDRESS;
  }

  pt.x -= d;
  d = (hed->AddressSpacing * hed->CharWidth);
  if(pt.x <= d)
  {
    return HEHT_ADDRESSSPACING;
  }

  pt.x -= d;
  d = (3 * hed->ColumnsPerLine * hed->CharWidth);
  if(pt.x <= d)
  {
    return HEHT_HEXDUMP;
  }

  pt.x -= d;
  d = (hed->SplitSpacing * hed->CharWidth);
  if(pt.x <= d)
  {
    return HEHT_HEXDUMPSPACING;
  }

  pt.x -= d;
  d = (hed->ColumnsPerLine * hed->CharWidth);
  if(pt.x <= d)
  {
    return HEHT_ASCIIDUMP;
  }

  return HEHT_RIGHTMARGIN;
}

static DWORD
HEXEDIT_PositionFromPoint(PHEXEDIT_DATA hed, POINTS pt, DWORD Hit, POINT *EditPos, BOOL *EditField)
{
  SCROLLINFO si;
  DWORD Pos, bufsize;

  si.cbSize = sizeof(SCROLLINFO);
  si.fMask = SIF_POS;
  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);

  EditPos->x = 0;

  if(hed->LineHeight > 0)
  {
    EditPos->y = min(si.nPos + (pt.y / hed->LineHeight), hed->nLines - 1);
  }
  else
  {
    EditPos->y = si.nPos;
  }

  switch(Hit)
  {
    case HEHT_LEFTMARGIN:
    case HEHT_ADDRESS:
    case HEHT_ADDRESSSPACING:
    case HEHT_HEXDUMP:
      pt.x -= (SHORT) hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth);
      *EditField = TRUE;
      break;

    default:
      pt.x -= hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth);
      *EditField = FALSE;
      break;
  }

  if(pt.x > 0)
  {
    INT BlockWidth = (*EditField ? hed->CharWidth * 3 : hed->CharWidth);
    EditPos->x = min(hed->ColumnsPerLine, pt.x / BlockWidth);
  }

  bufsize = (hed->hBuffer ? (DWORD) LocalSize(hed->hBuffer) : 0);
  Pos = (EditPos->y * hed->ColumnsPerLine) + EditPos->x;
  if(Pos > bufsize)
  {
    INT tmp = bufsize % hed->ColumnsPerLine;
    Pos = bufsize;
    EditPos->x = (tmp == 0 ? hed->ColumnsPerLine : tmp);
  }
  return Pos;
}

/*** Control specific messages ************************************************/

static LRESULT
HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
{
  if(Buffer != NULL && Size > 0)
  {
    LPVOID buf;

    if(hed->MaxBuffer > 0 && Size > hed->MaxBuffer)
    {
      Size = hed->MaxBuffer;
    }

    if(hed->hBuffer)
    {
      if(Size > 0)
      {
        if(LocalSize(hed->hBuffer) != Size)
        {
          hed->hBuffer = LocalReAlloc(hed->hBuffer, Size, LMEM_MOVEABLE | LMEM_ZEROINIT);
        }
      }
      else
      {
        hed->hBuffer = LocalFree(hed->hBuffer);
        hed->Position = 0;
        HEXEDIT_Update(hed);

        return 0;
      }
    }
    else if(Size > 0)
    {
      hed->hBuffer = LocalAlloc(LHND, Size);
    }

    if(Size > 0)
    {
      buf = LocalLock(hed->hBuffer);
      if(buf)
      {
        memcpy(buf, Buffer, Size);
      }
      else
        Size = 0;
      LocalUnlock(hed->hBuffer);
    }

    hed->Position = 0;
    HEXEDIT_Update(hed);
    return Size;
  }
  else if(hed->hBuffer)
  {
    hed->Position = 0;
    hed->hBuffer = LocalFree(hed->hBuffer);
    HEXEDIT_Update(hed);
  }

  return 0;
}

static LRESULT
HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
{
  size_t nCpy;

  if(!hed->hBuffer)
  {
    return 0;
  }

  if(Buffer != NULL && Size > 0)
  {
    nCpy = min(Size, LocalSize(hed->hBuffer));
    if(nCpy > 0)
    {
      PVOID buf;

      buf = LocalLock(hed->hBuffer);
      if(buf)
      {
        memcpy(Buffer, buf, nCpy);
      }
      else
        nCpy = 0;
      LocalUnlock(hed->hBuffer);
    }
    return nCpy;
  }

  return (LRESULT)LocalSize(hed->hBuffer);
}

static LRESULT
HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed, DWORD nMaxSize)
{
  hed->MaxBuffer = nMaxSize;
  if(hed->MaxBuffer > 0 && hed->hBuffer && LocalSize(hed->hBuffer) > hed->MaxBuffer)
  {
    /* truncate the buffer */
    hed->hBuffer = LocalReAlloc(hed->hBuffer, hed->MaxBuffer, LMEM_MOVEABLE);
    HEXEDIT_Update(hed);
  }
  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -