自定义控件wxIpCtrl –(Ip Address)
wxIpCtrl派生自wxPanel,构造函数看起来象这样:
class wxIpCtrl : public wxPanel
{
public:
wxIpCtrl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxString& ipaddr = wxT("192.168.1.12"), long style = wxIPCTRL_DEFAULT_STYLE);
wxString GetValue() const;
...
};
GetValue 的返回值是wxString类型,这也就是读取这个控件里用户交互的东东。
因为派生自wxPanel,所以把它当成wxPanel来用就可以了,象下面这样就可以产生它的一个实例:
wxIpCtrl* Panel1 = new wxIpCtrl(this, wxID_ANY);
运行下面的例子程序的效果图:

客户程序:
TestMain.cpp
/***************************************************************
* Name: TestMain.cpp
* Purpose: Code for Application Frame
* Author: XCool
* Created: 2012-04-05
* Copyright:
* License: LGPL
**************************************************************/
#include "TestMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(TestDialog)
#include <wx/intl.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(TestDialog)
const long TestDialog::ID_PANEL1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(TestDialog,wxDialog)
//(*EventTable(TestDialog)
//*)
END_EVENT_TABLE()
TestDialog::TestDialog(wxWindow* parent,wxWindowID id)
{
//(*Initialize(TestDialog)
wxFlexGridSizer* FlexGridSizer1;
Create(parent, id, _("wxWidgets app"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE, _T("id"));
SetClientSize(wxSize(348,239));
BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
FlexGridSizer1 = new wxFlexGridSizer(0, 3, 0, 0);
Panel1 = new wxIpCtrl(this, ID_PANEL1/*, wxDefaultPosition, wxSize(137,67), wxTAB_TRAVERSAL, _T("ID_PANEL1")*/);
FlexGridSizer1->Add(Panel1, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
BoxSizer1->Add(FlexGridSizer1, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
SetSizer(BoxSizer1);
BoxSizer1->SetSizeHints(this);
//*)
}
TestDialog::~TestDialog()
{
//(*Destroy(TestDialog)
//*)
}
void TestDialog::OnQuit(wxCommandEvent& event)
{
Close();
}
void TestDialog::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
TestMain.h
/***************************************************************
* Name: TestMain.h
* Purpose: Defines Application Frame
* Author: XCool
* Created: 2012-04-05
* Copyright:
* License: LGPL
**************************************************************/
#ifndef TESTMAIN_H
#define TESTMAIN_H
//(*Headers(TestDialog)
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/dialog.h>
//*)
#include "wxipctrl.h"
class TestDialog: public wxDialog
{
public:
TestDialog(wxWindow* parent,wxWindowID id = -1);
virtual ~TestDialog();
private:
//(*Handlers(TestDialog)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
//*)
//(*Identifiers(TestDialog)
static const long ID_PANEL1;
//*)
//(*Declarations(TestDialog)
wxIpCtrl* Panel1;
wxBoxSizer* BoxSizer1;
//*)
DECLARE_EVENT_TABLE()
};
#endif // TESTMAIN_H
TestApp.cpp
/***************************************************************
* Name: TestApp.cpp
* Purpose: Code for Application Class
* Author: XCool
* Created: 2012-04-05
* Copyright:
* License: LGPL
**************************************************************/
#include "TestApp.h"
//(*AppHeaders
#include "TestMain.h"
#include <wx/image.h>
//*)
IMPLEMENT_APP(TestApp);
bool TestApp::OnInit()
{
//(*AppInitialize
bool wxsOK = true;
wxInitAllImageHandlers();
if ( wxsOK )
{
TestDialog Dlg(0);
SetTopWindow(&Dlg);
Dlg.ShowModal();
wxsOK = false;
}
//*)
return wxsOK;
}
TestApp.h
/***************************************************************
* Name: TestApp.h
* Purpose: Defines Application Class
* Author: XCool
* Created: 2012-04-05
* Copyright:
* License: LGPL
**************************************************************/
#ifndef TESTAPP_H
#define TESTAPP_H
#include <wx/app.h>
class TestApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif // TESTAPP_H
以下为自定义控件 wxIpCtrl的源码:
wxIpCtrl.h
#ifndef WXIPCTRL_H_INCLUDED
#define WXIPCTRL_H_INCLUDED
#include <wx/wx.h>
DECLARE_EVENT_TYPE(wxEVT_IPCTRL_CHANGED, wxID_ANY);
// wxIpCtrl styles
#define wxIPCTRL_D_CLASS 1
#define wxIPCTRL_ALL_CLASSES 2
#define wxIPCTRL_SUBNET_MASK wxIPCTRL_ALL_CLASSES
#define wxIPCTRL_DEFAULT_STYLE 0
/**
* \class wxIPCtrl
*/
class wxIpCtrl : public wxPanel
{
long m_ipStyle;
wxArrayString m_defaultValue;
wxBoxSizer* m_sizer;
wxTextCtrl* m_editIP1;
wxTextCtrl* m_editIP2;
wxTextCtrl* m_editIP3;
wxTextCtrl* m_editIP4;
wxStaticText* m_dot1;
wxStaticText* m_dot2;
wxStaticText* m_dot3;
public:
wxIpCtrl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxString& ipaddr = wxT("192.168.1.12"), long style = wxIPCTRL_DEFAULT_STYLE);
wxString GetValue() const;
bool SetValue(const wxString& ipaddr);
void SetStyle(long style) { m_ipStyle = style; }
long GetStyle() { return m_ipStyle; }
virtual bool Enable(bool enable = true);
protected:
void CreateGui();
wxTextCtrl* CreateTextCtrl();
wxStaticText* CreateDot();
bool CheckIp(const wxString& ipaddr, wxArrayString& ipParts) const;
bool CheckRange(const wxString& value, unsigned long min, unsigned long max) const;
void DoSetValue(const wxArrayString& ipParts);
void DoSetDefaultValue();
virtual void OnChar(wxKeyEvent& event);
virtual void OnTextUpdated(wxCommandEvent& event);
};
#endif // WXIPCTRL_H_INCLUDED
wxIpCtrl.cpp
#include "wxipctrl.h"
#include <wx/regex.h>
#include <wx/msgdlg.h>
DEFINE_EVENT_TYPE(wxEVT_IPCTRL_CHANGED);
static
bool in_range(unsigned long value, unsigned long min, unsigned long max)
{
return min <= value && value <= max;
}
/**
*
*/
wxIpCtrl::wxIpCtrl(wxWindow *parent, wxWindowID id, const wxString& ipaddr, long style)
: wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL)
, m_ipStyle(style)
{
CreateGui();
m_defaultValue.Add( wxT("192") );
m_defaultValue.Add( wxT("168") );
m_defaultValue.Add( wxT("1") );
m_defaultValue.Add( wxT("12") );
if (m_ipStyle & wxIPCTRL_D_CLASS) {
m_defaultValue.Item(0) = wxT("224");
}
SetValue(ipaddr);
Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ) );
m_editIP1->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
m_editIP1->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
m_editIP2->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
m_editIP2->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
m_editIP3->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
m_editIP3->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
m_editIP4->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
m_editIP4->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
}
/**
*
*/
void wxIpCtrl::CreateGui()
{
SetBackgroundColour(*wxWHITE);
m_sizer = new wxBoxSizer(wxHORIZONTAL);
m_editIP1 = CreateTextCtrl();
m_dot1 = CreateDot();
m_editIP2 = CreateTextCtrl();
m_dot2 = CreateDot();
m_editIP3 = CreateTextCtrl();
m_dot3 = CreateDot();
m_editIP4 = CreateTextCtrl();
SetSizer(m_sizer);
Layout();
m_sizer->Fit(this);
}
/**
*
*/
wxTextCtrl* wxIpCtrl::CreateTextCtrl()
{
wxTextCtrl* txtCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(27, 15), wxNO_BORDER|wxTE_RIGHT);
txtCtrl->SetMaxLength(3);
m_sizer->Add(txtCtrl, 0, wxALIGN_BOTTOM|wxTOP, 5);
return txtCtrl;
}
/**
*
*/
wxStaticText* wxIpCtrl::CreateDot()
{
wxStaticText* staticTxt = new wxStaticText( this, wxID_ANY, _("."), wxDefaultPosition, wxDefaultSize, 0 );
staticTxt->Wrap( -1 );
m_sizer->Add(staticTxt, 0, wxALIGN_BOTTOM, 5);
return staticTxt;
}
/**
*
*/
bool wxIpCtrl::Enable(bool enable)
{
wxColour bkColour = enable ? wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) : wxSystemSettings::GetColour(wxSYS_COLOUR_MENU);
SetBackgroundColour(bkColour);
m_editIP1->SetBackgroundColour(bkColour);
m_editIP2->SetBackgroundColour(bkColour);
m_editIP3->SetBackgroundColour(bkColour);
m_editIP4->SetBackgroundColour(bkColour);
m_dot1->SetBackgroundColour(bkColour);
m_dot2->SetBackgroundColour(bkColour);
m_dot3->SetBackgroundColour(bkColour);
m_editIP1->SetEditable(enable);
m_editIP2->SetEditable(enable);
m_editIP3->SetEditable(enable);
m_editIP4->SetEditable(enable);
Refresh();
return true;
}
/**
*
*/
wxString wxIpCtrl::GetValue() const
{
return m_editIP1->GetValue() + wxT(".") + m_editIP2->GetValue() + wxT(".") + m_editIP3->GetValue() + wxT(".") + m_editIP4->GetValue();
}
/**
*
*/
bool wxIpCtrl::SetValue(const wxString& ipaddr)
{
wxArrayString ipParts;
if (CheckIp(ipaddr, ipParts) == false) {
DoSetDefaultValue();
return false;
}
DoSetValue(ipParts);
return true;
}
/**
*
*/
bool wxIpCtrl::CheckIp(const wxString& ipaddr, wxArrayString& ipParts) const
{
wxRegEx strregex(wxT("([0-9]{1,3})([.])([0-9]{1,3})([.])([0-9]{1,3})([.])([0-9]{1,3})"));
if (!strregex.Matches(ipaddr)) {
return false;
}
ipParts.clear();
ipParts.Add( strregex.GetMatch(ipaddr, 1) );
ipParts.Add( strregex.GetMatch(ipaddr, 3) );
ipParts.Add( strregex.GetMatch(ipaddr, 5) );
ipParts.Add( strregex.GetMatch(ipaddr, 7) );
unsigned long ip1, ip2, ip3, ip4;
ipParts[0].ToULong(&ip1);
ipParts[1].ToULong(&ip2);
ipParts[2].ToULong(&ip3);
ipParts[3].ToULong(&ip4);
if (m_ipStyle & wxIPCTRL_D_CLASS) {
if (!in_range(ip1, 224, 239)) {
return false;
}
}
else if (m_ipStyle & wxIPCTRL_ALL_CLASSES) {
if (!in_range(ip1, 0, 255)) {
return false;
}
}
else {
if (!in_range(ip1, 1, 223)) {
return false;
}
}
if ( !in_range(ip2, 0, 255) || !in_range(ip3, 0, 255) || !in_range(ip4, 0, 255) ) {
return false;
}
return true;
}
/**
*
*/
void wxIpCtrl::DoSetValue(const wxArrayString& ipParts)
{
assert(ipParts.size() == 4);
m_editIP1->ChangeValue(ipParts[0]);
m_editIP2->ChangeValue(ipParts[1]);
m_editIP3->ChangeValue(ipParts[2]);
m_editIP4->ChangeValue(ipParts[3]);
}
/**
*
*/
void wxIpCtrl::DoSetDefaultValue()
{
m_editIP1->ChangeValue(m_defaultValue[0]);
m_editIP2->ChangeValue(m_defaultValue[1]);
m_editIP3->ChangeValue(m_defaultValue[2]);
m_editIP4->ChangeValue(m_defaultValue[3]);
}
/**
*
*/
void wxIpCtrl::OnChar(wxKeyEvent& event)
{
const wxObject* evtObject = event.GetEventObject();
//if ((m_ipStyle & wxIPCTRL_D_CLASS) && (evtObject == m_editIP1) ) {
// // Do not allow to change the ip 1 (which must be 224)
// return;
//}
const int keyCode = event.GetKeyCode();
if (keyCode >= '0' && keyCode <= '9') {
event.Skip();
return;
}
if (keyCode == '.') {
// deal with '.'
if (evtObject == m_editIP1 && m_editIP1->GetStringSelection().Length() != m_editIP1->GetValue().Length()) {
m_editIP2->SetFocus();
m_editIP2->SetSelection(-1, -1);
}
else if (evtObject == m_editIP2 && m_editIP2->GetStringSelection().Length() != m_editIP2->GetValue().Length()) {
m_editIP3->SetFocus();
m_editIP3->SetSelection(-1, -1);
}
else if (evtObject == m_editIP3 && m_editIP3->GetStringSelection().Length() != m_editIP3->GetValue().Length()) {
m_editIP4->SetFocus();
m_editIP4->SetSelection(-1, -1);
}
}
else if (keyCode == WXK_BACK) {
if (evtObject == m_editIP2 && m_editIP2->GetValue().IsEmpty()) {
m_editIP1->SetFocus();
m_editIP1->SetInsertionPointEnd();
}
else if (evtObject == m_editIP3 && m_editIP3->GetValue().IsEmpty()) {
m_editIP2->SetFocus();
m_editIP2->SetInsertionPointEnd();
}
else if (evtObject == m_editIP4 && m_editIP4->GetValue().IsEmpty()) {
m_editIP3->SetFocus();
m_editIP3->SetInsertionPointEnd();
}
event.Skip();
}
else if (keyCode == WXK_LEFT || keyCode == WXK_UP) {
if (evtObject == m_editIP2 && m_editIP2->GetInsertionPoint() == 0) {
m_editIP1->SetFocus();
m_editIP1->SetInsertionPointEnd();
}
else if (evtObject == m_editIP3 && m_editIP3->GetInsertionPoint() == 0) {
m_editIP2->SetFocus();
m_editIP2->SetInsertionPointEnd();
}
else if (evtObject == m_editIP4 && m_editIP4->GetInsertionPoint() == 0) {
m_editIP3->SetFocus();
m_editIP3->SetInsertionPointEnd();
}
event.Skip();
}
else if (keyCode == WXK_RIGHT || keyCode == WXK_DOWN) {
if (evtObject == m_editIP1 && m_editIP1->GetInsertionPoint() == m_editIP1->GetLastPosition()) {
m_editIP2->SetFocus();
m_editIP2->SetInsertionPoint(0);
}
else if (evtObject == m_editIP2 && m_editIP2->GetInsertionPoint() == m_editIP2->GetLastPosition()) {
m_editIP3->SetFocus();
m_editIP3->SetInsertionPoint(0);
}
else if (evtObject == m_editIP3 && m_editIP3->GetInsertionPoint() == m_editIP3->GetLastPosition()) {
m_editIP4->SetFocus();
m_editIP4->SetInsertionPoint(0);
}
event.Skip();
}
else if (keyCode == WXK_TAB || keyCode == WXK_DELETE || keyCode == WXK_END || keyCode == WXK_HOME ) {
event.Skip();
}
}
/**
*
*/
void wxIpCtrl::OnTextUpdated(wxCommandEvent& event)
{
const wxString str = event.GetString();
if (str.Length() == 0) {
event.Skip();
return;
}
bool bSendEvtChanged = false;
const wxObject* evtObject = event.GetEventObject();
if (evtObject == m_editIP1) {
if (m_ipStyle & wxIPCTRL_ALL_CLASSES ||
m_ipStyle & wxIPCTRL_D_CLASS ) {
if (CheckRange(str, 0, 255)) {
if (str.Length() == 3) {
m_editIP2->SetFocus();
m_editIP2->SetSelection(-1, -1);
}
bSendEvtChanged = true;
}
else {
m_editIP1->SetValue(wxT("0"));
m_editIP1->SetFocus();
m_editIP1->SetSelection(-1, -1);
}
}
else {
if (CheckRange(str, 1, 223)) {
if (str.Length() == 3) {
m_editIP2->SetFocus();
m_editIP2->SetSelection(-1, -1);
}
bSendEvtChanged = true;
}
else {
m_editIP1->SetValue(wxT("1"));
m_editIP1->SetFocus();
m_editIP1->SetSelection(-1, -1);
}
}
}
else if (evtObject == m_editIP2) {
if (CheckRange(str, 0, 255)) {
if (str.Length() == 3) {
m_editIP3->SetFocus();
m_editIP3->SetSelection(-1, -1);
}
bSendEvtChanged = true;
}
else {
m_editIP2->SetValue(wxT("0"));
m_editIP2->SetFocus();
m_editIP2->SetSelection(-1, -1);
}
}
else if (evtObject == m_editIP3) {
if (CheckRange(str, 0, 255)) {
if (str.Length() == 3) {
m_editIP4->SetFocus();
m_editIP4->SetSelection(-1, -1);
}
bSendEvtChanged = true;
}
else {
m_editIP3->SetValue(wxT("0"));
m_editIP3->SetFocus();
m_editIP3->SetSelection(-1, -1);
}
}
else if (evtObject == m_editIP4) {
if (CheckRange(str, 0, 255)) {
// do nothing
bSendEvtChanged = true;
}
else {
m_editIP4->SetValue(wxT("0"));
m_editIP4->SetFocus();
m_editIP4->SetSelection(-1, -1);
}
}
if (bSendEvtChanged) {
wxCommandEvent evtChanged(wxEVT_IPCTRL_CHANGED, GetId());
evtChanged.SetString(GetValue());
evtChanged.SetEventObject(this);
AddPendingEvent(evtChanged);
}
event.Skip();
}
/**
*
*/
bool wxIpCtrl::CheckRange(const wxString& value, unsigned long min, unsigned long max) const
{
unsigned long v = 0;
value.ToULong(&v, 10);
bool inRange = in_range(v, min, max);
if (!inRange) {
wxString msg = wxString::Format(_("Invalid value : %s"), value.c_str());
::wxMessageBox(msg, _("Invalid value"), wxOK | wxICON_EXCLAMATION, NULL);
}
return inRange;
}

浙公网安备 33010602011771号