---- 1. Tipps zur Verwendung von Baumsteuerelementen in Delphi
---- Wir alle wissen, dass Entwickler hauptsächlich Delphi zur Entwicklung von Datenbankverwaltungssoftware verwenden. Aus diesem Grund ist die Verwendung von Baumsteuerelementen am besten mit der Datenbank verknüpft. Delphi bietet ein Baumsteuerelement TTreeView, mit dem komplexe hierarchische Beziehungen beschrieben werden können.
---- 1. Speichern und Laden von Baumknoteninformationen
---- Häufig verwendete Methoden sind die Verwendung der LoadFromFile- und SavetoFile-Methoden des Baumsteuerelements, um die Interaktion zwischen dem Baumsteuerelement und der Datei zu realisieren, oder die Verwendung der Assign-Methode, um die Interaktion zwischen dem Baumsteuerelement und DBMemo zu realisieren , die Interaktion mit der Datenbank. Der Vorteil dieser Methode besteht darin, dass die Programmierung relativ einfach ist. Der Nachteil besteht darin, dass die tatsächliche Anzahl der Knoten der Baumsteuerung sehr groß sein kann. Bei „großen Bäumen“ nimmt die Menge der geladenen und gespeicherten Daten zu Reduzieren Sie die Geschwindigkeit, erhöhen Sie den Systemaufwand und verursachen Sie Datenredundanz. Eine andere Methode besteht darin, nur „sichtbare“ Knoten im Baum zu generieren. Es gibt kein spezielles Datei- oder Datenbankfeld für die Aufzeichnung der gesamten Baumknotenstruktur, und die Baumknotenstruktur ist in jedem Datensatz der Datenbank verteilt.
---- Die spezifische Methode lautet: Erstellen Sie eine Datenbank, die Felder werden entsprechend dem tatsächlichen Geschäft bestimmt, es muss ein Feld vorhanden sein, dessen Informationen auf dem Knoten des Baumsteuerelements angezeigt werden, und es gibt auch ein Feld zum Speichern Die eindeutige Identifikationsnummer des Knotens besteht aus zwei Teilen gleicher Länge. Der erste Teil stellt die Knotennummer des aktuellen Knotens dar. Diese Identifikationsnummer entspricht eine „verknüpfte Liste“, die die Struktur der Knoten im Baum aufzeichnet. Vorteile dieser Methode: Wenn Benutzer einen „großen Baum“ betreiben, erweitern sie im Allgemeinen nicht alle Knoten, sondern verwenden nur einen begrenzten Teil. Gleichzeitig können sie nur Schicht für Schicht von der Wurzel des Baums aus erweitern Die Methode generiert nur „“ auf dem Baum. Daher ist die Geschwindigkeit beim Speichern und Laden von „großen Bäumen“ hoch, die Datenmenge ist gering und der Systemaufwand und die Datenredundanz sind gering. Nachteile: Die Programmierung ist komplizierter, aber diese Methode kann zu einer neuen Baumsteuerung kombiniert werden, was die Programmiereffizienz erheblich verbessert. Es ist zu beachten, dass die ID-Nummer eindeutig sein muss. Daher ist es besonders wichtig, wie die ID bei der Programmierung sinnvoll generiert wird.
---- 2. Beispiel für eine Datenbankstruktur
----Erstellen Sie eine Datenbank. Um den Vorgang zu vereinfachen, erstelle ich nur zwei Datenbankfelder, die wie folgt definiert sind:
Länge des Feldnamentyps
TextC10
LongIDC6
----Das LongID-Feld besteht tatsächlich aus zwei Segmenten. Jedes Segment besteht aus 3 Ziffern. LongID kann nur 1000 Datensätze darstellen. Definieren Sie LongID als Indexfeld und speichern Sie es als c:esttree ree.dbf. Bearbeiten Sie die DBF-Datei, erstellen Sie einen neuen Datensatz, setzen Sie das Feld „Text“ auf „TOP“ und das Feld „LongID“ auf „000“ (drei Leerzeichen vor drei „0“).
---- 3. Erstellen Sie ein Demoprogramm
---- Platzieren Sie TreeView1, Table1, PopupMenu1, Edit1 und Edit2 auf Form1. Das PopupMenu-Attribut von TreeView1 ist auf PopupMenu1 gesetzt; das DataBaseName-Attribut von Table1 ist auf c:esttree gesetzt, das TableName-Attribut ist auf tree.dbf gesetzt und das IndexFieldNames-Attribut ist auf LongID gesetzt; fügen Sie einzelne Elemente Add1 und Del1 zu PopupMenu1 hinzu, und Beschriftung ist Add bzw. Del; Edit1 verwendet, um den Textattributwert des neuen Knotens einzugeben, Edit2 wird verwendet, um die dreistellige ID-Nummer des neuen Knotens einzugeben. Speichern als c:esttree reeunit.pas und c:esttree esttree.dPR. Fügen Sie eine Zeile nach dem Schlüsselwort „Type“ in treeunit.pas hinzu: Pstr:^string;{Pstr ist ein String-Zeiger} Fügen Sie Code für das OnCreate-Ereignis von Form1 hinzu:
procedure TForm1.FormCreate(Sender: TObject);
var p:Pstr;Node:TTreeNode;
beginnen
mit Table1,Treeview1 tun
beginnen
offen;
Erste;
new(p);{Speicher für Zeiger p reservieren}
p^:=FieldByName(′LongID′).AsString;
Node:=Items.AddChildObject(nil,FieldByName
(′Text′).AsString,p);
if HasSubInDbf(Node) then Items
.AddChildObject(Node,′ ′,nil);{Wenn es einen untergeordneten Knoten gibt, fügen Sie einen leeren untergeordneten Knoten hinzu}
Ende;
Ende;
---- HasSubInDbf ist eine benutzerdefinierte Funktion. Die unabhängige Variable ist Node. Überprüfen Sie, ob der Knoten Node untergeordnete Knoten hat. Geben Sie True zurück, wenn vorhanden. Andernfalls geben Sie False zurück. Fügen Sie der Klassendefinition von TForm1 (den Prototypen von) eine Prototypdeklaration hinzu Andere benutzerdefinierte Funktionen werden ebenfalls ohne weitere Erklärung in der Klassendefinition von TForm1 deklariert. Der Funktionscode lautet wie folgt:
function TForm1.HasSubInDbf(Node:TTreeNode):Boolean;
beginnen
mit Tabelle1 tun
beginnen
Table1.FindNearest([copy(Pstr(Node.Data)^,4,3)+′000′]);
result:=copy(FieldByName(′LongID′).
AsString,1,3)=copy(Pstr(Node.Data)^,4,3);
{Zum Beispiel die Summe der ersten drei Ziffern des LongID-Feldinhalts des aktuellen Datensatzes in der Datenbank
Wenn die letzten drei Ziffern der Daten des Knotens gleich sind, sollte der Knoten untergeordnete Knoten haben}
Ende;
Ende;
Fügen Sie Code für das OnDeletion-Ereignis des TreeView1-Steuerelements hinzu. Es sollte darauf hingewiesen werden, dass:
Das OnDeletion-Ereignis kann nicht nur durch den Aufruf der Methode „Delete“ ausgelöst werden, sondern auch vor der Freigabe des Baumsteuerelements selbst.
Das OnDeletion-Ereignis wird ebenfalls ausgelöst, daher ist es „sicher“, dispose(node.data) hier hinzuzufügen:
Prozedur TForm1.TreeView1Deletion
(Sender: TObject; Knoten: TTreeNode);
beginnen
Dispose(Node.Data);{Knotendatenspeicher freigeben}
Ende;
Fügen Sie dem OnClick-Ereignis des Menüelements Add1 den folgenden Code hinzu:
procedure TForm1.Add1Click(Sender: TObject);
var p:pstr;Tmpstr:string;i:integer;
beginnen
versuchen
StrToInt(Edit2.Text);
Tmpstr:=Edit2.Text;{Hinweis: In der Praxis muss eine bessere Methode zum Generieren der ID verwendet werden}
außer;
ShowMessage('Geben Sie den Inhalt von Edit2 erneut ein');
abbrechen;
Ende;
mit TreeView1 tun
beginnen
neu(p);
p^:=copy(Pstr(Selected.Data)^,4,3)+TmpStr;
Items.AddChildObject(Selected,Edit1.Text,p);
Ende;
mit Table1 do{Eintrag in Datenbank hinzufügen}
beginnen
Anhängen;
FieldByName(′Text′).AsString:=Edit1.text;
FieldByName(′LongID′).AsString:=p^;
Post;
Ende;
TmpStr:=inttostr(strtoint(TmpStr)+1);
for i:=length(TmpStr) to 2 do TmpStr:=′0′+TmpStr;
Edit2.Text:=TmpStr;
Ende;
Fügen Sie dem OnClick-Ereignis des Menüelements Del1 den folgenden Code hinzu:
procedure TForm1.Del1Click(Sender: TObject);
var DelList:TStringList;LongID,NSubLongID:string;
beginnen
DelList:=TStringList.create;
DelList.Sorted:=True;
DelList.Add(Pstr(TreeView1.Selected.Data)^);
während DelList.Count>0 dies tut
beginnen
LongID:=DelList.Strings[0];
DelList.Delete(0);
Table1.SetKey;
Table1.FieldByName(′LongID′).AsString:=LongID;
if Table1.GotoKey then Table1.Delete;
if HasSubInDbf(TreeView1.Selected) dann
beginnen
NSubLongID:=Table1.FieldByName(′LongID′).AsString;
while (copy(NSubLongID,1,3)=copy
(LongID,4,3))und(nicht Table1.Eof) tun dies
beginnen
dellist.Add(NSubLongId);
Table1.Next;
NSubLongId:=Table1.FieldByName(′LongID′).AsString;
Ende;
Ende;
Ende;
DelList.Free;
TreeView1.Items.Delete(TreeView1.Selected);
Ende;
Fügen Sie Code für das OnExpanding-Ereignis von TreeView1 hinzu:
Prozedur TForm1.TreeView1Expanding
(Sender: TObject; Knoten: TTreeNode;
var AllowExpansion: Boolean);
var TmpNode:TTreeNode;NSubLongID:
String;p:Pstr;bm:TBookMark;
beginnen
mit Table1,TreeView1 tun
beginnen
Items.BeginUpdate;
SetKey;
FieldByName(′LongID′).AsString:=Pstr(Node.Data)^;
Wenn nicht GotoKey, dann Items.Delete(Node)
anders
beginnen
TmpNode:=Node.GetFirstChild;
if (TmpNode.Text=′ ′)and(TmpNode.Data=nil) then
beginnen
TmpNode.Delete;
if HasSubInDbf(Node) dann
beginnen
NSubLongID:=FieldByName(′LongID′).AsString;
while (copy(NSubLongID,1,3)=copy(Pstr
(Node.Data)^,4,3))und(nicht Eof) tun
beginnen
neu(p);
p^:=FieldByName(′LongID′).AsString;
bm:=GetBookMark;
TmpNode:=Items.AddChildObject(Node,
FieldByName(′Text′).AsString,p);
if HasSubInDbf(TmpNode) then Items.
AddChildObject(TmpNode,′ ′,nil);
GotoBookMark(bm);
FreeBookMark(bm);
Nächste;
NSubLongId:=FieldByName(′LongID′).AsString;
Ende; Ende; Ende;
Ende;
Items.EndUpdate;
Ende;
Ende;
---- Im Folgenden wird kurz auf die grundlegende Methode der Baumanzeige der Datenbank eingegangen. Außerdem wird beim Bearbeiten des Textattributs des Knotens im Baum gleichzeitig die Datenbank geändert Mehrere Benutzer gleichzeitig, die Konsistenz der Datenbank und des Baums sowie des Baums. Die Kopie und Replikation des oberen Knotens wird nicht im Detail beschrieben, und der Leser kann sie selbst verbessern.
---- 2. Verwendung der IP-Steuerung
---- In Netzwerkprogrammen kommt es häufig vor, dass Benutzer IP-Adressen eingeben müssen. Da uns Delphi jedoch kein Steuerelement zur Verfügung stellt, mit dem wir die IP-Zeichenfolge eingeben können, müssen wir das Tedit-Steuerelement (einzeiliges Textfeld) verwenden, um die vom Benutzer eingegebene IP-Zeichenfolge zu akzeptieren. Die Verwendung von Tedit zur Eingabe eines IP-Strings ist jedoch keine gute Idee, da die Handhabung sehr umständlich ist. Tatsächlich gibt es neben uns ein Windows-Steuerelement speziell für die Eingabe von IP-Strings. Das IP-Steuerelement weist illegale IP-Zeichenfolgen zurück (in jedem Teil können nur Zahlen zwischen 0 und 255 eingegeben werden). Dadurch können Sie problemlos den IP-Wert (32-Bit-Ganzzahl) ermitteln, der dem IP-Zeichenfolge im Steuerelement entspricht erspart Ihnen die Umrechnung zwischen IP-Strings und IP-Werten; außerdem können Sie den Bereich der IPs einschränken, die in die IP-Steuerung eingegeben werden können. In diesem Abschnitt wird erläutert, wie Sie Windows-IP-Steuerelemente in unserem Delphi-Programm verwenden.
---- In Windows gibt es zwei sehr wichtige dynamische Linkbibliotheken: commctrl.dll und comctl32.dll, bei denen es sich um die benutzerdefinierten Steuerelementbibliotheken von Windows (Windows Common Controls) handelt. Die benutzerdefinierte Steuerelementbibliothek enthält viele häufig verwendete Windows-Steuerelemente wie Statusbar, Coolbar, HotKey usw.; in Delphi wurden die meisten dieser Steuerelemente als visuelle Steuerelemente verpackt. Nach dem Start von Internet Explorer 3 durch Microsoft wurden der benutzerdefinierten Steuerelementbibliothek einige neue Steuerelemente hinzugefügt, darunter das Windows-IP-Steuerelement (Steuerelement zum Bearbeiten der IP-Adresse).
---- 1. Initialisieren Sie die benutzerdefinierte Windows-Steuerelementbibliothek
---- Windows bietet zwei API-Funktionen, InitCommonControls und InitCommonControlsEx, zum Initialisieren benutzerdefinierter Steuerelementbibliotheken. Anhand der Namen ist die Beziehung zwischen diesen beiden API-Funktionen nicht schwer zu erkennen: Letztere ist eine Erweiterung der ersteren. Wenn Sie IP-Steuerelemente in Ihrem Programm verwenden möchten, müssen Sie InitCommonControlsEx verwenden, um die Initialisierung benutzerdefinierter Steuerelementbibliotheken und -klassen abzuschließen. Der Prototyp der Funktion InitCommonControlsEx lautet wie folgt (Pascal-Syntax):
... ...
Erstellen Sie eine IP-Kontrolle
... ...
Verwenden Sie IP-Kontrollen. Im Programm kommunizieren wir mit der IP-Steuerung, indem wir Nachrichten an sie senden.
Die IP-Steuerung kann auf die folgenden sechs Meldungen reagieren. Diese Meldungen und ihre Bedeutung sind in der folgenden Tabelle aufgeführt:
... ...
Wenn Sie den IP-Wert erhalten möchten, der der IP-Zeichenfolge im IP-Steuerelement entspricht, sollten Sie senden
IPM_GETADDRESS-Nachricht und erfordert eine 32-Bit-Ganzzahladresse als
Der letzte Parameter von SendMessage.
... ...
---- 2. Benachrichtigungsmeldung zur IP-Kontrolle
---- Wenn die IP-Zeichenfolge geändert oder der Eingabefokus übertragen wird, sendet das IP-Steuerelement die Benachrichtigungsnachricht IPN_FIELDCHANGED an sein übergeordnetes Fenster. In den meisten Fällen können wir diese Benachrichtigung ignorieren. Das Folgende ist ein Beispiel für die Behandlung der Benachrichtigungsnachricht IPN_FIELDCHANGED:
procedure Tform1.WndProc(var Msg: TMessage);
var p:PNMHDR;
beginnen
geerbt;
wenn Msg.Msg=WM_NOTIFY
dann fang an
p:=Pointer(Msg.lParam);
wenn p^.code=IPN_FIELDCHANGED
dann fang an
{…
Verarbeiten der IPN_FIELDCHANGED-Benachrichtigungsnachricht des IP-Steuerelements
…}
Ende;
Ende;
Ende;
---- 3. Methoden und Anwendungen zur dynamischen Generierung von Steuerelementen
---- 1.Zwei Methoden zum Generieren von Steuerelementen in Delphi
---- (1). Steuerelemente im Formulardesign generieren
---- Beim Entwerfen eines Formulars ist es üblich, das erforderliche Steuerelement direkt in der Steuerelement-Toolbox auszuwählen, dann seine Eigenschaften festzulegen und auf Ereignisse zu reagieren.
---- (2). Steuerelemente im Programm dynamisch generieren
---- Manchmal müssen wir Steuerelemente dynamisch generieren, wenn das Programm ausgeführt wird. Dies hat zwei große Vorteile: Erstens kann es die Flexibilität des Programms erhöhen des Programms, offensichtlich Methode eins Es kann nicht realisiert werden und die dynamische Generierungsmethode im Programm muss verwendet werden.
---- Die Methode zum dynamischen Generieren von Steuerelementen im Programm ist in drei Schritte unterteilt: Definieren Sie zunächst den Typ des generierten Steuerelements, generieren Sie dann das Steuerelement mit der Funktion Erstellen und weisen Sie schließlich den relevanten Eigenschaften des Steuerelements Werte zu Kontrolle. Am Beispiel des TButton-Steuerelements sind die Schritte wie folgt:
---- a. Kontrolltyp definieren
var
Button1:TButton;
---- b. Steuerelemente generieren
Button1:=TButton.Create(self);
Button1.Parent:=Selbst;
// Im Allgemeinen wird das übergeordnete Steuerelement auf „Selbst“ gesetzt. Wenn der Wert von „Parent“ nicht festgelegt ist,
dann wird das Steuerelement nicht auf dem Bildschirm angezeigt
//zeige es an
---- c. Legen Sie andere Eigenschaften fest und definieren Sie zugehörige Ereignisreaktionsfunktionen, wie z. B. die Ereignisreaktionsfunktionen „Beschriftung“, „Links“, „Oben“, „Höhe“, „Breite“, „Sichtbar“, „Aktiviert“, „Hinweis“ und „onClick“.
---- 2. Anwendung einer dynamisch generierten Steuerungsmethode
---- Bei der Entwicklung von Produktionsplanungs- und -verwaltungssystemen ist es erforderlich, Produktionsplanungsdiagramme dynamisch zu generieren, die durch Gantt-Diagramme dargestellt werden, und es ist sehr nützlich, Formsteuerelemente zu verwenden, um den Verarbeitungsstatus von Teilen (die Verarbeitungsstartzeit) anzuzeigen und Endzeit jedes Prozesses). Mithilfe der Diagrammsteuerung wird die Auslastung der Verarbeitungsgeräte in einem dreidimensionalen Histogramm angezeigt, was sehr intuitiv ist. Jetzt erklären wir den Prozess der dynamischen Generierung von Formsteuerung und Diagrammsteuerung im Programm.
---- (1). Formsteuerung dynamisch generieren, um ein Produktionsplanungsdiagramm (Gantt-Diagramm) anzuzeigen.
Prozedur TCreateMultiCharts.ProcCreateCharts;
var
i,j,Rows,Columns,RowSpace,ChartsHeight:Integer;
ShapeChart:Array des Arrays von TShape;
beginnen
Rows:=16; //Die Anzahl der Zeilen im Shape-Kontrollarray
Columns:=8; //Spaltennummer des Formkontrollarrays
RowSpace:=20; // Formsteuerung des Zeilenabstands
ChartsHeight:=20; // Formkontrollhöhe
SetLength(ShapeChart,Rows,Columns);
//Legen Sie die Größe des ShapeChart-Arrays fest
for i:=0 to Rows do
for j:=0 to Columns do
beginnen
ShapeChart[i][j]:=TShape.Create(self);
mit ShapeChart[i,j] tun
beginnen
Parent:=Self; //Diese Zeile ist wichtig,
Andernfalls wird das Shape-Steuerelement nicht auf dem Bildschirm angezeigt.
Shape:=stRectangle; // Formsteuerungsform ist Rechteck
Top:=45+i*(RowSpace+ChartsHeight);
Left:=Round(180+Q[i,j].StartTime);
//Da Q[i,j].StartTime eine reelle Zahl ist, muss sie gerundet werden.
Breite:=Rund(Q[i,j].Wert)
Height:=ChartsHeight;
Brush.Color:=RandomColor;
//Benutzerdefinierte Funktion, Anweisungen sind beigefügt
Brush.Style:=bsSolid; //Legen Sie die Füllmethode fest
Aktiviert:=True;
Ende;
Ende;
Ende;
---- Hinweis: aQ ist ein zweidimensionales Array vom Datensatztyp, das wie folgt definiert ist:
Typ
TempData=Datensatz
Wert:Real;
Startzeit:Real;
Ende;
F:Array eines Arrays von TempData
Und den Komponenten von Q wurden in einem anderen Prozess Werte zugewiesen.
---- b. Um verschiedene Teile zu unterscheiden, wird Shape in verschiedenen Farben angezeigt. Zu diesem Zeitpunkt wird die Funktion RandomColor aufgerufen. Die Funktion ist:
Funktion TCreateMultiCharts.RandomColor;
var
rot,grün,blau:byte;
beginnen
rot:=zufällig(255);
grün:=random(255);
blau:=zufällig(255);
Ergebnis:=rot oder (grüner SHL 8) oder (blauer SHL 16);
Ende;
---- (2). Generieren Sie dynamisch die ChartSeries-Komponente des Charts-Steuerelements, um die Geräteauslastung anzuzeigen
Prozedur TFormMultiMachinesBurthen.
ShowMachineBurthenCharts;
var
i:Integer;
Burthen:Echt;
SeriesClass:TChartSeriesClass;
NewSeries:Array von TChartSeries;
beginnen
SetLength(NewSeries,CreateMultiCharts.Rows);
MaschinenBurthenCharts.height:=200;
MaschinenBurthenCharts.Width:=550;
for i:=0 to CreateMultiCharts.Rows tun
beginnen
SeriesClass:=TBarSeries; //Stellen Sie die Form auf ein dreidimensionales Balkendiagramm ein
NewSeries[i]:=SeriesClass.Create(Self);
NewSeries[i].ParentChart:=MachinesBurthenCharts;
NewSeries[i].Clear;
Burthen:=MachineBurthen[i];
Burthen:=Round(Burthen*100)/100; //Nur zwei Nachkommastellen übernehmen
NewSeries[i].add(Burthen,',NewSeries[i].SeriesColor);
Ende;
Ende;
---- Hinweis: (a).MachineBurthen[i] ist ein reales Array, sein Wert ist die Auslastung des entsprechenden Geräts, die in einer anderen Funktion berechnet wurde;
---- (b). MachinesBurthenCharts ist ein TChart-Steuerelement, das im Abschnitt „Typ“ beschrieben wird.
---- 3. Anzeige der Ergebnisse des Programmlaufs
---- (1) Generieren Sie dynamisch ein Shape-Steuerelement, um den Teileplanungsplan anzuzeigen (weggelassen).
---- (2) Generieren Sie dynamisch die ChartSeries-Komponente des Chart-Steuerelements und zeigen Sie die Geräteauslastung an (weggelassen).