---- 1. نصائح لاستخدام عناصر التحكم في الشجرة في دلفي
---- نعلم جميعًا أن المطورين يستخدمون دلفي بشكل أساسي لتطوير برامج إدارة قواعد البيانات، ولهذا السبب، فإن استخدام عناصر التحكم الشجرية يرتبط بشكل أفضل بقاعدة البيانات. توفر دلفي أداة تحكم شجرة TTreeView، والتي يمكن استخدامها لوصف العلاقات الهرمية المعقدة.
---- 1. تخزين وتحميل معلومات عقدة الشجرة
---- الطرق المستخدمة بشكل شائع هي استخدام طريقتي LoadFromFile وSavetoFile للتحكم في الشجرة لتحقيق التفاعل بين عنصر تحكم الشجرة والملف، أو استخدام طريقة التعيين لتحقيق التفاعل بين التحكم في الشجرة وDBMemo والتفاعل مع قاعدة البيانات. ميزة هذه الطريقة هي أن البرمجة بسيطة نسبيًا، والعيب هو أن العدد الفعلي للعقد في التحكم في الشجرة قد يكون كبيرًا جدًا بالنسبة إلى "الأشجار الكبيرة"، مما يؤدي إلى زيادة كمية البيانات المحملة والمخزنة تقليل السرعة وزيادة حمل النظام، مما يؤدي إلى تكرار البيانات. هناك طريقة أخرى تتمثل في إنشاء العقد "المرئية" فقط في الشجرة، دون وجود ملف أو حقل قاعدة بيانات يسجل على وجه التحديد بنية عقدة الشجرة بأكملها، وتفريق بنية عقدة الشجرة في كل سجل من قاعدة البيانات.
---- الطريقة المحددة هي: إنشاء قاعدة بيانات، ويتم تحديد الحقول وفقًا للأعمال الفعلية، ويجب أن يكون هناك حقل واحد سيتم عرض معلوماته على عقدة التحكم بالشجرة، كما يوجد أيضًا حقل لحفظ رقم التعريف الفريد للعقدة. يتكون رقم التعريف من جزأين متساويين في الطول، الجزء الأول يمثل رقم العقدة الأصلية للعقدة الحالية، والجزء الأخير يمثل رقم العقدة الحالية "قائمة مرتبطة" تسجل بنية العقد الموجودة على الشجرة. مزايا هذه الطريقة: عندما يقوم المستخدمون بتشغيل "شجرة كبيرة"، فإنهم عمومًا لا يقومون بتوسيع جميع العقد، ولكن يستخدمون فقط جزءًا محدودًا، وفي الوقت نفسه، يمكنهم فقط توسيع طبقة بعد طبقة من جذر الشجرة تنشئ الطريقة "" فقط على العقد "المرئية" على الشجرة، وبالتالي فإن سرعة تخزين وتحميل "الأشجار الكبيرة" سريعة، وكمية البيانات صغيرة، والحمل الزائد للنظام وتكرار البيانات صغير. العيوب: البرمجة أكثر تعقيدًا، ولكن يمكن دمج هذه الطريقة لتكوين شجرة تحكم جديدة، مما سيؤدي إلى تحسين كفاءة البرمجة بشكل كبير. تجدر الإشارة إلى أن رقم المعرف يجب أن يكون فريدًا، لذا فإن كيفية إنشاء المعرف بشكل معقول في البرمجة أمر مهم بشكل خاص.
---- 2. مثال على بنية قاعدة البيانات
----إنشاء قاعدة بيانات لتبسيط الإجراء، أقوم فقط بإنشاء حقلين في قاعدة البيانات، محددين على النحو التالي:
طول نوع اسم الحقل
نصC10
LongIDC6
----يتكون حقل LongID في الواقع من جزأين، كل مقطع مكون من 3 أرقام، ويمكن أن يمثل LongID 1000 سجل فقط. قم بتعريف LongID كحقل فهرس واحفظه كـ c: esttree ree.dbf. تحرير ملف DBF، وإنشاء سجل جديد، وتعيين حقل النص إلى TOP، وتعيين حقل LongID إلى "000" (ثلاث مسافات قبل ثلاث "0").
---- 3. إنشاء برنامج تجريبي
---- ضع TreeView1 وTable1 وPopupMenu1 وEdit1 وEdit2 في Form1. تم تعيين سمة PopupMenu الخاصة بـ TreeView1 على PopupMenu1؛ وتم تعيين سمة DataBaseName الخاصة بالجدول 1 على c: esttree، وتم تعيين سمة TableName على Tree.dbf، وتم تعيين سمة IndexFieldNames على LongID؛ وأضف عناصر فردية Add1 وDel1 إلى PopupMenu1، والتسمية التوضيحية هي إضافة وDel على التوالي؛ ويستخدم Edit1 لإدخال قيمة سمة النص للعقدة الجديدة، ويتم استخدام Edit2 لإدخال رقم المعرف المكون من 3 أرقام للعقدة الجديدة. احفظ باسم c:esttree reeunit.pas وc:esttree esttree.dPR. أضف سطرًا بعد الكلمة الأساسية Type في Treeunit.pas: Pstr:^string;{Pstr is a string pointer} أضف رمزًا لحدث OnCreate الخاص بـ Form1:
الإجراء TForm1.FormCreate(Sender: TObject);
var p:Pstr;Node:TTreeNode;
يبدأ
مع Table1، Treeview1 القيام به
يبدأ
يفتح؛
أولاً؛
جديد (ع)؛ {تخصيص الذاكرة للمؤشر ص}
p^:=FieldByName('LongID').AsString;
Node:=Items.AddChildObject(nil,FieldByName
('النص').AsString،p)؛
إذا كان HasSubInDbf(Node) ثم Items
.AddChildObject(Node, ′ ′,nil);{إذا كانت هناك عقدة فرعية، أضف عقدة فرعية فارغة}
نهاية؛
نهاية؛
---- HasSubInDbf هي وظيفة مخصصة، المتغير المستقل هو Node، تحقق مما إذا كانت العقدة لديها عقد فرعية، قم بإرجاع True إذا كانت هناك، وإلا قم بإرجاع False، وأضف إعلان نموذج أولي إلى تعريف فئة TForm1 (النماذج الأولية لـ تم أيضًا الإعلان عن وظائف مخصصة أخرى في تعريف فئة TForm1 دون مزيد من التوضيح)، رمز الوظيفة كما يلي:
وظيفة TForm1.HasSubInDbf(Node:TTreeNode):Boolean;
يبدأ
مع Table1 القيام به
يبدأ
Table1.FindNearest([copy(Pstr(Node.Data)^,4,3)+′000′]);
النتيجة: = نسخة (FieldByName('LongID').
AsString,1,3)=copy(Pstr(Node.Data)^,4,3);
{على سبيل المثال، مجموع الأرقام الثلاثة الأولى لمحتوى حقل LongID للسجل الحالي في قاعدة البيانات
إذا كانت الأرقام الثلاثة الأخيرة من بيانات العقدة هي نفسها، فيجب أن تحتوي العقدة على عقد فرعية}
نهاية؛
نهاية؛
إضافة تعليمات برمجية للحدث OnDeletion لعنصر التحكم TreeView1 تجدر الإشارة إلى ذلك.
لا يمكن تشغيل حدث OnDeletion فقط عن طريق استدعاء أسلوب الحذف، ولكن أيضًا قبل تحرير عنصر تحكم الشجرة نفسه،
يتم أيضًا تشغيل الحدث OnDeletion، لذلك من "الآمن" إضافةتخلص (node.data) هنا:
الإجراء TForm1.TreeView1Deletion
(المرسل: TObject؛ العقدة: TTreeNode)؛
يبدأ
التخلص (Node.Data)؛ {تحرير ذاكرة بيانات العقدة}
نهاية؛
أضف التعليمة البرمجية التالية إلى حدث OnClick لعنصر القائمة Add1:
الإجراء TForm1.Add1Click(Sender: TObject);
فار p:pstr;Tmpstr:string;i:integer;
يبدأ
يحاول
StrToInt(Edit2.Text);
Tmpstr:=Edit2.Text;{ملاحظة: في الممارسة العملية، يجب استخدام طريقة أفضل لإنشاء المعرف}
يستثني؛
ShowMessage('أعد إدخال محتوى Edit2');
إحباط؛
نهاية؛
مع TreeView1 القيام به
يبدأ
جديد(ع);
p^:=copy(Pstr(Selected.Data)^,4,3)+TmpStr;
Items.AddChildObject(Selected,Edit1.Text,p);
نهاية؛
باستخدام الجدول 1، افعل {أضف سجلاً في قاعدة البيانات}
يبدأ
إلحاق؛
FieldByName('Text').AsString:=Edit1.text;
FieldByName('LongID').AsString:=p^;
بريد؛
نهاية؛
TmpStr:=inttostr(strtoint(TmpStr)+1);
for i:=length(TmpStr) to 2 do TmpStr:=′0′+TmpStr;
Edit2.Text:=TmpStr;
نهاية؛
أضف التعليمة البرمجية التالية إلى حدث OnClick لعنصر القائمة Del1:
الإجراء TForm1.Del1Click(Sender: TObject);
فار DelList:TSTringList;LongID,NSubLongID:string;
يبدأ
DelList:=TSTringList.create;
DelList.Sorted:=True;
DelList.Add(Pstr(TreeView1.Selected.Data)^);
بينما DelList.Count>0 يفعل
يبدأ
LongID:=DelList.Strings[0];
DelList.Delete(0);
Table1.SetKey;
Table1.FieldByName('LongID').AsString:=LongID;
إذا Table1.GotoKey ثم Table1.Delete؛
إذا HasSubInDbf(TreeView1.Selected) ثم
يبدأ
NSubLongID:=Table1.FieldByName('LongID').AsString;
while (copy(NSubLongID,1,3)=copy
(LongID,4,3)) و(وليس Table1.Eof) يفعلان ذلك
يبدأ
dellist.Add(NSubLongId);
الجدول 1. التالي؛
NSubLongId:=Table1.FieldByName('LongID').AsString;
نهاية؛
نهاية؛
نهاية؛
DelList.Free;
TreeView1.Items.Delete(TreeView1.Selected);
نهاية؛
أضف رمزًا لحدث OnExpanding الخاص بـ TreeView1:
الإجراء TForm1.TreeView1Expanding
(المرسل: TObject؛ العقدة: TTreeNode؛
varallowExpansion: Boolean);
فار TmpNode:TTreeNode;NSubLongID:
سلسلة؛ص:Pstr؛bm:TBookMark؛
يبدأ
مع Table1، TreeView1 القيام به
يبدأ
Items.BeginUpdate;
SetKey;
FieldByName('LongID').AsString:=Pstr(Node.Data)^;
إذا لم يكن GotoKey ثم Items.Delete(Node)
آخر
يبدأ
TmpNode:=Node.GetFirstChild;
إذا (TmpNode.Text=′ ′) و(TmpNode.Data=nil) إذن
يبدأ
TmpNode.Delete;
إذا HasSubInDbf (عقدة) ثم
يبدأ
NSubLongID:=FieldByName('LongID').AsString;
while (copy(NSubLongID,1,3)=copy(Pstr
(Node.Data)^,4,3)) و(not Eof) افعل ذلك
يبدأ
جديد(ع);
p^:=FieldByName('LongID').AsString;
bm:=GetBookMark;
TmpNode:=Items.AddChildObject(عقدة،
FieldByName('Text').AsString,p);
إذا كان HasSubInDbf(TmpNode) ثم Items.
AddChildObject(TmpNode, ′ ′,nil);
GotoBookMark(bm);
FreeBookMark(bm);
التالي؛
NSubLongId:=FieldByName('LongID').AsString;
النهاية؛
نهاية؛
Items.EndUpdate;
نهاية؛
نهاية؛
---- يتحدث ما ورد أعلاه بإيجاز عن الطريقة الأساسية لعرض شجرة قاعدة البيانات. بالإضافة إلى ذلك، عند تحرير سمة النص للعقدة في الشجرة، يتم تعديل قاعدة البيانات في نفس الوقت لن يتم وصف تناسق قاعدة البيانات والشجرة والشجرة مع العديد من المستخدمين في نفس الوقت بالتفصيل، ولن يتم وصف النسخة والنسخ المتماثل للعقدة العليا، ويمكن للقراء تحسينها بأنفسهم.
---- 2. استخدام التحكم في الملكية الفكرية
---- في برامج الشبكة، غالبًا ما نواجه مواقف حيث يُطلب من المستخدمين إدخال عناوين IP. ومع ذلك، لا توفر لنا دلفي عنصر تحكم يمكن استخدامه لإدخال سلسلة IP، لذلك يتعين علينا استخدام عنصر تحكم Tedit (مربع نص من سطر واحد) لقبول سلسلة IP التي أدخلها المستخدم. ومع ذلك، فإن استخدام Tedit لإدخال سلسلة IP ليس فكرة جيدة لأنه من غير المناسب التعامل معه. في الواقع، يوجد بجانبنا عنصر تحكم Windows مخصص لإدخال سلاسل IP. سيرفض عنصر التحكم IP سلاسل IP غير القانونية (يمكن إدخال أرقام تتراوح بين 0..255 فقط في كل جزء)؛ فهو يتيح لك بسهولة الحصول على قيمة IP (عدد صحيح 32 بت) المطابق لسلسلة IP في عنصر التحكم يوفر عليك عناء التحويل بين سلاسل IP وقيم IP؛ بالإضافة إلى ذلك، يمكنك أيضًا تحديد نطاق عناوين IP التي يمكن إدخالها في عنصر تحكم IP. يقدم هذا القسم كيفية استخدام عناصر تحكم Windows IP في برنامج دلفي الخاص بنا.
---- هناك مكتبتان مهمتان جدًا للارتباطات الديناميكية في Windows: commctrl.dll وcomctl32.dll، وهما مكتبات التحكم المخصصة في Windows (عناصر التحكم العامة في Windows). تحتوي مكتبة التحكم المخصصة على العديد من عناصر تحكم Windows شائعة الاستخدام، مثل شريط الحالة، وCoolbar، وHotKey، وما إلى ذلك؛ وفي دلفي، تم تجميع معظم عناصر التحكم هذه كعناصر تحكم مرئية. بعد أن قامت Microsoft بإطلاق Internet Explorer 3، تمت إضافة بعض عناصر التحكم الجديدة إلى مكتبة التحكم المخصصة، بما في ذلك عنصر تحكم Windows IP (التحكم في تحرير عنوان IP).
---- 1. تهيئة مكتبة التحكم المخصصة لنظام التشغيل Windows
---- يوفر Windows وظيفتين لواجهة برمجة التطبيقات (API)، InitCommonControls وInitCommonControlsEx، لتهيئة مكتبات التحكم المخصصة. من خلال الأسماء، ليس من الصعب رؤية العلاقة بين هاتين الوظيفتين لواجهة برمجة التطبيقات: فالأخيرة عبارة عن تعزيز للأولى. إذا كنت تريد استخدام عناصر تحكم IP في برنامجك، فيجب عليك استخدام InitCommonControlsEx لإكمال تهيئة مكتبات وفئات التحكم المخصصة. النموذج الأولي للوظيفة InitCommonControlsEx كما يلي (بناء جملة باسكال):
... ...
إنشاء تحكم IP
... ...
استخدم ضوابط IP. نقوم في البرنامج بالتواصل مع جهاز التحكم IP عن طريق إرسال رسائل إليه.
يمكن لعنصر التحكم IP الرد على الرسائل الستة التالية ومعانيها موضحة في الجدول أدناه:
... ...
إذا كنت ترغب في الحصول على قيمة IP المقابلة لسلسلة IP في عنصر تحكم IP، فيجب عليك الإرسال
رسالة IPM_GETADDRESS، وتتطلب عنوانًا صحيحًا بطول 32 بت
المعلمة الأخيرة من SendMessage.
... ...
---- 2. رسالة إعلام بالتحكم في IP
---- عندما يتم تغيير سلسلة IP أو نقل تركيز الإدخال، سيرسل عنصر تحكم IP رسالة الإعلام IPN_FIELDCHANGED إلى نافذته الأصلية. في معظم الحالات، يمكننا تجاهل رسالة الإشعار هذه. ما يلي هو مثال للتعامل مع رسالة الإعلام IPN_FIELDCHANGED:
الإجراء Tform1.WndProc(var Msg: TMessage);
فار ص:PNMHDR؛
يبدأ
موروث؛
إذا Msg.Msg=WM_NOTIFY
ثم ابدأ
ع:=مؤشر(Msg.lParam);
إذا كان p^.code=IPN_FIELDCHANGED
ثم ابدأ
{…
معالجة رسالة الإعلام IPN_FIELDCHANGED الخاصة بعنصر تحكم IP
…}
نهاية؛
نهاية؛
نهاية؛
---- 3. طرق وتطبيقات توليد عناصر التحكم ديناميكيًا
---- 1. طريقتان لتوليد عناصر التحكم في دلفي
---- (1). إنشاء عناصر التحكم في تصميم النموذج
---- عند تصميم نموذج، من الشائع تحديد عنصر التحكم المطلوب مباشرة في صندوق أدوات التحكم، ثم تعيين خصائصه والاستجابة للأحداث.
---- (2). إنشاء عناصر التحكم في البرنامج بشكل ديناميكي
---- في بعض الأحيان، نحتاج إلى إنشاء عناصر تحكم ديناميكيًا أثناء تشغيل البرنامج. وهذا له ميزتان رئيسيتان: أولاً، يمكن أن يزيد من مرونة البرنامج؛ وثانيًا، إذا كان عدد عناصر التحكم التي تم إنشاؤها مرتبطًا بنتائج التشغيل المتوسطة من الواضح أن الطريقة الأولى لا يمكن تحقيقها، ويجب استخدام طريقة التوليد الديناميكي في البرنامج.
---- تنقسم طريقة إنشاء عناصر التحكم ديناميكيًا في البرنامج إلى ثلاث خطوات. أولاً، حدد نوع عنصر التحكم الذي تم إنشاؤه، ثم استخدم وظيفة الإنشاء لإنشاء عنصر التحكم، وأخيرًا قم بتعيين قيم للخصائص ذات الصلة لعنصر التحكم. يتحكم. بأخذ التحكم TButton كمثال، فإن الخطوات هي كما يلي:
---- أ. تحديد نوع التحكم
فار
Button1:TButton؛
---- ب. إنشاء الضوابط
Button1:=TButton.Create(self);
Button1.Parent:=Self;
// بشكل عام، قم بتعيين عنصر التحكم الأصلي الخاص به على Self.
ثم لن يكون التحكم على الشاشة
// اعرضه
---- ج. قم بتعيين خصائص أخرى وحدد وظائف الاستجابة للأحداث ذات الصلة، مثل وظائف الاستجابة للحدث Caption وLeft وTop وHeight وWidth وVisible وEnabled وHint وonClick، وما إلى ذلك.
---- 2. تطبيق طريقة التحكم المولدة ديناميكيًا
---- في تطوير جدولة الإنتاج وأنظمة الإدارة، من الضروري إنشاء مخططات جدولة الإنتاج ديناميكيًا، ممثلة بمخططات جانت، ومن المفيد جدًا استخدام عناصر التحكم في الشكل لعرض حالة معالجة الأجزاء (وقت بدء المعالجة ووقت انتهاء كل عملية مناسب). باستخدام التحكم في الرسم البياني، يتم عرض استخدام معدات المعالجة في رسم بياني ثلاثي الأبعاد، وهو أمر بديهي للغاية. الآن سنشرح عملية توليد التحكم في الشكل والتحكم في المخطط بشكل ديناميكي في البرنامج.
---- (1). إنشاء التحكم في الشكل ديناميكيًا لعرض مخطط خطة جدولة الإنتاج (مخطط جانت).
الإجراء TCreateMultiCharts.ProcCreateCharts;
فار
i,j,Rows,Columns,RowSpace,ChartsHeight:Integer;
ShapeChart: صفيف من مجموعة TShape؛
يبدأ
Rows:=16; // عدد الصفوف في مصفوفة التحكم في الشكل
الأعمدة: = 8؛ // رقم عمود صفيف التحكم في الشكل
RowSpace:=20; // تباعد صفوف التحكم في الشكل
ChartsHeight:=20;
SetLength(ShapeChart,Rows,Columns);
// قم بتعيين حجم صفيف ShapeChart
لأني:=0 للقيام بالصفوف
لـ j:=0 إلى الأعمدة تفعل
يبدأ
ShapeChart[i][j]:=TShape.Create(self);
باستخدام ShapeChart[i,j] do
يبدأ
الأصل:=Self; // هذا السطر ضروري،
وبخلاف ذلك، لن يتم عرض عنصر التحكم في الشكل على الشاشة.
Shape:=stRectangle; // شكل التحكم في الشكل مستطيل
الأعلى:=45+i*(RowSpace+ChartsHeight);
Left:=Round(180+Q[i,j].StartTime);
// لأن Q[i,j].StartTime هو رقم حقيقي، ويجب تقريبه.
العرض:=Round(Q[i,j].Value)
الارتفاع:=ارتفاع المخططات;
Brush.Color:=RandomColor;
// وظيفة مخصصة، يتم إرفاق التعليمات
Brush.Style:=bsSolid; // اضبط طريقة التعبئة
ممكّن:=صحيح؛
نهاية؛
نهاية؛
نهاية؛
---- ملاحظة: aQ عبارة عن مصفوفة ثنائية الأبعاد من نوع السجل، ويتم تعريفها على النحو التالي:
يكتب
TempData=سجل
القيمة: حقيقية؛
وقت البدء: حقيقي؛
نهاية؛
س: مجموعة من مجموعة TempData
وتم تعيين قيم لمكونات Q في عملية أخرى.
---- ب. من أجل التمييز بين الأجزاء المختلفة، يتم عرض الشكل بألوان مختلفة. في هذا الوقت، يتم استدعاء الوظيفة RandomColor. الوظيفة هي:
وظيفة TCreateMultiCharts.RandomColor؛
فار
الأحمر والأخضر والأزرق: بايت؛
يبدأ
أحمر:=عشوائي(255);
الأخضر:=عشوائي(255);
أزرق:=عشوائي(255);
النتيجة: = أحمر أو (أخضر ش 8) أو (أزرق ش 16)؛
نهاية؛
---- (2) قم بإنشاء مكون ChartSeries لعنصر تحكم المخططات بشكل ديناميكي لعرض استخدام الجهاز
الإجراء TFormMultiMachinesBurthen.
ShowMachineBurthenCharts;
فار
ط: عدد صحيح؛
بيرثين: حقيقي؛
فئة السلسلة: TChartSeriesClass؛
NewSeries: مجموعة من TChartSeries؛
يبدأ
SetLength(NewSeries,CreateMultiCharts.Rows);
MachinesBurthenCharts.height:=200;
MachinesBurthenCharts.Width:=550;
لأني:=0 إلى CreateMultiCharts.Rows
يبدأ
SeriesClass:=TBarSeries; // اضبط الشكل على مخطط شريطي ثلاثي الأبعاد
NewSeries[i]:=SeriesClass.Create(Self);
NewSeries[i].ParentChart:=MachinesBurthenCharts;
NewSeries[i].Clear;
Burthen:=MachineBurthen[i];
Burthen:=Round(Burthen*100)/100; // خذ رقمين فقط بعد العلامة العشرية
NewSeries[i].add(Burthen,',NewSeries[i].SeriesColor);
نهاية؛
نهاية؛
---- ملاحظة: (أ).MachineBurthen[i] عبارة عن مصفوفة حقيقية، وقيمتها هي استخدام الجهاز المقابل، والذي تم حسابه في وظيفة أخرى؛
---- (ب). MachinesBurthenCharts عبارة عن عنصر تحكم TChart، كما هو موضح في قسم النوع.
---- 3. عرض نتيجة تشغيل البرنامج
---- (1). قم بإنشاء عنصر تحكم في الشكل ديناميكيًا لعرض خطة جدولة الأجزاء (محذوفة)
---- (2). قم بإنشاء مكون ChartSeries لعنصر تحكم المخطط ديناميكيًا وعرض استخدام الجهاز (محذوف)