Tomorrow I will post whole code.
If next row present then just call Navigate NO AddRow here.
If row below visual rect Then Scroll by one step.
Tomorrow I will post whole code.
Code: Select all
#include <wx/wx.h>
#include <wx/scrolwin.h>
class MyFrame : public wxFrame
{
private:
wxPanel *panel,*p;
wxBoxSizer *vbox,*vbox1,*hbox;
wxTextCtrl *txt;
wxScrolledWindow *sw;
wxRect rect;
int flag=0,flag1=0;
wxButton *btn;
void OnKeyDown(wxKeyEvent &event){
event.Skip();
txt=(wxTextCtrl*)event.GetEventObject();
if(event.GetKeyCode()==8){
txt->Navigate(wxNavigationKeyEvent::IsBackward);
}else if(event.GetKeyCode()==13){
if(txt->GetName()=="ROW"){
if(!txt->GetParent()->GetNextSibling()){
AddRow(0);
}else{
p=wxDynamicCast(txt->GetParent()->GetNextSibling(),wxPanel);
}
sw->GetViewStart(&flag,&flag1);
rect=p->GetRect();
flag=rect.GetY()+rect.GetHeight();
rect=sw->GetRect();
if(flag>rect.GetHeight()){
flag1++;
sw->Scroll(0,flag1);
}
}
txt->Navigate(wxNavigationKeyEvent::IsForward);
}
}
void AddRow(int ind){
p=new wxPanel(sw);
hbox=new wxBoxSizer(wxHORIZONTAL);
for(int i=0;i<9;i++){
txt=new wxTextCtrl(p,wxID_ANY,wxT(""),wxDefaultPosition,wxSize(5,25),wxTE_PROCESS_ENTER);
txt->Bind(wxEVT_KEY_DOWN,&MyFrame::OnKeyDown,this);
hbox->Add(txt,1,wxEXPAND|wxALL,5);
}
txt=new wxTextCtrl(p,1,wxString::Format(wxT("%i"),ind),wxDefaultPosition,wxSize(5,25),wxTE_PROCESS_ENTER);
txt->SetName("ROW");
txt->Bind(wxEVT_KEY_DOWN,&MyFrame::OnKeyDown,this);
hbox->Add(txt,1,wxEXPAND|wxALL,5);
p->SetSizer(hbox);
vbox1->Add(p,0,wxEXPAND);
vbox1->Layout();
sw->FitInside();
}
public:
MyFrame() : wxFrame(NULL, wxID_ANY, "Test")
{
panel=new wxPanel(this);
vbox=new wxBoxSizer(wxVERTICAL);
vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
sw=new wxScrolledWindow(panel);
sw->SetScrollRate(35,35);
vbox1=new wxBoxSizer(wxVERTICAL);
sw->SetSizer(vbox1);
sw->FitInside();
for(flag=0;flag<100;flag++){
AddRow(flag);
}
vbox->Add(sw,1,wxEXPAND|wxALL,5);
vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
panel->SetSizer(vbox);
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame())->Show(true);
return true;
}
};
IMPLEMENT_APP(MyApp);
PB wrote: ↑Fri Apr 23, 2021 4:14 pm Out of curiousity, I tried if the autoscroll works when I use wxStaticBox instead of wxPanel as the parent of wxTextCtrls, which is then added to the wxScrolledWindow. It works, so the issue does not seem to be related to whether a wxTextCtrl is a direct child of the wxScrolled, its parent being a wxPanel may be the problem.
Once again, I would ask: Do the wxTextCtrls need to have an extra panel as their parent, cannot they be added as direct children of the wxScrolled?Code: Select all
#include <wx/wx.h> #include <wx/scrolwin.h> #include <wx/statbox.h> class MyFrame : public wxFrame { public: MyFrame() : wxFrame(nullptr, wxID_ANY, "Test") { m_scrolledPanel = new wxScrolledWindow(this, wxID_ANY); m_scrolledPanelSizer = new wxBoxSizer(wxVERTICAL); for ( size_t i = 0; i < 3; ++i ) AddTextCtrls(false); Bind(wxEVT_TEXT_ENTER, &MyFrame::OnTextEnter, this); m_scrolledPanel->SetSizer(m_scrolledPanelSizer); m_scrolledPanel->FitInside(); m_scrolledPanel->SetScrollRate(8, 8); SetClientSize(FromDIP(wxSize(600, 200))); } private: wxScrolledWindow* m_scrolledPanel{nullptr}; wxBoxSizer* m_scrolledPanelSizer{nullptr}; size_t m_textGroupsCount{0}; void AddTextCtrls(bool focus) { wxStaticBoxSizer* staticBoxSizer = nullptr; wxTextCtrl* textCtrl = nullptr; staticBoxSizer = new wxStaticBoxSizer(wxHORIZONTAL, m_scrolledPanel, wxString::Format("Panel #%zu", ++m_textGroupsCount)); for ( size_t i = 0; i < 3; ++i ) { textCtrl = new wxTextCtrl(staticBoxSizer->GetStaticBox(), wxID_ANY, wxString::Format("wxTextCtrl #%zu.%zu", m_textGroupsCount, i + 1), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); staticBoxSizer->Add(textCtrl, wxSizerFlags().Expand().Border()); } m_scrolledPanelSizer->Add(staticBoxSizer, wxSizerFlags().Expand().Border()); m_scrolledPanel->FitInside(); if ( focus ) staticBoxSizer->GetStaticBox()->SetFocus(); } void OnTextEnter(wxCommandEvent& event) { wxWindow* window = dynamic_cast<wxWindow*>(event.GetEventObject()); if ( !window->GetNextSibling() && // the last control in the last !window->GetParent()->GetNextSibling() ) // control group, add a new control group { AddTextCtrls(true); } else // just go to the next control { window->Navigate(); } } }; class MyApp : public wxApp { public: bool OnInit() override { (new MyFrame())->Show(); return true; } }; wxIMPLEMENT_APP(MyApp);
This sounds like you're re-inventing a control like wxListCtrl, wxDataViewCtrl or wxGrid. Are you aware of these classes?