Skip to content

Commit

Permalink
Added new DestroyWindow() method to the interface.
Browse files Browse the repository at this point in the history
Destroy() method renamed to Delete().
New DestroyDlg methods added to all dialogs.
These methods are now invoked from the CHexCtrl::OnDestroy(), to make sure the dialogs are always properly destroyed.
  • Loading branch information
jovibor committed Jan 3, 2025
1 parent ea4a29b commit be083ab
Show file tree
Hide file tree
Showing 18 changed files with 137 additions and 57 deletions.
5 changes: 3 additions & 2 deletions HexCtrl/HexCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,8 @@ namespace HEXCTRL {
virtual void ClearData() = 0; //Clears all data from HexCtrl's view (not touching data itself).
virtual bool Create(const HEXCREATE& hcs) = 0; //Main initialization method.
virtual bool CreateDialogCtrl(UINT uCtrlID, HWND hWndParent) = 0; //Сreates custom dialog control.
virtual void Destroy() = 0; //Deleter.
virtual void Delete() = 0; //IHexCtrl object deleter.
virtual void DestroyWindow() = 0; //Destroy HexCtrl window.
virtual void ExecuteCmd(EHexCmd eCmd) = 0; //Execute a command within HexCtrl.
[[nodiscard]] virtual auto GetActualWidth()const->int = 0; //Working area actual width.
[[nodiscard]] virtual auto GetBookmarks()const->IHexBookmarks* = 0; //Get Bookmarks interface.
Expand Down Expand Up @@ -466,7 +467,7 @@ namespace HEXCTRL {
virtual void ShowInfoBar(bool fShow) = 0; //Show/hide bottom Info bar.
};

struct IHexCtrlDeleter { void operator()(IHexCtrl* p)const { p->Destroy(); } };
struct IHexCtrlDeleter { void operator()(IHexCtrl* p)const { p->Delete(); } };
using IHexCtrlPtr = std::unique_ptr<IHexCtrl, IHexCtrlDeleter>;
[[nodiscard]] HEXCTRLAPI IHexCtrlPtr CreateHexCtrl();

Expand Down
35 changes: 26 additions & 9 deletions HexCtrl/src/CHexCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,20 @@ bool CHexCtrl::CreateDialogCtrl(UINT uCtrlID, HWND hWndParent)
return Create({ .hWndParent { hWndParent }, .uID { uCtrlID }, .fCustom { true } });
}

void CHexCtrl::Destroy()
void CHexCtrl::Delete()
{
//At this point the HexCtrl window should be destroyed anyway.
//This call is just to make sure it is.
DestroyWindow();

delete this;
}

