From c75f47da933ab63bdbe2adf756a200caf161bfce Mon Sep 17 00:00:00 2001 From: Neil Date: Sat, 19 Apr 2025 09:38:29 +1000 Subject: Move most of the implementation of the static ListBoxX::ControlWndProc to the member function ListBoxX::ListProc so it can directly access state. Stop using GWLP_USERDATA to hold the previous window procedure of subclassed window since it can be stored in the ListBoxX object with better type-safety. Decrease warnings for reinterpret_cast since it is a common Win32 idiom to pass pointers as integers to window procedures. --- win32/ListBox.cxx | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/win32/ListBox.cxx b/win32/ListBox.cxx index 68fe48d27..38806a373 100644 --- a/win32/ListBox.cxx +++ b/win32/ListBox.cxx @@ -73,6 +73,10 @@ using namespace Scintilla::Internal; namespace { +void *PtrFromLParam(Scintilla::sptr_t lParam) noexcept { + return reinterpret_cast(lParam); +} + struct ListItemData { const char *text; int pixId; @@ -152,6 +156,7 @@ class ListBoxX : public ListBox { int maxItemCharacters = 0; unsigned int aveCharWidth = 8; Window *parent = nullptr; + WNDPROC prevWndProc{}; int ctrlID = 0; UINT dpi = USER_DEFAULT_SCREEN_DPI; IListBoxDelegate *delegate = nullptr; @@ -183,6 +188,7 @@ class ListBoxX : public ListBox { LRESULT NcHitTest(WPARAM, LPARAM) const; void CentreItem(int n); void AllocateBitMap(); + LRESULT PASCAL ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); static LRESULT PASCAL ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); static constexpr POINT ItemInset {0, 0}; // Padding around whole item @@ -776,9 +782,8 @@ void ListBoxX::AllocateBitMap() { graphics.pixmapLine->Init(graphics.bm.DC(), GetID()); } -LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { +LRESULT PASCAL ListBoxX::ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { try { - ListBoxX *lbx = static_cast(PointerFromWindow(::GetParent(hWnd))); switch (iMessage) { case WM_ERASEBKGND: return TRUE; @@ -793,9 +798,7 @@ LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, const LRESULT lResult = ::SendMessage(hWnd, LB_ITEMFROMPOINT, 0, lParam); if (HIWORD(lResult) == 0) { ListBox_SetCurSel(hWnd, LOWORD(lResult)); - if (lbx) { - lbx->OnSelChange(); - } + OnSelChange(); } } return 0; @@ -803,11 +806,8 @@ LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, case WM_LBUTTONUP: return 0; - case WM_LBUTTONDBLCLK: { - if (lbx) { - lbx->OnDoubleClick(); - } - } + case WM_LBUTTONDBLCLK: + OnDoubleClick(); return 0; case WM_MBUTTONDOWN: @@ -818,32 +818,36 @@ LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, break; } - WNDPROC prevWndProc = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); if (prevWndProc) { return ::CallWindowProc(prevWndProc, hWnd, iMessage, wParam, lParam); } - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); } catch (...) { } return ::DefWindowProc(hWnd, iMessage, wParam, lParam); } +LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { + if (ListBoxX *lbx = static_cast(PointerFromWindow(::GetParent(hWnd)))) { + return lbx->ListProc(hWnd, iMessage, wParam, lParam); + } + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); +} + LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { case WM_CREATE: { HINSTANCE hinstanceParent = GetWindowInstance(HwndFromWindow(*parent)); // Note that LBS_NOINTEGRALHEIGHT is specified to fix cosmetic issue when resizing the list // but has useful side effect of speeding up list population significantly - lb = ::CreateWindowEx( - 0, TEXT("listbox"), TEXT(""), + lb = ::CreateWindowExW( + 0, WC_LISTBOXW, L"", WS_CHILD | WS_VSCROLL | WS_VISIBLE | LBS_OWNERDRAWFIXED | LBS_NODATA | LBS_NOINTEGRALHEIGHT, 0, 0, 150,80, hWnd, reinterpret_cast(static_cast(ctrlID)), hinstanceParent, nullptr); - WNDPROC prevWndProc = SubclassWindow(lb, ControlWndProc); - ::SetWindowLongPtr(lb, GWLP_USERDATA, reinterpret_cast(prevWndProc)); + prevWndProc = SubclassWindow(lb, ControlWndProc); } break; @@ -870,13 +874,13 @@ LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam break; case WM_MEASUREITEM: { - MEASUREITEMSTRUCT *pMeasureItem = reinterpret_cast(lParam); + MEASUREITEMSTRUCT *pMeasureItem = static_cast(PtrFromLParam(lParam)); pMeasureItem->itemHeight = ItemHeight(); } break; case WM_DRAWITEM: - Draw(reinterpret_cast(lParam)); + Draw(static_cast(PtrFromLParam(lParam))); break; case WM_DESTROY: @@ -890,7 +894,7 @@ LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam return TRUE; case WM_GETMINMAXINFO: { - MINMAXINFO *minMax = reinterpret_cast(lParam); + MINMAXINFO *minMax = static_cast(PtrFromLParam(lParam)); minMax->ptMaxTrackSize = MaxTrackSize(); minMax->ptMinTrackSize = MinTrackSize(); } @@ -946,12 +950,11 @@ LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam LRESULT PASCAL ListBoxX::StaticWndProc( HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { if (iMessage == WM_CREATE) { - CREATESTRUCT *pCreate = reinterpret_cast(lParam); + CREATESTRUCT *pCreate = static_cast(PtrFromLParam(lParam)); SetWindowPointer(hWnd, pCreate->lpCreateParams); } // Find C++ object associated with window. - ListBoxX *lbx = static_cast(PointerFromWindow(hWnd)); - if (lbx) { + if (ListBoxX *lbx = static_cast(PointerFromWindow(hWnd))) { return lbx->WndProc(hWnd, iMessage, wParam, lParam); } return ::DefWindowProc(hWnd, iMessage, wParam, lParam); -- cgit v1.2.3