65.9K
CodeProject 正在变化。 阅读更多。
Home

适用于 C++/Win32 应用程序的十六进制控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (84投票s)

2018年12月9日

MIT

16分钟阅读

viewsIcon

210160

downloadIcon

10403

使用 C++/MFC 编写的全功能十六进制控件

十六进制控件, C++/MFC

目录

引言

HexCtrl 是一个功能非常丰富的十六进制编辑器控件,用 C++/MFC 编写。

它实现为一个纯抽象接口,因此即使您的应用程序不直接使用 MFC,也可以使用它。它使用 /std:c++20 标准在 Visual Studio 2022 中编写。

HexCtrl 的主要功能

  • 查看和编辑高达 16EB (exabyte) 的数据
  • 以两种数据模式工作:内存虚拟数据模式
  • 功能齐全的 书签管理器
  • 功能齐全的 搜索和替换
  • 文本区域可更改编码
  • 多种 复制/粘贴 到/从剪贴板的选项
  • 撤销/重做
  • 使用 填充 和许多预定义的 操作 选项修改数据
  • 能够将数据可视地划分为 页面
  • 打印整个文档/页面范围/选区
  • 使用 自定义颜色 为数据块设置单独的颜色
  • 强大的可自定义 模板 系统
  • 通过外部配置文件 可分配的键盘快捷键
  • 可自定义的外观
  • 符合 /std:c++20 标准编写

安装

HexCtrl 可以通过两种不同的方式使用

  • 作为项目的一部分从源代码构建
  • 作为动态链接库 .dll 使用。

从源代码构建

构建过程非常简单

  1. HexCtrl 文件夹复制到项目的目录中。
  2. HexCtrl 文件夹中的所有文件添加到项目中(可以跳过
    HexCtrl/dep/rapidjson/rapidjson-amalgam.h 头文件库)。
  3. 在您打算使用 HexCtrl 的地方添加 #include "HexCtrl/HexCtrl.h"
  4. 声明 IHexCtrlPtr 成员变量:IHexCtrlPtr myHex { HEXCTRL::CreateHexCtrl() };
  5. 创建 控件实例。

如果您想在非 MFC 应用程序中从源代码构建 HexCtrl,您需要

  1. 在项目设置中添加对 在共享 DLL 中使用 MFC 的支持。
  2. 取消注释 HexCtrl.h 头文件中的行 //#define HEXCTRL_MANUAL_MFC_INIT

要将 HexCtrl 作为 .dll 使用,请执行以下操作

  1. HexCtrl.hHexCtrlDefs.h 文件复制到项目文件夹中。
  2. HexCtrl.lib 文件复制到项目文件夹中,以便链接器可以看到它。
  3. HexCtrl.dll 文件放在 .exe 文件旁边。
  4. 在您打算使用控件的地方添加以下行
#define HEXCTRL_SHARED_DLL //You can alternatively uncomment this line in HexCtrl.h.
#include "HexCtrl.h"` 
  1. 声明 IHexCtrlPtr 成员变量:IHexCtrlPtr myHex { HEXCTRL::CreateHexCtrl() };
  2. 创建 控件实例。

要构建 HexCtrl.dllHexCtrl.lib,请使用 DLL Project/DLL Project.vcxproj Visual Studio 项目文件。

备注

HexCtrl.dll 是用 MFC 静态链接 构建的。因此,即使您在自己的 MFC 项目中使用它,即使使用不同的 MFC 版本,也应该不会有任何干扰。

MFC 共享 DLL 构建 HexCtrl 结果有点棘手。即使在 AFX_MANAGE_STATE(AfxGetStaticModuleState()) 宏的帮助下,也总是出现 MFC 调试断言,其原因很难理解。

命名空间

HexCtrl 使用自己的命名空间 HEXCTRL。因此,是否在声明前使用命名空间前缀由您决定

HEXCTRL::

或在源文件开头全局定义命名空间

using namespace HEXCTRL;

创建

经典方法

Create 方法是您调用以创建 HexCtrl 实例的第一个方法。它将 HEXCREATE 结构作为参数,该结构提供了控件所需的所有信息。
HEXCREATE::dwStyleHEXCREATE::dwExStyle 分别是 窗口扩展窗口 样式,它们将传递给 HexCtrl 的窗口创建函数,根据您的需要设置这些样式。
有关所有可用的创建选项,请参阅 HEXCREATE 结构描述。

在对话框中

要在 对话框 中使用 HexCtrl,您当然可以使用 经典方法 创建它,调用 Create 方法并提供所有必要信息。

但您可以使用另一种选择

  1. Visual Studio 对话框设计器中的 工具箱 中的 自定义控件 放入对话框模板,并使其达到所需大小。
  2. 转到该控件的 属性,在 杂项 部分的 字段中,键入:HexCtrl
    为控件选择一个合适的 ID(本例中为 IDC_MY_HEX)。
    此外,您还可以在此处设置控件的 动态布局 属性,以便控件在对话框大小调整时表现得当。
  3. 在对话框类中声明 IHexCtrlPtr 成员变量
