diff --git a/.clang-tidy b/.clang-tidy index 18387db..c62cf89 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -12,6 +12,7 @@ Checks: '*, -misc-non-private-member-variables-in-classes, -misc-no-recursion, -misc-use-after-move, +-misc-use-internal-linkage, -modernize-use-trailing-return-type, -modernize-avoid-c-arrays, -modernize-use-ranges, diff --git a/HexCtrl/dep/ListEx/ListEx.ixx b/HexCtrl/dep/ListEx/ListEx.ixx index 75106ba..ae2dca2 100644 --- a/HexCtrl/dep/ListEx/ListEx.ixx +++ b/HexCtrl/dep/ListEx/ListEx.ixx @@ -121,11 +121,11 @@ export namespace HEXCTRL::LISTEX { * LISTEXCREATE - Main initialization helper struct for CListEx::Create method. * **********************************************************************************/ struct LISTEXCREATE { - CWnd* pParent { }; //Parent window. + HWND hWndParent { }; //Parent window. PCLISTEXCOLORS pColors { }; //ListEx colors. const LOGFONTW* pLFList { }; //ListEx LOGFONT. const LOGFONTW* pLFHdr { }; //Header LOGFONT. - CRect rect; //Initial rect. + RECT rect; //Initial rect. UINT uID { }; //ListEx control ID. DWORD dwStyle { }; //ListEx window styles. DWORD dwExStyle { }; //Extended window styles. @@ -160,7 +160,7 @@ export namespace HEXCTRL::LISTEX { class IListEx : public CMFCListCtrl { public: virtual bool Create(const LISTEXCREATE& lcs) = 0; - virtual void CreateDialogCtrl(UINT uCtrlID, CWnd* pParent) = 0; + virtual void CreateDialogCtrl(UINT uCtrlID, HWND hWndParent) = 0; virtual BOOL DeleteAllItems() = 0; virtual BOOL DeleteColumn(int nCol) = 0; virtual BOOL DeleteItem(int nItem) = 0; @@ -168,7 +168,7 @@ export namespace HEXCTRL::LISTEX { [[nodiscard]] virtual auto GetCellData(int iItem, int iSubitem)const->ULONGLONG = 0; [[nodiscard]] virtual auto GetColors()const->const LISTEXCOLORS & = 0; [[nodiscard]] virtual auto GetColumnSortMode(int iColumn)const->EListExSortMode = 0; - [[nodiscard]] virtual auto GetFont() -> CFont* = 0; + [[nodiscard]] virtual auto GetFont()const->LOGFONTW = 0; [[nodiscard]] virtual int GetSortColumn()const = 0; [[nodiscard]] virtual bool GetSortAscending()const = 0; virtual void HideColumn(int iIndex, bool fHide) = 0; @@ -177,6 +177,7 @@ export namespace HEXCTRL::LISTEX { int nSubItem = -1, int iDataAlign = LVCFMT_LEFT, bool fEditable = false) = 0; [[nodiscard]] virtual bool IsCreated()const = 0; [[nodiscard]] virtual bool IsColumnSortable(int iColumn) = 0; + virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMIS) = 0; virtual void ResetSort() = 0; //Reset all the sort by any column to its default state. virtual void SetCellColor(int iItem, int iSubitem, COLORREF clrBk, COLORREF clrText = -1) = 0; virtual void SetCellData(int iItem, int iSubitem, ULONGLONG ullData) = 0; @@ -187,12 +188,11 @@ export namespace HEXCTRL::LISTEX { virtual void SetColumnEditable(int iColumn, bool fEditable) = 0; virtual void SetColumnSortMode(int iColumn, bool fSortable, EListExSortMode eSortMode = { }) = 0; virtual void SetFont(const LOGFONTW& lf) = 0; - virtual void SetFont(CFont* pFont) = 0; virtual void SetHdrColumnColor(int iColumn, COLORREF clrBk, COLORREF clrText = -1) = 0; virtual void SetHdrColumnIcon(int iColumn, const LISTEXHDRICON& stIcon) = 0; //Icon for a given column. virtual void SetHdrFont(const LOGFONTW& lf) = 0; virtual void SetHdrHeight(DWORD dwHeight) = 0; - virtual void SetHdrImageList(CImageList* pList) = 0; + virtual void SetHdrImageList(HIMAGELIST pList) = 0; virtual void SetRowColor(DWORD dwRow, COLORREF clrBk, COLORREF clrText = -1) = 0; virtual void SetSortable(bool fSortable, PFNLVCOMPARE pfnCompare = nullptr, EListExSortMode eSortMode = EListExSortMode::SORT_LEX) = 0; @@ -795,7 +795,7 @@ namespace HEXCTRL::LISTEX::INTERNAL { class CListEx final : public IListEx { public: bool Create(const LISTEXCREATE& lcs)override; - void CreateDialogCtrl(UINT uCtrlID, CWnd* pParent)override; + void CreateDialogCtrl(UINT uCtrlID, HWND hWndParent)override; BOOL DeleteAllItems()override; BOOL DeleteColumn(int iIndex)override; BOOL DeleteItem(int iItem)override; @@ -803,7 +803,7 @@ namespace HEXCTRL::LISTEX::INTERNAL { [[nodiscard]] auto GetCellData(int iItem, int iSubItem)const->ULONGLONG override; [[nodiscard]] auto GetColors()const->const LISTEXCOLORS & override; [[nodiscard]] auto GetColumnSortMode(int iColumn)const->EListExSortMode override; - [[nodiscard]] auto GetFont() -> CFont* override; + [[nodiscard]] auto GetFont()const->LOGFONTW override; [[nodiscard]] int GetSortColumn()const override; [[nodiscard]] bool GetSortAscending()const override; void HideColumn(int iIndex, bool fHide)override; @@ -822,12 +822,11 @@ namespace HEXCTRL::LISTEX::INTERNAL { void SetColumnEditable(int iColumn, bool fEditable)override; void SetColumnSortMode(int iColumn, bool fSortable, EListExSortMode eSortMode = { })override; void SetFont(const LOGFONTW& lf)override; - void SetFont(CFont* pFont)override; void SetHdrColumnColor(int iColumn, COLORREF clrBk, COLORREF clrText = -1)override; void SetHdrColumnIcon(int iColumn, const LISTEXHDRICON& stIcon)override; //Icon for a given column. void SetHdrFont(const LOGFONTW& lf)override; void SetHdrHeight(DWORD dwHeight)override; - void SetHdrImageList(CImageList* pList)override; + void SetHdrImageList(HIMAGELIST pList)override; void SetRowColor(DWORD dwRow, COLORREF clrBk, COLORREF clrText)override; void SetSortable(bool fSortable, PFNLVCOMPARE pfnCompare, EListExSortMode eSortMode)override; static int CALLBACK DefCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); @@ -841,9 +840,9 @@ namespace HEXCTRL::LISTEX::INTERNAL { void FontSizeIncDec(bool fInc); void InitHeader()override; [[nodiscard]] auto GetCustomColor(int iItem, int iSubItem)const->std::optional; - [[nodiscard]] auto GetTooltip(int iItem, int iSubItem)const->std::optional; [[nodiscard]] int GetIcon(int iItem, int iSubItem)const; //Does cell have an icon associated. - afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMIS); + [[nodiscard]] auto GetTooltip(int iItem, int iSubItem)const->std::optional; + afx_msg void MeasureItem(LPMEASUREITEMSTRUCT pMIS); afx_msg void OnDestroy(); void OnEditInPlaceEnterPressed(); afx_msg void OnEditInPlaceKillFocus(); @@ -992,7 +991,7 @@ bool CListEx::Create(const LISTEXCREATE& lcs) const auto dwStyle = lcs.dwStyle | LVS_OWNERDRAWFIXED | LVS_REPORT; if (lcs.fDialogCtrl) { - if (SubclassDlgItem(lcs.uID, lcs.pParent) == FALSE) + if (SubclassDlgItem(lcs.uID, CWnd::FromHandle(lcs.hWndParent)) == FALSE) return false; const auto dwStyleCurr = GetWindowLongPtrW(m_hWnd, GWL_STYLE); @@ -1000,7 +999,7 @@ bool CListEx::Create(const LISTEXCREATE& lcs) m_fVirtual = dwStyleCurr & LVS_OWNERDATA; } else { - if (CreateEx(lcs.dwExStyle, dwStyle, lcs.rect, lcs.pParent, lcs.uID) == FALSE) + if (CreateEx(lcs.dwExStyle, dwStyle, lcs.rect, CWnd::FromHandle(lcs.hWndParent), lcs.uID) == FALSE) return false; m_fVirtual = dwStyle & LVS_OWNERDATA; @@ -1097,10 +1096,10 @@ bool CListEx::Create(const LISTEXCREATE& lcs) return true; } -void CListEx::CreateDialogCtrl(UINT uCtrlID, CWnd* pParent) +void CListEx::CreateDialogCtrl(UINT uCtrlID, HWND hWndParent) { LISTEXCREATE lcs; - lcs.pParent = pParent; + lcs.hWndParent = hWndParent; lcs.uID = uCtrlID; lcs.fDialogCtrl = true; @@ -1197,9 +1196,12 @@ auto CListEx::GetColumnSortMode(int iColumn)const->EListExSortMode return m_eDefSortMode; } -auto CListEx::GetFont()->CFont* +auto CListEx::GetFont()const->LOGFONTW { - return &m_fntList; + LOGFONTW lf { }; + ::GetObjectW(m_fntList, sizeof(lf), &lf); + + return lf; } long CListEx::GetFontSize() @@ -1481,19 +1483,6 @@ void CListEx::SetFont(const LOGFONTW& lf) Update(0); } -void CListEx::SetFont(CFont* pFont) -{ - assert(IsCreated()); - assert(pFont != nullptr); - if (!IsCreated() || pFont == nullptr) { - return; - } - - LOGFONTW lf { }; - pFont->GetLogFont(&lf); - SetFont(lf); -} - void CListEx::SetHdrHeight(DWORD dwHeight) { assert(IsCreated()); @@ -1506,14 +1495,14 @@ void CListEx::SetHdrHeight(DWORD dwHeight) GetHeaderCtrl().RedrawWindow(); } -void CListEx::SetHdrImageList(CImageList* pList) +void CListEx::SetHdrImageList(HIMAGELIST pList) { assert(IsCreated()); if (!IsCreated()) { return; } - GetHeaderCtrl().SetImageList(pList); + GetHeaderCtrl().SetImageList(CImageList::FromHandle(pList)); } void CListEx::SetHdrFont(const LOGFONTW& lf) @@ -1627,6 +1616,9 @@ int CALLBACK CListEx::DefCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lPar void CListEx::DrawItem(LPDRAWITEMSTRUCT pDIS) { + if (pDIS->hwndItem != m_hWnd) + return; + const auto iItem = pDIS->itemID; constexpr auto iTextIndentTop = 1; //To compensate what is added in the MeasureItem. constexpr auto iTextIndentLeft = 2; @@ -1772,6 +1764,30 @@ auto CListEx::GetCustomColor(int iItem, int iSubItem)const->std::optional(GetDlgCtrlID()); + const LISTEXICONINFO lii { .hdr { .hwndFrom { m_hWnd }, .idFrom { uCtrlID }, .code { LISTEX_MSG_GETICON } }, + .iItem { iItem }, .iSubItem { iSubItem } }; + GetParent()->SendMessageW(WM_NOTIFY, static_cast(uCtrlID), reinterpret_cast(&lii)); + return lii.iIconIndex; //By default it's -1, meaning no icon. + } + + const auto ID = MapIndexToID(iItem); + if (const auto it = m_umapCellIcon.find(ID); it != m_umapCellIcon.end()) { + if (const auto itInner = it->second.find(iSubItem); itInner != it->second.end()) { + return itInner->second; + } + } + + return -1; +} + auto CListEx::GetTooltip(int iItem, int iSubItem)const->std::optional { if (iItem < 0 || iSubItem < 0) { @@ -1799,44 +1815,23 @@ auto CListEx::GetTooltip(int iItem, int iSubItem)const->std::optional(GetDlgCtrlID()); - const LISTEXICONINFO lii { .hdr { .hwndFrom { m_hWnd }, .idFrom { uCtrlID }, .code { LISTEX_MSG_GETICON } }, - .iItem { iItem }, .iSubItem { iSubItem } }; - GetParent()->SendMessageW(WM_NOTIFY, static_cast(uCtrlID), reinterpret_cast(&lii)); - return lii.iIconIndex; //By default it's -1, meaning no icon. - } - - const auto ID = MapIndexToID(iItem); - if (const auto it = m_umapCellIcon.find(ID); it != m_umapCellIcon.end()) { - if (const auto itInner = it->second.find(iSubItem); itInner != it->second.end()) { - return itInner->second; - } - } - - return -1; -} - void CListEx::InitHeader() { GetHeaderCtrl().SubclassDlgItem(0, this); } -void CListEx::MeasureItem(LPMEASUREITEMSTRUCT lpMIS) +void CListEx::MeasureItem(LPMEASUREITEMSTRUCT pMIS) { + if (pMIS->CtlID != static_cast(GetDlgCtrlID())) + return; + //Set row height according to current font's height. auto pDC = GetDC(); pDC->SelectObject(m_fntList); TEXTMETRICW tm; GetTextMetricsW(pDC->m_hDC, &tm); ReleaseDC(pDC); - lpMIS->itemHeight = tm.tmHeight + tm.tmExternalLeading + 2; + pMIS->itemHeight = tm.tmHeight + tm.tmExternalLeading + 2; } void CListEx::OnDestroy() diff --git a/HexCtrl/res/HexCtrl.rc b/HexCtrl/res/HexCtrl.rc index 404ee6a..10dd8c8 100644 --- a/HexCtrl/res/HexCtrl.rc +++ b/HexCtrl/res/HexCtrl.rc @@ -170,7 +170,7 @@ EXSTYLE WS_EX_TOOLWINDOW CAPTION "Codepage" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - CONTROL "",IDC_HEXCTRL_CODEPAGE_LIST,"SysListView32",LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,0,32,309,288 + CONTROL "",IDC_HEXCTRL_CODEPAGE_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,0,32,309,288 LTEXT "Below are listed all codepages that are installed in the system.\r\nOnly single-byte codepages supported to work correctly.\nMultibyte codepages unsupported, such codepages are red highlighted.",IDC_STATIC,5,4,298,26 END diff --git a/HexCtrl/src/CHexCtrl.cpp b/HexCtrl/src/CHexCtrl.cpp index 4ad3f07..5d8ef60 100644 --- a/HexCtrl/src/CHexCtrl.cpp +++ b/HexCtrl/src/CHexCtrl.cpp @@ -1000,10 +1000,10 @@ auto CHexCtrl::GetWndHandle(EHexWnd eWnd, bool fCreate)const->HWND } return m_pDlgSearch->m_hWnd; case EHexWnd::DLG_CODEPAGE: - if (!IsWindow(m_pDlgCodepage->m_hWnd) && fCreate) { - m_pDlgCodepage->Create(IDD_HEXCTRL_CODEPAGE, CWnd::FromHandle(m_hWnd)); + if (!IsWindow(m_pDlgCodepage->GetHWND()) && fCreate) { + m_pDlgCodepage->CreateDlg(); } - return m_pDlgCodepage->m_hWnd; + return m_pDlgCodepage->GetHWND(); case EHexWnd::DLG_GOTO: if (!IsWindow(m_pDlgGoTo->GetHWND()) && fCreate) { m_pDlgGoTo->CreateDlg(); diff --git a/HexCtrl/src/Dialogs/CHexDlgBkmMgr.cpp b/HexCtrl/src/Dialogs/CHexDlgBkmMgr.cpp index 8c331f9..deed0e5 100644 --- a/HexCtrl/src/Dialogs/CHexDlgBkmMgr.cpp +++ b/HexCtrl/src/Dialogs/CHexDlgBkmMgr.cpp @@ -444,7 +444,7 @@ BOOL CHexDlgBkmMgr::OnInitDialog() { CDialogEx::OnInitDialog(); - m_pList->Create({ .pParent { this }, .uID { IDC_HEXCTRL_BKMMGR_LIST }, .dwSizeFontList { 10 }, + m_pList->Create({ .hWndParent { m_hWnd }, .uID { IDC_HEXCTRL_BKMMGR_LIST }, .dwSizeFontList { 10 }, .dwSizeFontHdr { 10 }, .fDialogCtrl { true } }); m_pList->SetExtendedStyle(LVS_EX_HEADERDRAGDROP); m_pList->SetSortable(true); @@ -573,7 +573,7 @@ void CHexDlgBkmMgr::OnListRClick(NMHDR* pNMHDR, LRESULT* /*pResult*/) m_menuList.TrackPopupMenuEx(TPM_LEFTALIGN, pt.x, pt.y, this, nullptr); } -void CHexDlgBkmMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* pResult) +void CHexDlgBkmMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* /*pResult*/) { const auto pLCI = reinterpret_cast(pNMHDR); @@ -581,14 +581,12 @@ void CHexDlgBkmMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* pResult) case 4: //Bk color. if (const auto* const pBkm = GetByIndex(static_cast(pLCI->iItem)); pBkm != nullptr) { pLCI->stClr.clrBk = pBkm->stClr.clrBk; - *pResult = TRUE; return; } break; case 5: //Text color. if (const auto* const pBkm = GetByIndex(static_cast(pLCI->iItem)); pBkm != nullptr) { pLCI->stClr.clrBk = pBkm->stClr.clrText; - *pResult = TRUE; return; } break; @@ -660,7 +658,7 @@ BOOL CHexDlgBkmMgr::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if (const auto* const pNMI = reinterpret_cast(lParam); pNMI->hdr.idFrom == IDC_HEXCTRL_BKMMGR_LIST) { switch (pNMI->hdr.code) { - //ON_NOTIFY(LVN_COLUMNCLICK, ...) macro doesn't work for CMFCListCtrl in neither virtual nor default mode. + //ON_NOTIFY(LVN_COLUMNCLICK, ...) macro doesn't work for CListCtrl in neither virtual nor default mode. //But it works for vanilla CListCtrl. Obviously it's MFC quirks. case LVN_COLUMNCLICK: if (!IsVirtual()) { diff --git a/HexCtrl/src/Dialogs/CHexDlgCodepage.cpp b/HexCtrl/src/Dialogs/CHexDlgCodepage.cpp index ca8b53f..d93d224 100644 --- a/HexCtrl/src/Dialogs/CHexDlgCodepage.cpp +++ b/HexCtrl/src/Dialogs/CHexDlgCodepage.cpp @@ -13,16 +13,6 @@ using namespace HEXCTRL::INTERNAL; -BEGIN_MESSAGE_MAP(CHexDlgCodepage, CDialogEx) - ON_NOTIFY(LVN_GETDISPINFOW, IDC_HEXCTRL_CODEPAGE_LIST, &CHexDlgCodepage::OnListGetDispInfo) - ON_NOTIFY(LVN_ITEMCHANGED, IDC_HEXCTRL_CODEPAGE_LIST, &CHexDlgCodepage::OnListItemChanged) - ON_NOTIFY(LISTEX::LISTEX_MSG_GETCOLOR, IDC_HEXCTRL_CODEPAGE_LIST, &CHexDlgCodepage::OnListGetColor) - ON_NOTIFY(LISTEX::LISTEX_MSG_LINKCLICK, IDC_HEXCTRL_CODEPAGE_LIST, &CHexDlgCodepage::OnListLinkClick) - ON_WM_ACTIVATE() - ON_WM_CLOSE() - ON_WM_DESTROY() -END_MESSAGE_MAP() - void CHexDlgCodepage::AddCP(std::wstring_view wsv) { if (const auto optCPID = stn::StrToUInt32(wsv); optCPID) { @@ -32,6 +22,28 @@ void CHexDlgCodepage::AddCP(std::wstring_view wsv) } } +void CHexDlgCodepage::CreateDlg() +{ + //m_Wnd is set in the OnInitDialog(). + if (const auto hWnd = ::CreateDialogParamW(wnd::GetHinstance(), MAKEINTRESOURCEW(IDD_HEXCTRL_CODEPAGE), + m_pHexCtrl->GetWndHandle(EHexWnd::WND_MAIN), wnd::DlgWndProc, reinterpret_cast(this)); + hWnd == nullptr) { + DBG_REPORT(L"CreateDialogParamW failed."); + } +} + +void CHexDlgCodepage::DestroyWindow() +{ + if (m_Wnd.IsWindow()) { + m_Wnd.DestroyWindow(); + } +} + +auto CHexDlgCodepage::GetHWND()const->HWND +{ + return m_Wnd; +} + void CHexDlgCodepage::Initialize(IHexCtrl* pHexCtrl) { assert(pHexCtrl); @@ -43,12 +55,24 @@ void CHexDlgCodepage::Initialize(IHexCtrl* pHexCtrl) bool CHexDlgCodepage::PreTranslateMsg(MSG* pMsg) { - if (m_hWnd == nullptr) - return false; - - if (::IsDialogMessageW(m_hWnd, pMsg) != FALSE) { return true; } + return m_Wnd.IsDlgMessage(pMsg); +} - return false; +auto CHexDlgCodepage::ProcessMsg(const MSG& stMsg)->INT_PTR +{ + switch (stMsg.message) { + case WM_ACTIVATE: return OnActivate(stMsg); + case WM_CLOSE: return OnClose(); + case WM_COMMAND: return OnCommand(stMsg); + case WM_DESTROY: return OnDestroy(); + case WM_DRAWITEM: return OnDrawItem(stMsg); + case WM_INITDIALOG: return OnInitDialog(stMsg); + case WM_MEASUREITEM: return OnMeasureItem(stMsg); + case WM_NOTIFY: return OnNotify(stMsg); + case WM_SIZE: return OnSize(stMsg); + default: + return 0; + } } void CHexDlgCodepage::SetDlgProperties(std::uint64_t u64Flags) @@ -56,33 +80,29 @@ void CHexDlgCodepage::SetDlgProperties(std::uint64_t u64Flags) m_u64Flags = u64Flags; } -BOOL CHexDlgCodepage::ShowWindow(int nCmdShow) +void CHexDlgCodepage::ShowWindow(int iCmdShow) { - if (!IsWindow(m_hWnd)) { - Create(IDD_HEXCTRL_CODEPAGE, CWnd::FromHandle(m_pHexCtrl->GetWndHandle(EHexWnd::WND_MAIN))); + if (!m_Wnd.IsWindow()) { + CreateDlg(); } - return CDialogEx::ShowWindow(nCmdShow); + m_Wnd.ShowWindow(iCmdShow); } //Private methods. -void CHexDlgCodepage::DoDataExchange(CDataExchange* pDX) -{ - CDialogEx::DoDataExchange(pDX); -} - bool CHexDlgCodepage::IsNoEsc()const { return m_u64Flags & HEXCTRL_FLAG_DLG_NOESC; } -void CHexDlgCodepage::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) +auto CHexDlgCodepage::OnActivate(const MSG& stMsg)->INT_PTR { if (!m_pHexCtrl->IsCreated()) - return; + return FALSE; + const auto nState = LOWORD(stMsg.wParam); if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE) { m_pList->SetItemState(-1, 0, LVIS_SELECTED); if (const auto iter = std::find_if(m_vecCodePage.begin(), m_vecCodePage.end(), @@ -94,7 +114,7 @@ void CHexDlgCodepage::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) } } - CDialogEx::OnActivate(nState, pWndOther, bMinimized); + return FALSE; //Default handler. } void CHexDlgCodepage::OnCancel() @@ -102,29 +122,87 @@ void CHexDlgCodepage::OnCancel() if (IsNoEsc()) //Not closing Dialog on Escape key. return; - CDialogEx::OnCancel(); + ShowWindow(SW_HIDE); } -void CHexDlgCodepage::OnDestroy() +auto CHexDlgCodepage::OnDestroy()->INT_PTR { - CDialogEx::OnDestroy(); - m_vecCodePage.clear(); m_u64Flags = { }; m_pHexCtrl = nullptr; + m_Wnd.Detach(); + + return TRUE; +} + +auto CHexDlgCodepage::OnDrawItem(const MSG& stMsg)->INT_PTR +{ + if (auto pDIS = reinterpret_cast(stMsg.lParam); + pDIS->CtlID == static_cast(IDC_HEXCTRL_CODEPAGE_LIST)) { + m_pList->DrawItem(pDIS); + } + + return TRUE; +} + +auto CHexDlgCodepage::OnMeasureItem(const MSG& stMsg)->INT_PTR +{ + if (auto pMIS = reinterpret_cast(stMsg.lParam); + pMIS->CtlID == static_cast(IDC_HEXCTRL_CODEPAGE_LIST)) { + m_pList->MeasureItem(pMIS); + } + + return TRUE; } -void CHexDlgCodepage::OnClose() +auto CHexDlgCodepage::OnNotify(const MSG& stMsg)->INT_PTR { - EndDialog(IDCANCEL); + auto pNMHDR = reinterpret_cast(stMsg.lParam); + if (pNMHDR->idFrom == IDC_HEXCTRL_CODEPAGE_LIST) { + switch (pNMHDR->code) { + case LVN_COLUMNCLICK: + SortList(); break; + case LVN_GETDISPINFOW: + OnListGetDispInfo(pNMHDR); break; + case LVN_ITEMCHANGED: + OnListItemChanged(pNMHDR); break; + case LISTEX::LISTEX_MSG_GETCOLOR: + OnListGetColor(pNMHDR); break; + case LISTEX::LISTEX_MSG_LINKCLICK: + OnListLinkClick(pNMHDR); break; + default: + break; + } + } + + return TRUE; } -BOOL CHexDlgCodepage::OnInitDialog() +auto CHexDlgCodepage::OnClose()->INT_PTR { - CDialogEx::OnInitDialog(); + ShowWindow(SW_HIDE); + return TRUE; +} - m_pList->Create({ .pParent { this }, .uID { IDC_HEXCTRL_CODEPAGE_LIST }, .dwSizeFontList { 10 }, - .dwSizeFontHdr { 10 }, .fDialogCtrl { true } }); +auto CHexDlgCodepage::OnCommand(const MSG& stMsg)->INT_PTR +{ + const auto uCtrlID = LOWORD(stMsg.wParam); + switch (uCtrlID) { + case IDOK: + case IDCANCEL: + OnCancel(); + break; + default: + return FALSE; + } + return TRUE; +} + +auto CHexDlgCodepage::OnInitDialog(const MSG& stMsg)->INT_PTR +{ + m_Wnd.Attach(stMsg.hwnd); + m_pList->Create({ .hWndParent { m_Wnd }, .uID { IDC_HEXCTRL_CODEPAGE_LIST }, .dwSizeFontList { 10 }, + .dwSizeFontHdr { 9 }, .fDialogCtrl { true } }); m_pList->SetExtendedStyle(LVS_EX_HEADERDRAGDROP); m_pList->SetSortable(true); m_pList->InsertColumn(0, L"Code page", LVCFMT_LEFT, 80); @@ -137,14 +215,14 @@ BOOL CHexDlgCodepage::OnInitDialog() EnumSystemCodePagesW(EnumCodePagesProc, CP_INSTALLED); m_pList->SetItemCountEx(static_cast(m_vecCodePage.size()), LVSICF_NOSCROLL); - if (const auto pLayout = GetDynamicLayout(); pLayout != nullptr) { - pLayout->SetMinSize({ 0, 0 }); - } + m_DynLayout.SetHost(m_Wnd); + m_DynLayout.AddItem(IDC_HEXCTRL_CODEPAGE_LIST, wnd::CDynLayout::MoveNone(), wnd::CDynLayout::SizeHorzAndVert(100, 100)); + m_DynLayout.EnableTrack(true); return TRUE; } -void CHexDlgCodepage::OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) +void CHexDlgCodepage::OnListGetDispInfo(NMHDR* pNMHDR) { const auto pDispInfo = reinterpret_cast(pNMHDR); const auto pItem = &pDispInfo->item; @@ -167,7 +245,7 @@ void CHexDlgCodepage::OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) } } -void CHexDlgCodepage::OnListItemChanged(NMHDR* pNMHDR, LRESULT* /*pResult*/) +void CHexDlgCodepage::OnListItemChanged(NMHDR* pNMHDR) { if (const auto* const pNMI = reinterpret_cast(pNMHDR); pNMI->iItem != -1 && pNMI->iSubItem != -1 && (pNMI->uNewState & LVIS_SELECTED)) { @@ -175,35 +253,27 @@ void CHexDlgCodepage::OnListItemChanged(NMHDR* pNMHDR, LRESULT* /*pResult*/) } } -void CHexDlgCodepage::OnListGetColor(NMHDR* pNMHDR, LRESULT* pResult) +void CHexDlgCodepage::OnListGetColor(NMHDR* pNMHDR) { if (const auto pLCI = reinterpret_cast(pNMHDR); m_vecCodePage[static_cast(pLCI->iItem)].uMaxChars > 1) { pLCI->stClr = { RGB(200, 80, 80), RGB(255, 255, 255) }; - *pResult = TRUE; return; } } -void CHexDlgCodepage::OnListLinkClick(NMHDR* pNMHDR, LRESULT* /*pResult*/) +void CHexDlgCodepage::OnListLinkClick(NMHDR* pNMHDR) { const auto* const pLLI = reinterpret_cast(pNMHDR); ShellExecuteW(nullptr, L"open", pLLI->pwszText, nullptr, nullptr, SW_SHOWNORMAL); } -BOOL CHexDlgCodepage::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) +auto CHexDlgCodepage::OnSize(const MSG& stMsg)->INT_PTR { - if (const auto* const pNMI = reinterpret_cast(lParam); pNMI->hdr.idFrom == IDC_HEXCTRL_CODEPAGE_LIST) { - switch (pNMI->hdr.code) { - case LVN_COLUMNCLICK: - SortList(); - return TRUE; - default: - break; - } - } - - return CDialogEx::OnNotify(wParam, lParam, pResult); + const auto iWidth = LOWORD(stMsg.lParam); + const auto iHeight = HIWORD(stMsg.lParam); + m_DynLayout.OnSize(iWidth, iHeight); + return TRUE; } void CHexDlgCodepage::SortList() @@ -236,6 +306,5 @@ void CHexDlgCodepage::SortList() BOOL CHexDlgCodepage::EnumCodePagesProc(LPWSTR pwszCP) { m_pThis->AddCP(pwszCP); - return TRUE; } \ No newline at end of file diff --git a/HexCtrl/src/Dialogs/CHexDlgCodepage.h b/HexCtrl/src/Dialogs/CHexDlgCodepage.h index 5f38b3d..caa0e68 100644 --- a/HexCtrl/src/Dialogs/CHexDlgCodepage.h +++ b/HexCtrl/src/Dialogs/CHexDlgCodepage.h @@ -6,34 +6,39 @@ ****************************************************************************************/ #pragma once #include "../../HexCtrl.h" -#include import HEXCTRL.HexUtility; namespace HEXCTRL::INTERNAL { - class CHexDlgCodepage final : public CDialogEx { + class CHexDlgCodepage final { public: void AddCP(std::wstring_view wsv); + void CreateDlg(); + void DestroyWindow(); + [[nodiscard]] auto GetHWND()const->HWND; void Initialize(IHexCtrl* pHexCtrl); [[nodiscard]] bool PreTranslateMsg(MSG* pMsg); + [[nodiscard]] auto ProcessMsg(const MSG& stMsg) -> INT_PTR; void SetDlgProperties(std::uint64_t u64Flags); - BOOL ShowWindow(int nCmdShow); + void ShowWindow(int iCmdShow); private: - void DoDataExchange(CDataExchange* pDX)override; [[nodiscard ]] bool IsNoEsc()const; - afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized); - void OnCancel()override; - afx_msg void OnClose(); - afx_msg void OnDestroy(); - BOOL OnInitDialog()override; - afx_msg void OnListGetDispInfo(NMHDR *pNMHDR, LRESULT *pResult); - afx_msg void OnListItemChanged(NMHDR *pNMHDR, LRESULT *pResult); - afx_msg void OnListGetColor(NMHDR *pNMHDR, LRESULT *pResult); - afx_msg void OnListLinkClick(NMHDR *pNMHDR, LRESULT *pResult); - BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)override; + auto OnActivate(const MSG& stMsg) -> INT_PTR; + void OnCancel(); + auto OnClose() -> INT_PTR; + auto OnCommand(const MSG& stMsg) -> INT_PTR; + auto OnDestroy() -> INT_PTR; + auto OnDrawItem(const MSG& stMsg) -> INT_PTR; + auto OnMeasureItem(const MSG& stMsg) -> INT_PTR; + auto OnNotify(const MSG& stMsg) -> INT_PTR; + auto OnInitDialog(const MSG& stMsg) -> INT_PTR; + void OnListGetDispInfo(NMHDR *pNMHDR); + void OnListItemChanged(NMHDR *pNMHDR); + void OnListGetColor(NMHDR *pNMHDR); + void OnListLinkClick(NMHDR *pNMHDR); + auto OnSize(const MSG& stMsg) -> INT_PTR; void SortList(); static BOOL CALLBACK EnumCodePagesProc(LPWSTR pwszCP); - DECLARE_MESSAGE_MAP(); private: struct CODEPAGE { int iCPID { }; @@ -41,6 +46,8 @@ namespace HEXCTRL::INTERNAL { UINT uMaxChars { }; }; inline static CHexDlgCodepage* m_pThis { }; + wnd::CWnd m_Wnd; //Main window. + wnd::CDynLayout m_DynLayout; IHexCtrl* m_pHexCtrl { }; LISTEX::IListExPtr m_pList { LISTEX::CreateListEx() }; std::vector m_vecCodePage; diff --git a/HexCtrl/src/Dialogs/CHexDlgGoTo.cpp b/HexCtrl/src/Dialogs/CHexDlgGoTo.cpp index bb7798e..2b35bee 100644 --- a/HexCtrl/src/Dialogs/CHexDlgGoTo.cpp +++ b/HexCtrl/src/Dialogs/CHexDlgGoTo.cpp @@ -86,13 +86,13 @@ void CHexDlgGoTo::SetDlgProperties(std::uint64_t u64Flags) m_u64Flags = u64Flags; } -void CHexDlgGoTo::ShowWindow(int nCmdShow) +void CHexDlgGoTo::ShowWindow(int iCmdShow) { if (!m_Wnd.IsWindow()) { CreateDlg(); } - m_Wnd.ShowWindow(nCmdShow); + m_Wnd.ShowWindow(iCmdShow); } @@ -187,13 +187,13 @@ bool CHexDlgGoTo::IsNoEsc()const auto CHexDlgGoTo::OnActivate(const MSG& stMsg)->INT_PTR { - const auto nState = LOWORD(stMsg.wParam); - const auto* const pHexCtrl = GetHexCtrl(); + const auto pHexCtrl = GetHexCtrl(); if (!pHexCtrl->IsCreated() || !pHexCtrl->IsDataSet()) - return TRUE; + return FALSE; + const auto nState = LOWORD(stMsg.wParam); if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE) { - //UpdateComboMode(); + UpdateComboMode(); } return FALSE; //Default handler. @@ -210,7 +210,6 @@ void CHexDlgGoTo::OnCancel() auto CHexDlgGoTo::OnClose()->INT_PTR { ShowWindow(SW_HIDE); - return TRUE; } diff --git a/HexCtrl/src/Dialogs/CHexDlgGoTo.h b/HexCtrl/src/Dialogs/CHexDlgGoTo.h index ca598df..66ded4e 100644 --- a/HexCtrl/src/Dialogs/CHexDlgGoTo.h +++ b/HexCtrl/src/Dialogs/CHexDlgGoTo.h @@ -21,7 +21,7 @@ namespace HEXCTRL::INTERNAL { [[nodiscard]] auto ProcessMsg(const MSG& stMsg) -> INT_PTR; void Repeat(bool fFwd = true); //fFwd: true - forward, false - backward. void SetDlgProperties(std::uint64_t u64Flags); - void ShowWindow(int nCmdShow); + void ShowWindow(int iCmdShow); private: enum class EGoMode : std::uint8_t; [[nodiscard]] auto GetHexCtrl()const->IHexCtrl*; diff --git a/HexCtrl/src/Dialogs/CHexDlgSearch.cpp b/HexCtrl/src/Dialogs/CHexDlgSearch.cpp index dd1807d..193a2f4 100644 --- a/HexCtrl/src/Dialogs/CHexDlgSearch.cpp +++ b/HexCtrl/src/Dialogs/CHexDlgSearch.cpp @@ -963,7 +963,7 @@ BOOL CHexDlgSearch::OnInitDialog() iIndex = m_comboMode.AddString(L"Structs"); m_comboMode.SetItemData(iIndex, static_cast(ESearchMode::MODE_STRUCT)); - m_pList->Create({ .pParent { this }, .uID { IDC_HEXCTRL_SEARCH_LIST }, .dwSizeFontList { 10 }, + m_pList->Create({ .hWndParent { m_hWnd }, .uID { IDC_HEXCTRL_SEARCH_LIST }, .dwSizeFontList { 10 }, .dwSizeFontHdr { 10 }, .fDialogCtrl { true } }); m_pList->SetExtendedStyle(LVS_EX_HEADERDRAGDROP); m_pList->InsertColumn(0, L"№", LVCFMT_LEFT, 50); diff --git a/HexCtrl/src/Dialogs/CHexDlgTemplMgr.cpp b/HexCtrl/src/Dialogs/CHexDlgTemplMgr.cpp index 77448be..abf6f79 100644 --- a/HexCtrl/src/Dialogs/CHexDlgTemplMgr.cpp +++ b/HexCtrl/src/Dialogs/CHexDlgTemplMgr.cpp @@ -671,7 +671,7 @@ BOOL CHexDlgTemplMgr::OnInitDialog() { CDialogEx::OnInitDialog(); - m_pList->Create({ .pParent { this }, .uID { IDC_HEXCTRL_TEMPLMGR_LIST }, .dwSizeFontList { 10 }, + m_pList->Create({ .hWndParent { m_hWnd }, .uID { IDC_HEXCTRL_TEMPLMGR_LIST }, .dwSizeFontList { 10 }, .dwSizeFontHdr { 10 }, .fDialogCtrl { true } }); m_pList->SetExtendedStyle(LVS_EX_HEADERDRAGDROP); m_pList->InsertColumn(m_iIDListApplFieldType, L"Type", LVCFMT_LEFT, 85); @@ -982,7 +982,7 @@ void CHexDlgTemplMgr::OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) } } -void CHexDlgTemplMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* pResult) +void CHexDlgTemplMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* /*pResult*/) { static constexpr auto clrTextBluish { RGB(16, 42, 255) }; //Bluish text. static constexpr auto clrTextGreenish { RGB(0, 110, 0) }; //Green text. @@ -1008,7 +1008,6 @@ void CHexDlgTemplMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* pResult) pLCI->stClr.clrText = clrTextBluish; } } - *pResult = TRUE; return; } @@ -1018,14 +1017,12 @@ void CHexDlgTemplMgr::OnListGetColor(NMHDR* pNMHDR, LRESULT* pResult) if (eType != type_custom && eType != custom_size) { pLCI->stClr.clrText = clrTextBluish; pLCI->stClr.clrBk = static_cast(-1); //Default bk color. - *pResult = TRUE; return; } break; case m_iIDListApplFieldClrs: pLCI->stClr.clrBk = pField->stClr.clrBk; pLCI->stClr.clrText = pField->stClr.clrText; - *pResult = TRUE; return; default: break; diff --git a/HexCtrl/src/HexUtility.ixx b/HexCtrl/src/HexUtility.ixx index 825d371..a98f4bd 100644 --- a/HexCtrl/src/HexUtility.ixx +++ b/HexCtrl/src/HexUtility.ixx @@ -8,6 +8,7 @@ module; #include #include "../HexCtrl.h" #include +#include #include #include #include @@ -472,6 +473,97 @@ export namespace HEXCTRL::INTERNAL { ::ExtTextOutW(hDC, 0, 0, ETO_OPAQUE, pRC, nullptr, 0, nullptr); } + class CDynLayout { + public: + //Ratio settings, for how much to move or resize an item when parent is resized. + struct ItemRatio { + float m_flXRatio { }; + float m_flYRatio { }; + }; + + void AddItem(int iIDItem, ItemRatio move, ItemRatio size); + void EnableTrack(bool fTrack); + void OnSize(int iWidth, int iHeight)const; //Should be hooked into the host window WM_SIZE handler. + void SetHost(HWND hWnd) { assert(hWnd != nullptr); m_hWndHost = hWnd; } + + //Static helper methods to use in the AddItem. + [[nodiscard]] static ItemRatio MoveNone() { return { }; } + [[nodiscard]] static ItemRatio MoveHorz(int iXRatio) { + iXRatio = std::clamp(iXRatio, 0, 100); return { .m_flXRatio { iXRatio / 100.F }, .m_flYRatio { } }; + } + [[nodiscard]] static ItemRatio MoveVert(int iYRatio) { + iYRatio = std::clamp(iYRatio, 0, 100); return { .m_flXRatio { }, .m_flYRatio { iYRatio / 100.F } }; + } + [[nodiscard]] static ItemRatio MoveHorzAndVert(int iXRatio, int iYRatio) { + iXRatio = std::clamp(iXRatio, 0, 100); iYRatio = std::clamp(iYRatio, 0, 100); + return { .m_flXRatio { iXRatio / 100.F }, .m_flYRatio { iYRatio / 100.F } }; + } + [[nodiscard]] static ItemRatio SizeNone() { return { }; } + [[nodiscard]] static ItemRatio SizeHorz(int iXRatio) { + iXRatio = std::clamp(iXRatio, 0, 100); return { .m_flXRatio { iXRatio / 100.F }, .m_flYRatio { } }; + } + [[nodiscard]] static ItemRatio SizeVert(int iYRatio) { + iYRatio = std::clamp(iYRatio, 0, 100); return { .m_flXRatio { }, .m_flYRatio { iYRatio / 100.F } }; + } + [[nodiscard]] static ItemRatio SizeHorzAndVert(int iXRatio, int iYRatio) { + iXRatio = std::clamp(iXRatio, 0, 100); iYRatio = std::clamp(iYRatio, 0, 100); + return { .m_flXRatio { iXRatio / 100.F }, .m_flYRatio { iYRatio / 100.F } }; + } + private: + struct ItemData { + HWND hWnd { }; //Item window. + RECT rcOrig { }; //Item original client area rect after EnableTrack(true). + ItemRatio move; //How much to move the item. + ItemRatio size; //How much to resize the item. + }; + HWND m_hWndHost { }; //Host window. + RECT m_rcHostOrig { }; //Host original client area rect after EnableTrack(true). + std::vector m_vecItems; //All items to resize/move. + bool m_fTrack { true }; + }; + + void CDynLayout::AddItem(int iIDItem, ItemRatio move, ItemRatio size) { + const auto hWnd = ::GetDlgItem(m_hWndHost, iIDItem); + assert(hWnd != nullptr); + if (hWnd != nullptr) { + m_vecItems.emplace_back(ItemData { .hWnd { hWnd }, .move { move }, .size { size } }); + } + } + + void CDynLayout::EnableTrack(bool fTrack) { + m_fTrack = fTrack; + if (fTrack) { + ::GetClientRect(m_hWndHost, &m_rcHostOrig); + for (auto& [hWnd, rc, move, size] : m_vecItems) { + ::GetWindowRect(hWnd, &rc); + ::ScreenToClient(m_hWndHost, reinterpret_cast(&rc)); + ::ScreenToClient(m_hWndHost, reinterpret_cast(&rc) + 1); + } + } + } + + void CDynLayout::OnSize(int iWidth, int iHeight)const { + if (!m_fTrack) + return; + + const auto iHostWidth = m_rcHostOrig.right - m_rcHostOrig.left; + const auto iHostHeight = m_rcHostOrig.bottom - m_rcHostOrig.top; + const auto iDeltaX = iWidth - iHostWidth; + const auto iDeltaY = iHeight - iHostHeight; + + const auto hDWP = ::BeginDeferWindowPos(static_cast(m_vecItems.size())); + for (const auto& [hWnd, rc, move, size] : m_vecItems) { + const auto iNewLeft = static_cast(rc.left + (iDeltaX * move.m_flXRatio)); + const auto iNewTop = static_cast(rc.top + (iDeltaY * move.m_flYRatio)); + const auto iOrigWidth = rc.right - rc.left; + const auto iOrigHeight = rc.bottom - rc.top; + const auto iNewWidth = static_cast(iOrigWidth + (iDeltaX * size.m_flXRatio)); + const auto iNewHeight = static_cast(iOrigHeight + (iDeltaY * size.m_flYRatio)); + ::DeferWindowPos(hDWP, hWnd, nullptr, iNewLeft, iNewTop, iNewWidth, iNewHeight, SWP_NOZORDER | SWP_NOACTIVATE); + } + ::EndDeferWindowPos(hDWP); + } + class CRect : public RECT { public: CRect() { left = 0; top = 0; right = 0; bottom = 0; } @@ -503,7 +595,7 @@ export namespace HEXCTRL::INTERNAL { CWnd operator=(HWND) = delete; operator HWND()const { return m_hWnd; } [[nodiscard]] bool operator==(const CWnd& rhs)const { return m_hWnd == rhs.m_hWnd; } - [[nodiscard]] bool operator==(const HWND hWnd)const { return m_hWnd == hWnd; } + [[nodiscard]] bool operator==(HWND hWnd)const { return m_hWnd == hWnd; } void Attach(HWND hWnd) { assert(::IsWindow(hWnd)); m_hWnd = hWnd; } [[nodiscard]] auto ChildWindowFromPoint(POINT pt)const->HWND { assert(IsWindow()); return ::ChildWindowFromPoint(m_hWnd, pt); @@ -512,7 +604,9 @@ export namespace HEXCTRL::INTERNAL { assert(IsWindow()); ::ClientToScreen(m_hWnd, reinterpret_cast(pRC)); ::ClientToScreen(m_hWnd, (reinterpret_cast(pRC)) + 1); } - bool DestroyWindow()const { assert(IsWindow()); return ::DestroyWindow(m_hWnd); } + bool DestroyWindow() { + assert(IsWindow()); const auto ret = ::DestroyWindow(m_hWnd); m_hWnd = nullptr; return ret; + } void Detach() { m_hWnd = nullptr; } [[nodiscard]] auto GetClientRect()const->RECT { assert(IsWindow()); RECT rc; ::GetClientRect(m_hWnd, &rc); return rc;