I came up to the point that I need a control for the input of numbers which should be highly flexible. Perhaps someone finds it usual, so I put it here.
This control behaves like a wxTextCtrl (which it is derived from), but accepts numbers only. You can define min and max values, you can define if the number should be int only (no decimal point accepted) or that certain numbers should not be shown (eg. if you want to have a blank field instead of showing a "0").
If you find any errors or write any extensions, please post them here.
Tested under Windows with VC only.
So here we go:
wxNumberCtrl.h
Code: Select all
#ifndef _WXNUMBERCTRL_H_
#define _WXNUMBERCTRL_H_
#ifdef __GNUG__
#pragma interface "wxNumberCtrl.cpp"
#endif
// includes
#include "wx/wx.h"
#include "wx/textctrl.h"
class wxNumberCtrl: public wxTextCtrl
{
DECLARE_CLASS( wxNumberCtrl )
public:
wxNumberCtrl( ){};
wxNumberCtrl(wxWindow* parent, wxWindowID id, const int value = 0,
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
long style = 0, const wxValidator& validator = wxDefaultValidator,
const wxString& idname = wxTextCtrlNameStr)
{
Create( parent, id, value, pos, size, style, validator, idname);
};
wxNumberCtrl(wxWindow* parent, wxWindowID id, wxString s,
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
long style = 0, const wxValidator& validator = wxDefaultValidator,
const wxString& idname = wxTextCtrlNameStr)
{
Create( parent, id, 0, pos, size, style, validator, idname);
};
/// Creation
bool Create(wxWindow* parent, wxWindowID id, const int value = 0,
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
long style = 0 , const wxValidator& validator = wxDefaultValidator,
const wxString& idname = wxTextCtrlNameStr);
// Methoden zum Zugriff auf interne Variablen
//Lesen
int GetInt();
double GetDouble();
//Setzen
void SetRingBell(bool ring);
void SetInt(int i);
void SetDouble(double d, wxString s=wxT("%0.9g"));
void SetRange(double minimum, double maximum);
void SetNoShow(double ns, bool b=true);
void AcceptIntOnly(bool b);
private:
DECLARE_EVENT_TABLE()
void OnKillFocus(wxFocusEvent& event);
void OnChar(wxKeyEvent& event);
void OnKeyUp(wxKeyEvent& event);
wxString oldvalue;
int min, max;
double noshownumber;
bool ringbell, noshow, intonly;
};
#endif
Code: Select all
#ifdef __GNUG__
#pragma implementation "wxNumberCtrl.h"
#endif
#include "wx/wx.h"
#include "wx/textctrl.h"
#include "wxNumberCtrl.h"
IMPLEMENT_CLASS( wxNumberCtrl, wxTextCtrl )
BEGIN_EVENT_TABLE( wxNumberCtrl, wxTextCtrl )
EVT_KEY_DOWN(wxNumberCtrl::OnChar )
EVT_KEY_UP(wxNumberCtrl::OnKeyUp)
EVT_KILL_FOCUS(wxNumberCtrl::OnKillFocus )
END_EVENT_TABLE()
bool wxNumberCtrl::Create(wxWindow* parent, wxWindowID id, const int value,
const wxPoint& pos, const wxSize& size,
long style, const wxValidator& validator,
const wxString& idname)
{
wxString s;
if (value!=0)
s.Printf("%i",value);
max=INT_MAX;
min=-(INT_MAX-1);
noshow=false;
if (!wxTextCtrl::Create(parent, id, s, pos, size, style, validator, idname))
return false;
else
return true;
}
void wxNumberCtrl::SetRange(double minimum, double maximum)
{
double d;
if (minimum>maximum)
{
d=minimum;
minimum=maximum;
maximum=d;
}
min=minimum;
max=maximum;
}
void wxNumberCtrl::SetRingBell(bool ring)
{
ringbell=ring;
}
int wxNumberCtrl::GetInt()
{
wxString s;
long val;
s=GetValue();
if (noshow)
{
if (GetLastPosition()==0)
val=noshownumber;
else
s.ToLong(&val, 10);
}
else
{
s.ToLong(&val, 10);
}
return (int) val;
}
void wxNumberCtrl::SetInt(int i)
{
wxString s;
s.Printf("%i",i);
SetValue(s);
if ((noshow)&&(i==noshownumber))
Clear();
}
double wxNumberCtrl::GetDouble()
{
wxString s;
s=wxTextCtrl::GetValue();
double val;
if (noshow)
{
if (GetLastPosition()==0)
val=noshownumber;
else
s.ToDouble(&val);
}
else
{
s.ToDouble(&val);
}
return val;
}
void wxNumberCtrl::SetDouble(double d, wxString s)
{
wxString t;
t.Printf(s,d);
SetValue(t);
if ((noshow)&&(d==noshownumber))
Clear();
}
void wxNumberCtrl::OnChar(wxKeyEvent& event)
{
oldvalue=GetValue();
switch (event.GetKeyCode())
{
case '0':
case WXK_NUMPAD0:
if (!((GetDouble()==0)&&(oldvalue.Find('.')==-1))) //keine doppelte Null
event.Skip();
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case WXK_NUMPAD1:
case WXK_NUMPAD2:
case WXK_NUMPAD3:
case WXK_NUMPAD4:
case WXK_NUMPAD5:
case WXK_NUMPAD6:
case WXK_NUMPAD7:
case WXK_NUMPAD8:
case WXK_NUMPAD9:
if(GetDouble()==0) Clear();
case WXK_DELETE:
case WXK_RIGHT:
case WXK_LEFT:
case WXK_BACK:
case WXK_TAB:
case WXK_NUMPAD_END:
case WXK_NUMPAD_BEGIN:
case WXK_HOME:
case WXK_END:
case WXK_RETURN:
event.Skip();
break;
case WXK_NUMPAD_DECIMAL:
case '.':
case ',':
if (!intonly)
if (oldvalue.Find('.')==-1) //keine doppelten Punkte zulassen
WriteText(".");
break;
case WXK_NUMPAD_SUBTRACT:
case '-':
if (min<0)
event.Skip();
break;
default:
if (ringbell) wxBell();
event.Skip(false);
break;
}
}
void wxNumberCtrl::OnKeyUp(wxKeyEvent& event)
{
double d=GetDouble();
if ((d>max)||(d<min))
{
SetValue(oldvalue);
if (ringbell) wxBell();
}
}
void wxNumberCtrl::SetNoShow(double ns, bool b)
{
noshow=b;
noshownumber=ns;
}
void wxNumberCtrl::OnKillFocus(wxFocusEvent& event)
{
if (noshow)
{
if (GetDouble()==noshownumber)
Clear();
}
}
void wxNumberCtrl::AcceptIntOnly(bool b)
{
intonly=b;
}
Sebastian