الدرس الثالث من دورة برمجة العناصر.
#1
بسم الله الرحمن الرحيم .
وأفضل الصلاة وأتم التسليم على سيد الخلق الرسول الأمين محمد وعلى آله و أصحابه الطاهرين إلى يوم الدين.
أولاً أشكر إدارة المنتدى على تثبيت الدرسين الأول والثاني. و أقدم الشكر إلى كل من ساهم أو يساهم في إتمام هذه الدورة...

أحب أن أضيف فقط بأن القسم العملي قادم إن شاء الله ولكن هنالك العديد من المواضيع النظرية التي يجب شرحها حتى تكون مرجع لنا عند الإنتقال إلى القسم العملي...

ونبدأ بعون الله بالدرس الثالث.

مناهج القراءة للخصائص هي عبارة عن توابع(Functions) لا تأخذ أية وسائط(بارمترات) بإستثناء ما هو مدون في الأسفل . وتعيد هذه التوابع قيمة من نفس نوع الخاصية . وبالعادة يكون اسم التابع مؤلفاً من Get متبوعاً بأسم الخاصية. على سبيل المثال فإن منهج القراءة للخاصية المسماة Count يكون GetCount.
الإستثناء الوحيد لهذه القاعدة () لا تأخذ أية وسائط(بارمترات) يحصل فقط مع الخصائص من النوع المصفوفي (array properties) والتي سيتم شرحها فيما بعد أو من النوع الذي يستخدم المحدد (Index) والذي أعطينا عليه مثال في الدرس الثاني.

وللحصول على معلومات أكثر تفصيلاً حول المحدد index يمكن الإطلاع على Object Pascal Language Guide بما يخص هذا الموضوع.

مناهج الكتابة (The write method):
مناهج الكتابة هي عبارة عن إجرائيات (procedures) تأخذ وسيط وحيد عادة من نفس نوع الخاصية بإستثناء ما هو مدون في الأسفل , و يمكن تمرير هذا المتحول بإحدى الطريقتين بالمرجع أو بالقيمة . ويمكن تسمية هذه المناهج بأي أسم يريده المستخدم . وهي عادة تكون مؤلفة من Set متبوعة بإسم الخاصية . فعلى سبيل المثال الخاصية Count يكون أسم منهج الكتابة فيها SetCount. والقيمة الممررة كوسيط تصبح القيمة الجديدة للخاصية. والإستثناء الوحيد لهذه القاعدة هو الخصائص من النوع المصفوفي (array properties) والتي سيتم شرحها فيما بعد أو من النوع الذي يستخدم المحدد (Index) والذي أعطينا عليه مثال في الدرس الثاني.
مناهج الكتابة وقبل تغيير قيمة الخاصية عادة تقوم بفحص فيما إذا كانت القيمة الجديدة تختلف عن القيمة الحالية. فعلى سبيل المثال منهج الكتابة التالي للخاصية المسماة Count (هذه الخاصية من النوع integer) تخزن القيمة الحالية في الحقل المسمى FCount :

PHP كود :
procedure TMyComponent.SetCount(Value: Integer);

begin
  
if Value <> FCount then
  begin
    FCount 
:= Value;
    
Update;
  
End;
End; 

القيم الإفتراضية للخاصية Default property values :عندما تقوم بالتصريح عن خاصية ما فأنه يمكنك تعيين قيمة إفتراضية لها , ويقوم دلفي بإستخدام القيمة الإفتراضية لتخزين الخاصية في ملف النموذج. ولتعيين قيمة إفتراضية للخاصية قم بألحاق الموجه default بالتصريح الخاص بالخاصية والمثال التالي يوضح ما سبق :

PHP كود :
property Cool Boolean read GetCool write SetCool default True; 

ملاحظة: التصريح عن قيمة إفتراضية للخاصية لا يجعل للخاصية هذه القيمة .وذلك لأن منهج باني العناصر (component’s constructor) ينبغي عليه تهيئة قيم الخاصية عند البناء . فهو على سبيل المثال يقوم بتعيين القيم النصية على القيمة null و القيم الصحيحة على القيمة 0 والقيم المنطقية على القيمة False .

تعيين عدم وجود قيمة إفتراضية Specifying no default value :
عند التصريح عن خاصية ما يمكن تغيين بأن الخاصية لا تمتلك قيمة إفتراضية . حتى ولو كانت الخاصية الموروثة تمتلك قيمة إفتراضية . ولإجراء ما سبق نقوم بإلحاق الموجه nodefault بتصريح الإجرائية . وعلى سبيل المثال :\
property FavoriteFlavor string nodefault;
عندما تقوم بالتصريح لأول مرة عن خاصية فليس هنالك داعي لجعل هذه الخاصية (خاصيتك الأولى) لا تملك قيمة إفتراضية . والمثال التالي يشرح ما سبق بوضوح أكثر:
ففي هذا المثال تصريح عن عنصر يمتلك خاصية منطقية (Boolean) وحيدة مسماة IsTrue وبعد التصريح سوف نجد المنهج الباني للعنصر السابق والذي يقوم بتهيئة الخاصية :
PHP كود :
type

  TSampleComponent 
= class(TComponent(
  private
    
FIsTrue: Boolean;
  public
    
constructor Create(AOwner: TComponent); override;
  
published
    property IsTrue
: Boolean read FIsTrue write FIsTrue default True;
  
end;
...
constructor TSampleComponent.Create(AOwner: TComponent);
begin
  inherited Create
(AOwner);               { إستدعاء الباني الإفتراضي}

  
FIsTrue := True;                        تعيين القيمة الإفتراضية للخاصية}}
End; 

