keyboard/focus handling improved a bit more:

1. wxFrame doesn't give focus to anything at all on activation
2. last control restored more often (some problems still persist)
3. buttons process enter
4. text controls with wxTE_PROCESS_TAB still leave TAB work as dialog
   navigation key if the event wasn't processed


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2842 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-06-20 21:51:15 +00:00
parent 7c54578678
commit 319fefa910
6 changed files with 67 additions and 34 deletions

View File

@@ -79,15 +79,15 @@ public:
void OnFocus(wxFocusEvent& event); void OnFocus(wxFocusEvent& event);
// called by wxWindow whenever it gets focus // called by wxWindow whenever it gets focus
void SetLastFocus(long focus) { m_lastFocus = focus; } void SetLastFocus(wxWindow *win) { m_winLastFocused = win; }
long GetLastFocus() const { return m_lastFocus; } wxWindow *GetLastFocus() const { return m_winLastFocused; }
protected: protected:
// common part of all ctors // common part of all ctors
void Init(); void Init();
// the child which had the focus last time this panel was activated // the child which had the focus last time this panel was activated
long m_lastFocus; wxWindow *m_winLastFocused;
// a default button or NULL // a default button or NULL
wxButton *m_btnDefault; wxButton *m_btnDefault;

View File

@@ -191,6 +191,16 @@ wxWindowBase::~wxWindowBase()
wxASSERT_MSG( GetChildren().GetCount() == 0, _T("children not destroyed") ); wxASSERT_MSG( GetChildren().GetCount() == 0, _T("children not destroyed") );
// make sure that there are no dangling pointers left pointing to us
wxPanel *panel = wxDynamicCast(GetParent(), wxPanel);
if ( panel )
{
if ( panel->GetLastFocus() == this )
{
panel->SetLastFocus((wxWindow *)NULL);
}
}
#if wxUSE_CARET #if wxUSE_CARET
if ( m_caret ) if ( m_caret )
delete m_caret; delete m_caret;

View File

