X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2e733ec74cdef0818ec171376f99049362b643b2..43c42c18d36c703a88b1b7b697bac27fe5608eca:/src/msw/headerctrl.cpp?ds=sidebyside diff --git a/src/msw/headerctrl.cpp b/src/msw/headerctrl.cpp index 2fb4dea8c1..4845715d03 100644 --- a/src/msw/headerctrl.cpp +++ b/src/msw/headerctrl.cpp @@ -23,7 +23,10 @@ #pragma hdrstop #endif +#if wxUSE_HEADERCTRL + #ifndef WX_PRECOMP + #include "wx/app.h" #include "wx/log.h" #endif // WX_PRECOMP @@ -36,6 +39,15 @@ #include "wx/msw/wrapcctl.h" #include "wx/msw/private.h" +#ifndef HDM_SETBITMAPMARGIN + #define HDM_SETBITMAPMARGIN 0x1234 +#endif + +#ifndef Header_SetBitmapMargin + #define Header_SetBitmapMargin(hwnd, margin) \ + ::SendMessage((hwnd), HDM_SETBITMAPMARGIN, (WPARAM)(margin), 0) +#endif + // from src/msw/listctrl.cpp extern int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick); @@ -52,6 +64,7 @@ void wxHeaderCtrl::Init() m_numColumns = 0; m_imageList = NULL; m_scrollOffset = 0; + m_colBeingDragged = -1; } bool wxHeaderCtrl::Create(wxWindow *parent, @@ -68,9 +81,19 @@ bool wxHeaderCtrl::Create(wxWindow *parent, if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) return false; - if ( !MSWCreateControl(WC_HEADER, _T(""), pos, size) ) + if ( !MSWCreateControl(WC_HEADER, wxT(""), pos, size) ) return false; + // special hack for margins when using comctl32.dll v6 or later: the + // default margin is too big and results in label truncation when the + // column width is just about right to show it together with the sort + // indicator, so reduce it to a smaller value (in principle we could even + // use 0 here but this starts to look ugly) + if ( wxApp::GetComCtl32Version() >= 600 ) + { + Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE)); + } + return true; } @@ -78,13 +101,15 @@ WXDWORD wxHeaderCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const { WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle); - if ( style & wxHD_DRAGDROP ) + if ( style & wxHD_ALLOW_REORDER ) msStyle |= HDS_DRAGDROP; // the control looks nicer with these styles and there doesn't seem to be // any reason to not use them so we always do (as for HDS_HORZ it is 0 // anyhow but include it for clarity) - msStyle |= HDS_HORZ | HDS_BUTTONS | HDS_FLAT | HDS_FULLDRAG | HDS_HOTTRACK; + // NOTE: don't use however HDS_FLAT because it makes the control look + // non-native when running WinXP in classic mode + msStyle |= HDS_HORZ | HDS_BUTTONS | HDS_FULLDRAG | HDS_HOTTRACK; return msStyle; } @@ -132,7 +157,7 @@ wxSize wxHeaderCtrl::DoGetBestSize() const HDLAYOUT layout = { &rc, &wpos }; if ( !Header_Layout(GetHwnd(), &layout) ) { - wxLogLastError(_T("Header_Layout")); + wxLogLastError(wxT("Header_Layout")); return wxControl::DoGetBestSize(); } @@ -172,7 +197,7 @@ void wxHeaderCtrl::DoSetCount(unsigned int count) { if ( !Header_DeleteItem(GetHwnd(), 0) ) { - wxLogLastError(_T("Header_DeleteItem")); + wxLogLastError(wxT("Header_DeleteItem")); } } @@ -244,7 +269,7 @@ void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx) // notice that we need to store the string we use the pointer to until we // pass it to the control hdi.mask |= HDI_TEXT; - wxWxCharBuffer buf = col.GetTitle().wx_str(); + wxWxCharBuffer buf = col.GetTitle().t_str(); hdi.pszText = buf.data(); hdi.cchTextMax = wxStrlen(buf); @@ -261,6 +286,7 @@ void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx) if ( !m_imageList ) { m_imageList = new wxImageList(bmpWidth, bmpHeight); + (void) // suppress mingw32 warning about unused computed value Header_SetImageList(GetHwnd(), GetHimagelistOf(m_imageList)); } else // already have an image list @@ -285,7 +311,7 @@ void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx) if ( col.GetAlignment() != wxALIGN_NOT ) { - hdi.mask |= HDI_FORMAT; + hdi.mask |= HDI_FORMAT | HDF_LEFT; switch ( col.GetAlignment() ) { case wxALIGN_LEFT: @@ -324,7 +350,7 @@ void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx) if ( ::SendMessage(GetHwnd(), HDM_INSERTITEM, MSWToNativeIdx(idx), (LPARAM)&hdi) == -1 ) { - wxLogLastError(_T("Header_InsertItem()")); + wxLogLastError(wxT("Header_InsertItem()")); } } @@ -342,7 +368,7 @@ void wxHeaderCtrl::DoSetColumnsOrder(const wxArrayInt& order) if ( !Header_SetOrderArray(GetHwnd(), orderShown.size(), &orderShown[0]) ) { - wxLogLastError(_T("Header_GetOrderArray")); + wxLogLastError(wxT("Header_GetOrderArray")); } m_colIndices = order; @@ -449,18 +475,18 @@ wxEventType wxHeaderCtrl::GetClickEventType(bool dblclk, int button) switch ( button ) { case 0: - evtType = dblclk ? wxEVT_COMMAND_HEADER_DCLICK - : wxEVT_COMMAND_HEADER_CLICK; + evtType = dblclk ? wxEVT_HEADER_DCLICK + : wxEVT_HEADER_CLICK; break; case 1: - evtType = dblclk ? wxEVT_COMMAND_HEADER_RIGHT_DCLICK - : wxEVT_COMMAND_HEADER_RIGHT_CLICK; + evtType = dblclk ? wxEVT_HEADER_RIGHT_DCLICK + : wxEVT_HEADER_RIGHT_CLICK; break; case 2: - evtType = dblclk ? wxEVT_COMMAND_HEADER_MIDDLE_DCLICK - : wxEVT_COMMAND_HEADER_MIDDLE_CLICK; + evtType = dblclk ? wxEVT_HEADER_MIDDLE_DCLICK + : wxEVT_HEADER_MIDDLE_CLICK; break; default: @@ -500,6 +526,9 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) case HDN_ITEMCLICK: case HDN_ITEMDBLCLICK: evtType = GetClickEventType(code == HDN_ITEMDBLCLICK, nmhdr->iButton); + + // We're not dragging any more. + m_colBeingDragged = -1; break; // although we should get the notifications about the right clicks @@ -513,14 +542,19 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( idx != wxNOT_FOUND ) { idx = MSWFromNativeIdx(idx); - evtType = GetClickEventType(code == NM_RDBLCLK, 1); + + // due to a bug in mingw32 headers NM_RDBLCLK is signed + // there so we need a cast to avoid warnings about signed/ + // unsigned comparison + evtType = GetClickEventType( + code == static_cast(NM_RDBLCLK), 1); } //else: ignore clicks outside any column } break; case HDN_DIVIDERDBLCLICK: - evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK; + evtType = wxEVT_HEADER_SEPARATOR_DCLICK; break; @@ -531,7 +565,7 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // ASCII and Unicode versions of this message case HDN_BEGINTRACKA: case HDN_BEGINTRACKW: - // non-resizeable columns can't be resized no matter what, don't + // non-resizable columns can't be resized no matter what, don't // even generate any events for them if ( !GetColumn(idx).IsResizeable() ) { @@ -539,7 +573,7 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; } - evtType = wxEVT_COMMAND_HEADER_BEGIN_RESIZE; + evtType = wxEVT_HEADER_BEGIN_RESIZE; // fall through case HDN_ENDTRACKA: @@ -548,7 +582,7 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( evtType == wxEVT_NULL ) { - evtType = wxEVT_COMMAND_HEADER_END_RESIZE; + evtType = wxEVT_HEADER_END_RESIZE; // don't generate events with invalid width const int minWidth = GetColumn(idx).GetMinWidth(); @@ -557,6 +591,11 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) } break; + // The control is not supposed to send HDN_TRACK when using + // HDS_FULLDRAG (which we do use) but apparently some versions of + // comctl32.dll still do it, see #13506, so catch both messages + // just in case we are dealing with one of these buggy versions. + case HDN_TRACK: case HDN_ITEMCHANGING: if ( nmhdr->pitem && (nmhdr->pitem->mask & HDI_WIDTH) ) { @@ -573,7 +612,7 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // generate the resizing event from here as we don't seem // to be getting HDN_TRACK events at all, at least with // comctl32.dll v6 - evtType = wxEVT_COMMAND_HEADER_RESIZING; + evtType = wxEVT_HEADER_RESIZING; } } break; @@ -587,14 +626,24 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( nmhdr->iItem == -1 ) break; + // If we are dragging a column that is not draggable and the mouse + // is moved over a different column then we get the column number from + // the column under the mouse. This results in an unexpected behaviour + // if this column is draggable. To prevent this remember the column we + // are dragging for the complete drag and drop cycle. + if ( m_colBeingDragged == -1 ) + { + m_colBeingDragged = idx; + } + // column must have the appropriate flag to be draggable - if ( !GetColumn(idx).IsReorderable() ) + if ( !GetColumn(m_colBeingDragged).IsReorderable() ) { veto = true; break; } - evtType = wxEVT_COMMAND_HEADER_BEGIN_REORDER; + evtType = wxEVT_HEADER_BEGIN_REORDER; break; case HDN_ENDDRAG: @@ -608,11 +657,17 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) order = MSWFromNativeOrder(order); - evtType = wxEVT_COMMAND_HEADER_END_REORDER; + evtType = wxEVT_HEADER_END_REORDER; + + // We (successfully) ended dragging the column. + m_colBeingDragged = -1; break; case NM_RELEASEDCAPTURE: - evtType = wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED; + evtType = wxEVT_HEADER_DRAGGING_CANCELLED; + + // Dragging the column was cancelled. + m_colBeingDragged = -1; break; } @@ -627,22 +682,24 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( order != -1 ) event.SetNewOrder(order); - if ( GetEventHandler()->ProcessEvent(event) ) - { - if ( event.IsAllowed() ) - return true; // skip default message handling below + const bool processed = GetEventHandler()->ProcessEvent(event); - // we need to veto the default handling of this message, don't - // return to execute the code in the "if veto" branch below + if ( processed && !event.IsAllowed() ) veto = true; - } - else // not processed + + if ( !veto ) { // special post-processing for HDN_ENDDRAG: we need to update the // internal column indices array if this is allowed to go ahead as // the native control is going to reorder its columns now - if ( evtType == wxEVT_COMMAND_HEADER_END_REORDER ) + if ( evtType == wxEVT_HEADER_END_REORDER ) MoveColumnInOrderArray(m_colIndices, idx, order); + + if ( processed ) + { + // skip default processing below + return true; + } } } @@ -660,3 +717,5 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) } #endif // wxHAS_GENERIC_HEADERCTRL + +#endif // wxUSE_HEADERCTRL