Author: Dmitry Kovalenko
Programming is fun. Sometimes projects and apps are more serious, sometimes less. On my recent Delphi 10.1 Update 2 presentation two times I have been asked about data-aware versions of new VCL Win10 calendar controls. Here is the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
<strong> unit</strong> uDBCalendarView; <strong>interface</strong> <strong>uses</strong> System.Classes, Vcl.WinXCalendars, Data.DB, VCL.DBCtrls; <strong>type</strong> TDBCalendarView = <strong>class</strong>(TCalendarView) <strong>private</strong> FDataLink: TFieldDataLink; <strong>procedure</strong> DataChange(Sender: TObject); <strong>procedure</strong> SetDataField(const Value: string); <strong>procedure</strong> SetDataSource(const Value: TDataSource); <strong>function</strong> GetDataField: string; <strong>function</strong> GetDataSource: TDataSource; <strong>function</strong> GetField: TField; <strong>function</strong> GetFieldDate: TDate; <strong>protected</strong> <strong>procedure</strong> Loaded; <strong>override</strong>; <strong>procedure</strong> Notification(AComponent: TComponent; Operation: TOperation); <strong>override</strong>; <strong>public</strong> <strong>constructor</strong> Create(AOwner: TComponent); <strong>destructor</strong> Destroy; <strong>override</strong>; <strong>property</strong> Field: TField <strong>read</strong> GetField; <strong>published</strong> <strong>property</strong> DataField: <strong>string</strong> <strong>read</strong> GetDataField <strong>write</strong> SetDataField; <strong>property</strong> DataSource: TDataSource <strong>read</strong> GetDataSource <strong>write</strong> SetDataSource; <strong>end</strong>; <strong>implementation</strong> <strong>uses</strong> System.SysUtils; <em>{ TDBCalendarView }</em> <strong>constructor</strong> TDBCalendarView.Create(AOwner: TComponent); <strong>begin</strong> <strong>inherited</strong> Create(AOwner); Enabled := False; <em>// read-only</em> FDataLink := TFieldDataLink.Create; FDataLink.Control := Self; FDataLink.OnDataChange := DataChange; <strong>end</strong>; <strong>destructor</strong> TDBCalendarView.Destroy; <strong>begin</strong> FDataLink.Free; <strong>inherited</strong>; <strong>end</strong>; <strong>procedure</strong> TDBCalendarView.Loaded; <strong>begin</strong> <strong>inherited</strong> Loaded; <strong>if</strong> (csDesigning <strong>in</strong> ComponentState) <strong>then</strong> DataChange(Self); <strong>end</strong>; <strong>procedure</strong> TDBCalendarView.Notification(AComponent: TComponent; Operation: TOperation); <strong>begin</strong> <strong>inherited</strong> Notification(AComponent, Operation); <strong>if</strong> (Operation = opRemove) <strong>and</strong> (FDataLink <> <strong>nil</strong>) <strong>and</strong> (AComponent = DataSource) <strong>then</strong> DataSource := <strong>nil</strong>; <strong>end</strong>; <strong>procedure</strong> TDBCalendarView.DataChange(Sender: TObject); <strong>begin</strong> self.Date := GetFieldDate; <strong>end</strong>; <strong>function</strong> TDBCalendarView.GetField: TField; <strong>begin</strong> Result := FDataLink.Field; <strong>end</strong>; <strong>function</strong> TDBCalendarView.GetDataField: <strong>string</strong>; <strong>begin</strong> Result := FDataLink.FieldName; <strong>end</strong>; <strong>procedure</strong> TDBCalendarView.SetDataField(<strong>const</strong> Value: <strong>string</strong>); <strong>begin</strong> FDataLink.FieldName := Value; <strong>end</strong>; <strong>function</strong> TDBCalendarView.GetDataSource: TDataSource; <strong>begin</strong> Result := FDataLink.DataSource; <strong>end</strong>; <strong>procedure</strong> TDBCalendarView.SetDataSource(<strong>const</strong> Value: TDataSource); <strong>begin</strong> <strong>if</strong> <strong>not</strong> (FDataLink.DataSourceFixed <strong>and</strong> (csLoading <strong>in</strong> ComponentState)) <strong>then</strong> FDataLink.DataSource := Value; <strong>if</strong> Value <> <strong>nil</strong> <strong>then</strong> Value.FreeNotification(Self); <strong>end</strong>; <strong>function</strong> TDBCalendarView.GetFieldDate: TDate; <strong>begin</strong> <strong>if</strong> FDataLink.Field <> <strong>nil</strong> <strong>then</strong> <strong>begin</strong> <strong>if</strong> (FDataLink.Field.DataType <strong>in</strong> [ftDate, ftDateTime, ftTimeStamp, ftTime]) <strong>then</strong> Result := FDataLink.Field.AsDateTime <strong>else</strong> Result := Now; <strong>end</strong> <strong>else</strong> <strong>if</strong> csDesigning <strong>in</strong> ComponentState <strong>then</strong> Result := Now; <strong>end</strong>; <strong>end</strong>. |
One of the best things about Delphi is that it comes with the source code. After a lot of googling for examples of custom database aware Delphi components, the actual source code of “TDBText” component in “VCL.DBCtrls” unit was the best resource.
The most important part of a custom data-aware field component is private “TFieldDataLink”. It does all the job, but as component implementer you need to expose its “DataSource” and “FieldName” properties. In the constructor there is also “OnDataChanged” event connected to “DataChanged” procedure. In this way the calendar control knows when it needs to refresh itself. This is centralized in the “GetFieldDate” method that reads the date from the internal “FDataLink.Field”.
Not a rocket science:-)
The source code of custom Win10 VCL data-aware components can be downloaded from this link.
The test application of data-aware “TCalendarView” and “TCalendarPicker” looks like this and is using RAD Studio InterBase “EMPLOYEE” database.
Let’s take a look at how you can create WinAPI Calendar in this article about RAD Studio 10.2.
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition