Example #1
0
void wxHeaderCtrl::DoMoveCol(unsigned int idx, unsigned int pos)
{
    MoveColumnInOrderArray(m_colIndices, idx, pos);

    Refresh();
}
Example #2
0
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);
}