When can you trust a window size?

Volker Bartheld dr_versaeg at freenet.de
Wed Nov 15 08:25:23 PST 2006


Hi Troels!

> >I usually use EVT_IDLE handler if I need to do something "soon after"
> >window is shown on screen.
>Below is shown a fancy method to handle the "soon after" situation in a 
>fairly clean way.
>(http://wxforum.shadonet.com/viewtopic.php?p=49422#49422)

Actually this is a totally cool thing to do and it casually helped me
solve - or at least dramatically reduce - the "stolen focus issue"
(check out Message-ID: <4rro90Fse3o8U1 at mid.individual.net> for more
info) I mentioned in the other thread.

As it seems, neither overriding wxWindow::AcceptsFocus() nor
catching/handling wxActivateEvent and returning wxEvent::Skip(true) or
giving back the focus with
FindWindow(wxActivateEvent::GetID())->SetFocus() did the trick.

On wxMac and wxLin, I couldn't reproduce this behaviour, so a Win32-only
solution was acceptable. I decided to remember the HWND of the current
foreground window via the native ::GetForegroundWindow() function in the
c'tor and then resetting the foreground window to the current state in
the OnIdleOnce() handler via ::SetForegroundWindow(). Anyway and whoever
is interested, I'm posting the code snippet at the bottom of this reply.

But I still have a question: Why do you create a new event type plus
handler for it and push this into the wxWindow's list event handlers?
Wouldn't it be good enough to

DECLARE_EVENT_TYPE(wxEVT_IDLEONCE, -1)
DEFINE_EVENT_TYPE(wxEVT_IDLEONCE)

, and then just add it in the c'tor

    wxCommandEvent e(wxEVT_IDLEONCE, GetId());
    AddPendingEvent(e);

and grab it via

EVT_COMMAND(wxID_ANY, wxEVT_IDLEONCE, MyFrame::OnIdleOnce)

? OK, anybody could post this event an make the handler fire false
positive - is it that what you wanted to avoid?

Thanks a lot for your hints,

Volker


<nofocus_frame.cpp>
 #define EVT_IDLE_ONCE(func) wx__DECLARE_EVT0(wxEVT_IDLE_ONCE, wxIdleEventHandler(func))
 static wxEventType wxEVT_IDLE_ONCE=wxNewEventType();
 class wxIdleOnceEvtHandler : public wxEvtHandler
 {
 public:
   bool m_fired;
   wxEvtHandler* m_target;
   wxIdleOnceEvtHandler(wxEvtHandler* target) : m_target(target), wxEvtHandler(), m_fired(false) {}
   virtual bool wxIdleOnceEvtHandler::ProcessEvent(wxEvent& event)
   {
     if((event.GetEventType()==wxEVT_IDLE) && !m_fired)
     {
       m_fired=true;
       wxIdleEvent& idle=(wxIdleEvent&)event;
       wxIdleEvent temp(idle);
       temp.SetEventType(wxEVT_IDLE_ONCE);
       wxPostEvent(m_target, temp);
     }
     return wxEvtHandler::ProcessEvent(event);
   }
 };
 
 class CMyDialog : public wxFrame
 {
   DECLARE_DYNAMIC_CLASS(CMyDialog)
 public:
   CMyDialog::CMyDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize, long style=wxSIMPLE_BORDER|wxSTAY_ON_TOP|wxFRAME_NO_TASKBAR|wxSUNKEN_BORDER, const wxString& name=wxT("dialogBox"))
     : wxFrame(parent, id, title, pos, size, style, name), m_idleonce(NULL), m_hWndFocus(NULL)
   {
     m_idleonce=new wxIdleOnceEvtHandler(this);
     PushEventHandler(m_idleonce);
     
     SetSizer(new wxBoxSizer(wxVERTICAL));
     wxBoxSizer* pTextSizer=new wxBoxSizer(wxHORIZONTAL);
     pTextSizer->Add(new wxTextCtrl(this, wxID_ANY, wxT("Text here...")), 0, wxALL, 4);
     pTextSizer->AddStretchSpacer();
     pTextSizer->Add(new wxButton(this, ID_OK, wxT("OK")), 0, wxALL, 4);
     GetSizer()->Add(pTextSizer, 1, wxEXPAND | wxALL, 4);
     Fit();
     CenterOnScreen();
     m_hWndFocus=::GetForegroundWindow();
     Show();
   }
   CMyDialog::~CMyDialog()
   {
     RemoveEventHandler(m_idleonce);
     delete m_idleonce;
   }
   void CMyDialog::OnOK(wxCommandEvent& event)
   {
     wxCommandEvent e(wxEVT_END_DIALOG, GetId());
     GetParent()->AddPendingEvent(e);
     Destroy();
   }
   void CMyDialog::OnIdleOnce(wxIdleEvent&) { ::SetForegroundWindow(m_hWndFocus); }
 private:
   DECLARE_EVENT_TABLE()
   CMyDialog::CMyDialog() {}
   wxIdleOnceEvtHandler* m_idleonce;
   HWND m_hWndFocus;
 };
 IMPLEMENT_DYNAMIC_CLASS(CMyDialog, wxFrame)
 BEGIN_EVENT_TABLE(CMyDialog, wxFrame)
 EVT_BUTTON(ID_OK, CMyDialog::OnOK)
 EVT_BUTTON(ID_CANCEL, CMyDialog::OnOK)
 EVT_IDLE_ONCE(CMyDialog::OnIdleOnce)
 END_EVENT_TABLE()
</nofocus_frame.cpp>

__
Mail replies to/an V B A R T H E L D at G M X dot D E






More information about the wx-users mailing list