View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001614 | JEDI VCL | 00 JVCL Components | public | 2004-04-09 17:47 | 2004-04-11 02:21 |
Reporter | glchapman | Assigned To | user72 | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | |||||
Target Version | Fixed in Version | ||||
Summary | 0001614: D5: TJvDateTimePicker.MsgSetDateTime: invalid call to CheckNullValue | ||||
Description | Before returning, TJvDateTimePicker.MsgSetDateTime calls CheckNullValue, which checks the current value of the DateTime property to see if it is the null value. Unfortunately (in Delphi 5 anyway), TCommonCalender.SetDateTime does not update the FDateTime field until after MsgSetDateTime has returned. Thus the CheckNullValue call checks the old DateTime rather than the one being set through MsgSetDateTime. | ||||
Additional Information | My inclination would be to fix this by changing CheckNullValue so that it accepts a datetime parameter as the value to test. However, changing CheckNullValue's signature would break any subclasses which have overridden it. I'm not sure what the JVCL policy is on that sort of thing, so I'll leave it to you to determine the best fix. | ||||
Tags | No tags attached. | ||||
|
Suggestion: add overloaded CheckNullValue: function CheckNullValue: Boolean; overload;virtual; function CheckNullValue(const ANullText, AFormat: string; AKind: TDateTimeKind; ADateTime, ANullDate: TDateTime): Boolean;overload;virtual; implementation: function TJvDateTimePicker.CheckNullValue: Boolean; begin Result := CheckNullValue(NullText, Format, Kind, DateTime, NullDate); end; function TJvDateTimePicker.CheckNullValue(const ANullText, AFormat: string; AKind: TDateTimeKind; ADateTime, ANullDate: TDateTime): Boolean; begin // Warren added NullText length check so that this feature can be disabled if not used! if Length(ANullText) = 0 then begin Result := false; end else Result := ((AKind = dtkDate) and (Trunc(ADateTime) = Trunc(ANullDate)) or ((AKind = dtkTime) and WithinDelta(ADateTime, ANullDate))); if Result then SendMessage(Handle, DTM_SETFORMAT, 0, Integer(PChar(ANullText))) else SendMessage(Handle, DTM_SETFORMAT, 0, Integer(PChar(AFormat))); end; change MsgSetDateTime: function TJvDateTimePicker.MsgSetDateTime(Value: TSystemTime): Boolean; begin Result := inherited MsgSetDateTime(Value); CheckNullValue(NullText, Format, Kind, SystemTimeToDateTime(Value), NullDate); end; Would that work? |
|
It works, but there is still potential breakage of subclasses since an overridden CheckNullValue(void) will no longer be called when processing MsgSetDateTime. Rather than that silent, run-time breakage, I would prefer an explicit compile-time breakage through changing the signature of CheckNullValue. It should be a trivial change for any subclass to adapt to the new signature. |
|
Damn, forgot to log in again. The previous comment was by me. |
|
Thinking a little more, how about using your suggested fix, but removing the virtual from the first (no parameters) overload of CheckNullValue. This would compile-time break any subclasses which overrode CheckNullValue (forcing them to adopt to the new virtual signature), but would allow any subclasses which simply called CheckNullValue() to compile without change. |
|
Sounds OK to me. I'll try it and see what happens... |
|
Seems to work fine. Update in CVS |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-04-09 17:47 | glchapman | New Issue | |
2004-04-10 00:22 |
|
Note Added: 0003771 | |
2004-04-10 00:24 |
|
Status | new => feedback |
2004-04-10 07:04 | anonymous | Note Added: 0003783 | |
2004-04-10 07:05 | glchapman | Note Added: 0003784 | |
2004-04-10 07:23 | glchapman | Note Added: 0003785 | |
2004-04-10 14:13 |
|
Note Added: 0003791 | |
2004-04-11 02:21 |
|
Status | feedback => resolved |
2004-04-11 02:21 |
|
Resolution | open => fixed |
2004-04-11 02:21 |
|
Assigned To | => user72 |
2004-04-11 02:21 |
|
Note Added: 0003794 |