wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
ihamod
In need of some credit
In need of some credit
Posts: 2
Joined: Thu Feb 16, 2017 12:16 am

wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by ihamod »

Platform: MingW - MSW
Versions: 3.0.2 & 3.1.0

When a wxDatePickerCtrl is added within an ExtraControl of a wxFileDialog the invocation of the function wxDatePickerCtrl::GetValue() fails with two assertions when there is an attempt to retrieve the wxDateTime object.
1. assert "(0<day) etc." failed in Set(): Invalid date in wxDateTime::Set()"
2. assert "m_date.IsValid() == dt.IsValid() && (!dt.IsValid() || dt == m_date)" failed in GetValue(): bug in wxDateTimePickerCtrl: m_date not in sync

The same code works without a problem with GCC in Linux.

The DatePickerCtrl itself works normally if it is used e.g. in a Dialog and the wxDatePickerCtrl::GetValue() retrieves the wxDatetime. However I have two use 2 dialogs to get necessary input, since I did not manage to find a solution if it is used within an ExtraControl. Possibly a bug?
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by doublemax »

Please provide a minimal, compilable sample that shows the problem, ideally a patch to one of the wxWidgets samples.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by PB »

I have tried the minimal possible sample on Windows 7 with wxWidgets GIT master head, see below and I get
..\..\src\common\datetime.cpp(625): assert ""month < MONTHS_IN_YEAR"" failed in wxDateTime::GetNumberOfDays(): invalid month
I have no time to look into it any further atm, perhaps I did something wrong in the code.

Code: Select all

#include <wx/wx.h>
#include <wx/filedlg.h>
#include <wx/datectrl.h>

class MyExtraPanel : public wxPanel
{
public:
    MyExtraPanel(wxWindow *parent, const wxDateTime& dt)
        : wxPanel(parent)
    {    
        wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
        m_datePickerCtrl = new wxDatePickerCtrl(this, wxID_ANY, dt);
        sizer->Add(m_datePickerCtrl, wxSizerFlags(1).Border(wxALL, 5));
        SetSizerAndFit(sizer);
    }
    
    wxDateTime GetDate() const
    {
        return m_datePickerCtrl->GetValue();
    }

    static wxWindow* CreateMyExtraPanel(wxWindow *parent)
    {
        return new MyExtraPanel(parent, wxDateTime::Today());
    } 
private:   
    wxDatePickerCtrl* m_datePickerCtrl;
};    

class MyApp : public wxApp
{
public:	
    bool OnInit()
    {
        wxFileDialog fd(NULL, "Open file dialog", wxEmptyString, wxEmptyString, "All files (*.*)|*.*");        
        
        fd.SetExtraControlCreator(&MyExtraPanel::CreateMyExtraPanel);
        fd.ShowModal();
        wxLogMessage("Date picked: %s", static_cast<MyExtraPanel*>(fd.GetExtraControl())->GetDate().FormatDate());
        
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);
ihamod
In need of some credit
In need of some credit
Posts: 2
Joined: Thu Feb 16, 2017 12:16 am

Re: wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by ihamod »

The code sample given by PB is almost identical with how I use it in my code. It works if I compile it on Linux but it does not work if I compile it with MingW in Windows.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by PB »

I looked a bit more into the issue. The problem is in

Code: Select all

wxDateTime wxDatePickerCtrl::MSWGetControlValue() const
{
    wxDateTime dt;
    SYSTEMTIME st;
    if ( DateTime_GetSystemtime(GetHwnd(), &st) == GDT_VALID )
    {
        dt.SetFromMSWSysDate(st);
    }

    return dt;
}
For some reason the DateTime_GetSystemtime() macro returns GDT_VALID yet the st variable is not filled in and is therefore invalid. Must be something related to wxFileDialog because the pretty much identical code for wxDialog works as expected. I have noticed that when using the panel as the extra control for the file dialog, the panel is always created twice, with a different parent and the second instance is actually used?

Anyway, looks like a bug to me but I have no idea how to fix it. Perhaps creating a ticket on wxTrac may be a good idea?

Code: Select all

#include <wx/wx.h>
#include <wx/filedlg.h>
#include <wx/datectrl.h>

class MyExtraPanel : public wxPanel
{
public:
    MyExtraPanel(wxWindow *parent, const wxDateTime& dt)
        : wxPanel(parent)
    {   
        wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
        m_datePickerCtrl = new wxDatePickerCtrl(this, wxID_ANY, dt);
        sizer->Add(m_datePickerCtrl, wxSizerFlags(1).Border(wxALL, 5));
        SetSizerAndFit(sizer);
        wxLogMessage("MyExtraPanel (%p) created for parent %p.", this, parent);
    }    
    
    wxDateTime GetDate() const
    {
        return m_datePickerCtrl->GetValue();
    }

    static wxWindow* CreateMyExtraPanel(wxWindow *parent)
    {
        wxDateTime dt(25, wxDateTime::Jun, 2000);        
        return new MyExtraPanel(parent, dt);
    }
private:   
    wxDatePickerCtrl* m_datePickerCtrl;
};   


class MyApp : public wxApp
{
public:   
    bool OnInit()
    {
/*
        wxDialog dlg(NULL, wxID_ANY, "Date dialog");
        MyExtraPanel* ep = static_cast<MyExtraPanel*>(MyExtraPanel::CreateMyExtraPanel(&dlg));
        dlg.ShowModal();
        wxLogMessage("Date from wxDialog (panel %p): %s", ep, ep->GetDate().FormatISODate());
*/        
        wxFileDialog fd(NULL, "Open file with date dialog", wxEmptyString, wxEmptyString, "All files (*.*)|*.*");              
        fd.SetExtraControlCreator(&MyExtraPanel::CreateMyExtraPanel);
        fd.ShowModal();
        wxLogMessage("Date from wxFileDialog (panel %p): %s", 
            fd.GetExtraControl(), static_cast<MyExtraPanel*>(fd.GetExtraControl())->GetDate().FormatISODate());
       
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by doublemax »

I traced through that too, and in think that GetHwnd() returns an invalid handle when it reaches that code. wxFileDialog is a wrapper around the native dialog. My theory is that the native dialog is already destroyed at that time and with it the extra panel. So from Windows point of view that window is already destroyed, just not from wxWidgets point of view. It is strange that the function returns GDT_VALID though.

The workaround would be that you can't rely on the lifetime of the controls in the extra panel, you need to keep track of their values while the panel is still alive, e.g. with wxEVT_UPDATE_UI events and store it in a separate variable.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxDatePickerCtrl problem within an ExtraControl of a wxFileDialog | MingW - MSW platform |wx-3.0.2 / 3.1.0

Post by PB »

doublemax wrote:My theory is that the native dialog is already destroyed at that time and with it the extra panel.
You are obviously correct, I was being stupid. From wxWidgets point of view, there is no dialog. The native file dialog is displayed with GetOpenFileName() function deep inside wxFileDialog::ShowModal() and therefore destroyed long time before I tried to access its child.

Perhaps this could be better documented, as someone who is not familiar with the underlying implementation may not be aware how it works.
Post Reply