Click here to Skip to main content
13,869,178 members
Click here to Skip to main content
Add your own
alternative version

Stats

21.8K views
423 downloads
31 bookmarked
Posted 9 Dec 2018
Licenced CPOL

MFC HEX Control

, 19 Feb 2019
Rate this:
Please Sign up or sign in to vote.
HEX control for MFC apps

MFC HexControl

Table of contents

​​Introduction

Being good low level wrapper library for Windows API in general, MFC was always lacking a good native controls support.

This always forced people to implement their own common stuff for every day needs.

This HEX control is a tiny attempt to expand standard MFC functionality, because at the time of writing this article, MFC doesn't have native support for such feature.

Implementation

This HEX control is implemented as CWnd derived class, and can be used as a child or float window in any place of your existing MFC application. Control was build and tested in Visual Studio 2017 under Windows 10.

Using the Code

The usage of this control is quite simple:

  1. Add all files from the archive into your project.
  2. Add #include "HexCtrl.h" line in where you suppose to use control.
  3. Declare CHexCtrl member variable — CHexCtrl myHex;.
  4. Call myHex.Create function to create control instance.
  5. Call myHex.SetData method to set the actual data to display as hex.

Control uses its own namespace — HEXCTRL. So it's up to you, to use namespace preffix - HEXCTRL::, or define namespace in the file's beginning - using namespace HEXCTRL;.

Child or Float

CHexCtrl::Create method takes HEXCREATESTRUCT as its argument:

struct HEXCREATESTRUCT
    {
        CWnd*        pwndParent { };             //Parent window pointer.
        UINT         uId { };                    //Hex control id.
        DWORD        dwExStyles { };             //Extended window styles.
        CRect        rc { };                     //Initial rect.
        bool         fFloat { false };           //Is float or child - incorporated into another window.
        const        LOGFONT* pLogFont { };      //Font to be used. Default if it's nullptr.
        CWnd*        pwndMsg { };                //Pointer to the window that is going to recieve command messages, 
                                                 //such as HEXCTRL_MSG_GETDISPINFO. If zero - parent window is used.
    };

You can choose whether control will behave as a child or independent floating window by setting fFloat member of this struct.

HEXCREATESTRUCT hcs;
hcs.fFloat = true;
bool Create(hcs);

Virtual Mode

In third argument of CHexCtrl::SetData member function, control can be set to work in Virtual Mode.

What it means is that when control is about to display the next byte it will first ask for this byte's value from its parent window, in form of WM_NOTIFY message. This is pretty much the same as the standart MFC List Control works when it's created with LVS_OWNERDATA flag.

This mode can be quite useful, for instance, in cases where you need to display very big amount of data, that can't fit in memory all at once.

void SetData(const unsigned char* pData, ULONGLONG ullCount, bool fVirtual = false);

In control's parent window process WM_NOTIFY message as follows:

BOOL CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    PHEXNOTIFY pHexNtfy = (PHEXNOTIFY)lParam;

    if (pHexNtfy->hdr.idFrom == IDC_MY_HEX_CTRL)
    {
        switch (pHexNtfy->hdr.code)
        {
        case HEXCTRL_MSG_GETDISPINFO:
            pHexNtfy->chByte = /*code for set given byte data*/;
            break;
        }
   }
}

lParam will hold a pointer to HEXNOTIFY structure, which is described below:

struct HEXNOTIFY
    {
        NMHDR            hdr;
        ULONGLONG        ullByteIndex;
        unsigned char    chByte;
    };
    using PHEXNOTIFY = HEXNOTIFY*;

Its first member is a standard Windows' NMHDR structure. It will have its code member equal to HEXCTRL_MSG_GETDISPINFO, indicating that HexControl's byte request has arrived.

The second member is the index of the byte be displayed. And the third is the actual byte, that you have to set in response.

OnDestroy

When HexControl window is destroyed it sends WM_NOTIFY message to its parent window with NMHDR::code equals to HEXCTRL_MSG_DESTROY

Scroll Bars

When i started to work with very big files i immediately faced one very nasty inconvenience:

The standard Windows scrollbars can hold only signed integer value, which is too little to scroll through many gigabytes of data. It could be some workarounds and crutches involved to overcome this, but frankly saying i hate this kind of approach.

That's why HexControl uses its own scrollbars. They work with unsigned long long values, which is way bigger than standart signed ints. These scrollbars behave as normal Windows scrollbars, and even reside in the non client area, as the latter do.

Methods

CHexCtrl class has a set of methods, that you can use to set your data to display as hex, or to customize your hex control appearance. These methods' usage is pretty straightforward and clean from their naming.

void SetData(const unsigned char* pData, ULONGLONG ullSize, bool fVirtual = false, ULONGLONG ullOffset = 0, CWnd* pwndMsg = nullptr);
void ClearData();
void SetCapacity(DWORD dwCapacity);
void SetFont(const LOGFONT* pLogFontNew) const
void SetFontSize(UINT nSize) const;
void SetColor(COLORREF clrTextHex, COLORREF clrTextAscii, COLORREF clrTextCaption,
              COLORREF clrBk, COLORREF clrBkSelected) const;
