I've made a minimal example that has a main app with a frame, and the frame has a CustomTextCtrl and CustomPanel as children.
I have two questions from this, and would appreciate any help or ideas:
1. When you run the program, you'll see the event order is the following when you type into the TextCtrl
- MyApp::OnCharHook
- CustomTextCtrl::OnText
My question is, how should I achieve this? And, is there a way to do this which makes it so the MyApp::OnCharHook doesn't need to manually check the state of the CustomTextCtrl? The reason for this latter desire is that if I have multiple TextCtrls, it would be tedious and not scalable to check every TextCtrl that could possibly be active.
2. If I click into the TextCtrl, it correctly shows the blinking cursor and allows me to type. Clicking anywhere outside the TextCtrl (including the CustomPanel) then removes the blinking cursor, and I can no longer type. This is correct, expected behavior. The problem is that in my actual program, clicking from my TextCtrl to my wxGLCanvas doesn't make the TextCtrl stop blinking.
How can I get the behavior of clicking into a wxPanel to be the same behavior as clicking into a wxGLCanvas? (I didn't paste the code for this, because it's notoriously long to have a minimal OpenGL example, but I could if necessary.)
UPDATE: I solved #2 by simply calling
Code: Select all
if (event.LeftDown() || event.LeftDClick())
{
this->SetFocus();
Code: Select all
#include "wx/wx.h"
#include <iostream>
class CustomTextCtrl : public wxTextCtrl
{
public:
CustomTextCtrl(wxWindow *parent,
wxWindowID id)
: wxTextCtrl(parent, id) { }
void OnText(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};
class CustomPanel : public wxPanel {
public:
CustomPanel(wxWindow* parent)
: wxPanel(parent)
{
this->SetBackgroundColour(wxColour(100, 100, 200));
this->Refresh();
}
void OnMouse(wxMouseEvent& event);
wxDECLARE_EVENT_TABLE();
};
enum
{
TextBox_OnText = wxID_HIGHEST + 10,
};
class MyApp : public wxApp
{
wxFrame *frame;
public:
bool OnInit()
{
frame = new wxFrame((wxFrame *)NULL, -1, wxT("wxWidgets"), wxPoint(50,50), wxSize(800, 600));
CustomPanel* blue_panel = new CustomPanel(frame);
int size = 200;
int spacing = 100;
blue_panel->SetSize(size, size);
blue_panel->SetPosition(wxPoint(spacing, spacing));
CustomTextCtrl* textCtrl = new CustomTextCtrl(frame, TextBox_OnText);
textCtrl->ChangeValue("test text");
frame->Show();
return true;
}
wxDECLARE_EVENT_TABLE();
void OnCharHook(wxKeyEvent& event);
void OnMouse(wxMouseEvent& event);
};
IMPLEMENT_APP(MyApp)
wxBEGIN_EVENT_TABLE(MyApp, wxApp)
EVT_CHAR_HOOK(MyApp::OnCharHook)
EVT_MOUSE_EVENTS(MyApp::OnMouse)
wxEND_EVENT_TABLE()
void MyApp::OnCharHook(wxKeyEvent& event)
{
std::cout << "MyApp::OnCharHook\n";
event.Skip();
}
void MyApp::OnMouse(wxMouseEvent& event)
{
event.Skip();
}
wxBEGIN_EVENT_TABLE(CustomPanel, wxPanel)
EVT_MOUSE_EVENTS(CustomPanel::OnMouse)
wxEND_EVENT_TABLE()
void CustomPanel::OnMouse(wxMouseEvent& event)
{
static int iteration = 0;
if (event.LeftUp())
{
std::cout << "Lift at " << "(" << event.GetX() << ", " << event.GetY() << ") [" << iteration++ << "]\n";
}
else if (event.LeftDown() || event.LeftDClick())
{
std::cout << "Click at " << "(" << event.GetX() << ", " << event.GetY() << ") [" << iteration++ << "]\n";
}
event.Skip(); // continue to propagate (to parent?)
}
wxBEGIN_EVENT_TABLE(CustomTextCtrl, wxTextCtrl)
EVT_TEXT(TextBox_OnText, CustomTextCtrl::OnText)
wxEND_EVENT_TABLE()
void CustomTextCtrl::OnText(wxCommandEvent& event)
{
std::cout << "CustomTextCtrl::OnText\n";
}