@@ -42,7 +42,7 @@ END_EVENT_TABLE()
void wxPanel::Init() void wxPanel::Init()
{ {
m_lastFocus = 0; m_winLastFocused = (wxWindow *)NULL;
m_btnDefault = (wxButton *)NULL; m_btnDefault = (wxButton *)NULL;
} }
@@ -144,11 +144,13 @@ void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event )
void wxPanel::OnFocus(wxFocusEvent& event) void wxPanel::OnFocus(wxFocusEvent& event)
{ {
if (m_lastFocus != 0) if ( m_winLastFocused )
{ {
wxWindow* child = FindWindow(m_lastFocus); // it might happen that the window got reparented...
if (child) if ( m_winLastFocused->GetParent() != this )
child->SetFocus(); m_winLastFocused = (wxWindow *)NULL;
else
m_winLastFocused->SetFocus();
} }
else else
event.Skip(); event.Skip();

View File

@@ -86,9 +86,6 @@ bool wxFrame::Create(wxWindow *parent,
m_hwndToolTip = 0; m_hwndToolTip = 0;
#endif #endif
if (!parent)
wxTopLevelWindows.Append(this);
SetName(name); SetName(name);
m_windowStyle = style; m_windowStyle = style;
m_frameMenuBar = NULL; m_frameMenuBar = NULL;
@@ -119,6 +116,9 @@ bool wxFrame::Create(wxWindow *parent,
if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0) if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0)
parent = NULL; parent = NULL;
if (!parent)
wxTopLevelWindows.Append(this);
MSWCreate(m_windowId, parent, wxFrameClassName, this, title, MSWCreate(m_windowId, parent, wxFrameClassName, this, title,
x, y, width, height, style); x, y, width, height, style);
@@ -609,17 +609,29 @@ void wxFrame::OnSize(wxSizeEvent& event)
// subwindow found. // subwindow found.
void wxFrame::OnActivate(wxActivateEvent& event) void wxFrame::OnActivate(wxActivateEvent& event)
{ {
for(wxNode *node = GetChildren().First(); node; node = node->Next()) for ( wxWindowList::Node *node = GetChildren().GetFirst();
{ node;
// Find a child that's a subwindow, but not a dialog box. node = node->GetNext() )
wxWindow *child = (wxWindow *)node->Data();
if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
!child->IsKindOf(CLASSINFO(wxDialog)))
{ {
child->SetFocus(); // FIXME all this is totally bogus - we need to do the same as wxPanel,
return; // but how to do it without duplicating the code?
// restore focus
wxWindow *child = node->GetData();
if ( !child->IsTopLevel()
#if wxUSE_TOOLBAR
&& !wxDynamicCast(child, wxToolBar)
#endif // wxUSE_TOOLBAR
#if wxUSE_STATUSBAR
&& !wxDynamicCast(child, wxStatusBar)
#endif // wxUSE_STATUSBAR
)
{
child->SetFocus();
return;
}
} }
}
} }
// The default implementation for the close window event. // The default implementation for the close window event.

View File

@@ -1107,13 +1107,13 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
break; break;
case WXK_TAB: case WXK_TAB:
// only produce navigation event if we don't process TAB ourself or // always produce navigation event - even if we process TAB
// if it's a Shift-Tab keypress (we assume nobody will ever need // ourselves the fact that we got here means that the user code
// this key combo for himself) // decided to skip processing of this TAB - probably to let it
// do its default job.
// //
// NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
// handled by Windows // handled by Windows
if ( event.ShiftDown() || !(m_windowStyle & wxTE_PROCESS_TAB) )
{ {
wxNavigationKeyEvent eventNav; wxNavigationKeyEvent eventNav;
eventNav.SetDirection(!event.ShiftDown()); eventNav.SetDirection(!event.ShiftDown());

View File

@@ -246,6 +246,11 @@ void wxWindow::Init()
// wxWnd // wxWnd
m_hMenu = 0; m_hMenu = 0;
m_hWnd = 0;
// pass WM_GETDLGCODE to DefWindowProc()
m_lDlgCode = 0;
m_xThumbSize = 0; m_xThumbSize = 0;
m_yThumbSize = 0; m_yThumbSize = 0;
m_backgroundTransparent = FALSE; m_backgroundTransparent = FALSE;
@@ -325,11 +330,6 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
DLGC_WANTTAB | DLGC_WANTMESSAGE; DLGC_WANTTAB | DLGC_WANTMESSAGE;
} }
else
{
// default behaviour
m_lDlgCode = 0;
}
MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL, MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL,
pos.x, pos.y, pos.x, pos.y,
@@ -1382,6 +1382,7 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg)
if ( bProcess ) if ( bProcess )
{ {
bool bCtrlDown = (::GetKeyState(VK_CONTROL) & 0x100) != 0; bool bCtrlDown = (::GetKeyState(VK_CONTROL) & 0x100) != 0;
bool bShiftDown = (::GetKeyState(VK_SHIFT) & 0x100) != 0;
// WM_GETDLGCODE: ask the control if it wants the key for itself, // WM_GETDLGCODE: ask the control if it wants the key for itself,
// don't process it if it's the case (except for Ctrl-Tab/Enter // don't process it if it's the case (except for Ctrl-Tab/Enter
@@ -1398,13 +1399,16 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg)
switch ( msg->wParam ) switch ( msg->wParam )
{ {
case VK_TAB: case VK_TAB:
if ( lDlgCode & DLGC_WANTTAB ) { // assume that nobody wants Shift-TAB for himself - if we
// don't do it there is no easy way for a control to grab
// TABs but still let Shift-TAB work as navugation key
if ( (lDlgCode & DLGC_WANTTAB) && !bShiftDown ) {
bProcess = FALSE; bProcess = FALSE;
} }
else { else {
// Ctrl-Tab cycles thru notebook pages // Ctrl-Tab cycles thru notebook pages
bWindowChange = bCtrlDown; bWindowChange = bCtrlDown;
bForward = !(::GetKeyState(VK_SHIFT) & 0x100); bForward = !bShiftDown;
} }
break; break;
@@ -1431,6 +1435,11 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg)
// it // it
return FALSE; return FALSE;
} }
else if ( lDlgCode & DLGC_BUTTON )
{
// buttons want process Enter themselevs
bProcess = FALSE;
}
// else: but if it does not it makes sense to make it // else: but if it does not it makes sense to make it
// work like a TAB - and that's what we do. // work like a TAB - and that's what we do.
// Note that Ctrl-Enter always works this way. // Note that Ctrl-Enter always works this way.
@@ -2318,10 +2327,10 @@ bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd))
#endif // wxUSE_CARET #endif // wxUSE_CARET
// panel wants to track the window which was the last to have focus in it // panel wants to track the window which was the last to have focus in it
wxWindow *parent = GetParent(); wxPanel *panel = wxDynamicCast(GetParent(), wxPanel);
if ( parent && parent->IsKindOf(CLASSINFO(wxPanel)) ) if ( panel )
{ {
((wxPanel *)parent)->SetLastFocus(GetId()); panel->SetLastFocus(this);
} }
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId); wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);