Berechtigungsformular mit TreeView, ListView und CheckBox oder ganz anders?
-
Also, ich habe immer noch ein Problem.
Ich habe nun die XStringGrid Komponente drin, aber Checkboxen bekomme ich da keine raus. Habe aber mit ihr einfach meine Checkbox positioniert. Und das ganze mit Inline Funktionen gelöst.
Problem:
Entweder habe ich nur eine Checkbox beim Start des Formulars eingeblendet und zwar in der Zelle, die den Fokus hat oder ich klicke so wie im unterem Beispiel jedes Feld an. Dann wird in jedem Feld eine CheckBox erstellt.Gibt es aber irgendwie ein Ereignis, dass ich bei TreeView oder StringGrid auswählen kann, dass ich automatisch in jeder Zelle eine Checkbox anzeigen kann?
Habe versucht die XStringGrid1->Col und XStringGrid1->Row wie in einem Array durchzuzählen und dort jeweils mit
PlaceCheckBox(pCheckBox);eine CheckBox zu setzen, aber irgendwie funktioniert das nicht.
Hat mir jemand noch mal einen Tip?
void __fastcall TFormBerechtigungen::PlaceCheckBox(TCheckBox *pCheckBox1) { // Maße eines Gitterfensters bestimmen TRect Rect = XStringGrid1->CellRect(XStringGrid1->Col,XStringGrid1->Row); // CheckBox den obersten Punkt des XStringGrid zuweisen pCheckBox1->Top = XStringGrid1->Top; // CheckBox den linken Punkt des XStringGrid zuweisen pCheckBox1->Left = XStringGrid1->Left; // CheckBox Top Position zuweisen pCheckBox1->Top = pCheckBox1->Top + Rect.Top + XStringGrid1->GridLineWidth +1; // CheckBox Left Position zuweisen pCheckBox1->Left = pCheckBox1->Left + Rect.Left + XStringGrid1->GridLineWidth +14; // CheckBox Höhe zuweisen pCheckBox1->Height = (Rect.Bottom - Rect.Top) - 1; // CheckBox Breite zuweisen pCheckBox1->Width = (Rect.Right - Rect.Left) - 17; // CheckBox sichtbar machen pCheckBox1->Visible = true; // CheckBox Focus zuweisen pCheckBox1->SetFocus(); }void __fastcall TFormBerechtigungen::XStringGrid1Click(TObject *Sender) { pCheckBox = new TCheckBox(GroupBox1); pCheckBox->Parent = GroupBox1; pCheckBox->Color = clWindow; pCheckBox->Alignment = taRightJustify; pCheckBox->Visible = false; pCheckBox->OnClick = CheckBoxClick; PlaceCheckBox(pCheckBox); }
-
Es macht vielleicht Sinn, statt der GroupBox das StringGrid als Parent der CheckBox anzugeben.
-
Habe ich abgeändert, aber das Problem bleibt das selbe. Bekomme nur in der ersten Zelle den Button automatisch angezeigt und bei den anderen muß ich reinklicken.
-
Ich hab jetzt zwar nicht die XStringGrid Komponente aber du kannst das doch auch ganz einfach über ein entsprechendes Array bzw besser noch mit entsprechendem vector von 'TCheckBox' machen.
Du erzeugst dynamisch zur Laufzeit soviel neue Instanzen von TCheckBox wie du in deinem Grid benötigst.
Die positionierst du dann 'über' dem Grid.
Am besten natürlich wenn du da gleich von StringGrid ableitest.
-
Also ich komm hier von einem zum Anderem. Ich habe es nun geschaft, dynamisch so viele CheckBoxen zu erstellen wie ich benötige. Diese habe ich auch der XStringGrid Komponente zugeordnet. Die CheckBoxen sind auch in den entsprechenden Feldern positioniert.
Aber irgendwie mache ich noch etwas falsch beim Zuweisen.
Ich kann jetzt zwar die Buttons betätigen und das OnClick Ereignis wird ausgelöst, aber ich bekomme in der OnClick Funktion keine Informationen mehr darüber in welcher Zeile oder Spalte des StringGrids ich mich befinde.
Aufrufe wie
XStringGrid->Colliefern immer nur eine Eins zurück.
Das komische ist, ich kann darin noch nicht mal abfragen, ob eine Checkbox checked ist. Die Überprüfung wirkt sich in keinster Weise aus.
Ich habe mir die Faq zu dynamisch erzeugte Komponenten durchgelesen...
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39206.html
...da ich vermute, dass mein Fehler in den mit new erzeugten CheckBoxen liegt. Das was ich da gefunden habe, kann ich bei mir so nicht anwenden, da ich keine const int Variable nehmen kann. Ich weiß ja erst beim Aufruf im TreeView wie viele Checkboxen ich brauche.
void __fastcall TFormBerechtigungen::PlaceCheckBox(int Row, int Col) { for(int Zeile =1; Zeile<Row; Zeile++) { for(int Spalte =1; Spalte<Col; Spalte++) { pCheckBox = new TCheckBox(pXStringGrid); pCheckBox->Parent = pXStringGrid; pCheckBox->Color = clWindow; pCheckBox->Alignment = taRightJustify; // Maße eines Gitterfensters bestimmen TRect Rect = pXStringGrid->CellRect(pXStringGrid->Col,pXStringGrid->Row); // CheckBox den obersten Punkt des XStringGrid zuweisen pCheckBox->Top = pXStringGrid->Top; // CheckBox den linken Ounkt des XStringGrid zuweisen pCheckBox->Left = pXStringGrid->Left; // CheckBox obere Position zuordnen pCheckBox->Top = pCheckBox->Top // pXStringGrid->Top beibehalten + (Rect.Top * Zeile) // Position von Erster Zelle * Anzahl Zeilen + pXStringGrid->GridLineWidth +1 // Gitter Linie addieren - pXStringGrid->Top; // Positionsverschiebung pXStringGrid->Top abziehen // Position der Zellen ermitteln TRect Rect1 = pXStringGrid->CellRect(Spalte-1,Zeile-1); // CheckBox linke Position zuordnen pCheckBox->Left = pCheckBox->Left // pXStringGrid->Left beibehalten + Rect1.Right // Position Rechts Zelle + pXStringGrid->GridLineWidth +1 // Gitter Linie addieren - pXStringGrid->Left // Positionsverschiebung pXStringGrid->Left abziehen + 12; // Positionierung in der Mitte // CheckBox Höhe zuweisen pCheckBox->Height = (Rect.Bottom - Rect.Top) - 2; // CheckBox Breite zuweisen pCheckBox->Width = (Rect.Right - Rect.Left) - 17; // CheckBox anzeigen pCheckBox->Visible = true; // CheckBox Funktion zuweisen pCheckBox->OnClick = CheckBoxClick; } } }Also, wenn mir nun einfach jemand sagen kann. Schau mal was du da machst, so ruft das doch kein Mensch auf, dann wäre das echt super.
-
Schau mal was du da machst, so ruft das doch kein Mensch auf...

Ja, so ist das auch nichts. Du erzeugst dynamisch jede Menge neue CheckBoxen.
Nur musst du ja irgendwie auch darauf zugreifen können.
Dann machst du dir ein Array oder besser noch einen vector ungefähr so:TCheckBox *checkboxen[9][6];Dann erzeugst du deine Checkboxen
for (int y=0;y<6;y++) { for(int x=0;x<9;x++) { checkboxen[x][y]=new TCheckBox(Form1); checkboxen[x][y]->Parent ... ... } }
-
Ok, meinen Fehler verstehe ich nun. Nur weiß ich immer noch nicht wie ich ihn genau behebe.
TCheckBox *checkboxen[9][6];Das hier geht bei mir nicht, da auch hier die Angabe des Arrays fest definiert sein muß. Wenn ich hier sowas versuche
TCheckBox *checkboxen[Row][Col];bekomme ich eine Fehlermeldung, dass die Ausdrücke Konstant sein müssen.
Mit einem vector habe ich bis jetzt noch nicht gearbeitet. Habe mich aber ein wenig eingelesen. Dabei würde so etwas gehen.
std::vector<TCheckBox*> pCheckBoxstd::vector<TCheckBox*> pCheckBox[];Aber das hier geht nicht.
std::vector<TCheckBox*> pCheckBox[][];So kann ich aber auch meine CheckBoxen nicht mit
checkboxen[x][y]=new TCheckBox(Form1);initialisieren. Es sei denn ich löse es so:
checkboxen[x]=new TCheckBox(Form1);und zähle alle erzeugten vector Komponenten. Aber wird das so gehandhabt?
Wie muß ich eigentlich von einem vector den Speicher wieder freigeben. Habe gelesen, dass er nicht wieder freigegeben wird, wenn das Parent Form gelöscht wird?
-
Dir fehlen ja wirklich noch grundlegende C++ Kenntnisse, und dann willst du eine GUI programmieren.
Ein paar Tips gebe ich dir, aber beschäftige dich erstmal mit einem kleineren Projekt, dann ist der Frustfaktor auch nicht so groß!
1. Du solltest dir ersteinmal die Hilfe zu den Komponenten ansehen, um die Eigenschaften, Methoden und Ereignisse zu verstehen (die BCB6-Hilfe ist dafür besser geeignet als die beim TurboExplorer).
Für ein StringGrid gibt es das Ereignis OnSelectCell (statt das allgemeingültige OnClick)2. Ein std::vector<> kapselt ein dynamisches Array, d.h. du brauchst keine Größe (wie bei den Arrays) angeben:
#include <vector> std::vector<TCheckBox*> pCheckBoxes; // Deklaration des vectors (als privates Form-Member) TCheckBox *pCheckBox = new TCheckBox(0); pCheckBox->Parent = this; ... // weitere Eigenschaften pCheckBoxes->push_back(pCheckBox); // neues Element hinzufügenWie kommt es, daß du noch nicht die Standard-Datentypen der C++ Library kennst (diese werden in jedem C++ Buch / Tutorial und auch hier im Forum erklärt)?
-
Th schrieb:
Dir fehlen ja wirklich noch grundlegende C++ Kenntnisse, und dann willst du eine GUI programmieren.
Ein paar Tips gebe ich dir, aber beschäftige dich erstmal mit einem kleineren Projekt, dann ist der Frustfaktor auch nicht so groß!
Bis jetzt hatte ich nur mit reinem C zu tun. Ich brauche das ganze für das Technikerprojekt. Da komm ich aber mit reinem C nicht so weit, da eine GUI gefordert ist. Der Borland Builder ist die Entwicklungsumgebung, die sie bereits haben und in der das Projekt realisiert werden soll.
Ich habe mir nun ein paar Bücher gekauft von Richard Kaiser und Helmut Erlenkötter und lese mich gerade feste ein. Die Hilfe von Borland Builder nutze ich so gut es geht und ich lese auch viel hier im Forum.
Für ein StringGrid gibt es das Ereignis OnSelectCell (statt das allgemeingültige OnClick)
Das Ereignis habe ich gesehen und ausprobiert. Für mich ist aber die ausgewählte Zelle erstmal nicht von Bedeutung. Ich benutze die StringGrid Komponente um einmal die Anzahl der Checkboxen zu ermitteln und um meine Checkboxen in tabellarischer Form zu den Aufgaben und Level zu positionieren.
Ich möchte wissen ob zu einer bestimmten Aufgabe die CheckBox gesetzt oder nicht gesetzt ist. Diesen Zustand speicher ich mir dann in einem zweidimensionalem Array ab.
So kann ich aus dem CheckBox Zustand und der Tag Variable der Aufgabe vergleichen ob diese auf true oder false ist und erlaube oder verbiete dem jeweiligem User die Benutzung der Aufgabe.So kann ich mir einen Zugriffslevel für jede Aufgabe zusammenbauen.
Ungefähr in dieser Art:
if(Aufgabe.Tag != CheckBoxZustand[x][y]) { // Tue irgendwas } else { // Fehler ausgeben Application->MessageBoxA("Keine Berechtigung","Achtung",MB_OK): }2. Ein std::vector<> kapselt ein dynamisches Array, d.h. du brauchst keine Größe (wie bei den Arrays) angeben
Ok, das wußte ich nicht. Dachte ich könnte da auch sowas wie ein zweidimensionales Array anlegen um dann über die Zellen den jeweiligen CheckBox Zustand abfragen. Würde es erleichtern beim Abspeichern.
Stricke mein Programm mal um. Danke für die Hilfe.
-
Ok, das wußte ich nicht. Dachte ich könnte da auch sowas wie ein zweidimensionales Array anlegen ...
Das kannst du ja auch. Nur mit dem Vorteil das es dynamisch ist.
Und die Abfrage würde dann so aussehenif(CheckBoxZustand[x][y]->Checked) { // Tue irgendwas } else { // Fehler ausgeben Application->MessageBoxA("Keine Berechtigung","Achtung",MB_OK): }
-
Habe mir das Tutorial "Aufbau der STL - Container" durchgelesen und das mit dem vector ausprobiert. Bekomme es aber irgendwie nicht hin auf meine CheckBoxen zuzugreifen.
Sie werden zwar erzeugt und in den vector geschoben, aber den Zustand konnte ich nicht abfragen.
Habe das dann mal mit einfachen integer Werten probiert, dann kann ich die auch wieder auslesen.Habe aber mittlerweile eine andere Lösung für mein Problem.
DynamicArray<TCheckBox*>CheckBox; // CheckBox Container anlegen ... void __fastcall TFormBerechtigungen::PlaceCheckBox(int Row, int Col) { int Anzahl = Row * Col; // Anzahl benötigter CheckBoxen ermitteln CheckBox.Length = Anzahl; // Array auf diese Länge setzten for (int i = 0; i < CheckBox.Length; i++) { CheckBox[i] = new TCheckBox(pXStringGrid); // Neue CheckBoxen erstellen } int i=0; // Bei CheckBox Null beginnen for(int Zeile =1; Zeile<Row; Zeile++) { for(int Spalte =1; Spalte<Col; Spalte++) { CheckBox[i]->Parent = pXStringGrid; CheckBox[i]->Color = clWindow; CheckBox[i]->Alignment = taRightJustify; ... // CheckBox Funktion zuweisen CheckBox[i]->OnClick = CheckBoxClick; i++; // nächste CheckBox } } }Das Array ist zwar nicht Zweidimensional und es ist bestimmt nicht die schönste Lösung, aber zumindest funktioniert es.
Falls mir jemand noch zum Verständnis am Beispiel von Th erklären kann wie ich die CheckBox hole und ihren Zustand erfrage wäre das super.