How to receive paint events in wxDialog Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
cecilio
I live to help wx-kind
I live to help wx-kind
Posts: 189
Joined: Fri Dec 03, 2004 8:44 am
Location: spain
Contact:

How to receive paint events in wxDialog

Post by cecilio »

My app displays a modal dialog. The dialog has only a sizer and two controls. I've defined a handler method for paint events and added the EVT_PAINT entry to the events table, but my handler method is only invoked when the ShowModal() method is invoked or if I minimize and maximize my app. Other actions, such as moving another application window over the dialog window, even hiding it totally, never triggers a paint event (or my handler is not invoked). What should I do to receive paint events when the dialog window is exposed?

Working on Linux, with wxWidgest 2.8.12

Thank you,
Cecilio
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to receive paint events in wxDialog

Post by doublemax »

Do you have a wxPanel as background for the controls? Then you have to catch the paint event for that panel, not the dialog.

If that's not it, please show some code.
Use the source, Luke!
cecilio
I live to help wx-kind
I live to help wx-kind
Posts: 189
Joined: Fri Dec 03, 2004 8:44 am
Location: spain
Contact:

Re: How to receive paint events in wxDialog

Post by cecilio »

Thanks doublemax. The dialog has a sizer and two controls on it: an static text and a gauge. This is the code:

Code: Select all


const long k_id_timer = wxNewId();

//---------------------------------------------------------------------------------------
class HelpDlg : public wxDialog
{
protected:
    wxStaticText* m_pMsg;
    wxGauge* m_pGauge;
    wxTimer m_timer;
    int m_numPaints;

public:
	HelpDlg(wxWindow* pParent = NULL);
	~HelpDlg();

    void create_controls();

    // event handlers
    void on_focus_lost(wxFocusEvent& WXUNUSED(event));
    void on_timer_event(wxTimerEvent& WXUNUSED(event));
    void on_paint(wxPaintEvent& WXUNUSED(event));

protected:
    DECLARE_EVENT_TABLE()
};

//=======================================================================================
// HelpDlg implementation
//=======================================================================================

BEGIN_EVENT_TABLE(HelpDlg, wxDialog)
    EVT_TIMER       (k_id_timer, HelpDlg::on_timer_event)
    EVT_KILL_FOCUS  (HelpDlg::on_focus_lost)
    EVT_PAINT       (HelpDlg::on_paint)
END_EVENT_TABLE()


//---------------------------------------------------------------------------------------
HelpDlg::HelpDlg(wxWindow* pParent)
    : wxDialog(pParent, wxID_ANY, _("Help system"),
               wxDefaultPosition, wxSize(400,150),
               wxDEFAULT_DIALOG_STYLE)
    , m_timer(this, k_id_timer)
    , m_numPaints(0)
{
    create_controls();
    m_pGauge->SetRange(100);
    m_pGauge->SetValue(0);
    CentreOnScreen();
    m_timer.Start(200, wxTIMER_CONTINUOUS);     //200ms
}

//---------------------------------------------------------------------------------------
HelpDlg::~HelpDlg()
{
    m_timer.Stop();
}

//---------------------------------------------------------------------------------------
void HelpDlg::create_controls()
{
	this->SetSizeHints( wxDefaultSize, wxDefaultSize );

	wxBoxSizer* pMainSizer;
	pMainSizer = new wxBoxSizer( wxVERTICAL );

	pMainSizer->Add( 0, 0, 1, wxEXPAND, 5 );

	m_pMsg = new wxStaticText( this, wxID_ANY, _("Opening Internet browser. Please wait ..."), wxDefaultPosition, wxDefaultSize, 0 );
	m_pMsg->Wrap( -1 );
	pMainSizer->Add( m_pMsg, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );

	m_pGauge = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL );
	pMainSizer->Add( m_pGauge, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );


	pMainSizer->Add( 0, 0, 1, wxEXPAND, 5 );

	this->SetSizer( pMainSizer );
	this->Layout();
}

//---------------------------------------------------------------------------------------
void HelpDlg::on_timer_event(wxTimerEvent& WXUNUSED(event))
{
    int value = m_pGauge->GetValue();
    m_pGauge->SetValue( value == 100 ? 0 : value + 2 );
}

//---------------------------------------------------------------------------------------
void HelpDlg::on_focus_lost(wxFocusEvent& WXUNUSED(event))
{
   EndModal(wxID_CANCEL);
}

//---------------------------------------------------------------------------------------
void HelpDlg::on_paint(wxPaintEvent& event)
{
    wxPaintDC dc(this);
    m_numPaints++;
    event.Skip(true);
}

I'm using an wxExtHelpController to display help in a browser. But as it takes some time since the user clicks on 'Help' button until the browser opens, I'm trying to create a pop-up window (this dialog) witha gauge to somehow inform the user that something is going on. My idea is to remove this dialog as soon as I detect that the browser has opened. For this, I tried to use the kill focus event (rationale: if the browser gets the focus, this dialog should lose it, but this doesn't work) and now I'm exploring the paint event: the browser will hide this dialog, therefore as soon as the user returns to the application the dialog will receive a paint event and I will detect this and close the dialog. Any ideas about why it is not receiving paint events? Any other ideas for closing the dialog?

Thank you,
Cecilio
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to receive paint events in wxDialog

Post by doublemax »

I'm not sure why you don't receive any paint event in that case. If you receive a paint event when you resize the window, the code should be correct. Maybe the OS buffered the content, because it could not have changed.

But in any case the whole thing seems a bit "hackish" to me. Is it really necessary to display some kind of busy information? Even if it takes 1-2 seconds until the browser opens, the user will be surprised only when it happens at the first time (if ever).

If you really want to pursue this, try catching wxActivateEvent, it should be triggered when a toplevel window becomes active/inactive.
Use the source, Luke!
cecilio
I live to help wx-kind
I live to help wx-kind
Posts: 189
Joined: Fri Dec 03, 2004 8:44 am
Location: spain
Contact:

Re: How to receive paint events in wxDialog

Post by cecilio »

Yes, I receive paint events but only the first one or when the app is minimized and then maximized. The dialog is not resizable. I do not understand why it doesn't receive paint events after another window moves over the dialog. But, nevertheless, I will look for other solutions, as your suggesstion of catching wxActivateEvent. Thanks for this idea! Others are also welcomed :wink:

And, yes, the whole thing is a bit "hackish", but I think it is necessary as it is not 1-2 seconds but 6-8 secs. Of course depends on the machine, the workload, and if the browser is already running or not. In my machine with the browser closed, times go from 2 secs to 8 secs. If it were only 1-2 secs I will agree with you and do nothing, but as I have experienced longer delays I would prefer to ensure that the user gets any feedback.

Thank you,
Cecilio
Post Reply