自定义控件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;
}
原文地址:https://www.cnblogs.com/godspeedsam/p/2433159.html