IHexCtrlPtr m_myHex { CreateHexCtrl() };
  1. 从对话框的 OnInitDialog 方法中调用 CreateDialogCtrl 方法。
BOOL CMyDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    
    m_myHex->CreateDialogCtrl(IDC_MY_HEX, m_hWnd);
}

设置数据

要为 HexCtrl 设置数据,使用 SetData 方法。
下面的代码展示了如何构造 HexCtrl 对象并显示当前应用程序内存的前 0x1FF 字节。

IHexCtrlPtr myHex { CreateHexCtrl() };

HEXCREATE hcs;
hcs.hWndParent = m_hWnd;
hcs.rect = {0, 0, 600, 400}; //Window rect.
myHex->Create(hcs);

HEXDATA hds;
hds.spnData = { reinterpret_cast<std::byte*>(GetModuleHandle(nullptr)), 0x1FF };
myHex->SetData(hds);

下一个示例展示了如何将 std::string 的文本显示为十六进制数据

std::string str = "My string";
HEXDATA hds;
hds.spnData = { reinterpret_cast<std::byte*>(str.data()), str.size() };
myHex->SetData(hds);

虚拟数据模式

除了标准默认模式(其中 HexCtrl 仅持有内存中某些字节的指针)之外,它还具有额外的虚拟模式。
此模式可能非常有用,例如,当您需要显示大量无法一次性全部放入内存的数据时。

如果设置了 HEXDATA::pHexVirtData 指针,则所有数据例程都将通过它完成。此指针是 IHexVirtData 类类型,它是一个纯抽象基类。您必须从中派生自己的类并实现其所有公共方法。然后,在调用 SetData 方法之前,通过 HEXDATA::pHexVirtData 提供指向此派生类创建对象的指针。

虚拟书签

HexCtrl 具有与任意数量的书签区域一起工作的内在功能。这些区域可以分配单独的背景和文本颜色以及描述。

但是,如果您有庞大而复杂的数据逻辑,并且想自己处理所有这些书签,您可以使用虚拟书签模式来完成。在此模式下,所有书签的负担都由您自己处理,通过实现 IHexBookmarks 接口并调用 SetVirtualBkm 方法向 HexCtrl 提供此实现的指针。

自定义颜色

如果您想用自定义颜色来着色数据,您必须借助 IHexVirtColors 接口。

模板


HexCtrl 的模板是一个强大的数据结构描述系统,使用简单的 .json 文件。这些文件可以通过 HexControl 的内部模板管理器或通过 API 加载。

{
    "$schema": "https://raw.githubusercontent.com/jovibor/HexCtrl/master/docs/HexCtrl.Templates.Schema.json",
    "TemplateName": "SampleTemplate",
    "Data": {
        "endianness": "little",
        "clrBk": "#999999",
        "clrText": "#FFFFFF",
        "Fields": [
            {
                "name": "MyCustomDataSingle",
                "type": "MyCustomType"
            },
            {
                "name": "CustomComplexData",
                "type": "MyCustomComplexType"
            },
            {
                "name": "ArrayOfDWORDs",
                "type": "DWORD",
                "array": 10
            },
            {
                "name": "MyCustomDataArray",
                "type": "MyCustomType",
                "array": 4
            }
        ]
    },
    "CustomTypes": [
        {
            "TypeName": "MyCustomType",
            "Fields": [
                {
                    "name": "myCustomTypeField1",
                    "type": "DWORD"
                },
                {
                    "name": "myCustomTypeField2",
                    "type": "DWORD"
                }
            ]
        },
        {
            "TypeName": "MyCustomComplexType",
            "Fields": [
                {
                    "name": "MyCustomTypeData1",
                    "type": "MyCustomType"
                },
                {
                    "name": "MyCustomTypeData2",
                    "type": "MyCustomType"
                }
            ]
        }
    ]
}

每个此类文件都包含以下属性

  • TemplateName [必填,字符串] - 模板的名称
  • Data [必填,对象] - 包含所有模板字段信息的主对象
  • CustomTypes [可选,数组] - 用户定义类型的数组,可以在 Fieldstype 属性中引用

CustomTypes 对象与 Fields 对象相同,唯一的区别是 Fields 对象没有 TypeName 属性。

每个 DataCustomType 对象都包含带有实际结构成员的 Fields 属性。

Fields [数组] - 是一个对象数组,其中每个对象代表一个结构数据成员。任何此类对象都可以有自己的 Fields 子对象,这些子对象将代表嵌套结构。
Fields 的属性包括

  • name - [必填,字符串] - 字段名称
  • description - [可选,字符串] - 字段描述
  • type - [可选,字符串] - 字段类型,例如
    bool, char, unsigned char, byte, short, unsigned short, WORD, long, unsigned long, int, unsigned int, DWORD, long long, unsigned long long, QWORD, float, double, time32_t, time64_t, FILETIME, SYSTEMTIME, GUID,或在 CustomTypes 部分定义的任何自定义类型
  • size - [可选,整数] - 字段大小(以字节为单位),如果未提供 type 字段
  • array - [可选,整数] - 数组大小,如果给定字段是字段数组
  • endianness - [可选,字符串] - 字段字节序,“little”或“big”。默认情况下,所有字段都是小端字节序。
  • clrBk - [可选,字符串] - 字段背景颜色
  • clrText - [可选,字符串] - 字段文本颜色

