combobox.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 844 行 · 第 1/2 页

CPP
844
字号
    {
        wxFAIL_MSG(_T("not read only combobox without edit control?"));
    }

    return (WXHWND)hwndEdit;
}

// ----------------------------------------------------------------------------
// wxComboBox creation
// ----------------------------------------------------------------------------

bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
                        const wxString& value,
                        const wxPoint& pos,
                        const wxSize& size,
                        int n, const wxString choices[],
                        long style,
                        const wxValidator& validator,
                        const wxString& name)
{
    // pretend that wxComboBox is hidden while it is positioned and resized and
    // show it only right before leaving this method because otherwise there is
    // some noticeable flicker while the control rearranges itself
    m_isShown = false;

    if ( !CreateAndInit(parent, id, pos, size, n, choices, style,
                        validator, name) )
        return false;

    // we shouldn't call SetValue() for an empty string because this would
    // (correctly) result in an assert with a read only combobox and is useless
    // for the other ones anyhow
    if ( !value.empty() )
        SetValue(value);

    // a (not read only) combobox is, in fact, 2 controls: the combobox itself
    // and an edit control inside it and if we want to catch events from this
    // edit control, we must subclass it as well
    if ( !(style & wxCB_READONLY) )
    {
        gs_wndprocEdit = wxSetWindowProc((HWND)GetEditHWND(),
                                         wxComboEditWndProc);
    }

    // and finally, show the control
    Show(true);

    return true;
}

bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
                        const wxString& value,
                        const wxPoint& pos,
                        const wxSize& size,
                        const wxArrayString& choices,
                        long style,
                        const wxValidator& validator,
                        const wxString& name)
{
    wxCArrayString chs(choices);
    return Create(parent, id, value, pos, size, chs.GetCount(),
                  chs.GetStrings(), style, validator, name);
}

