Text Selection Change Event for wxTextCtrl

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
purplex88
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 247
Joined: Mon Feb 24, 2014 3:14 pm

Text Selection Change Event for wxTextCtrl

Post by purplex88 »

Is there a selection changed event for wxTextCtrl? What I am trying to do is get the "number of characters" which are selected as the selection changes.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Text Selection Change Event for wxTextCtrl

Post by doublemax »

As you probably already guessed: No.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7478
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Text Selection Change Event for wxTextCtrl

Post by ONEEYEMAN »

Hi,
What is you wx version and OS?

Thank you.
purplex88
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 247
Joined: Mon Feb 24, 2014 3:14 pm

Re: Text Selection Change Event for wxTextCtrl

Post by purplex88 »

Windows 8.1 OS and wxWidgets 3.1. Perhaps, windows API allows for it?
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7478
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Text Selection Change Event for wxTextCtrl

Post by ONEEYEMAN »

Hi,
Yes, and not just Windows API. GTK and OSX implementation are also available.
There is a ticket on trac about it even.

Thank you.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7478
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Text Selection Change Event for wxTextCtrl

Post by ONEEYEMAN »

Just to be complete: here is the ticket with the patch implementing the feature.

Please apply, test and leave a comment, so that it could be included in the next release.

Thank you.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Text Selection Change Event for wxTextCtrl

Post by PB »

In addition to the proper library patch referenced above, here is a quick untested MSW only hack that obtains information about selection change.

Please notice that you get the message whenever the cursor position changes as well. I recommend running the test code below and observing what gets logged after which user actions.

Code: Select all

#include <wx/wx.h>

#if defined(__WXMSW__) && defined(wxUSE_RICHEDIT)

#include <richedit.h>

class MyTextCtrl : public wxTextCtrl
{
public:
    MyTextCtrl (wxWindow* parent, wxWindowID id, 
                const wxString& value = wxEmptyString, 
                const wxPoint& pos = wxDefaultPosition, 
                const wxSize& size = wxDefaultSize, 
                long style = 0, 
                const wxValidator& validator = wxDefaultValidator, 
                const wxString& name = wxTextCtrlNameStr)
        : wxTextCtrl(parent, id, value, pos, size, style | wxTE_RICH2, validator, name)
    {

        LRESULT flags = ::SendMessage(GetHWND(), EM_GETEVENTMASK, 0, 0);
        
        if ( flags != 0 )
            ::SendMessage(GetHWND(), EM_SETEVENTMASK, 0, (LPARAM)(flags | ENM_SELCHANGE));

        m_prevSeltyp = SEL_EMPTY;
        m_ignoreConsecutiveSelEmptyNotifications = true;
    }

    void SetIgnoreConsecutiveSelEmptyNotifications(bool ignore)
    {
        m_ignoreConsecutiveSelEmptyNotifications = ignore;
    }

    bool GetIgnoreConsecutiveSelEmptyNotifications() const
    {
        return m_ignoreConsecutiveSelEmptyNotifications;
    }

    virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) wxOVERRIDE
    {
        const NMHDR* hdr = (NMHDR*)lParam; 
        
        if ( hdr->code == EN_SELCHANGE )
        {
            const SELCHANGE* selChange = (SELCHANGE*)lParam; 
            wxString selectionType = "EN_SELCHANGE:";

            if ( selChange->seltyp == SEL_EMPTY )
            {
                if ( m_prevSeltyp == SEL_EMPTY && m_ignoreConsecutiveSelEmptyNotifications )
                    return true; 
                selectionType += " SEL_EMPTY";
            }
            else
            {                
                if ( selChange->seltyp & SEL_TEXT )
                    selectionType+= " SEL_TEXT";
                if ( selChange->seltyp & SEL_OBJECT )
                    selectionType += " SEL_OBJECT";
                if ( selChange->seltyp & SEL_MULTICHAR )
                    selectionType += " SEL_MULTICHAR";
                if ( selChange->seltyp & SEL_MULTIOBJECT )
                    selectionType += " SEL_MULTIOBJECT";
            }
            m_prevSeltyp = selChange->seltyp;            
            wxLogMessage("%s (%ld, %ld)", selectionType, selChange->chrg.cpMin, selChange->chrg.cpMax);
            return true;
        }
        
        return wxTextCtrl::MSWOnNotify(idCtrl, lParam, result);
    }
private:
    WORD m_prevSeltyp;
    bool m_ignoreConsecutiveSelEmptyNotifications;
};
#else

typedef wxTextCtrl MyTextCtrl;

#endif // #if defined(__WXMSW__) && defined(wxUSE_RICHEDIT)

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "EN_SELCHANGE Test", wxDefaultPosition, wxSize(800, 600))
    {       
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
   
        MyTextCtrl* editCtrl = new MyTextCtrl(this, wxID_ANY, wxEmptyString, 
            wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);        
        mainSizer->Add(editCtrl, 3, wxEXPAND | wxALL , 5);
   
        wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, 
            wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);        
        mainSizer->Add(logCtrl, 2, wxEXPAND | wxALL , 5);
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));
      
        SetSizer(mainSizer);         
    }	
};

class MyApp : public wxApp
{
public:	
	bool OnInit()
	{
        (new MyFrame)->Show();
        return true;
	}
}; wxIMPLEMENT_APP(MyApp);
Post Reply