Fields 属性位于同一级别的 endiannessclrBkclrText 属性将表示该级别及以下所有 Fields 对象的默认属性,除非在字段本身中明确重新定义。

有关可用模板,请查看 Templates 目录。

方法

HexCtrl 有许多方法可用于自定义其外观并管理其行为。

ClearData

void ClearData();

清除 HexCtrl 视图中的数据,但不触及数据本身。

Create

bool Create(const HEXCREATE& hcs);

主要初始化方法。
HEXCREATE 作为参数。如果成功创建则返回 true,否则返回 false

CreateDialogCtrl

bool CreateDialogCtrl(UINT uCtrlID, HWND hwndDlg);

自定义控件 对话框模板创建 HexCtrl。将控件的 ID 和对话框的窗口 句柄 作为参数。有关更多信息,请参阅 创建 部分。

Destroy

void Destroy();

销毁控件。
仅当您使用通过调用 CreateRawHexCtrl 函数获得的原始 IHexCtrl 指针时才调用此方法。否则不要使用它。

备注
通常您不需要调用此方法,除非您通过 CreateRawHexCtrl 工厂函数获得的原始指针使用 HexCtrl。如果您以标准方式通过 CreateHexCtrl 函数获得的 IHexCtrlPtr 指针使用 HexCtrl,此方法将自动调用。

ExecuteCmd

void ExecuteCmd(EHexCmd enCmd)const;

执行 EHexCmd 枚举中预定义命令之一。所有这些命令基本上都复制了控件的内部菜单。

GetActualWidth

int GetActualWidth()const;

返回 HexCtrl 边界矩形的宽度,即绘制的工作区域的宽度。

GetBookmarks

auto GetBookmarks()const->IHexBookmarks*;

返回指向 IHexBookmarks 接口的指针,该接口负责书签机制。

GetCacheSize

auto GetCacheSize()const->DWORD;

返回 HEXDATA 中设置的当前缓存大小。

GetCapacity

DWORD GetCapacity()const;

返回当前容量。

GetCaretPos

ULONGLONG GetCaretPos()const;

检索当前插入符号位置偏移。

GetColors

auto GetColors()const->HEXCOLORS;

返回当前 HEXCOLORS

GetData

auto GetData(HEXSPAN hss)const->std::byte*;

无论控件在哪种模式下工作,都返回指向数据偏移的指针。

请注意,在虚拟模式下,返回的数据大小不能超过当前 缓存大小,因此可能小于获取的大小。
在默认模式下,返回的指针只是 SetData 方法中设置的数据指针的偏移量。

GetDataSize

auto GetDataSize()const->ULONGLONG;

返回当前设置的数据大小。

GetDateInfo

auto GetDateInfo()const->std::tuple<DWORD, wchar_t>;

返回 日期格式-排序指定符 和日期分隔符。

GetEncoding

int GetEncoding()const;

获取当前使用的代码页。

GetFont

auto GetFont()->LOGFONTW;

检索当前字体 LOGFONTW

GetGroupMode

auto GetGroupMode()const->EHexDataSize;

检索当前数据分组模式。

GetMenuHandle

HMENU GetMenuHandle()const;

检索控件上下文菜单的 HMENU 句柄。您可以使用此句柄根据您的需要自定义菜单。

控件的内部菜单使用的菜单 ID 范围从 0x8001 开始。因此,如果您希望添加自己的新菜单,请从 0x9000 开始分配菜单 ID,以免发生冲突。

当用户点击自定义菜单时,控件会向其父窗口发送 WM_NOTIFY 消息,其中 LPARAM 指向 HEXMENUINFO,其 hdr.code 成员设置为 HEXCTRL_MSG_MENUCLICK,并且 wMenuID 字段包含被点击菜单的 ID

GetPagesCount

DWORD GetPageSize()const;

获取由 SetPageSize 设置的当前页数。

GetPagePos

auto GetPagePos()->ULONGLONG const;

获取光标所在的当前页。

GetPageSize

DWORD GetPageSize()const;

获取由 SetPageSize 设置的当前页面大小。

GetSelection

auto GetSelection()const->std::vector<HEXSPAN>;

返回包含当前选区偏移量和大小的 std::vector

GetTemplates

auto GetTemplates()const->IHexTemplates*;

返回指向内部 IHexTemplates 接口的指针,该接口负责模板机制。

GetUnprintableChar

wchar_t GetUnprintableChar()const;

返回不可打印字符的替换字符。

GetWindowHandle

HWND GetWindowHandle(EHexWnd enWnd)const

检索 HexCtrl 某个窗口的窗口句柄。将 EHexWnd 枚举作为参数。

