wxTimePickerCtrl Format

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
Rob'
Experienced Solver
Experienced Solver
Posts: 53
Joined: Mon Dec 08, 2008 10:10 pm

wxTimePickerCtrl Format

Post by Rob' » Sat Feb 08, 2020 5:19 pm

Is it possible the change the format of wxTimePickerCtrl? I would like to suppress the seconds.

Thanks in advance.
Rob'

Martin Silenus
Earned a small fee
Earned a small fee
Posts: 14
Joined: Tue Nov 05, 2019 8:33 pm

Re: wxTimePickerCtrl Format

Post by Martin Silenus » Sun Feb 09, 2020 12:16 pm

I have been struggling with wxDatePickerCtrl and wxTimePickerCtrl a bit myself too.

Both have a data exchange format using wxDateTime, however
- in case of wxDatePickerCtrl, the time part is "ignored"
- in case of wxTimePickerCtrl, the date part is "ignored"
however the "unused" parts are still there since it is inherently linked to the time model underlying wxDateTime.

The only way I found to correctly suppress the unused parts is to manually copy the useful parts, e.g. (in simplified code)

Code: Select all

// from my GUI, interfacing with wxDatePickerCtrl
void MessageDialog::OnDatePickerFilterTimeFromChange(wxDateEvent& event)
{
    MessageRetriever->SetStartDate(event.GetDate());
}

// in my object code 
void MessageRetriever::SetStartDate(wxDateTime NewStartDate) // only date portion is used
{
    StartDateTime.SetYear(NewStartDate.GetYear());
    StartDateTime.SetMonth(NewStartDate.GetMonth());
    StartDateTime.SetDay(NewStartDate.GetDay());
}
or similarly for time

Code: Select all

void MessageDialog::OnTimePickerFilterTimeFromChange(wxDateEvent& event)
{
    MessageRetriever->SetStartTime(event.GetDate());
}

void MessageRetriever::SetStartTime(wxDateTime NewStartTime) // only time portion is used
{
    StartDateTime.SetHour(NewStartTime.GetHour());
    StartDateTime.SetMinute(NewStartTime.GetMinute());
    StartDateTime.SetSecond(NewStartTime.GetSecond());
}
Note that in my application, StartDateTime is still a wxDateTime element which uses both date and time components. It is however the GUI interface that is split up in two widgets, one for date and another for time.

Hope it helps with your problem

Rob'
Experienced Solver
Experienced Solver
Posts: 53
Joined: Mon Dec 08, 2008 10:10 pm

Re: wxTimePickerCtrl Format

Post by Rob' » Mon Feb 10, 2020 7:16 pm

Thank you for your reply. But it does not cover my problem. What I want to accomplish is the user should not see the seconds in the input field and it also shouldn't be necessary to enter a complete time with hours, minutes and seconds. I'm looking for something similar to a format string that I can pass to the control, i.e. "HH:mm". Any ideas?

Rob'

User avatar
doublemax
Moderator
Moderator
Posts: 14793
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxTimePickerCtrl Format

Post by doublemax » Mon Feb 10, 2020 8:06 pm

I don't see an easy way to do this. I think your best chance is to copy the code of the generic implementation of wxTimePickerCtrl and modify it. It's in <wxdir>/src/generic/timectrlg.cpp
Use the source, Luke!

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2388
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxTimePickerCtrl Format

Post by PB » Mon Feb 10, 2020 8:07 pm

The MSW native control wxTimePickerCtrl wraps should be capable of that but I have no idea about other OSes.

EDIT
FWIW, it seems to work just fine on MSW (in a real app the time format string must be built for the user locale) but obviously if one needs to use the app outside of Windows, it is not of much use.
custom_timepicker.png
custom_timepicker.png (2.83 KiB) Viewed 259 times

Code: Select all

#include <wx/wx.h>
#include <wx/timectrl.h>

#ifdef __WXMSW__
    #include <wx/msw/wrapcctl.h>
#endif

class MyDialog : public wxDialog
{
public:
    MyDialog() : wxDialog(nullptr, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
                
        wxTimePickerCtrl* timePickerDefault = new wxTimePickerCtrl(this, wxID_ANY);
        mainSizer->Add(timePickerDefault, wxSizerFlags().Border());

        wxTimePickerCtrl* timePickerCustom = new wxTimePickerCtrl(this, wxID_ANY);
#ifdef __WXMSW__
        //::SendMessageW(timePickerCustom->GetHWND(), DTM_SETFORMAT, 0, LPARAM(L"h:m"));
        DateTime_SetFormat(timePickerCustom->GetHWND(), L"h:m");
#endif
        mainSizer->Add(timePickerCustom, wxSizerFlags().Border());
        
        mainSizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Expand().Border());

        SetSizerAndFit(mainSizer);
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        MyDialog().ShowModal();
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);

sw
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Mar 16, 2019 8:09 pm

Re: wxTimePickerCtrl Format

Post by sw » Tue Feb 11, 2020 11:16 am

Another potential idea is that you could hook into the kill focus event of a control and always set the seconds component to '00'.

I had a similar scenario to yours wherein I did not want to allow a user to enter seconds. I eventually just opted to set the seconds to whenever a user clicks out of the control.

Code: Select all

// binding
myTimeCtrl->Bind(
    wxEVT_KILL_FOCUS,
    &MyDialog::OnTimeFocusLost,
    this
);

void MyDialog::OnTimeFocusLost(wxFocusEvent& event)
{
    wxDateTime secondsInitializedToZero = wxDateTime::Now();
    secondsInitializedToZero.SetSecond(0);
    myTimeCtrl->SetValue(secondsInitializedToZero);
    
    event.Skip();
}

Rob'
Experienced Solver
Experienced Solver
Posts: 53
Joined: Mon Dec 08, 2008 10:10 pm

Re: wxTimePickerCtrl Format

Post by Rob' » Fri Feb 14, 2020 9:47 am

Thanks to all! I'm going to try PB's approach.

Rob'

Post Reply