void wxHeaderCtrl::DoMoveCol(unsigned int idx, unsigned int pos) { MoveColumnInOrderArray(m_colIndices, idx, pos); Refresh(); }
bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { NMHEADER * const nmhdr = (NMHEADER *)lParam; wxEventType evtType = wxEVT_NULL; int width = 0; int order = -1; bool veto = false; const UINT code = nmhdr->hdr.code; // we don't have the index for all events, e.g. not for NM_RELEASEDCAPTURE // so only access for header control events (and yes, the direction of // comparisons with FIRST/LAST is correct even if it seems inverted) int idx = code <= HDN_FIRST && code > HDN_LAST ? nmhdr->iItem : -1; if ( idx != -1 ) { // we also get bogus HDN_BEGINDRAG with -1 index so don't call // MSWFromNativeIdx() unconditionally for nmhdr->iItem idx = MSWFromNativeIdx(idx); } switch ( code ) { // click events // ------------ 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 // via HDN_ITEM[DBL]CLICK too according to MSDN this simply doesn't // happen in practice on any Windows system up to 2003 case NM_RCLICK: case NM_RDBLCLK: { POINT pt; idx = wxMSWGetColumnClicked(&nmhdr->hdr, &pt); if ( idx != wxNOT_FOUND ) { idx = MSWFromNativeIdx(idx); // 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<UINT>(NM_RDBLCLK), 1); } //else: ignore clicks outside any column } break; case HDN_DIVIDERDBLCLICK: evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK; break; // column resizing events // ---------------------- // see comments in wxListCtrl::MSWOnNotify() for why we catch both // ASCII and Unicode versions of this message case HDN_BEGINTRACKA: case HDN_BEGINTRACKW: // non-resizable columns can't be resized no matter what, don't // even generate any events for them if ( !GetColumn(idx).IsResizeable() ) { veto = true; break; } evtType = wxEVT_COMMAND_HEADER_BEGIN_RESIZE; // fall through case HDN_ENDTRACKA: case HDN_ENDTRACKW: width = nmhdr->pitem->cxy; if ( evtType == wxEVT_NULL ) { evtType = wxEVT_COMMAND_HEADER_END_RESIZE; // don't generate events with invalid width const int minWidth = GetColumn(idx).GetMinWidth(); if ( width < minWidth ) width = minWidth; } 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) ) { // prevent the column from being shrunk beneath its min width width = nmhdr->pitem->cxy; if ( width < GetColumn(idx).GetMinWidth() ) { // don't generate any events and prevent the change from // happening veto = true; } else // width is acceptable { // 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; } } break; // column reordering events // ------------------------ case HDN_BEGINDRAG: // Windows sometimes sends us events with invalid column indices 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(m_colBeingDragged).IsReorderable() ) { veto = true; break; } evtType = wxEVT_COMMAND_HEADER_BEGIN_REORDER; break; case HDN_ENDDRAG: wxASSERT_MSG( nmhdr->pitem->mask & HDI_ORDER, "should have order" ); order = nmhdr->pitem->iOrder; // we also get messages with invalid order when column reordering // is cancelled (e.g. by pressing Esc) if ( order == -1 ) break; order = MSWFromNativeOrder(order); evtType = wxEVT_COMMAND_HEADER_END_REORDER; // We (successfully) ended dragging the column. m_colBeingDragged = -1; break; case NM_RELEASEDCAPTURE: evtType = wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED; // Dragging the column was cancelled. m_colBeingDragged = -1; break; } // do generate the corresponding wx event if ( evtType != wxEVT_NULL ) { wxHeaderCtrlEvent event(evtType, GetId()); event.SetEventObject(this); event.SetColumn(idx); event.SetWidth(width); if ( order != -1 ) event.SetNewOrder(order); const bool processed = GetEventHandler()->ProcessEvent(event); if ( processed && !event.IsAllowed() ) veto = true; 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 ) MoveColumnInOrderArray(m_colIndices, idx, order); if ( processed ) { // skip default processing below return true; } } } if ( veto ) { // all of HDN_BEGIN{DRAG,TRACK}, HDN_TRACK and HDN_ITEMCHANGING // interpret TRUE return value as meaning to stop the control // default handling of the message *result = TRUE; return true; } return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result); }