GoToOffset

void GoToOffset(ULONGLONG ullOffset, int iRelPos = 0)

转到给定偏移量。第二个参数 iRelPos 可以取三个不同的值

  • -1 - 偏移量将显示在顶部行。
  •   0 - 偏移量将显示在中间。
  •   1 - 偏移量将显示在底部行。

HasSelection

bool HasSelection()const;

如果 HexCtrl 有任何区域被选中,则返回 true

HitTest

auto HitTest(POINT pt, bool fScreen = true)const->std::optional<HEXHITTEST>

在屏幕 fScreen = true 或客户端 fScreen = false 坐标中对给定点进行命中测试。如果成功,则返回 HEXHITTEST 结构。

IsCmdAvail

bool IsCmdAvail(EHexCmd enCmd)const;

如果给定命令当前可以执行,则返回 true,否则返回 false

IsCreated

bool IsCreated()const;

显示 HexCtrl 是否已创建。

IsDataSet

bool IsDataSet()const;

显示是否已向 HexCtrl 设置数据

IsMutable

bool IsMutable()const;

显示 HexCtrl 当前是否处于编辑模式。

IsOffsetAsHex

bool IsOffsetAsHex()const;

“偏移量”当前显示为十六进制还是十进制。可以通过双击偏移量区域来更改。

IsOffsetVisible

auto IsOffsetVisible(ULONGLONG ullOffset)const->HEXVISION;

检查偏移量可见性并返回 HEXVISION 作为结果。

IsVirtual

bool IsVirtual()const;

如果 HexCtrl 当前在 虚拟数据模式 下工作,则返回 true

ModifyData

void ModifyData(const HEXMODIFY& hms);

修改当前在 HexCtrl 中设置的数据,详见 HEXMODIFY 结构。

Redraw

void Redraw();

重绘主窗口。

SetCapacity

void SetCapacity(DWORD dwCapacity);

设置 HexCtrl 的当前容量。

SetCaretPos

void SetCaretPos(ULONGLONG ullOffset, bool fHighLow = true, bool fRedraw = true);

将插入点设置到给定偏移量。fHighLow 标志显示十六进制块的哪个部分(低或高)必须设置插入点。

SetColors

void SetColors(const HEXCOLORS& clr);

设置控件的所有颜色。将 HEXCOLORS 作为参数。

SetConfig

bool SetConfig(std::wstring_view wstrPath);

设置带有键绑定的 JSON 配置文件路径,以便在 HexCtrl 中使用,或设置空路径 (L"") 以使用默认值。此文件使用 EHexCmd 枚举值作为键,字符串数组作为值。

{
    "CMD_DLG_SEARCH": [ "ctrl+f", "ctrl+h" ],
    "CMD_SEARCH_NEXT": [ "f3" ],
    "CMD_SEARCH_PREV": [ "shift+f3" ]
}

有关默认值,请参阅项目源代码中的 IDR_HEXCTRL_JSON_KEYBIND.json 文件。

SetData

void SetData(const HEXDATA& hds);

用于在只读或可变模式下设置要显示数据的主要方法。将 HEXDATA 作为参数。

SetDateInfo

void SetDateInfo(DWORD dwFormat, wchar_t wchSepar);

设置 日期格式-排序指定符 以及日期分隔符。

SetEncoding

void SetEncoding(int iCodePage);

设置 HexCtrl 文本区域的代码页。将 代码页标识符 作为参数,或 -1 表示默认的仅 ASCII 字符。

注意: 代码页标识符必须表示 单字节字符集。目前不支持多字节字符集。

SetFont

void SetFont(const LOGFONTW& lf);

HexCtrl 设置新字体。此字体必须是等宽字体。

SetGroupMode

void SetGroupMode(EHexDataSize enGroupMode);

设置当前数据分组模式。有关更多信息,请参阅 EHexDataSize

SetMutable

void SetMutable(bool fEnable);

启用或禁用可变模式。在可变模式下,所有数据都可以修改。

SetOffsetMode

void SetOffsetMode(bool fHex);

设置偏移区域显示为十六进制 (fHex=true) 或十进制 (fHex=false)。

SetPageSize

void SetPageSize(DWORD dwSize, const wchar_t* wstrName = L"Page");

设置页大小,用于绘制分隔线。此大小应为当前 容量 大小的倍数才能生效。第二个参数设置要在 HexCtrl 底部信息区域中显示的名称(“Page”、“Sector”等...)。
要删除分隔符,只需将 dwSize 设置为 0。

SetVirtualBkm

void SetVirtualBkm(IHexBookmarks* pVirtBkm);

虚拟书签 模式设置指针,如果设置为 nullptr 则禁用此模式。

SetRedraw

void SetRedraw(bool fRedraw);

HexCtrl 窗口是否应重绘。例如,是否应处理 WM_PAINT 消息。

SetSelection

void SetSelection(const std::vector<HEXSPAN>& vecSel, bool fRedraw = true, bool fHighlight = false);

设置当前选区或高亮显示选区,如果 fHighlighttrue