WXDWORD wxComboBox::MSWGetStyle(long style, WXDWORD *exstyle) const
{
    // we never have an external border
    WXDWORD msStyle = wxChoice::MSWGetStyle
                      (
                        (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle
                      );

    // usually WS_TABSTOP is added by wxControl::MSWGetStyle() but as we're
    // created hidden (see Create() above), it is not done for us but we still
    // want to have this style
    msStyle |= WS_TABSTOP;

    // remove the style always added by wxChoice
    msStyle &= ~CBS_DROPDOWNLIST;

    if ( style & wxCB_READONLY )
        msStyle |= CBS_DROPDOWNLIST;
#ifndef __WXWINCE__
    else if ( style & wxCB_SIMPLE )
        msStyle |= CBS_SIMPLE; // A list (shown always) and edit control
#endif
    else
        msStyle |= CBS_DROPDOWN;

    // there is no reason to not always use CBS_AUTOHSCROLL, so do use it
    msStyle |= CBS_AUTOHSCROLL;

    // NB: we used to also add CBS_NOINTEGRALHEIGHT here but why?

    return msStyle;
}

// ----------------------------------------------------------------------------
// wxComboBox text control-like methods
// ----------------------------------------------------------------------------

void wxComboBox::SetValue(const wxString& value)
{
    if ( HasFlag(wxCB_READONLY) )
        SetStringSelection(value);
    else
        SetWindowText(GetHwnd(), value.c_str());

    m_value = value;
    m_selectionOld = GetSelection();
}

// Clipboard operations
void wxComboBox::Copy()
{
    SendMessage(GetHwnd(), WM_COPY, 0, 0L);
}

void wxComboBox::Cut()
{
    SendMessage(GetHwnd(), WM_CUT, 0, 0L);
}

void wxComboBox::Paste()
{
    SendMessage(GetHwnd(), WM_PASTE, 0, 0L);
}

void wxComboBox::Undo()
{
    if (CanUndo())
    {
        HWND hEditWnd = (HWND) GetEditHWND() ;
        if ( hEditWnd )
            ::SendMessage(hEditWnd, EM_UNDO, 0, 0);
    }
}

void wxComboBox::Redo()
{
    if (CanUndo())
    {
        // Same as Undo, since Undo undoes the undo, i.e. a redo.
        HWND hEditWnd = (HWND) GetEditHWND() ;
        if ( hEditWnd )
            ::SendMessage(hEditWnd, EM_UNDO, 0, 0);
    }
}

void wxComboBox::SelectAll()
{
    SetSelection(0, GetLastPosition());
}

bool wxComboBox::CanUndo() const
{
    if (!IsEditable())
        return false;

    HWND hEditWnd = (HWND) GetEditHWND() ;
    if ( hEditWnd )
        return ::SendMessage(hEditWnd, EM_CANUNDO, 0, 0) != 0;
    else
        return false;
}

bool wxComboBox::CanRedo() const
{
    if (!IsEditable())
        return false;

    HWND hEditWnd = (HWND) GetEditHWND() ;
    if ( hEditWnd )
        return ::SendMessage(hEditWnd, EM_CANUNDO, 0, 0) != 0;
    else
        return false;
}

bool wxComboBox::HasSelection() const
{
    long from, to;
    GetSelection(&from, &to);
    return from != to;
}

bool wxComboBox::CanCopy() const
{
    // Can copy if there's a selection
    return HasSelection();
}

bool wxComboBox::CanCut() const
{
    return IsEditable() && CanCopy() ;
}

bool wxComboBox::CanPaste() const
{
    if ( !IsEditable() )
        return false;

    // Standard edit control: check for straight text on clipboard
    if ( !::OpenClipboard(GetHwndOf(wxTheApp->GetTopWindow())) )
        return false;

    bool isTextAvailable = ::IsClipboardFormatAvailable(CF_TEXT) != 0;
    ::CloseClipboard();

    return isTextAvailable;
}

bool wxComboBox::IsEditable() const
{
    return !HasFlag(wxCB_READONLY);
}

void wxComboBox::SetEditable(bool WXUNUSED(editable))
{
  // Can't implement in MSW?
//  HWND hWnd = GetHwnd();
//  SendMessage(hWnd, EM_SETREADONLY, (WPARAM)!editable, (LPARAM)0L);
}

void wxComboBox::SetInsertionPoint(long pos)
{
    if ( GetWindowStyle() & wxCB_READONLY )
        return;

#ifdef __WIN32__
    HWND hWnd = GetHwnd();
    ::SendMessage(hWnd, CB_SETEDITSEL, 0, MAKELPARAM(pos, pos));
    HWND hEditWnd = (HWND) GetEditHWND() ;
    if ( hEditWnd )
    {
        // Scroll insertion point into view
        SendMessage(hEditWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
        // Why is this necessary? (Copied from wxTextCtrl::SetInsertionPoint)
        SendMessage(hEditWnd, EM_REPLACESEL, 0, (LPARAM) wxEmptyString);
    }
#endif // __WIN32__
}

void wxComboBox::SetInsertionPointEnd()
{
    // setting insertion point doesn't make sense for read only comboboxes
    if ( !(GetWindowStyle() & wxCB_READONLY) )
    {
        wxTextPos pos = GetLastPosition();
        SetInsertionPoint(pos);
    }
}

long wxComboBox::GetInsertionPoint() const
{
    // CB_GETEDITSEL returns the index of the first character of the selection in
    // its low-order word
    DWORD pos= (DWORD)::SendMessage(GetHwnd(), CB_GETEDITSEL, 0, 0L);
    return LOWORD(pos);
}

wxTextPos wxComboBox::GetLastPosition() const
{
    HWND hEditWnd = (HWND) GetEditHWND();

    // Get number of characters in the last (only) line. We'll add this to the character
    // index for the last line, 1st position.
    wxTextPos lineLength = (wxTextPos)SendMessage(hEditWnd, EM_LINELENGTH, (WPARAM) 0, (LPARAM)0L);

    return lineLength;
}

void wxComboBox::Replace(long from, long to, const wxString& value)
{
#if wxUSE_CLIPBOARD
    Remove(from, to);

    // Now replace with 'value', by pasting.
    wxSetClipboardData(wxDF_TEXT, (wxObject *)(const wxChar *)value, 0, 0);

    // Paste into edit control
    SendMessage(GetHwnd(), WM_PASTE, (WPARAM)0, (LPARAM)0L);
#else
    wxUnusedVar(from);
    wxUnusedVar(to);
    wxUnusedVar(value);
#endif
}

void wxComboBox::Remove(long from, long to)
{
    // Set selection and remove it
    SetSelection(from, to);
    SendMessage(GetHwnd(), WM_CUT, (WPARAM)0, (LPARAM)0);
}

void wxComboBox::SetSelection(long from, long to)
{
    // if from and to are both -1, it means (in wxWidgets) that all text should
    // be selected, translate this into Windows convention
    if ( (from == -1) && (to == -1) )
    {
        from = 0;
    }

    if ( SendMessage(GetHwnd(), CB_SETEDITSEL,
                     0, (LPARAM)MAKELONG(from, to)) == CB_ERR )
    {
        wxLogDebug(_T("CB_SETEDITSEL failed"));
    }
}

void wxComboBox::GetSelection(long* from, long* to) const
{
    DWORD dwStart, dwEnd;
    if ( ::SendMessage(GetHwnd(), CB_GETEDITSEL,
                       (WPARAM)&dwStart, (LPARAM)&dwEnd) == CB_ERR )
    {
        *from =
        *to = 0;
    }
    else
    {
        *from = dwStart;
        *to = dwEnd;
    }
}

int wxComboBox::GetSelection() const
{
    return wxChoice::GetSelection();
}

// ----------------------------------------------------------------------------
// overridden wxChoice methods
// ----------------------------------------------------------------------------

void wxComboBox::SetSelection(int n)
{
    wxChoice::SetSelection(n);
    m_selectionOld = n;
}

// ----------------------------------------------------------------------------
// standard event handling
// ----------------------------------------------------------------------------

void wxComboBox::OnCut(wxCommandEvent& WXUNUSED(event))
{
    Cut();
}

void wxComboBox::OnCopy(wxCommandEvent& WXUNUSED(event))
{
    Copy();
}

void wxComboBox::OnPaste(wxCommandEvent& WXUNUSED(event))
{
    Paste();
}

void wxComboBox::OnUndo(wxCommandEvent& WXUNUSED(event))
{
    Undo();
}

void wxComboBox::OnRedo(wxCommandEvent& WXUNUSED(event))
{
    Redo();
}

void wxComboBox::OnDelete(wxCommandEvent& WXUNUSED(event))
{
    long from, to;
    GetSelection(& from, & to);
    if (from != -1 && to != -1)
        Remove(from, to);
}

void wxComboBox::OnSelectAll(wxCommandEvent& WXUNUSED(event))
{
    SetSelection(-1, -1);
}

void wxComboBox::OnUpdateCut(wxUpdateUIEvent& event)
{
    event.Enable( CanCut() );
}

void wxComboBox::OnUpdateCopy(wxUpdateUIEvent& event)
{
    event.Enable( CanCopy() );
}

void wxComboBox::OnUpdatePaste(wxUpdateUIEvent& event)
{
    event.Enable( CanPaste() );
}

void wxComboBox::OnUpdateUndo(wxUpdateUIEvent& event)
{
    event.Enable( CanUndo() );
}

void wxComboBox::OnUpdateRedo(wxUpdateUIEvent& event)
{
    event.Enable( CanRedo() );
}

void wxComboBox::OnUpdateDelete(wxUpdateUIEvent& event)
{
    event.Enable(HasSelection() && IsEditable()) ;
}

void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent& event)
{
    event.Enable(GetLastPosition() > 0);
}

#endif // wxUSE_COMBOBOX

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?