适用于 C++/Win32 应用程序的十六进制控件
使用 C++/MFC 编写的全功能十六进制控件
十六进制控件, C++/MFC
目录
- 引言
- 安装
- 创建
- 设置数据
- 虚拟数据模式
- 虚拟书签
- 自定义颜色
- 模板
- 方法
展开
- ClearData
- Create
- CreateDialogCtrl
- Destroy
- ExecuteCmd
- GetActualWidth
- GetBookmarks
- GetCacheSize
- GetCapacity
- GetCaretPos
- GetColors
- GetData
- GetDataSize
- GetDateInfo
- GetEncoding
- GetFont
- GetGroupMode
- GetMenuHandle
- GetPagesCount
- GetPagePos
- GetPageSize
- GetSelection
- GetTemplates
- GetUnprintableChar
- GetWindowHandle
- GoToOffset
- HasSelection
- HitTest
- IsCmdAvail
- IsCreated
- IsDataSet
- IsMutable
- IsOffsetAsHex
- IsOffsetVisible
- IsVirtual
- ModifyData
- Redraw
- SetCapacity
- SetCaretPos
- SetColors
- SetConfig
- SetData
- SetDateInfo
- SetEncoding
- SetFont
- SetGroupMode
- SetMutable
- SetOffsetMode
- SetPageSize
- SetVirtualBkm
- SetRedraw
- SetSelection
- SetUnprintableChar
- SetWheelRatio
- ShowInfoBar
- 结构体
- 接口
- Enums
- 通知消息
- 导出的函数
- 外观
- 许可
引言
HexCtrl 是一个功能非常丰富的十六进制编辑器控件,用 C++/MFC 编写。
它实现为一个纯抽象接口,因此即使您的应用程序不直接使用 MFC,也可以使用它。它使用 /std:c++20 标准在 Visual Studio 2022 中编写。
HexCtrl 的主要功能
- 查看和编辑高达 16EB (exabyte) 的数据
- 以两种数据模式工作:内存 和 虚拟数据模式
- 功能齐全的 书签管理器
- 功能齐全的 搜索和替换
- 文本区域可更改编码
- 多种 复制/粘贴 到/从剪贴板的选项
- 撤销/重做
- 使用 填充 和许多预定义的 操作 选项修改数据
- 能够将数据可视地划分为 页面
- 打印整个文档/页面范围/选区
- 使用 自定义颜色 为数据块设置单独的颜色
- 强大的可自定义 模板 系统
- 通过外部配置文件 可分配的键盘快捷键
- 可自定义的外观
- 符合 /std:c++20 标准编写
安装
HexCtrl 可以通过两种不同的方式使用
- 作为项目的一部分从源代码构建
- 作为动态链接库 .dll 使用。
从源代码构建
构建过程非常简单
- 将 HexCtrl 文件夹复制到项目的目录中。
- 将 HexCtrl 文件夹中的所有文件添加到项目中(可以跳过
HexCtrl/dep/rapidjson/rapidjson-amalgam.h 头文件库)。 - 在您打算使用 HexCtrl 的地方添加
#include "HexCtrl/HexCtrl.h"
。 - 声明
IHexCtrlPtr
成员变量:IHexCtrlPtr myHex { HEXCTRL::CreateHexCtrl() };
- 创建 控件实例。
如果您想在非 MFC 应用程序中从源代码构建 HexCtrl,您需要
- 在项目设置中添加对 在共享 DLL 中使用 MFC 的支持。
- 取消注释
HexCtrl.h
头文件中的行//#define HEXCTRL_MANUAL_MFC_INIT
。
动态链接库
要将 HexCtrl 作为 .dll 使用,请执行以下操作
- 将 HexCtrl.h 和 HexCtrlDefs.h 文件复制到项目文件夹中。
- 将 HexCtrl.lib 文件复制到项目文件夹中,以便链接器可以看到它。
- 将 HexCtrl.dll 文件放在 .exe 文件旁边。
- 在您打算使用控件的地方添加以下行
#define HEXCTRL_SHARED_DLL //You can alternatively uncomment this line in HexCtrl.h.
#include "HexCtrl.h"`
- 声明
IHexCtrlPtr
成员变量:IHexCtrlPtr myHex { HEXCTRL::CreateHexCtrl() };
- 创建 控件实例。
要构建 HexCtrl.dll 和 HexCtrl.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::dwStyle
和 HEXCREATE::dwExStyle
分别是 窗口 和 扩展窗口 样式,它们将传递给 HexCtrl 的窗口创建函数,根据您的需要设置这些样式。
有关所有可用的创建选项,请参阅 HEXCREATE
结构描述。
在对话框中
要在 对话框 中使用 HexCtrl,您当然可以使用 经典方法 创建它,调用 Create
方法并提供所有必要信息。
但您可以使用另一种选择
- 将 Visual Studio 对话框设计器中的 工具箱 中的 自定义控件 放入对话框模板,并使其达到所需大小。
- 转到该控件的 属性,在 杂项 部分的 类 字段中,键入:HexCtrl。
为控件选择一个合适的 ID(本例中为 IDC_MY_HEX)。
此外,您还可以在此处设置控件的 动态布局 属性,以便控件在对话框大小调整时表现得当。
- 在对话框类中声明
IHexCtrlPtr
成员变量
IHexCtrlPtr m_myHex { CreateHexCtrl() };
- 从对话框的
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 [可选,数组] - 用户定义类型的数组,可以在 Fields 的 type 属性中引用
CustomTypes 对象与 Fields 对象相同,唯一的区别是 Fields 对象没有 TypeName 属性。
每个 Data 或 CustomType 对象都包含带有实际结构成员的 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 属性位于同一级别的 endianness、clrBk 和 clrText 属性将表示该级别及以下所有 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);
设置当前选区或高亮显示选区,如果 fHighlight
为 true
。
SetUnprintableChar
void SetUnprintableChar(wchar_t wch);
设置不可打印字符的替换字符。
SetWheelRatio
void SetWheelRatio(double dbRatio, bool fLines);
设置一个滚动页的滚动量。
一页是指一次鼠标滚轮滚动或一次“Page Down”键操作。当 fLines
为 true
时,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*;
成员 vecSpan
是 std::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
方法返回。两个成员 i8Vert
和 i8Horz
分别表示垂直和水平可见性。这些成员可以处于三种不同的状态
-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 文件。