إنشاء خصائص مصفوفية Creating array properties :
بعض الخصائص تصلح ليتم فهرستها كمصفوفات .على سبيل المثال الخاصية Lines للعنصر TMemo هي قائمة مفهرسة من النصوص والتي تقوم بتشكيل النص المكون لل memo . ويمكن للمستخدم معالجتها كمصفوفة سلاسل محرفية (نصوص).
الخصائص المصفوفية يمكن التصريح عنها كباقي الخصائص مع بعض الإستثناءات :
1- التصريح يتضمن واحد أو أكثر من الفهارس(indexes). ويمكن للفهارس أن تكون من أي نوع .
2- القسمين read و write من التصريح ,يجب أن تكون مناهج وليست حقول .
مناهج القراءة والكتابة لأي خاصية مصفوفية ينبغي أن تمتلك وسائط إضافية تستجيب للفهرسة . كما ينبغي أن تكون الوسطاء بنفس الترتيب وبنفس نوع الفهارس المحددة في التصريح .
هنالك بعض الفوارق الهامة بين الخصائص المصفوفية وبين المصفوفات: فهرس الخاصية المصفوفية ليس من الضروري أن يكون من النوع الصححيح(integer) يمكن فهرسة الخاصية بالنوع النصي (string). والمثال التالي يوضح إمكانية التصريح عن خاصية تعيد قيمة نصية بلإستناد إلى فهرسة صحيحة (integer index):
PHP كود :
type

  TDemoComponent 
= class(TComponent)
  private
    function 
GetNumberName(Index: Integer): string;
  public
    
property NumberName[Index: Integer]: string read GetNumberName;
  
end;
...
function 
TDemoComponent.GetNumberName(Index: Integer): string;
begin
  Result 
:= 'Unknown';
  case 
Index of
    
-MaxInt..-1: Result := 'Negative';
0: Result := 'ZerO';

1..100: Result := 'Small';
   
101:.MaxInt: Result := 'Large';
  
End;
End; 

إنشاء خصائص مكونات فرعية(الخاصية عبارة عن مكون) Creating properties for subcomponents:بشكل إفتراضي . وعندما تكون قيم الخاصية هي عبارة عن عنصر أخر, فإنك تقوم بإسناد القيمة للخاصية بإضافة مثيل للعنصر على شكل بيانات أو وحدات نمطية . ومن ثم إسناد ذلك المثيل كقيمة للخاصية , و مع ذلك فمن الممكن أيضاً للعنصر الخاص بك أن يقوم بإنشاء مثيل للكائن يقوم بتحقيق قيمة الخاصية. هكذا عناصر مخصصة تدعى مكونات أو عناصر فرعية subcomponents.
العناصر الفرعية يمكن أن تكون مكونات ثابتة (أحفاد للصنف TPersistent) ,خلافاً لمكونات منفصلة يحدث أن يمكن إسنادها كقيم للخاصية ,الخصائص المنشورة للمكونات الفرعية يجري حفظها مع العنصر الذي يقوم بإنشاءها . ومن أجل إنجاز ذلك ينبغي تحقيق الشروط التالية:
1- مالك(Owner)العناصر الفرعية يجب أن يكون العنصر الذي ينشأ هذه الخصائص ويستخدمها كقيمة للخاصية المنشورة. من أجل المكونات الفرعية التي ترث من الصنف TComponent يمكن إنجاز ذلك بتعيين خاصية المالك (Owner).يجب تجاوز override المنهج GetOwner للكائن الثابت ليتم إعادة إنشاء العنصر من جديد.
2- المكونات الفرعية هي أحفاد للصنف TComponent وينبغي أن تحدد كونها مكونات فرعية وذلك بإستدعاء المنهج SetSubComponent نموذجياً يجري إستدعاء المنهج السابق سواء عن طريق المالك أو عن طريق باني المكونات الفرعية.
نموذجياً الخصائص التي تكون قيمها مكونات فرعية تكون خصائص قابلة للقراءة فقط read-only . وذلك لأنه وعند السماح بتغيير قيمة الخاصية فان معين الخاصية يقوم بتحرير المكون الفرعي من جديد . والمثال التالي يوضح معين خاصية قيمتها من النوع TTimer:
PHP كود :
procedure TDemoComponent.SetTimerProp(Value: TTimer);

begin
  
if Value <> FTimer then
  begin
    
if Value <> nil then
    begin
      
if (FTimer <> nil) and( FTimer.Owner = self) then
        FTimer
.Free;
      
FTimer := Value;
      
FTimer,FreeNotification(self);
    
end
    
else { nil value}
    
begin
      
if FTimer.Owner <> self then
      
{
        
FTimer := TTimer.Create(self);

        
FTimer.SetSubComponent(True);
        
FTimer.FreeNotification(self);
      }
    
End;
  
End;
End; 
لاحظ بأن معين الخاصية في الأعلى يستدعي المنهج FreeNotification للعنصر الذي يتم تعيينه كقيمة للخاصية .هذا الإستدعاء للمنهج السابق يسمح بالتأكد من أن العنصر الذي هو قيمة للخاصية يرسل إعلام قبل تهديمه في الذاكرة , ويقوم بإرسال هذا الإعلام بإستدعاءه للمنهج Notification ويمكن معالجة هذا الإعلام بتجاوز overriding المنهج Notification كما في الشكل التالي:
PHP كود :
procedure TDemoComponent.Notification(AComponent: TComponent; Operation: TOperation);

begin
  inherited Notification
(AComponent, Operation);
  if (
Operation = opRemove) and (AComponent = FTimer) then
    FTimer 
:= nil;
End; 
الدرس التالي: http://www.delphi4arab.net/forum/showthr...p?tid=2621
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم