Blog
All Blog Posts | Next Post | Previous Post
Fixing 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