← Blog

Handling Clipboard Operations in wxWidgets Text Controls

Implement cut, copy, and paste in wxWidgets text controls. Handle clipboard operations correctly across Linux, macOS, and Windows with wxTextCtrl.

Handling common clipboard tasks for your text fields is a must-have for any serious application that needs to accept keyboard input from the users. Surprisingly, it’s not that easy in wxWidgets, especially considering the differences between platforms (Linux, Mac, and Windows).

I explain the problem in detail in my Text Fields video (the “Clipboard Operations” chapter). In the Menus tutorial, I talk about menus in general and constructing the Edit menu with the clipboard commands in particular.

wxWidgets: Text Controls and Validators Play video: wxWidgets: Text Controls and Validators

Check these out if you need more information, or scroll down for the solution to the clipboard problem in wxWidgets.

wxWidgets: Main Menu and Context Menus Play video: wxWidgets: Main Menu and Context Menus

Text Fields and the Main Menu

Here’s a minimal wxWidgets application with a multiline text field and an Edit menu.

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

wxIMPLEMENT_APP(MyApp);

class MyFrame : public wxFrame
{
public:
    MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
};

bool MyApp::OnInit()
{
    MyFrame *frame = new MyFrame("Hello World", wxDefaultPosition, wxDefaultSize);
    frame->Show(true);
    return true;
}

MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
    : wxFrame(nullptr, wxID_ANY, title, pos, size)
{
    wxMenuBar *menuBar = new wxMenuBar();

    wxMenu *editMenu = new wxMenu();

    editMenu->Append(wxID_UNDO);
    editMenu->Append(wxID_REDO);
    editMenu->AppendSeparator();
    editMenu->Append(wxID_CUT);
    editMenu->Append(wxID_COPY);
    editMenu->Append(wxID_PASTE);

    menuBar->Append(editMenu, "&Edit");

    SetMenuBar(menuBar);

    auto textField = new wxTextCtrl(this, wxID_ANY, "", 
        wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);

	SetMinClientSize(FromDIP(wxSize(400,300)));
}

Note that we used default IDs for the clipboard commands in the Edit menu: wxID_CUT, wxID_COPY, and wxID_PASTE.

The Problem

In theory using the default IDs should ensure that these menu commands are handled correctly by the text control. After all, if we check out the wxTextCtrl sources, we see that indeed the control handles the related menu events:

// wxTextCtrl sources

wxBEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
    EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
    EVT_CHAR(wxTextCtrl::OnChar)
    EVT_KEY_DOWN(wxTextCtrl::OnKeyDown)
    EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
    EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
    EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
    EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
    EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
    EVT_MENU(wxID_CLEAR, wxTextCtrl::OnDelete)
    EVT_MENU(wxID_SELECTALL, wxTextCtrl::OnSelectAll)

    EVT_CONTEXT_MENU(wxTextCtrl::OnContextMenu)

    EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
    EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
    EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
    EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
    EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
    EVT_UPDATE_UI(wxID_CLEAR, wxTextCtrl::OnUpdateDelete)
    EVT_UPDATE_UI(wxID_SELECTALL, wxTextCtrl::OnUpdateSelectAll)
wxEND_EVENT_TABLE()

So, we should be able to copy, cut, and paste by using our menu commands. And if you check this on MacOS, it looks like we are able to do so, so the events work!

Well, not so fast. Actually, wxWidgets’ implementation on Mac handles the clipboard events natively, bypassing its own events mechanism (by the way, if you want to know more about wxWidgets events, I recommend this video). If we try the same code on Windows and Linux, we see that there’s no reaction to the clipboard events.

So what’s wrong?

The problem is that the framework sends these events to the main frame, not to our text field. There’s no propagation upward because the main frame sits on the top of the windows hierarchy, so text fields never get the clipboard events.

The Solution

We need to manually propagate the clipboard events to the correct text field. As we may have more than one field, we want to find the one with the focus and send the proper EVT_MENU and EVT_UPDATE_UI there.

To do this, we must override the default ProcessEvent method in MyFrame. First, add the declaration to the MyFrame class:

class MyFrame : public wxFrame
{
public:
    MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
private:
    bool ProcessEvent(wxEvent &event) override;
};

Then add the implementation.

bool MyFrame::ProcessEvent(wxEvent &event)
{
    static wxEvent *lastEvent = nullptr;

    if (event.GetEventType() == wxEVT_MENU || event.GetEventType() == wxEVT_UPDATE_UI)
    {
        if (lastEvent != &event)
        {
            lastEvent = &event;
            auto focusedChild = wxFindFocusDescendant(this);
            if (focusedChild && focusedChild->GetEventHandler()->ProcessEvent(event))
            {
                lastEvent = nullptr;
                return true;
            }

            lastEvent = nullptr;
        }
    }

    return wxFrame::ProcessEvent(event);
}

We override the default behavior for two types of events:

  1. wxEVT_MENU - triggered when the user clicks a menu item. Initiates a clipboard action,
  2. wxEVT_UPDATE_UI - triggered when the menu item needs a refresh, for example, when the user opens the menu. This is a chance for the control to update the appearance of a UI item, for example, grey out the Cut or Copy menu items when there’s no selection.

Our algorithm finds the focused control and passes the event there. Note the if (lastEvent != &event) guard. This mechanics is needed to avoid an infinite event loop: when we pass an event to a control, it propagates to the parent, finally reaching MyFrame and going into ProcessEvent again. At this point, we need to break the cycle using our static variable.

Conclusion

And that’s it. This quick fix helps with the Edit menu items behavior on Linux and Windows and makes the clipboard actions work smoothly.

For a practical example of wxTextCtrl in a real application, see Writing a Markdown Editor with wxWidgets and cmark.

Written by Luke. I build custom software for businesses, made for the way your team works. Fixed price, delivered in days or weeks. I've been shipping software since 2008, co-founded Codahead, a software house in Kraków, and I've published C++ tutorials on YouTube for six years.

Recent posts

All
Your First Triangle in Apple Metal: Shaders and Vertex Buffers Oct 2026Draw a triangle with Apple Metal in a Swift playground: write the vertex and fragment shaders, build the render pipeline, send vertices with setVertexBytes or an MTLBuffer, and get the memory alignment right. Your Business Deserves a Native App Oct 2026Many of your team's apps are web pages in disguise, and you pay for it in waiting. When Shopify rebuilt its shopping app as native, it started opening twice as fast on Android. Here's what native could do for your business. XFCE on 4K Displays: Correct Scaling in Five Settings Oct 2026XFCE's Window Scaling option only scales GTK apps. Here are the five settings that make a 4K display look right in GTK, Qt, Firefox and Emacs, plus fractional scaling.