void CHexCtrl::DestroyWindow()
{
m_Wnd.DestroyWindow();
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

void CHexCtrl::ExecuteCmd(EHexCmd eCmd)
Expand Down Expand Up @@ -1465,9 +1471,6 @@ void CHexCtrl::ModifyData(const HEXMODIFY& hms)

bool CHexCtrl::PreTranslateMsg(MSG* pMsg)
{
//The common if(!IsCreated()) check is ommited here for max throughput.
assert(IsCreated());

if (m_pDlgBkmMgr->PreTranslateMsg(pMsg)) { return true; }
if (m_pDlgDataInterp->PreTranslateMsg(pMsg)) { return true; }
if (m_pDlgModify->PreTranslateMsg(pMsg)) { return true; }
Expand Down Expand Up @@ -6900,25 +6903,39 @@ auto CHexCtrl::OnContextMenu(const MSG& msg)->LRESULT
auto CHexCtrl::OnDestroy()->LRESULT
{
//All these cleanups below are important when HexCtrl window is destroyed but IHexCtrl object
//itself is still alive. The IHexCtrl object is alive until the IHexCtrl::Destroy() method is called.
//Child windows of IHexCtrl (dialogs, tooltips, etc...) will be destroyed automatically by Windows.
//itself is still alive. The IHexCtrl object is alive until the IHexCtrl::Delete() method is called.
//Child windows of the IHexCtrl (e.g. tooltips) will be destroyed automatically by Windows.

//Note: The MSDN for the DestroyWindow clearly states that:
//"If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated
//child or owned windows when it destroys the parent or owner window. The function first destroys child or
//owned windows, and then it destroys the parent or owner window."
//But it doesn't seem to always be the case for owned dialog windows in some environments.
//These DestroyDlg() calls to make sure the dialogs are always properly destroyed.

ClearData();
m_pDlgBkmMgr->DestroyDlg();
m_pDlgCodepage->DestroyDlg();
m_pDlgDataInterp->DestroyDlg();
m_pDlgModify->DestroyDlg();
m_pDlgGoTo->DestroyDlg();
m_pDlgSearch->DestroyDlg();
m_pDlgTemplMgr->DestroyDlg();
m_pDlgTemplMgr->UnloadAll(); //Templates could be loaded without creating the dialog itself.
m_vecHBITMAP.clear();
m_vecKeyBind.clear();
m_vecUndo.clear();
m_vecRedo.clear();
m_vecCharsWidth.clear();
m_pDlgTemplMgr->UnloadAll(); //Explicitly unloading all loaded Templates.
m_MenuMain.DestroyMenu();
::DeleteObject(m_hFntMain);
::DeleteObject(m_hFntInfoBar);
::DeleteObject(m_hPenLines);
::DeleteObject(m_hPenDataTempl);
m_pScrollV->DestroyWindow(); //Not a child of the IHexCtrl.
m_pScrollH->DestroyWindow(); //Not a child of the IHexCtrl.
m_fCreated = false;
ParentNotify(HEXCTRL_MSG_DESTROY);
m_fCreated = false;

return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions HexCtrl/src/CHexCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ namespace HEXCTRL::INTERNAL {
void ClearData()override;
bool Create(const HEXCREATE& hcs)override;
bool CreateDialogCtrl(UINT uCtrlID, HWND hWndParent)override;
void Destroy()override;
void DestroyWindow();
void Delete()override;
void DestroyWindow()override;
void ExecuteCmd(EHexCmd eCmd)override;
[[nodiscard]] auto GetActualWidth()const->int override;
[[nodiscard]] auto GetBookmarks()const->IHexBookmarks* override;
Expand Down
67 changes: 37 additions & 30 deletions HexCtrl/src/Dialogs/CHexDlgBkmMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ auto CHexDlgBkmMgr::AddBkm(const HEXBKM& hbs, bool fRedraw)->ULONGLONG
ullID = 1; //Bookmarks' ID starts from 1.
if (const auto iter = std::max_element(m_vecBookmarks.begin(), m_vecBookmarks.end(),
[](const HEXBKM& ref1, const HEXBKM& ref2) {
return ref1.ullID < ref2.ullID; }); iter != m_vecBookmarks.end()) {
return ref1.ullID < ref2.ullID; }); iter != m_vecBookmarks.end()) {
ullID = iter->ullID + 1; //Increasing next bookmark's ID by 1.
}
m_vecBookmarks.emplace_back(hbs.vecSpan, hbs.wstrDesc, ullID, hbs.ullData, hbs.stClr);
Expand All @@ -53,6 +53,13 @@ void CHexDlgBkmMgr::CreateDlg()
}
}

void CHexDlgBkmMgr::DestroyDlg()
{
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

auto CHexDlgBkmMgr::GetHWND()const->HWND
{
return m_Wnd;
Expand Down Expand Up @@ -176,8 +183,8 @@ auto CHexDlgBkmMgr::HitTest(ULONGLONG ullOffset)->PHEXBKM
if (const auto rIter = std::find_if(m_vecBookmarks.rbegin(), m_vecBookmarks.rend(),
[ullOffset](const HEXBKM& ref) { return std::any_of(ref.vecSpan.begin(), ref.vecSpan.end(),
[ullOffset](const HEXSPAN& refV) {
return ullOffset >= refV.ullOffset && ullOffset < (refV.ullOffset + refV.ullSize); }); });
rIter != m_vecBookmarks.rend()) {
return ullOffset >= refV.ullOffset && ullOffset < (refV.ullOffset + refV.ullSize); }); });
rIter != m_vecBookmarks.rend()) {
pBkm = &*rIter;
}
}
Expand Down Expand Up @@ -253,7 +260,7 @@ void CHexDlgBkmMgr::RemoveByOffset(ULONGLONG ullOffset)
if (const auto iter = std::find_if(m_vecBookmarks.rbegin(), m_vecBookmarks.rend(),
[ullOffset](const HEXBKM& ref) { return std::any_of(ref.vecSpan.begin(), ref.vecSpan.end(),
[ullOffset](const HEXSPAN& refV) {
return ullOffset >= refV.ullOffset && ullOffset < (refV.ullOffset + refV.ullSize); }); });
return ullOffset >= refV.ullOffset && ullOffset < (refV.ullOffset + refV.ullSize); }); });
iter != m_vecBookmarks.rend()) {
RemoveBookmark(iter->ullID);
}
Expand Down Expand Up @@ -312,34 +319,34 @@ void CHexDlgBkmMgr::SortData(int iColumn, bool fAscending)
//iColumn is column number in CHexDlgBkmMgr::m_ListEx.
std::sort(m_vecBookmarks.begin(), m_vecBookmarks.end(),
[iColumn, fAscending](const HEXBKM& st1, const HEXBKM& st2) {
int iCompare { };
switch (iColumn) {
case 0:
break;
case 1: //Offset.
if (!st1.vecSpan.empty() && !st2.vecSpan.empty()) {
const auto ullOffset1 = st1.vecSpan.front().ullOffset;
const auto ullOffset2 = st2.vecSpan.front().ullOffset;
iCompare = ullOffset1 != ullOffset2 ? (ullOffset1 < ullOffset2 ? -1 : 1) : 0;
}
break;
case 2: //Size.
if (!st1.vecSpan.empty() && !st2.vecSpan.empty()) {
auto ullSize1 = std::reduce(st1.vecSpan.begin(), st1.vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
auto ullSize2 = std::reduce(st2.vecSpan.begin(), st2.vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
iCompare = ullSize1 != ullSize2 ? (ullSize1 < ullSize2 ? -1 : 1) : 0;
}
break;
case 3: //Description.
iCompare = st1.wstrDesc.compare(st2.wstrDesc);
break;
default:
break;
int iCompare { };
switch (iColumn) {
case 0:
break;
case 1: //Offset.
if (!st1.vecSpan.empty() && !st2.vecSpan.empty()) {
const auto ullOffset1 = st1.vecSpan.front().ullOffset;
const auto ullOffset2 = st2.vecSpan.front().ullOffset;
iCompare = ullOffset1 != ullOffset2 ? (ullOffset1 < ullOffset2 ? -1 : 1) : 0;
}
break;
case 2: //Size.
if (!st1.vecSpan.empty() && !st2.vecSpan.empty()) {
auto ullSize1 = std::reduce(st1.vecSpan.begin(), st1.vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
auto ullSize2 = std::reduce(st2.vecSpan.begin(), st2.vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
iCompare = ullSize1 != ullSize2 ? (ullSize1 < ullSize2 ? -1 : 1) : 0;
}
break;
case 3: //Description.
iCompare = st1.wstrDesc.compare(st2.wstrDesc);
break;
default:
break;
}

return fAscending ? iCompare < 0 : iCompare > 0;
return fAscending ? iCompare < 0 : iCompare > 0;
});
}

Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgBkmMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace HEXCTRL::INTERNAL {
public:
auto AddBkm(const HEXBKM& hbs, bool fRedraw) -> ULONGLONG override; //Returns new bookmark Id.
void CreateDlg();
void DestroyDlg();
[[nodiscard]] auto GetHWND()const->HWND;
[[nodiscard]] auto GetByID(ULONGLONG ullID) -> PHEXBKM override; //Bookmark by ID.
[[nodiscard]] auto GetByIndex(ULONGLONG ullIndex) -> PHEXBKM override; //Bookmark by index (in inner list).
Expand Down
9 changes: 8 additions & 1 deletion HexCtrl/src/Dialogs/CHexDlgCodepage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ void CHexDlgCodepage::CreateDlg()
}
}

void CHexDlgCodepage::DestroyDlg()
{
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

auto CHexDlgCodepage::GetHWND()const->HWND
{
return m_Wnd;
Expand Down Expand Up @@ -94,7 +101,7 @@ bool CHexDlgCodepage::IsNoEsc()const

auto CHexDlgCodepage::OnActivate(const MSG& msg)->INT_PTR
{
if (!m_pHexCtrl->IsCreated())
if (m_pHexCtrl == nullptr || !m_pHexCtrl->IsCreated())
return FALSE;

const auto nState = LOWORD(msg.wParam);
Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgCodepage.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace HEXCTRL::INTERNAL {
public:
void AddCP(std::wstring_view wsv);
void CreateDlg();
void DestroyDlg();
[[nodiscard]] auto GetHWND()const->HWND;
void Initialize(IHexCtrl* pHexCtrl, HINSTANCE hInstRes);
[[nodiscard]] bool PreTranslateMsg(MSG* pMsg);
Expand Down
17 changes: 12 additions & 5 deletions HexCtrl/src/Dialogs/CHexDlgDataInterp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ void CHexDlgDataInterp::CreateDlg()
}
}

void CHexDlgDataInterp::DestroyDlg()
{
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

auto CHexDlgDataInterp::GetDlgItemHandle(EHexDlgItem eItem)const->HWND
{
if (!m_Wnd.IsWindow()) {
Expand Down Expand Up @@ -324,7 +331,7 @@ bool CHexDlgDataInterp::IsShowAsHex()const

auto CHexDlgDataInterp::OnActivate(const MSG& msg)->INT_PTR
{
if (!m_pHexCtrl->IsCreated())
if (m_pHexCtrl == nullptr || !m_pHexCtrl->IsCreated())
return FALSE;

const auto nState = LOWORD(msg.wParam);
Expand Down Expand Up @@ -418,7 +425,7 @@ auto CHexDlgDataInterp::OnInitDialog(const MSG& msg)->INT_PTR

using enum EGroup; using enum EName; using enum EDataSize;
m_vecData.reserve(21);
m_vecData.emplace_back(L"Binary:", L"", GR_BINARY, NAME_BINARY, SIZE_BYTE);
m_vecData.emplace_back(L"Binary view:", L"", GR_BINARY, NAME_BINARY, SIZE_BYTE);
m_vecData.emplace_back(L"Int8:", L"", GR_INTEGRAL, NAME_INT8, SIZE_BYTE);
m_vecData.emplace_back(L"Unsigned Int8:", L"", GR_INTEGRAL, NAME_UINT8, SIZE_BYTE);
m_vecData.emplace_back(L"Int16:", L"", GR_INTEGRAL, NAME_INT16, SIZE_WORD);
Expand All @@ -427,6 +434,8 @@ auto CHexDlgDataInterp::OnInitDialog(const MSG& msg)->INT_PTR
m_vecData.emplace_back(L"Unsigned Int32:", L"", GR_INTEGRAL, NAME_UINT32, SIZE_DWORD);
m_vecData.emplace_back(L"Int64:", L"", GR_INTEGRAL, NAME_INT64, SIZE_QWORD);
m_vecData.emplace_back(L"Unsigned Int64:", L"", GR_INTEGRAL, NAME_UINT64, SIZE_QWORD);
m_vecData.emplace_back(L"Float:", L"", GR_FLOAT, NAME_FLOAT, SIZE_DWORD);
m_vecData.emplace_back(L"Double:", L"", GR_FLOAT, NAME_DOUBLE, SIZE_QWORD);
m_vecData.emplace_back(L"time32_t:", L"", GR_TIME, NAME_TIME32T, SIZE_DWORD);
m_vecData.emplace_back(L"time64_t:", L"", GR_TIME, NAME_TIME64T, SIZE_QWORD);
m_vecData.emplace_back(L"FILETIME:", L"", GR_TIME, NAME_FILETIME, SIZE_QWORD);
Expand All @@ -435,8 +444,6 @@ auto CHexDlgDataInterp::OnInitDialog(const MSG& msg)->INT_PTR
m_vecData.emplace_back(L"MS-DOS time:", L"", GR_TIME, NAME_MSDOSTIME, SIZE_QWORD);
m_vecData.emplace_back(L"MS-UDTTM time:", L"", GR_TIME, NAME_MSDTTMTIME, SIZE_DWORD);
m_vecData.emplace_back(L"Windows SYSTEMTIME:", L"", GR_TIME, NAME_SYSTEMTIME, SIZE_DQWORD);
m_vecData.emplace_back(L"Float:", L"", GR_FLOAT, NAME_FLOAT, SIZE_DWORD);
m_vecData.emplace_back(L"Double:", L"", GR_FLOAT, NAME_DOUBLE, SIZE_QWORD);
m_vecData.emplace_back(L"GUID:", L"", GR_MISC, NAME_GUID, SIZE_DQWORD);
m_vecData.emplace_back(L"GUID v1 UTC time:", L"", GR_GUIDTIME, NAME_GUIDTIME, SIZE_DQWORD);

Expand Down Expand Up @@ -988,7 +995,7 @@ template<ut::TSize1248 T>
void CHexDlgDataInterp::ShowValueBinary(T tData)
{
const auto pGrid = GetListData(EName::NAME_BINARY);
constexpr auto pSepar { L" " };
constexpr auto pSepar { L" " };
if constexpr (sizeof(T) == sizeof(std::uint8_t)) {
pGrid->wstrValue = std::format(L"{:08b}", tData);
}
Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgDataInterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace HEXCTRL::INTERNAL {
CHexDlgDataInterp();
~CHexDlgDataInterp();
void CreateDlg();
void DestroyDlg();
[[nodiscard]] auto GetDlgItemHandle(EHexDlgItem eItem)const->HWND;
[[nodiscard]] auto GetHglDataSize()const->DWORD;
[[nodiscard]] auto GetHWND()const->HWND;
Expand Down
9 changes: 8 additions & 1 deletion HexCtrl/src/Dialogs/CHexDlgGoTo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ void CHexDlgGoTo::CreateDlg()
}
}

void CHexDlgGoTo::DestroyDlg()
{
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

void CHexDlgGoTo::Initialize(IHexCtrl* pHexCtrl, HINSTANCE hInstRes)
{
if (pHexCtrl == nullptr || hInstRes == nullptr) {
Expand Down Expand Up @@ -181,7 +188,7 @@ bool CHexDlgGoTo::IsNoEsc()const
auto CHexDlgGoTo::OnActivate(const MSG& msg)->INT_PTR
{
const auto pHexCtrl = GetHexCtrl();
if (!pHexCtrl->IsCreated() || !pHexCtrl->IsDataSet())
if (pHexCtrl == nullptr || !pHexCtrl->IsCreated() || !pHexCtrl->IsDataSet())
return FALSE;

const auto nState = LOWORD(msg.wParam);
Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgGoTo.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace HEXCTRL::INTERNAL {
class CHexDlgGoTo final {
public:
void CreateDlg();
void DestroyDlg();
void Initialize(IHexCtrl* pHexCtrl, HINSTANCE hInstRes);
[[nodiscard]] auto GetHWND()const->HWND;
[[nodiscard]] bool IsRepeatAvail()const;
Expand Down
7 changes: 7 additions & 0 deletions HexCtrl/src/Dialogs/CHexDlgModify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,13 @@ void CHexDlgModify::CreateDlg()
}
}

void CHexDlgModify::DestroyDlg()
{
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

auto CHexDlgModify::GetDlgItemHandle(EHexDlgItem eItem)const->HWND
{
if (!m_Wnd.IsWindow()) {
Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgModify.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace HEXCTRL::INTERNAL {
CHexDlgModify();
~CHexDlgModify();
void CreateDlg();
void DestroyDlg();
[[nodiscard]] auto GetDlgItemHandle(EHexDlgItem eItem)const->HWND;
[[nodiscard]] auto GetHWND()const->HWND;
void Initialize(IHexCtrl* pHexCtrl, HINSTANCE hInstRes);
Expand Down
9 changes: 8 additions & 1 deletion HexCtrl/src/Dialogs/CHexDlgSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ void CHexDlgSearch::CreateDlg()
}
}

void CHexDlgSearch::DestroyDlg()
{
if (m_Wnd.IsWindow()) {
m_Wnd.DestroyWindow();
}
}

auto CHexDlgSearch::GetDlgItemHandle(EHexDlgItem eItem)const->HWND
{
if (!m_Wnd.IsWindow()) {
Expand Down Expand Up @@ -749,7 +756,7 @@ bool CHexDlgSearch::IsWildcard()const

auto CHexDlgSearch::OnActivate(const MSG& msg)->INT_PTR
{
if (!m_pHexCtrl->IsCreated())
if (m_pHexCtrl == nullptr || !m_pHexCtrl->IsCreated())
return FALSE;

const auto nState = LOWORD(msg.wParam);
Expand Down
Loading

0 comments on commit be083ab

Please sign in to comment.