![]() |
Kalender
Hallo,
habe gerade einen kleinen Kalender fertig gestellt und stelle in hiermit zur Verfügung! Ich habe bisher keinerlei Anpassungen bzg. anderer Delphiversionen vorgenommen, so wie es ist läuft es unter D7 (wegen DateUtils), sollte aber mit ein paar Anpassungen auch unter andernen Versionen laufen. Der Kalender hat (leider) ein paar Bugs die sich leider nicht so einfach finden lassen und weil das so ist, ist er auch Open-Source. Die einzigste Bedingung die ich habe, ist das alle Änderungen hier veröffentlich werden. Gruss Alter Mann [Edit] Ups... Jetzt sind alle Dateien bei. [Edit] Plus Beispiel inkl. aller Dateien für Delphi 7.[/Edit] [/Edit] PS Kleine Anmerkung sei noch gestattet: Das Beispiel zeigt ungefähr wo es hingehen soll, vielleicht noch DB-Anbindung. Was mich da ein wenig verwundert ist die Darstellung zur Desginzeit und zur Laufzeit bzw. die unterschiedliche Darstellung zwischen Componenten auf Form plaziert und zur Laufzeit erstellt(siehe Calendar.zip), genauso im Beispiel. |
Re: Kalender
Ööhhhmmm.... da fehlt aber die Unit uCalendar im Archiv :angel:
|
Re: Kalender
echt ey
|
Re: Kalender
Hallo
Ich habe mir nartürlich Gedanken gemacht und den ganzen Code neugeschrieben. Es sind soweit alle 'irrsinnigen' Bugs rausgeflogen und 'andere?' dafür reingekommen. Die jeniegen die sich den alten Code angetan haben, meine Bewunderung und Entschuldigung. Für alle Intressierten: Es fehlt noch die DB-Anbindung und Multiselect. Aber vielleicht ist ja der/die Eine oder Andere so Hilfsbereit und stellt die entsprechende Ableitung zur Verfügung. Viele Grüsse Alter Mann |
Re: Kalender
Hi,
auch wenn es scheinbar keiner Braucht, hier die DB-Anbindung. Doch zuerst müssen wir die Kalender-Componente aktuallisieren:
Delphi-Quellcode:
TCalendarControl = class(TCustomControl)
private ... FDates : Array of TDateTime; FMaxRecords : Integer; ... protected ... procedure DataChange(Sender: TObject); virtual; function DateInArray(aDate : TDateTime) : Boolean; ... end; ... constructor TCalendarControl.Create(aOwner : TComponent); begin ... SetLength(FDates, 31); FMaxRecords := -1; ... end; ... procedure TCalendarControl.DataChange(Sender: TObject); begin end; function TCalendarControl.DateInArray(aDate : TDateTime) : Boolean; var I : Integer; begin Result := False; for I := Low(FDates) to High(FDates) do if FDates[I] = aDate then begin Result := True; Break; end; end; ... procedure TCalendarControl.DoDateChange(aOldDate, aNewDate : TDateTime); begin SetLength(FDates, 0); SetLength(FDates, 31); FMaxRecords := -1; DataChange(Self); if Assigned(FOnDateChange) then FOnDateChange(Self, aOldDate, aNewDate); end; ... procedure TCalendarControl.Paint; ... if DateInArray(CE.EntryDate) then Font.Style := Font.Style + [fsBold] else Font.Style := Font.Style - [fsBold]; if FOptions.TrailingDays then ... end;
Delphi-Quellcode:
Um die Sache Rund zu machen fehlt noch dies:
TDBCalendarControl = class(TCalendarControl)
private FDataLink : TFieldDataLink; function GetDataField: string; function GetDataSource: TDataSource; function GetField: TField; procedure SetDataField(const Value: string); procedure SetDataSource(Value: TDataSource); procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK; protected procedure DataChange(Sender: TObject); override; function IsDateTimeField : Boolean; procedure Loaded; override; procedure LoadDatesForMonth; procedure Notification(aComponent: TComponent; Operation: TOperation); override; public constructor Create(aOwner: TComponent); override; destructor Destroy; override; property Field: TField read GetField; property DataField: string read GetDataField write SetDataField; property DataSource: TDataSource read GetDataSource write SetDataSource; end; ... { ************ TDBCalendarControl } (* public *) constructor TDBCalendarControl.Create(aOwner: TComponent); begin inherited Create(aOwner); FDataLink := TFieldDataLink.Create; FDataLink.Control := Self; FDataLink.OnDataChange := DataChange; end; destructor TDBCalendarControl.Destroy; begin FDataLink.Free; FDataLink := nil; inherited Destroy; end; (* private *) procedure TDBCalendarControl.DataChange(Sender: TObject); begin if (FDataLink.Field <> nil) and not FDataLink.DataSourceFixed then begin if FMaxRecords <> FDataLink.DataSet.RecordCount - 1 then begin FMaxRecords := FDataLink.DataSet.RecordCount - 1; FDataLink.DataSourceFixed := True; LoadDatesForMonth; end; end; end; function TDBCalendarControl.GetDataField: string; begin Result := FDataLink.FieldName; end; function TDBCalendarControl.GetDataSource: TDataSource; begin Result := FDataLink.DataSource; end; function TDBCalendarControl.GetField: TField; begin Result := FDataLink.Field; end; procedure TDBCalendarControl.SetDataField(const Value: string); begin FDataLink.FieldName := Value; end; procedure TDBCalendarControl.SetDataSource(Value: TDataSource); begin if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then FDataLink.DataSource := Value; if Value <> nil then Value.FreeNotification(Self); end; procedure TDBCalendarControl.CMGetDataLink(var Message: TMessage); begin Message.Result := Integer(FDataLink); end; (* protected *) function TDBCalendarControl.IsDateTimeField : Boolean; begin with FDataLink do Result := (Field <> nil) and (Field.DataType in [ftDateTime, ftTimeStamp]); end; procedure TDBCalendarControl.LoadDatesForMonth; var I : Integer; DT : TDateTime; Y1, Y2, M1, M2, D1, D2 : Word; begin FDataLink.DataSet.First; for I := 0 to FDataLink.DataSet.RecordCount - 1 do begin if IsDateTimeField then DT := Trunc(FDataLink.Field.AsDateTime) else DT := Trunc(FDataLink.Field.AsDateTime); DecodeDate(DT, Y1, M1, D1); DecodeDate(FDate, Y2, M2, D2); if (Y1 = Y2) and (M1 = M2) then FDates[D1] := DT; FDataLink.DataSet.Next; end; Invalidate; FDataLink.DataSourceFixed := False; end; procedure TDBCalendarControl.Loaded; begin inherited Loaded; if (csDesigning in ComponentState) then DataChange(Self); end; procedure TDBCalendarControl.Notification(aComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil; end;
Delphi-Quellcode:
Das war es.TExDBCalendar = class(TDBCalendarControl) published property CalendarDate; property Colors; property DataField; property DataSource; property Font; property Options; property OnDayClick; property OnDateChange; end; Gruss |
Re: Kalender
Hallo Alter Mann,
dass ein solches Control niemand braucht möchte ich nicht unterschreiben. Jedenfalls finde ich es nett von dir, dass du deine Komponente hier zur Verfügung stellst. Beim Drüberschauen stellt sich mir die Frage, ob nicht ein Bookmark die Methode LoadDatesFromMonth() aufwerten würde. Immerhin verschiebst du den Datensatzzeiger. Dann sehe ich eine bedingte Zuweisung an DT, bei der beide Zweige gleich lauten, sodass die Bedingung eigentlich ungeprüft entfallen kann. Für einen produktiven Einsatz würde ich eine lose Kopplung zwischen Control und Datenbank vorziehen. Hast du dir mal die Komponente TMonthCalendar und dort speziell das Ereignis OnGetMonthInfo() angeschaut? Freundliche Grüße |
Re: Kalender
Hi marabu,
TMonthCalendar habe ich mir schon angeschaut, allerdings nicht OnGetMonthInfo, was ich nachholen werde. Das mit DT ist mir auch klar, habe aber noch keine bessere Idee. Mitarbeit erwünscht. Bis bald und Danke. Gruss Alter Mann |
Re: Kalender
Hi marabu,
manchmal bin auch ich schnell(beim drüberlesen) :wink: Klar PMonthDayState würde die Sache auch machen, aber die Compo auch 'aufblähen'. Man muss auf OnGetMonthInfo reagieren und die Sache in Paint doch wieder umsetzen. Es sei denn, es gibt Handfeste Argumente, die dagegen Sprechen. MfG Alter Mann |
Re: Kalender
Mir gefällt die Entkopplung von Funktionalitäten, wie sie über OnGetMonthInfo() möglich wird.
Zu der Typprüfung: Ich würde einfach eine Exception werfen, wenn sich der Feldtyp beim ersten Zugriff als falsch herausstellt. Die Prüfung sollte auf keinen Fall innerhalb einer Schleife über potentiell Tausenden von Datensätzen statt finden. Statt DataSet.First() bietet sich vielleicht DataSet.Locate() an. So könntest du in einer riesigen Tabelle Laufzeitvorteile gewinnen. Und nicht das Bookmarking vergessen. Gute Nacht |
Re: Kalender
Hi marabu,
wie würde das Aussehen? Zitat:
Alter Mann PS Entschuldigung wenn ich Dich von einer anderen 'wichtigeren' Sache abhalte. Gute Nacht |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz