📄 choice.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: choice.cpp
// Purpose: wxChoice
// Author: Julian Smart
// Modified by: Vadim Zeitlin to derive from wxChoiceBase
// Created: 04/01/98
// RCS-ID: $Id: choice.cpp,v 1.107.2.3 2006/03/30 09:19:04 JS Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "choice.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_CHOICE && !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
#ifndef WX_PRECOMP
#include "wx/choice.h"
#include "wx/utils.h"
#include "wx/log.h"
#include "wx/brush.h"
#include "wx/settings.h"
#endif
#include "wx/msw/private.h"
#if wxUSE_EXTENDED_RTTI
WX_DEFINE_FLAGS( wxChoiceStyle )
wxBEGIN_FLAGS( wxChoiceStyle )
// new style border flags, we put them first to
// use them for streaming out
wxFLAGS_MEMBER(wxBORDER_SIMPLE)
wxFLAGS_MEMBER(wxBORDER_SUNKEN)
wxFLAGS_MEMBER(wxBORDER_DOUBLE)
wxFLAGS_MEMBER(wxBORDER_RAISED)
wxFLAGS_MEMBER(wxBORDER_STATIC)
wxFLAGS_MEMBER(wxBORDER_NONE)
// old style border flags
wxFLAGS_MEMBER(wxSIMPLE_BORDER)
wxFLAGS_MEMBER(wxSUNKEN_BORDER)
wxFLAGS_MEMBER(wxDOUBLE_BORDER)
wxFLAGS_MEMBER(wxRAISED_BORDER)
wxFLAGS_MEMBER(wxSTATIC_BORDER)
wxFLAGS_MEMBER(wxBORDER)
// standard window styles
wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
wxFLAGS_MEMBER(wxCLIP_CHILDREN)
wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
wxFLAGS_MEMBER(wxWANTS_CHARS)
wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
wxFLAGS_MEMBER(wxVSCROLL)
wxFLAGS_MEMBER(wxHSCROLL)
wxEND_FLAGS( wxChoiceStyle )
IMPLEMENT_DYNAMIC_CLASS_XTI(wxChoice, wxControl,"wx/choice.h")
wxBEGIN_PROPERTIES_TABLE(wxChoice)
wxEVENT_PROPERTY( Select , wxEVT_COMMAND_CHOICE_SELECTED , wxCommandEvent )
wxPROPERTY( Font , wxFont , SetFont , GetFont , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
wxPROPERTY_COLLECTION( Choices , wxArrayString , wxString , AppendString , GetStrings , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
wxPROPERTY( Selection ,int, SetSelection, GetSelection, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
wxPROPERTY_FLAGS( WindowStyle , wxChoiceStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
wxEND_PROPERTIES_TABLE()
wxBEGIN_HANDLERS_TABLE(wxChoice)
wxEND_HANDLERS_TABLE()
wxCONSTRUCTOR_4( wxChoice , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size )
#else
IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
#endif
/*
TODO PROPERTIES
selection (long)
content (list)
item
*/
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// creation
// ----------------------------------------------------------------------------
bool wxChoice::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
int n, const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name)
{
// Experience shows that wxChoice vs. wxComboBox distinction confuses
// quite a few people - try to help them
wxASSERT_MSG( !(style & wxCB_DROPDOWN) &&
!(style & wxCB_READONLY) &&
!(style & wxCB_SIMPLE),
_T("this style flag is ignored by wxChoice, you ")
_T("probably want to use a wxComboBox") );
return CreateAndInit(parent, id, pos, size, n, choices, style,
validator, name);
}
bool wxChoice::CreateAndInit(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
int n, const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name)
{
// initialize wxControl
if ( !CreateControl(parent, id, pos, size, style, validator, name) )
return false;
// now create the real HWND
if ( !MSWCreateControl(wxT("COMBOBOX"), wxEmptyString, pos, size) )
return false;
// choice/combobox normally has "white" (depends on colour scheme, of
// course) background rather than inheriting the parent's background
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
// initialize the controls contents
for ( int i = 0; i < n; i++ )
{
Append(choices[i]);
}
// and now we may finally size the control properly (if needed)
SetBestSize(size);
return true;
}
bool wxChoice::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name)
{
wxCArrayString chs(choices);
return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
style, validator, name);
}
bool wxChoice::MSWShouldPreProcessMessage(WXMSG *pMsg)
{
MSG *msg = (MSG *) pMsg;
// if the dropdown list is visible, don't preprocess certain keys
if ( msg->message == WM_KEYDOWN
&& (msg->wParam == VK_ESCAPE || msg->wParam == VK_RETURN) )
{
if (::SendMessage(GetHwndOf(this), CB_GETDROPPEDSTATE, 0, 0))
{
return false;
}
}
return wxControl::MSWShouldPreProcessMessage(pMsg);
}
WXDWORD wxChoice::MSWGetStyle(long style, WXDWORD *exstyle) const
{
// we never have an external border
WXDWORD msStyle = wxControl::MSWGetStyle
(
(style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle
);
// WS_CLIPSIBLINGS is useful with wxChoice and doesn't seem to result in
// any problems
msStyle |= WS_CLIPSIBLINGS;
// wxChoice-specific styles
msStyle |= CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL;
if ( style & wxCB_SORT )
msStyle |= CBS_SORT;
return msStyle;
}
wxChoice::~wxChoice()
{
Free();
}
// ----------------------------------------------------------------------------
// adding/deleting items to/from the list
// ----------------------------------------------------------------------------
int wxChoice::DoAppend(const wxString& item)
{
int n = (int)SendMessage(GetHwnd(), CB_ADDSTRING, 0, (LPARAM)item.c_str());
if ( n == CB_ERR )
{
wxLogLastError(wxT("SendMessage(CB_ADDSTRING)"));
}
else // ok
{
// we need to refresh our size in order to have enough space for the
// newly added items
if ( !IsFrozen() )
UpdateVisibleHeight();
}
InvalidateBestSize();
return n;
}
int wxChoice::DoInsert(const wxString& item, int pos)
{
wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index"));
int n = (int)SendMessage(GetHwnd(), CB_INSERTSTRING, pos, (LPARAM)item.c_str());
if ( n == CB_ERR )
{
wxLogLastError(wxT("SendMessage(CB_INSERTSTRING)"));
}
else // ok
{
if ( !IsFrozen() )
UpdateVisibleHeight();
}
InvalidateBestSize();
return n;
}
void wxChoice::Delete(int n)
{
wxCHECK_RET( n < GetCount(), wxT("invalid item index in wxChoice::Delete") );
if ( HasClientObjectData() )
{
delete GetClientObject(n);
}
SendMessage(GetHwnd(), CB_DELETESTRING, n, 0);
if ( !IsFrozen() )
UpdateVisibleHeight();
InvalidateBestSize();
}
void wxChoice::Clear()
{
Free();
SendMessage(GetHwnd(), CB_RESETCONTENT, 0, 0);
if ( !IsFrozen() )
UpdateVisibleHeight();
InvalidateBestSize();
}
void wxChoice::Free()
{
if ( HasClientObjectData() )
{
size_t count = GetCount();
for ( size_t n = 0; n < count; n++ )
{
delete GetClientObject(n);
}
}
}
// ----------------------------------------------------------------------------
// selection
// ----------------------------------------------------------------------------
int wxChoice::GetSelection() const
{
// if m_lastAcceptedSelection is set, it means that the dropdown is
// currently shown and that we want to use the last "permanent" selection
// instead of whatever is under the mouse pointer currently
//
// otherwise, get the selection from the control
return m_lastAcceptedSelection == wxID_NONE ? GetCurrentSelection()
: m_lastAcceptedSelection;
}
int wxChoice::GetCurrentSelection() const
{
return (int)SendMessage(GetHwnd(), CB_GETCURSEL, 0, 0);
}
void wxChoice::SetSelection(int n)
{
SendMessage(GetHwnd(), CB_SETCURSEL, n, 0);
}
// ----------------------------------------------------------------------------
// string list functions
// ----------------------------------------------------------------------------
int wxChoice::GetCount() const
{
return (int)SendMessage(GetHwnd(), CB_GETCOUNT, 0, 0);
}
int wxChoice::FindString(const wxString& s) const
{
#if defined(__WATCOMC__) && defined(__WIN386__)
// For some reason, Watcom in WIN386 mode crashes in the CB_FINDSTRINGEXACT message.
// wxChoice::Do it the long way instead.
int count = GetCount();
for ( int i = 0; i < count; i++ )
{
// as CB_FINDSTRINGEXACT is case insensitive, be case insensitive too
if ( GetString(i).IsSameAs(s, false) )
return i;
}
return wxNOT_FOUND;
#else // !Watcom
//TODO: Evidently some MSW versions (all?) don't like empty strings
//passed to SendMessage, so we have to do it ourselves in that case
if ( s.empty() )
{
int count = GetCount();
for ( int i = 0; i < count; i++ )
{
if ( GetString(i).empty() )
return i;
}
return wxNOT_FOUND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -