Codejock Forums Homepage
Forum Home Forum Home > Codejock Products > Visual C++ MFC > General Discussion
  New Posts New Posts RSS Feed - Serialize CDateTimeCtrl state impossible?
  FAQ FAQ  Forum Search   Events   Register Register  Login Login

Serialize CDateTimeCtrl state impossible?

 Post Reply Post Reply
Author
Message
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Topic: Serialize CDateTimeCtrl state impossible?
    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/
Back to Top
ABuenger View Drop Down
Newbie
Newbie
Avatar

Joined: 02 February 2006
Status: Offline
Points: 1075
Post Options Post Options   Thanks (0) Thanks(0)   Quote ABuenger Quote  Post ReplyReply Direct Link To This Post Posted: 15 April 2009 at 6:25am
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
Back to Top
Oleg View Drop Down
Admin Group
Admin Group


Joined: 21 May 2003
Location: United States
Status: Offline
Points: 11234
Post Options Post Options   Thanks (0) Thanks(0)   Quote Oleg Quote  Post ReplyReply Direct Link To This Post Posted: 15 April 2009 at 8:25am
Hello,
 
Yes, I saw same issue, but seems CDateTimeCtrl  doesn't have method to make this :(
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 15 April 2009 at 4:25pm
I believe it can be done by simulating a click...
PokerMemento - http://www.pokermemento.com/
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 01 July 2009 at 3:34am
There must be a way! This is so annoying... No ideas?
PokerMemento - http://www.pokermemento.com/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 01 July 2009 at 11:41pm
 
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);
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 04 July 2009 at 7:25pm
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/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 04 July 2009 at 7:40pm
 
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 05 July 2009 at 6:26am
I'm impressed!
 
Thanks a lot! :)
PokerMemento - http://www.pokermemento.com/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 06 July 2009 at 10:42am
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
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 07 July 2009 at 3:06am
Yeah, but in your previous post, you used GDT_NONE instead of simulating a click?
PokerMemento - http://www.pokermemento.com/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 07 July 2009 at 7:56am
This is not about GDT_NONE - it's about opposite - how to porgrammatically set to VALID state and get internal Value - like GetTime
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 22 July 2009 at 4:40pm
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/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 22 July 2009 at 4:45pm
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!
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 22 July 2009 at 4:45pm
Originally posted by mdoubson mdoubson wrote:

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
 
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/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 23 July 2009 at 3:54pm

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!?
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 23 July 2009 at 11:04pm
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/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 24 July 2009 at 1:29am
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
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 25 July 2009 at 2:38am
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/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 26 July 2009 at 3:07am
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)
Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 03 August 2009 at 2:37pm
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/
Back to Top
mdoubson View Drop Down
Senior Member
Senior Member
Avatar

Joined: 17 November 2008
Status: Offline
Points: 1705
Post Options Post Options   Thanks (0) Thanks(0)   Quote mdoubson Quote  Post ReplyReply Direct Link To This Post Posted: 03 August 2009 at 2:54pm
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; }

 

Back to Top
znakeeye View Drop Down
Senior Member
Senior Member
Avatar

Joined: 26 July 2006
Status: Offline
Points: 1672
Post Options Post Options   Thanks (0) Thanks(0)   Quote znakeeye Quote  Post ReplyReply Direct Link To This Post Posted: 04 August 2009 at 3:01am
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/
Back to Top
 Post Reply Post Reply
  Share Topic   

Forum Jump Forum Permissions View Drop Down

Forum Software by Web Wiz Forums® version 12.04
Copyright ©2001-2021 Web Wiz Ltd.

This page was generated in 0.188 seconds.