combobox.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 844 行 · 第 1/2 页
CPP
844 行
/////////////////////////////////////////////////////////////////////////////
// Name: msw/combobox.cpp
// Purpose: wxComboBox class
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id: combobox.cpp,v 1.112.2.1 2006/01/28 00:44:27 VZ Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "combobox.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_COMBOBOX
#ifndef WX_PRECOMP
#include "wx/settings.h"
#include "wx/log.h"
// for wxEVT_COMMAND_TEXT_ENTER
#include "wx/textctrl.h"
#endif
#include "wx/app.h"
#include "wx/combobox.h"
#include "wx/brush.h"
#include "wx/clipbrd.h"
#include "wx/msw/private.h"
#if wxUSE_TOOLTIPS
#if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
#include <commctrl.h>
#endif
#include "wx/tooltip.h"
#endif // wxUSE_TOOLTIPS
// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------
#if wxUSE_EXTENDED_RTTI
WX_DEFINE_FLAGS( wxComboBoxStyle )
wxBEGIN_FLAGS( wxComboBoxStyle )
// 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)
wxFLAGS_MEMBER(wxCB_SIMPLE)
wxFLAGS_MEMBER(wxCB_SORT)
wxFLAGS_MEMBER(wxCB_READONLY)
wxFLAGS_MEMBER(wxCB_DROPDOWN)
wxEND_FLAGS( wxComboBoxStyle )
IMPLEMENT_DYNAMIC_CLASS_XTI(wxComboBox, wxControl,"wx/combobox.h")
wxBEGIN_PROPERTIES_TABLE(wxComboBox)
wxEVENT_PROPERTY( Select , wxEVT_COMMAND_COMBOBOX_SELECTED , wxCommandEvent )
wxEVENT_PROPERTY( TextEnter , wxEVT_COMMAND_TEXT_ENTER , wxCommandEvent )
// TODO DELEGATES
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( Value ,wxString, SetValue, GetValue, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
wxPROPERTY( Selection ,int, SetSelection, GetSelection, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
wxPROPERTY_FLAGS( WindowStyle , wxComboBoxStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
wxEND_PROPERTIES_TABLE()
wxBEGIN_HANDLERS_TABLE(wxComboBox)
wxEND_HANDLERS_TABLE()
wxCONSTRUCTOR_5( wxComboBox , wxWindow* , Parent , wxWindowID , Id , wxString , Value , wxPoint , Position , wxSize , Size )
#else
IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
#endif
BEGIN_EVENT_TABLE(wxComboBox, wxControl)
EVT_MENU(wxID_CUT, wxComboBox::OnCut)
EVT_MENU(wxID_COPY, wxComboBox::OnCopy)
EVT_MENU(wxID_PASTE, wxComboBox::OnPaste)
EVT_MENU(wxID_UNDO, wxComboBox::OnUndo)
EVT_MENU(wxID_REDO, wxComboBox::OnRedo)
EVT_MENU(wxID_CLEAR, wxComboBox::OnDelete)
EVT_MENU(wxID_SELECTALL, wxComboBox::OnSelectAll)
EVT_UPDATE_UI(wxID_CUT, wxComboBox::OnUpdateCut)
EVT_UPDATE_UI(wxID_COPY, wxComboBox::OnUpdateCopy)
EVT_UPDATE_UI(wxID_PASTE, wxComboBox::OnUpdatePaste)
EVT_UPDATE_UI(wxID_UNDO, wxComboBox::OnUpdateUndo)
EVT_UPDATE_UI(wxID_REDO, wxComboBox::OnUpdateRedo)
EVT_UPDATE_UI(wxID_CLEAR, wxComboBox::OnUpdateDelete)
EVT_UPDATE_UI(wxID_SELECTALL, wxComboBox::OnUpdateSelectAll)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// function prototypes
// ----------------------------------------------------------------------------
LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// ---------------------------------------------------------------------------
// global vars
// ---------------------------------------------------------------------------
// the pointer to standard radio button wnd proc
static WNDPROC gs_wndprocEdit = (WNDPROC)NULL;
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wnd proc for subclassed edit control
// ----------------------------------------------------------------------------
LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HWND hwndCombo = ::GetParent(hWnd);
wxWindow *win = wxFindWinFromHandle((WXHWND)hwndCombo);
switch ( message )
{
// forward some messages to the combobox to generate the appropriate
// wxEvents from them
case WM_KEYUP:
case WM_KEYDOWN:
case WM_CHAR:
case WM_SYSCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SETFOCUS:
case WM_KILLFOCUS:
{
wxComboBox *combo = wxDynamicCast(win, wxComboBox);
if ( !combo )
{
// we can get WM_KILLFOCUS while our parent is already half
// destroyed and hence doesn't look like a combobx any
// longer, check for it to avoid bogus assert failures
if ( !win->IsBeingDeleted() )
{
wxFAIL_MSG( _T("should have combo as parent") );
}
}
else if ( combo->MSWProcessEditMsg(message, wParam, lParam) )
{
// handled by parent
return 0;
}
}
break;
case WM_GETDLGCODE:
{
wxCHECK_MSG( win, 0, _T("should have a parent") );
if ( win->GetWindowStyle() & wxPROCESS_ENTER )
{
// need to return a custom dlg code or we'll never get it
return DLGC_WANTMESSAGE;
}
}
break;
// deal with tooltips here
#if wxUSE_TOOLTIPS && defined(TTN_NEEDTEXT)
case WM_NOTIFY:
{
wxCHECK_MSG( win, 0, _T("should have a parent") );
NMHDR* hdr = (NMHDR *)lParam;
if ( hdr->code == TTN_NEEDTEXT )
{
wxToolTip *tooltip = win->GetToolTip();
if ( tooltip )
{
TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
ttt->lpszText = (wxChar *)tooltip->GetTip().c_str();
}
// processed
return 0;
}
}
break;
#endif // wxUSE_TOOLTIPS
}
return ::CallWindowProc(CASTWNDPROC gs_wndprocEdit, hWnd, message, wParam, lParam);
}
// ----------------------------------------------------------------------------
// wxComboBox callbacks
// ----------------------------------------------------------------------------
WXLRESULT wxComboBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
// TODO: handle WM_CTLCOLOR messages from our EDIT control to be able to
// set its colour correctly (to be the same as our own one)
switch ( nMsg )
{
case CB_SETCURSEL:
// Selection was set with SetSelection. Update the value too.
if ((int)wParam > GetCount())
m_value.clear();
else
m_value = GetString(wParam);
m_selectionOld = -1;
break;
case WM_SIZE:
// wxStaticBox can generate this message, when modifying the control's style.
// This causes the content of the combobox to be selected, for some reason.
case WM_STYLECHANGED:
{
// combobox selection sometimes spontaneously changes when its
// size changes, restore it to the old value if necessary
long fromOld, toOld;
GetSelection(&fromOld, &toOld);
WXLRESULT result = wxChoice::MSWWindowProc(nMsg, wParam, lParam);
long fromNew, toNew;
GetSelection(&fromNew, &toNew);
if ( fromOld != fromNew || toOld != toNew )
{
SetSelection(fromOld, toOld);
}
return result;
}
}
return wxChoice::MSWWindowProc(nMsg, wParam, lParam);
}
bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam)
{
switch ( msg )
{
case WM_CHAR:
// for compatibility with wxTextCtrl, generate a special message
// when Enter is pressed
if ( wParam == VK_RETURN )
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
InitCommandEvent(event);
event.SetString(GetValue());
event.SetInt(GetSelection());
if ( ProcessCommand(event) )
{
// don't let the event through to the native control
// because it doesn't need it and may generate an annoying
// beep if it gets it
return true;
}
}
// fall through
case WM_SYSCHAR:
return HandleChar(wParam, lParam, true /* isASCII */);
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
return HandleKeyDown(wParam, lParam);
case WM_SYSKEYUP:
case WM_KEYUP:
return HandleKeyUp(wParam, lParam);
case WM_SETFOCUS:
return HandleSetFocus((WXHWND)wParam);
case WM_KILLFOCUS:
return HandleKillFocus((WXHWND)wParam);
}
return false;
}
bool wxComboBox::MSWCommand(WXUINT param, WXWORD id)
{
wxString value;
int sel = -1;
switch ( param )
{
case CBN_SELENDOK:
case CBN_SELCHANGE:
sel = GetSelection();
// we may sometimes get 2 CBN_SELCHANGE events or a CBN_SELENDOK
// before CBN_SELCHANGE with the same index when the user selects
// an item in the combobox -- ignore duplicates
if ( sel > -1 && sel != m_selectionOld )
{
m_selectionOld = sel;
// GetValue() would still return the old value from here but
// according to the docs we should return the new value if the
// user calls it in his event handler, so update internal
// m_value
m_value = GetString(sel);
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, GetId());
event.SetInt(sel);
event.SetEventObject(this);
event.SetString(m_value);
ProcessCommand(event);
}
else // no valid selection
{
m_selectionOld = sel;
// hence no EVT_TEXT neither
break;
}
// fall through: for compability with wxGTK, also send the text
// update event when the selection changes (this also seems more
// logical as the text does change)
case CBN_EDITCHANGE:
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
// if sel != -1, value was initialized above (and we can't use
// GetValue() here as it would return the old selection and we
// want the new one)
if ( sel == -1 )
{
m_value = wxGetWindowText(GetHwnd());
m_selectionOld = -1;
}
else // we're synthesizing text updated event from sel change
{
// We need to retrieve the current selection because the
// user may have changed it in the previous handler (for
// CBN_SELCHANGE above).
sel = GetSelection();
if ( sel > -1 )
{
m_value = GetString(sel);
}
}
event.SetString(m_value);
event.SetEventObject(this);
ProcessCommand(event);
}
break;
default:
return wxChoice::MSWCommand(param, id);
}
// let the def window proc have it by returning false, but do not pass the
// message we've already handled here (notably CBN_SELCHANGE) to the base
// class as it would generate another event for them
return false;
}
WXHWND wxComboBox::GetEditHWND() const
{
// this function should not be called for wxCB_READONLY controls, it is
// the callers responsability to check this
wxASSERT_MSG( !(GetWindowStyle() & wxCB_READONLY),
_T("read-only combobox doesn't have any edit control") );
POINT pt;
pt.x = pt.y = 4;
HWND hwndEdit = ::ChildWindowFromPoint(GetHwnd(), pt);
if ( !hwndEdit || hwndEdit == GetHwnd() )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?