Blog
All Blog Posts | Next Post | Previous PostFixing the VCL TDateTimePicker checkbox handling bug for Windows Vista
Sunday, July 19, 2009
In all Delphi versions before Delphi 2009 update pack 3, there is a bug with the standard TDateTimePicker component with respect to handling the checkbox click when DateTimePicker.ShowCheckBox is set to true. Where on operating systems older than Windows Vista, clicking the checkbox triggers the OnChange event and properly updates the TDateTimePicker public property Checked, it fails to do so on Windows Vista.Example:
procedure TForm1.DateTimePicker1Change(Sender: TObject); begin if (Sender as TDateTimePicker).Checked then listbox1.Items.Add('datetimepicker checked') else listbox1.Items.Add('datetimepicker unchecked'); end;
To fix this, two possibilities are: patch COMCTRLS.PAS or write a descendent class that fixes the issue. To avoid having to recompile the VCL, the latter solution is the easiest but requires to use your own class in applications rather than the standard TDateTimePicker.
Solution 1: patching COMCTRLS.PAS:
procedure TDateTimePicker.CNNotify(var Message: TWMNotify); var DT: TDateTime; AllowChange: Boolean; begin with Message, NMHdr^ do begin Result := 0; case code of DTN_DATETIMECHANGE: begin with PNMDateTimeChange(NMHdr)^ do begin if FDroppedDown and (dwFlags = GDT_VALID) then begin FLastChange := st; FDateTime := SystemTimeToDateTime(FLastChange); end else begin if FShowCheckbox and (dwFlags = GDT_NONE) then // patch here FChecked := False else if dwFlags = GDT_VALID then begin FLastChange := st; DT := SystemTimeToDateTime(st); if Kind = dtkDate then SetDate(DT) else SetTime(DT); if FShowCheckbox then FChecked := True; end; end; Change; end; end; ...
Solution 2: creating a descendent class:
TFixedDateTimePicker = class(TDateTimePicker) private procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY; end; { TFixedDateTimePicker } procedure TFixedDateTimePicker.CNNotify(var Message: TWMNotify); begin with Message, NMHdr^ do begin if ShowCheckBox then begin with PNMDateTimeChange(NMHdr)^ do begin Checked := dwFlags <> GDT_NONE; end; end; end; inherited; end;
Fortunately, this issue was fixed from Delphi 2009 update pack 3.
Bruno Fierens
This blog post has received 1 comment.
All Blog Posts | Next Post | Previous Post
void __fastcall TFixedDateTimePicker::CNNotify(TWMNotify& msg)
{
if(ShowCheckbox)
{
if(msg.NMHdr->code == DTN_DATETIMECHANGE)
{
PNMDateTimeChange c = reinterpret_cast<PNMDateTimeChange>(msg.NMHdr);
Checked = (c->dwFlags != GDT_NONE);
}
}
TDateTimePicker::Dispatch(&msg); // Default processing
}
...
private:
void __fastcall CNNotify(TWMNotify& msg);
public:
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(CN_NOTIFY, TWMNotify, CNNotify)
END_MESSAGE_MAP(TDateTimePicker)
...
Antony Corbett