自定义控件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; }