void SetSelection(ULONGLONG ullOffset, ULONGLONG ullSize = 1);

Example

The function you use to set a data to display as hex is CHexCtrl::SetData.
It has two main parameters:

  1. const unsigned char* pData — pointer to arbitrary data in memory
  2. ULONGLONG ullCount — amount of bytes to display

The code below constructs CHexCtrl object and displays first 0x1FF bytes of your app's memory:

CHexCtrl myHex.
HEXCREATESTRUCT hcs;
myHex.Create(hcs);
myHex.SetData((unsigned char*)GetModuleHandle(0), 0x1FF);

The next example displays std::string's text string as hex:

std::string str = "My string";
myHex.SetData((unsigned char*)str.data(), str.size());

Positioning And Sizing

To properly resize and position CHexCtrl control, you should handle WM_SIZE message in its parent window, in something like that way:

void CMyWnd::OnSize(UINT nType, int cx, int cy)
{
    .
    .
    myHex.SetWindowPos(this, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOZORDER);
}

Appearance

  • To change control's font size - «Ctrl+MouseWheel»
  • To change control's capacity - «Ctrl+Shift+MouseWheel»

Support

If you have any useful feature to suggest, or if you found a bug — please let me know in the comments section below.

Licensing

This software is available under the "MIT License modified with The Commons Clause".

https://github.com/jovibor/Pepper/blob/master/LICENSE

History

  • 8th December, 2018 - First version
  • 21st December, 2018 - v1.1 Some tweaks and fixes
  • 23rd December, 2018 - v1.2 C++17 obligation has been alleviated
  • 25th December, 2018 - v1.3
    • Added
      • Bottom info bar
      • Ability to change capacity
    • Fixes
      • Some selection related bugs fixed
  • 28th December, 2018 - v1.4
    • Added
      • Search support
      • Selection offset into info bar
      • About box
    • Fixed
      • Some minor bugs fixed
  • 4th January, 2019 - v1.5 Further improvements and fixes
  • 7th January, 2019 - v1.5.1 Little fix.
  • 12th February, 2019 - v1.7 Lots of reworks, improvements and fixes.
  • 19th February, 2019 - v1.7.5 Fixed some regressions. HEXCTRLCREATE added.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jovibor
Russian Federation Russian Federation
No Biography provided

You may also be interested in...

Pro

Comments and Discussions

 
BugHm, I'm sorry Pin
TomBengsch14-Feb-19 21:12
memberTomBengsch14-Feb-19 21:12 
GeneralRe: Hm, I'm sorry Pin
Jovibor15-Feb-19 2:49
memberJovibor15-Feb-19 2:49 
GeneralRe: Hm, I'm sorry Pin
TomBengsch17-Feb-19 18:22
memberTomBengsch17-Feb-19 18:22 
GeneralRe: Hm, I'm sorry Pin
Jovibor17-Feb-19 18:58
memberJovibor17-Feb-19 18:58 
PraiseNice Pin
Rick York25-Dec-18 19:22
mveRick York25-Dec-18 19:22 
GeneralRe: Nice Pin
Jovibor25-Dec-18 19:39
memberJovibor25-Dec-18 19:39 
PraiseExcellent! Pin
koothkeeper21-Dec-18 11:10
professionalkoothkeeper21-Dec-18 11:10 
GeneralRe: Excellent! Pin
Jovibor21-Dec-18 13:42
memberJovibor21-Dec-18 13:42 
QuestionDialogs Pin
Rick York19-Dec-18 15:02
mveRick York19-Dec-18 15:02 
AnswerRe: Dialogs Pin
Jovibor19-Dec-18 20:11
memberJovibor19-Dec-18 20:11 
GeneralRe: Dialogs Pin
Rick York19-Dec-18 20:43
mveRick York19-Dec-18 20:43 
GeneralRe: Dialogs Pin
Jovibor19-Dec-18 22:08
memberJovibor19-Dec-18 22:08 
QuestionError with std:byte Pin
Member 18025911-Dec-18 16:26
memberMember 18025911-Dec-18 16:26 
AnswerRe: Error with std:byte Pin
Jovibor11-Dec-18 19:05
memberJovibor11-Dec-18 19:05 
GeneralRe: Error with std:byte Pin
Member 18025912-Dec-18 6:18
memberMember 18025912-Dec-18 6:18 
GeneralRe: Error with std:byte Pin
Jovibor12-Dec-18 13:21
memberJovibor12-Dec-18 13:21 
AnswerRe: Error with std:byte Pin
Rick York20-Dec-18 11:25
mveRick York20-Dec-18 11:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190214.1 | Last Updated 19 Feb 2019
Article Copyright 2018 by Jovibor
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid