TDate Datum in TMonthCalendar anzeigen
-
Linnea schrieb:
na dann ist es doch recht einfach: mach die SQL-Abfrage in die Funktion, beim SQL-Kommando kannst du sogar nur die mit dem gerade angezeigten Monat eingrenzen, dann ein Feld mit den Werten füllen und anzeigen, fertig.
hmm einfach
dann will ichs mal probieren
ich hab mir meine sql anweisung
Form3->ADOQuery1->SQL->Clear(); Form3->ADOQuery1->SQL->Add("Select MHD From DerInhalt"); Form3->ADOQuery1->Open();
dann hab ich hier mein kalenderprogramm von vorhin:
MHDX = "21.04.2010"; int j = 0; TDateTime date[2] = {TDateTime("01.01.1990"),TDateTime("01.01.1990")}; for (int u=1; u < 2; u++) { if (date[u]=="01.01.1990") break; { date[u]=MHDX; u=3; } } WORD day,month,year,hour,minute,seconde,millisecond; unsigned Buffer = MonthBoldInfo; for (int i = 0; i < 2; i++) { DecodeDateTime(date[i],year,month,day,hour,minute,seconde,millisecond); unsigned bolddays[31]; if (Month == month) { bolddays[j] = day; MonthCalendar1->BoldDays(bolddays,j,Buffer); j++; } } MonthBoldInfo = Buffer;
aber jetzt zusammenfügen?!?!?!?!?
wohin werden die mhds aus der tabele gespeichert wenn ich sie mit meiner sql abrufe?
-
ungetestet, aber ein bißchen was kannst du ja auch selbst machen:
ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat "); ADOQuery1->Parameters->ParamByName("monat")->Value = Month; ADOQuery1->Open(); int count = ADOQuery1->RecordCount; if (count <= 0) return; unsigned feld[31]; unsigned Buffer = MonthBoldInfo; for (ADOQuery1->First();!ADOQuery1->Eof;ADOQuery1->Next()) { feld[ADOQuery1->RecNo-1] = ADOQuery1->FieldByName("ttag")->AsInteger; } MonthCalendar1->BoldDays(feld,count-1,Buffer); ADOQuery1->Close(); MonthBoldInfo = Buffer;
[Edit] ups da hab ich wohl noch die Abfrage nach dem Jahr des angezeigten Kalender vergessen
-
hmm das funktioniert ja schon aber irgendwie markiert er mir nur die mhds von april und mai...
hab in der tabelle aber noch von oktober... und von nächstem jahr stehen.
was ist da denn der fehler? ist das array zu klein gewählt?
-
Nein, die SQL-Abfrage ist, so wie sie da steht, unvollständig: es fehlt die Abfrage des Jahres, dazu brauchst du die Information in welchem Kalenderblatt du grad bist und die bekommst du aus Date vom MonthCalender. Und noch als Tip: YearOf gibt das Jahr eines Datumswertes zurück.
das Array kann - wie ja kpeter schon feststellte - nur maximal 31 Tage haben, soviel Tage hat nunmal ein Monat maximal
und jetzt bitte mal das Hirnschmalz umrühren :p
-
Hallo,
auch ich muss einen Hinweis hinzutun, da ich denke, dass das Verhalten der Komponente noch nicht
ganz bewusst ist.Je nachdem, wie weit die Komponente auf dem Formular aufgezogen ist, und somit Monate sichtbar sind,
sooft tritt (bereits bei Programmstart) das Ereignis OnGetMonthInfo auf.Dazu kommt ein OnGetMonthInfo für den Vormonat und eins für einen Monat nach den letzten abgebildeten.
D.h., wenn drei Monate von der Kompo abgebildet werden, treten 5 Ereinisse auf. Leicht nachzuprüfen im Debug-Modus.
Die Daten für diese Monate müssen also bereitstehen, damit die Anzeige der Bolddays korrekt erfolgt.mfg
kpeter
-
ohje... ihr überfordert mich gerade ein bischen....
das ganze ist für mich totales neuland....
ich probier mal bischen rum. meld mich dann wieder!
-
Linnea schrieb:
es fehlt die Abfrage des Jahres, dazu brauchst du die Information in welchem Kalenderblatt du grad bist und die bekommst du aus Date vom MonthCalender. Und noch als Tip: YearOf gibt das Jahr eines Datumswertes zurück.
hmm ich hab ne idee aber kein plan ob ich auf dem richtigen weg bin...
also meine "idee":
ich muss mittels ner if schleife schauen ob das date vom monthcalender = yearof dem wert dem mhd den ich mittels einer sql anweisung aus meiner tabelle auslese.
falls das richtig sein sollte, hab ich leider kein plan wie ich das um setzen soll...
-
einfacher ists die SQL-Anweisung um die Suche nach dem Jahr zu erweitern:
ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat and year = :jahr "); ADOQuery1->Parameters->ParamByName("monat")->Value = Month; ADOQuery1->Parameters->ParamByName("jahr")->Value = YearOf(MonthCalendar1->Date); ADOQuery1->Open();
Das geht allerdings nur gut wenn du nur einen Monat im MonthCalendar anzeigen läßt.
Wenn du mehrere Monate gleichzeitig anzeigen willst wirds etwas komplizierter. Aber auch dafür gibts eine Lösung in den Weiten des Internets
-
Linnea schrieb:
einfacher ists die SQL-Anweisung um die Suche nach dem Jahr zu erweitern:
ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat and year = :jahr "); ADOQuery1->Parameters->ParamByName("monat")->Value = Month; ADOQuery1->Parameters->ParamByName("jahr")->Value = YearOf(MonthCalendar1->Date); ADOQuery1->Open();
hmm klar, einfacher gehts immmer.... wenn man weiss wie:)
aber muss das nicht so heissen:Linnea schrieb:
ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat and year(MHD) = :jahr ");
[/cpp]Linnea schrieb:
Das geht allerdings nur gut wenn du nur einen Monat im MonthCalendar anzeigen läßt.
Wenn du mehrere Monate gleichzeitig anzeigen willst wirds etwas komplizierter. Aber auch dafür gibts eine Lösung in den Weiten des Internets
was meinst du damit?
ich möchte, wenn ich den kalender durchklicke von monat zu monat die jeweiligen tage sehen...
-
Otz110 schrieb:
aber muss das nicht so heissen:
Linnea schrieb:
ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat and year(MHD) = :jahr ");
[/cpp]richtig
Otz110 schrieb:
ich möchte, wenn ich den kalender durchklicke von monat zu monat die jeweiligen tage sehen...
Wenn du den MonthCalendar auf das Formular legst, kannst du das mal größer ziehen, dann werden je nach Größe des Feldes mehrere Kalenderblätter angezeigt. Das Maximum liegt bei 4x3 Kalenderblätter, also ein Jahr.
Wenn du aber nur einen Monat anzeigen willst ist der Quellcode, so wie vorher besprochen, durchaus ausreichend
-
hmm also ich hab jetzt diesen quellcode:
void __fastcall TForm1::MonthCalendar1GetMonthInfo(TObject *Sender, DWORD Month, DWORD &MonthBoldInfo) { Form3->ADOQuery1->SQL->Clear(); Form3->ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat and year(MHD) = :jahr "); Form3->ADOQuery1->Parameters->ParamByName("monat")->Value = Month; Form3->ADOQuery1->Parameters->ParamByName("jahr")->Value = YearOf(MonthCalendar1->Date); Form3->ADOQuery1->Open(); int count = Form3->ADOQuery1->RecordCount; if (count <= 0) return; unsigned feld[31]; unsigned Buffer = MonthBoldInfo; for (Form3->ADOQuery1->First();!Form3->ADOQuery1->Eof;Form3->ADOQuery1->Next()) { feld[Form3->ADOQuery1->RecNo] = Form3->ADOQuery1->FieldByName("ttag")->AsInteger; } MonthCalendar1->BoldDays(feld,count-1,Buffer); Form3->ADOQuery1->Close(); MonthBoldInfo = Buffer;
aber irgendwas klappt da noch nicht.
ich hab in meiner access tabelle das datum 09.01.1987 drin! wenn ich den monat aufrufe ist zuerst der 14.01. markiert. wenn ich jetzt einen monat weiter mache und wieder zurück ist aufeinmal der 11.01. markier. was kann das sein?
-
Zeile 14 ist noch falsch:
feld[Form3->ADOQuery1->RecNo[u]-1[/u]] = Form3->ADOQuery1->FieldByName("ttag")->AsInteger;
hat aber trotzdem noch nen Haken: wenn man auf Dez 1986 geht und danach auf Jan 1987 ist der Wert auch nicht da...
Das liegt daran, daß auch der Vormonat und der Monat nach dem angezeigten mit ausgewertet werden und dann interessanterweise nicht das blaumarkierte Datum genommen wird, sondern das was im Vormonat markiert ist.Die einzig wirklich gute Lösung für das Problem ist eine Komponente von TMonthCalendar abzuleiten und beim OnGetMonthInfo auch das angezeigte Jahr mit auszugeben, siehe hier. Ich schau mal ob ich die Komplettlösung hinbekomm.
-
hier mal die Lösung mit Beispielaufruf:
man macht einen neue Unit und speichert die unter MonthCalFix, der Header (.h) hat folgenden Inhalt:
#ifndef MonthCalFixH #define MonthCalFixH #include <Controls.hpp> #include <ComCtrls.hpp> //--------------------------------------------------------------------------- typedef void __fastcall (__closure *TOnGetYearMonthInfoEvent)(TObject *Sender, Word Year, Word Month, MONTHDAYSTATE &MonthBoldInfo); class TMonthCalendarFix : public TMonthCalendar { typedef TMonthCalendar inherited; private: TOnGetYearMonthInfoEvent FOnGetMonthInfo; MESSAGE void __fastcall CNNotify(TWMNotify &Message); protected: // Protected declarations public: // Public declarations __fastcall TMonthCalendarFix(TComponent *Owner); BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(CN_NOTIFY, TWMNotify, CNNotify) END_MESSAGE_MAP(TMonthCalendar) __published: __property TOnGetYearMonthInfoEvent OnGetMonthInfo = {read=FOnGetMonthInfo, write=FOnGetMonthInfo}; }; #endif
in der .cpp steht:
//--------------------------------------------------------------------------- #pragma hdrstop #include "MonthCalFix.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- __fastcall TMonthCalendarFix::TMonthCalendarFix(TComponent *Owner) : TMonthCalendar(Owner) { } //--------------------------------------------------------------------------- void __fastcall TMonthCalendarFix::CNNotify(TWMNotify &Message) { switch( Message.NMHdr->code ) { case MCN_GETDAYSTATE: { LPNMDAYSTATE lpnmDayState = (LPNMDAYSTATE) Message.NMHdr; memset(lpnmDayState->prgDayState, 0, lpnmDayState->cDayState * sizeof(MONTHDAYSTATE)); if( FOnGetMonthInfo ) { LPMONTHDAYSTATE CurState = lpnmDayState->prgDayState; Word YearNo = lpnmDayState->stStart.wYear; //the year is passed anyways, so why not use it? for(Word I = 0; I < lpnmDayState->cDayState; ++I) { Word MonthNo = lpnmDayState->stStart.wMonth + I; if( MonthNo > 12 ) { MonthNo -= 12; ++YearNo; } FOnGetMonthInfo(this, YearNo, MonthNo, *CurState); ++CurState; } } Message.NMHdr->code = 0; //don't handle this message again in inherited handler break; } /* the MCN_SELCHANGE message is also fired for year and month changes, actually it is also fired just before MCN_SELECT */ case MCN_SELCHANGE: Message.NMHdr->code = MCN_SELECT; //make inherited handler assume it's MCN_SELECT break; } inherited::Dispatch(&Message); }
diese Unit bindet man dann dort ein wo man den Kalender haben möchte, in diesem Beispiel in Unit1/Form1 (die Kommentare bezeichnen die Funktionen/Zeilen, die in eine eigene Anwendung übernommen werden müssen):
#include "MonthCalFix.h" //eingebundener Hearder des MonthCalendarFix //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: TADOConnection *ADOConnection1; TADOQuery *ADOQuery1; TButton *Button1; void __fastcall Button1Click(TObject *Sender); private: void __fastcall MonthCalendarFixGetMonthInfo(TObject *Sender, Word Year, Word Month, MONTHDAYSTATE &MonthBoldInfo); //OnGetMonthInfo TMonthCalendarFix *MonthCalendarFix; //MonthCalendarZeiger public: __fastcall TForm1(TComponent* Owner); __fastcall ~TForm1(void); //Destructor des Formulars };
in der cpp:
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { //der Konstructor von Form1 ist im Normalfall schon vorhanden //folgendes zeigt den MonthCalendarFix an MonthCalendarFix = new TMonthCalendarFix(Form1); MonthCalendarFix->Parent = Form1; MonthCalendarFix->Top = 200; MonthCalendarFix->Left = 200; MonthCalendarFix->Visible = true; MonthCalendarFix->OnGetMonthInfo = MonthCalendarFixGetMonthInfo; } //--------------------------------------------------------------------------- // der Destructor von Form1 __fastcall TForm1::~TForm1(void) { delete MonthCalendarFix; } //--------------------------------------------------------------------------- // die neue OnGetMonthInfo-Methode void __fastcall TForm1::MonthCalendarFixGetMonthInfo(TObject *Sender, Word Year, Word Month, MONTHDAYSTATE &MonthBoldInfo) { ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("Select distinct day(MHD) as ttag From DerInhalt where month(MHD) = :monat and year(MHD) = :jahr "); ADOQuery1->Parameters->ParamByName("monat")->Value = Month; ADOQuery1->Parameters->ParamByName("jahr")->Value = Year; ADOQuery1->Open(); int count = ADOQuery1->RecordCount; if (count <= 0) return; unsigned feld[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; unsigned Buffer = MonthBoldInfo; for (ADOQuery1->First();!ADOQuery1->Eof;ADOQuery1->Next()) { feld[ADOQuery1->RecNo-1] = ADOQuery1->FieldByName("ttag")->AsInteger; } MonthCalendarFix->BoldDays(feld,count-1,Buffer); ADOQuery1->Close(); MonthBoldInfo = Buffer; }
-
ohje das ist aber gewachsen....
erstmal danke für die mühe:)
muss mich da jetzt mal durch kämpfen und schauen ob ich das zum laufen bekomme
-
kann man das nicht bischen kürzen?!
so etwa die länge die wir zuvor hatten ereichen?grüße