SetUnprintableChar

void SetUnprintableChar(wchar_t wch);

设置不可打印字符的替换字符。

SetWheelRatio

void SetWheelRatio(double dbRatio, bool fLines);

设置一个滚动页的滚动量。
一页是指一次鼠标滚轮滚动或一次“Page Down”键操作。当 fLinestrue 时,dbRatio 是滚动的文本行数。当它为 false 时,dbRatio 表示可见屏幕高度的滚动比例。

ShowInfoBar

void ShowInfoBar(bool fShow);

显示/隐藏底部信息栏。

结构体

下面列出了所有 HexCtrl 结构。

HEXBKM

书签结构,用于 BkmAdd 方法。

struct HEXBKM
{
    std::vector<HEXSPAN> vecSpan { };                //Vector of offsets and sizes.
    std::wstring         wstrDesc { };               //Bookmark description.
    ULONGLONG            ullID { };                  //Bookmark ID, assigned internally by framework.
    ULONGLONG            ullData { };                //User defined custom data.
    COLORREF             clrBk { RGB(240, 240, 0) }; //Bk color.
    COLORREF             clrText { RGB(0, 0, 0) };   //Text color.
};
using PHEXBKM = HEXBKM*;

成员 vecSpanstd::vector<HEXSPAN> 类型,因为书签可能具有几个非相邻区域。例如,当按住 Alt 键进行块选择时。

HEXBKMINFO

书签信息结构。

struct HEXBKMINFO
{
    NMHDR   hdr { };  //Standard Windows header.
    PHEXBKM pBkm { }; //Bookmark pointer.
};

HEXCOLOR

HexCtrl 自定义颜色。

struct HEXCOLOR
{
    COLORREF clrBk { };   //Bk color.
    COLORREF clrText { }; //Text color.
};
using PHEXCOLOR = HEXCOLOR*;

HEXCOLORINFO

十六进制块颜色信息结构。

struct HEXCOLORINFO
{
    NMHDR     hdr { };       //Standard Windows header.
    ULONGLONG ullOffset { }; //Offset for the color.
    PHEXCOLOR pClr { };      //Pointer to the color struct.
};

HEXCOLORS

此结构描述所有 HexCtrl 颜色。所有这些颜色都有其默认值。

struct HEXCOLORS
{
    COLORREF clrFontHex { GetSysColor(COLOR_WINDOWTEXT) };      //Hex-chunks font color.
    COLORREF clrFontText { GetSysColor(COLOR_WINDOWTEXT) };     //Text font color.
    COLORREF clrFontSel { GetSysColor(COLOR_HIGHLIGHTTEXT) };   //Selected hex/text font color.
    COLORREF clrFontDataInterp { RGB(250, 250, 250) };          //Data Interpreter text/hex font color.
    COLORREF clrFontCaption { RGB(0, 0, 180) };                 //Caption font color
    COLORREF clrFontInfoName { GetSysColor(COLOR_WINDOWTEXT) }; //Font color of the Info bar parameters.
    COLORREF clrFontInfoData { RGB(0, 0, 180) };                //Font color of the Info bar data.
    COLORREF clrFontCaret { RGB(255, 255, 255) };               //Caret font color.
    COLORREF clrBk { GetSysColor(COLOR_WINDOW) };               //Background color.
    COLORREF clrBkSel { GetSysColor(COLOR_HIGHLIGHT) };         //Background color of the selected Hex/ASCII.
    COLORREF clrBkDataInterp { RGB(147, 58, 22) };              //Data Interpreter Bk color.
    COLORREF clrBkInfoBar { GetSysColor(COLOR_BTNFACE) };       //Background color of the bottom Info bar.
    COLORREF clrBkCaret { RGB(0, 0, 255) };                     //Caret background color.
    COLORREF clrBkCaretSel { RGB(0, 0, 200) };                  //Caret background color in selection.
};

HEXCREATE

用于 HexCtrl 创建的主要初始化结构。

struct HEXCREATE
{
    HEXCOLORS stColor { };          //All HexCtrl colors.
    HWND      hWndParent { };       //Parent window handle.
    PLOGFONTW pLogFont { };         //Monospaced font to be used, or nullptr for default.
    RECT      rect { };             //Initial window rect.
    UINT      uID { };              //Control ID if it's a child window.
    DWORD     dwStyle { };          //Window styles.
    DWORD     dwExStyle { };        //Extended window styles.
    double    dbWheelRatio { 1.0 }; //Either screen-ratio or lines amount to scroll with Page-scroll.
    bool      fPageLines { false }; //Treat dbWheelRatio as a screen-ratio (false) or as amount of lines.
    bool      fInfoBar { true };    //Show bottom Info bar or not.
    bool      fCustom { false };    //If it's a custom control in a dialog.
};

HEXDATA

用于设置要在控件中显示数据的主要结构。

struct HEXDATA
{
    std::span<std::byte> spnData { };              //Data to display.
    IHexVirtData*        pHexVirtData { };         //Pointer for Virtual mode.
    IHexVirtColors*      pHexVirtColors { };       //Pointer for Custom Colors class.
    DWORD                dwCacheSize { 0x800000 }; //In Virtual mode max cached size of data to fetch.
    bool                 fMutable { false };       //Is data mutable (editable) or read-only.
    bool                 fHighLatency { false };   //Do not redraw window until scrolling completes.
};

HEXDATAINFO

用于 IHexVirtData 中的数据信息结构。

struct HEXDATAINFO
{
    NMHDR                hdr { };       //Standard Windows header.
    HEXSPAN              stHexSpan { }; //Offset and size of the data bytes.
    std::span<std::byte> spnData { };   //Data span.
};

HEXHITTEST

结构用于 HitTest 方法。

struct HEXHITTEST
{
    ULONGLONG ullOffset { };     //Offset.
    bool      fIsText { false }; //Is cursor at Text or Hex area.
    bool      fIsHigh { false }; //Is it High or Low part of the byte.
};

HEXMODIFY

此结构用于表示数据修改参数。
enModifyMode 设置为 EHexModifyMode::MODIFY_ONCE 时,pData 中的字节只会替换相应的数据字节。
如果 enModifyMode 等于 EHexModifyMode::MODIFY_REPEAT,则会进行几次块替换。
例如,如果

  • SUM(vecSpan.ullSize) == 9
  • spnData.size() == 3
  • enModifyMode 设置为 EHexModifyMode::MODIFY_REPEAT
  • 内存中 vecSpan.ullOffset 处的字节为 010203040506070809
  • spnData.data() 指向的字节为 030405

那么,修改后,vecSpan.ullOffset 处的字节将变为 030405030405030405

如果 enModifyMode 等于 EHexModifyMode::MODIFY_OPERATION,则 enOperMode 将发挥作用,显示必须对数据执行何种操作。

struct HEXMODIFY
{
    EHexModifyMode       enModifyMode { EHexModifyMode::MODIFY_ONCE }; //Modify mode.
    EHexOperMode         enOperMode { };       //Operation mode, used only in MODIFY_OPERATION mode.
    EHexDataSize         enDataSize { };       //Operation data size.
    std::span<std::byte> spnData { };          //Data span.
    std::vector<HEXSPAN> vecSpan { };          //Vector of data offsets and sizes.
    bool                 fBigEndian { false }; //Treat the data as a big endian, used only in MODIFY_OPERATION mode.
};

HEXMENUINFO

菜单信息结构。

struct HEXMENUINFO
{
    NMHDR hdr { };        //Standard Windows header.
    POINT pt { };         //Mouse position when clicked.
    WORD  wMenuID { };    //Menu identifier.
    bool  fShow { true }; //Whether to show menu or not, in case of HEXCTRL_MSG_CONTEXTMENU.
};

HEXSPAN

此结构主要用于选择和书签例程。它保存数据区域的偏移量和大小。

struct HEXSPAN
{
    ULONGLONG ullOffset { };
    ULONGLONG ullSize { };
};

HEXVISION

此结构由 IsOffsetVisible 方法返回。两个成员 i8Verti8Horz 分别表示垂直和水平可见性。这些成员可以处于三种不同的状态

  • -1 — 偏移量高于可见区域或位于可见区域左侧。
  •   1 — 偏移量低于可见区域或位于可见区域右侧。
  •   0 — 偏移量可见。
struct HEXVISION
{
    std::int8_t i8Vert { }; //Vertical offset.
    std::int8_t i8Horz { }; //Horizontal offset.
    operator bool() { return i8Vert == 0 && i8Horz == 0; }; //For test simplicity: if(IsOffsetVisible()).
};

接口

IHexBookmarks

IHexBookmarks 接口负责 HexCtrl 的书签机制。要获取此接口的指针,请使用 GetBookmarks 方法。

class IHexBookmarks
{
public:
    virtual ULONGLONG AddBkm(const HEXBKM& hbs, bool fRedraw = true) = 0;   //Add new bookmark, returns the new bookmark's ID.
    virtual void ClearAll() = 0;                                            //Clear all bookmarks.
    [[nodiscard]] virtual auto GetByID(ULONGLONG ullID)->PHEXBKM = 0;       //Get bookmark by ID.
    [[nodiscard]] virtual auto GetByIndex(ULONGLONG ullIndex)->PHEXBKM = 0; //Get bookmark by index.
    [[nodiscard]] virtual ULONGLONG GetCount() = 0;                         //Get bookmarks count.
    [[nodiscard]] virtual auto HitTest(ULONGLONG ullOffset)->PHEXBKM = 0;   //HitTest for given offset.
    virtual void RemoveByID(ULONGLONG ullID) = 0;                           //Remove bookmark by a given ID.
};

IHexBookmarks::AddBkm

ULONGLONG AddBkm(const HEXBKM& hbs, bool fRedraw = false)

向控件添加新书签,返回创建的书签 ID。

示例

HEXBKM hbs;
hbs.vecSpan.emplace_back(0x1, 10);
hbs.clrBk = RGB(0, 255, 0);
hbs.clrText = RGB(255, 255, 255);
hbs.wstrDesc = L"My bookmark, with green bk and white text.";
myHex->GetBookmarks()->Add(hbs);

IHexBookmarks::ClearAll

void ClearAll();

清除所有书签。

IHexBookmarks::GetByID

GetByID(ULONGLONG ullID)->HEXBKM*;

按 ID 获取书签。

IHexBookmarks::GetByIndex

auto GetByIndex(ULONGLONG ullIndex)->HEXBKM*;

按索引获取书签。

IHexBookmarks::GetCount

ULONGLONG GetCount();

获取书签数量。

IHexBookmarks::HitTest

auto HitTest(ULONGLONG ullOffset)->HEXBKM*;

测试给定偏移量,如果偏移量包含书签,则检索指向 HEXBKM 的指针。

IHexBookmarks::RemoveByID

void RemoveByID(ULONGLONG ullID);

移除具有给定 ID 的书签。

IHexTemplates

class IHexTemplates
{
public:
    virtual int ApplyTemplate(ULONGLONG ullOffset, int iTemplateID) = 0; //Apply template to a given offset.
    virtual void DisapplyByID(int iAppliedID) = 0;
    virtual void DisapplyByOffset(ULONGLONG ullOffset) = 0;
    virtual int LoadTemplate(const wchar_t* pFilePath) = 0; //Returns loaded template ID on success, zero otherwise.
    virtual void ShowTooltips(bool fShow) = 0;
    virtual void UnloadTemplate(int iTemplateID) = 0;       //Unload/remove loaded template from memory.
};

IHexVirtColors

class IHexVirtColors
{
public:
    void OnHexGetColor(HEXCOLORINFO&) = 0;
};

此接口用于为数据区域设置自定义背景/文本颜色。
要使用此功能,在调用 SetData 方法之前,将 HEXDATA::pHexVirtColors 成员设置为实现此接口的类的有效实例。

此接口的 OnHexGetColor 方法将 HEXCOLORINFO 结构作为参数。方法完成后,此结构的 pClr 成员必须指向有效的 HEXCOLOR 结构,或者指向 nullptr 以使用默认颜色。

IHexVirtData

class IHexVirtData
{
public:
    virtual void OnHexGetData(HEXDATAINFO&) = 0;       //Data to get.
    virtual void OnHexSetData(const HEXDATAINFO&) = 0; //Data to set, if mutable.
};

Enums

EHexCmd

可在 HexCtrl 中执行的命令枚举。

enum class EHexCmd : std::uint8_t
{
    CMD_SEARCH_DLG = 0x01, CMD_SEARCH_NEXT, CMD_SEARCH_PREV,
    CMD_NAV_GOTO_DLG, CMD_NAV_REPFWD, CMD_NAV_REPBKW, CMD_NAV_DATABEG, CMD_NAV_DATAEND,
    CMD_NAV_PAGEBEG, CMD_NAV_PAGEEND, CMD_NAV_LINEBEG, CMD_NAV_LINEEND,
    CMD_GROUPBY_BYTE, CMD_GROUPBY_WORD, CMD_GROUPBY_DWORD, CMD_GROUPBY_QWORD,
    CMD_BKM_ADD, CMD_BKM_REMOVE, CMD_BKM_NEXT, CMD_BKM_PREV, CMD_BKM_REMOVEALL, CMD_BKM_DLG_MGR,
    CMD_CLPBRD_COPY_HEX, CMD_CLPBRD_COPY_HEXLE, CMD_CLPBRD_COPY_HEXFMT, CMD_CLPBRD_COPY_TEXTUTF16,
    CMD_CLPBRD_COPY_BASE64, CMD_CLPBRD_COPY_CARR, CMD_CLPBRD_COPY_GREPHEX, CMD_CLPBRD_COPY_PRNTSCRN,
    CMD_CLPBRD_COPY_OFFSET, CMD_CLPBRD_PASTE_HEX, CMD_CLPBRD_PASTE_TEXTUTF16, CMD_CLPBRD_PASTE_TEXTCP,
    CMD_MODIFY_OPERS_DLG, CMD_MODIFY_FILLZEROS, CMD_MODIFY_FILLDATA_DLG, CMD_MODIFY_UNDO, CMD_MODIFY_REDO,
    CMD_SEL_MARKSTART, CMD_SEL_MARKEND, CMD_SEL_ALL, CMD_SEL_ADDLEFT, CMD_SEL_ADDRIGHT, CMD_SEL_ADDUP,
    CMD_SEL_ADDDOWN, CMD_DATAINTERP_DLG, CMD_ENCODING_DLG, CMD_APPEAR_FONTCHOOSE, CMD_APPEAR_FONTINC,
    CMD_APPEAR_FONTDEC, CMD_APPEAR_CAPACINC, CMD_APPEAR_CAPACDEC, CMD_PRINT_DLG, CMD_ABOUT_DLG,
    CMD_CARET_LEFT, CMD_CARET_RIGHT, CMD_CARET_UP, CMD_CARET_DOWN,
    CMD_SCROLL_PAGEUP, CMD_SCROLL_PAGEDOWN,
    CMD_TEMPL_APPLYCURR, CMD_TEMPL_DISAPPLY, CMD_TEMPL_DISAPPALL, CMD_TEMPL_DLG_MGR
};

EHexDataSize

要操作的数据大小,用于 EHexModifyMode::MODIFY_OPERATION 模式。也用于在 SetGroupMode 方法中设置数据分组模式。

enum class EHexDataSize : std::uint8_t
{
    SIZE_BYTE = 0x01, SIZE_WORD = 0x02, SIZE_DWORD = 0x04, SIZE_QWORD = 0x08
};

EHexModifyMode

数据修改模式的枚举,用于 HEXMODIFY

enum class EHexModifyMode : std::uint8_t
{
    MODIFY_ONCE, MODIFY_REPEAT, MODIFY_OPERATION, MODIFY_RAND_MT19937, MODIFY_RAND_FAST
};

EHexOperMode

数据操作模式的枚举,当 HEXMODIFY::enModifyMode 设置为 MODIFY_OPERATION 时,用于 HEXMODIFY

enum class EHexOperMode : std::uint8_t
{
    OPER_ASSIGN, OPER_OR, OPER_XOR, OPER_AND, OPER_NOT, OPER_SHL, OPER_SHR, OPER_ROTL,
    OPER_ROTR, OPER_SWAP, OPER_ADD, OPER_SUB, OPER_MUL, OPER_DIV, OPER_CEIL, OPER_FLOOR
};

EHexWnd

所有 HexCtrl 内部窗口的枚举。此枚举用作 GetWindowHandle 方法中的参数以检索窗口句柄。

enum class EHexWnd : std::uint8_t
{
    WND_MAIN, DLG_BKMMANAGER, DLG_DATAINTERP, DLG_FILLDATA,
    DLG_OPERS, DLG_SEARCH, DLG_ENCODING, DLG_GOTO, DLG_TEMPLMGR
};

通知消息

在其工作期间,HexCtrl 通过 WM_NOTIFY 机制向 HEXCREATE::hwndParent 窗口发送有关其不同状态的通知消息。
WM_NOTIFY 消息的 LPARAM 将包含指向 NMHDR 标准 Windows 结构的指针。根据通知消息,LPARAM 可以被转换为指向另一个结构的指针,详情请参阅消息描述。

HEXCTRL_MSG_BKMCLICK

如果点击了书签,则发送。LPARAM 将包含指向 HEXBKMINFO 结构的指针。

HEXCTRL_MSG_CARETCHANGE

当插入符位置改变时发送。LPARAM 将包含指向 NMHDR 结构的指针。

HEXCTRL_MSG_CONTEXTMENU

在即将显示上下文菜单时发送。LPARAM 将包含指向 HEXMENUINFO 结构的指针。您可以通过在响应中将 PHEXMENUINFO->fShow 标志设置为 false 来禁用上下文菜单的显示。

HEXCTRL_MSG_DESTROY

发送此消息表示 HexCtrl 窗口即将被销毁。LPARAM 将包含指向 NMHDR 结构的指针。

HEXCTRL_MSG_MENUCLICK

当用户定义的自定义菜单被点击时发送。LPARAM 将包含指向 HEXMENUINFO 结构的指针。

HEXCTRL_MSG_SELECTION

完成选择后发送。LPARAM 将包含指向 NMHDR 结构的指针。

HEXCTRL_MSG_SETDATA

发送此消息表示数据已更改。LPARAM 将包含指向 NMHDR 结构的指针。

导出的函数

HexCtrl 有几个 "C" 接口函数,当它作为 .dll 构建时会导出这些函数。

CreateRawHexCtrl

extern "C" HEXCTRLAPI IHexCtrl* __cdecl CreateRawHexCtrl();

创建原始 IHexCtrl 接口指针的主要函数。您几乎不需要在代码中使用此函数。但是,如果您使用它,则需要手动调用 Destroy 方法。

GetHexCtrlInfo

extern "C" HEXCTRLAPI HEXCTRLINFO __cdecl GetHexCtrlInfo();

返回 HEXCTRLINFO 结构,其中包含 HexCtrl 的版本信息。

HEXCTRLINFO

包含 HexCtrl 版本信息的服务结构。

struct HEXCTRLINFO
{
    const wchar_t* pwszVersion { };        //WCHAR version string.
    union {
        unsigned long long ullVersion { }; //ULONGLONG version number.
        struct {
            short wMajor;
            short wMinor;
            short wMaintenance;
        }stVersion;
    };
};

外观

更改控件字体大小 — Ctrl+鼠标滚轮
更改控件容量 — Ctrl+Shift+鼠标滚轮

许可

本软件根据 “HexCtrl 许可” 提供,对任何 非商业 用途免费。
请参阅 LICENSE 文件。

© . All rights reserved.