Serialize CDateTimeCtrl state impossible? |
Post Reply |
Author | |
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
Posted: 15 April 2009 at 4:03am |
If you create a CDateTimeCtrl with the DTS_SHOWNONE style, the control will have a checkbox where you can choose "no time". This check can be checked using SetTime(&stValidTime) and unchecked with SetTime(NULL). When you click it manually, the time value is not changed even though the check is not toggled. When doing this programmatically with SetTime() the time is reset (NULL = no time).This yields a problem when serializing the state of the control from a given source (like the Registry).
Q: How do you set a valid time AND uncheck the control programmatically?
|
|
PokerMemento - http://www.pokermemento.com/
|
|
ABuenger
Newbie Joined: 02 February 2006 Status: Offline Points: 1075 |
Post Options
Thanks(0)
|
Haven't used CDateTimeCtrl before, but why aren't you using the XTP control?
(If they don't have a drop in replacement put it on the wish list) |
|
Codejock support
|
|
Oleg
Admin Group Joined: 21 May 2003 Location: United States Status: Offline Points: 11234 |
Post Options
Thanks(0)
|
Hello,
Yes, I saw same issue, but seems CDateTimeCtrl doesn't have method to make this :(
|
|
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
I believe it can be done by simulating a click...
|
|
PokerMemento - http://www.pokermemento.com/
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
There must be a way! This is so annoying... No ideas?
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
CDateTimeCtrl m_DateTimeCtrl;
CRect rect(20, 20, 250, 45);
m_DateTimeCtrl.Create(WS_VISIBLE | WS_CHILD | WS_TABSTOP | DTS_SHOWNONE | DTS_SHORTDATEFORMAT, rect, this, 1005); m_DateTimeCtrl.SetFormat(_T("ddd, MMM d, yyyy - HH:mm:ss")); //Now uncheck it - I always use such thing for datetime fields where app ALLOWS user to keep it not filled
//and if it unchecked - ignore it for store
::SendMessage(m_DateTimeCtrl.GetSafeHwnd(), (UINT) DTM_SETSYSTEMTIME, (WPARAM) (DWORD) GDT_NONE, (LPARAM) NULL);
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Thanks for your reply.
Now, try this:
1) Date should equal 17 january 1982 (not today's date, that is).
2) Checkbox should be unchecked.
This state is possible to achieve when the user clicks the control, but (afaik) impossible to accomplish programmatically.
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
I'm impressed!
Thanks a lot! :)
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
As you know CDateTimeCtrl not allow to retrieve datetime value (visible on display) if unchecked.
This is simple code to programmatically change mode without user click - after you can get value - and uncheck CDateTimeCtrl control back.
LPARAM lparam = MAKELPARAM(10, 15);
m_DateTimeCtrl.SendMessage(WM_LBUTTONDOWN, NULL, lparam);
//Of course 10 (y) and 15 (x) is coordinates for standard case - normal font. Need to adjust for some custom setup like large font
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Yeah, but in your previous post, you used GDT_NONE instead of simulating a click?
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
This is not about GDT_NONE - it's about opposite - how to porgrammatically set to VALID state and get internal Value - like GetTime
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
No, this can't be done!
The problem lies in CDateTimeCtrl::GetTime(). When the control is unchecked, the time cannot be read! This means the time cannot be stored, hence not serialized (yes, deserialization is possible). You would have to capture all date changes and store the date on your own...
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
Control will not answer you on your call but still keep previously set value on it's display. I demonstarted how to get it back!
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Sorry, missed that post. But still, the solution is quite ugly (not to mention that the coordinate of the checkbox cannot be safely determined).
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
If somebody ask a question: "How do you set a valid time AND uncheck the control programmatically?" and recive positive answer - last he can do in his comment - use term ugly or talk about safe way!?
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Sorry, didn't mean it that way :(
The problem is not your solution. The problem is that Microsoft implemented the control this way.
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
OK.
This is a simple way to bypass "the coordinate of the checkbox cannot be safely determined"
for (int i = 0; i < 30; i++)
{ //LPARAM lparam = MAKELPARAM(10, 15);LPARAM lparam = MAKELPARAM(i, 15); m_DateTimeCtrl.SendMessage(WM_LBUTTONDOWN, NULL, lparam); COleDateTime dt; m_DateTimeCtrl.GetTime(dt); if (dt.GetStatus() == COleDateTime::valid){ CString s; s.Format(_T( "Valid with i =%d"), i);AfxMessageBox(s); break;} } i = 0 - bad, 1 - good |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Thanks for your hints.
Though, I believe this is the best solution:
BOOL CDateTimeCtrlEx::OnDateTimeChanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);
m_lastDate = pDTChange->st;
*pResult = 0; return FALSE; // Let the parent handle the message as well!
}
"m_lastDate" will always contain the latest selection, no matter if the checkbox was checked or not. Though, just in case, I only use this variable if GetTime() fails (which it does when unchecked). One must also be careful with calls to SetTime() since it cannot be overloaded. |
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
No - this is not true - in the moment user uncheck control - m_lastDate will have invalid data. Proper syntax for notification - void - you can use *pResult to pass TRUE or FALSE)
|
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Disagree.
If you use ON_NOTIFY_REFLECT_EX() in your message map, your message handler may or may not allow the parent window to handle the message. If the handler returns FALSE, the message will be handled by the parent as well, while a call that returns TRUE does not allow the parent to handle it.
And
If you want more than one object in the notification routing to handle a message, you can use ON_NOTIFY_EX (or ON_NOTIFY_EX_RANGE) rather than ON_NOTIFY (or ON_NOTIFY_RANGE).
If the user unchecks the control, m_lastDate is assigned a valid date. Just verified this.
|
|
PokerMemento - http://www.pokermemento.com/
|
|
mdoubson
Senior Member Joined: 17 November 2008 Status: Offline Points: 1705 |
Post Options
Thanks(0)
|
Sure I did before posting:
void CMFC_DATEDlg::OnDateTimeChanged(NMHDR *pNMHDR, LRESULT *pResult){LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);m_lastDate = pDTChange->st; SetWindowText(m_lastDate.Format()); *pResult = 0; } |
|
znakeeye
Senior Member Joined: 26 July 2006 Status: Offline Points: 1672 |
Post Options
Thanks(0)
|
Strange. Anyway, you don't have to assign it if it is invalid.
if ((pDTChange->dwFlags == GDT_VALID)
m_lastDate = pDTChange->st;
Strange indeed, since my date value is not changed when debugging during "unchecking"...
|
|
PokerMemento - http://www.pokermemento.com/
|
|
Post Reply | |
Tweet
|
Forum Jump | Forum Permissions You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |