نوشتن کامپوننت
در نوشتن یک کامپوننت به چند روش میشه عمل کرد که ما فعلا به این مبحث نمی پردازیم و فقط از این مطلب به صورت گذری عبور می کنیم . اگر خدا بخواد بعدا یه مطلب مفصل تر در مورد کامپوننت نویسی ارائه می کنم .
1-1 - برای این کار می توانید وارد منوی Component در دلفی شده و گزینه New Component رو که با شکل( Icon) چرخ دنده مشخص شده انتخاب کنید .
1-2- از پنجره باز شده یک کلاس از کلاسهای مورد نظر را انتخاب کنید و یک نام جدید برای کلاس خودتان انتخاب و وارد کنید
نکته : معمولا در مرحله اول نوشتن یک کامپوننت بدین شکل عمل می کنند که در اینجا نیز یک کلاس پدر قائل میشویم و معمولا نام را با کلمه Custom شروع می کنیم به طور مثال برای ساخت کامپوننتی با انشعاب از کلاس TLabel با نام TSuperLabel بدین شکل عمل می کنیم (TCustomSuperLabel ) بدین شکل اگر خواستیم انشعاب دیگری از کلاس TSuperLabe بگیریم با استفاده از کلاس (TCustomSuperLabel ) عمل می کنیم یا اگر تغییری خواستیم اعمال کنیم در کلاس (TCustomSuperLabel ) اعمال می کنیم .
1-3 - پس از ست کردن تمام گزینه های پنجره برای ساخت کامپوننت گزینه Install را زده و اجازه ساخت را صادر می نمایید . در پنجره بار شده نام پکت جدید یا دلخواه خود را وارد نمایید گزینه OK را کلیک کنید .
1-4 - در پنجره ایجاد شده شما قسمتهای مختلف پروژه رو می بینید که با نام پروژه آغار گردیده و تا( END همراه با نقطه ) ادامه دارد.
unit QCustomSuperLabel;
interface
uses (0)
SysUtils, Classes, Controls, StdCtrls;
type
TCustomSuperLabel = class(TLabel) { | TCustomLabel} (1)
{Other Objects Or Important Calss}
{ابجکتها ویا کلاسهای مورد استفاده در کلاس }
protected (2)
{Protected declarations }
{در این بخش صفت ها ، توابع و روالهای محافظت شده را ایجاد می کنید }
private (3)
{ Private declarations }
{در این بخش توابع و روالهای مخصوص همین کلاس را ایجاد می کنید }
public (4)
{ Public declarations }
{در این بخش صفت ها ، توابع و روالهای سراسری را ایجاد می کنید }
published (5)
{ Published declarations }
{در این بخش صفت ها ، توابع و روالهای سراسری را ایجاد می کنید }
end;
procedure Register; (6)
implementation
procedure Register;
begin
RegisterComponents({نام تب دلخواه ->} 'Shid', [TCustomSuperLabel]); (7)
end;
end.
0 ) دقت کنید در این بخش مبایست نام یونیت (Unit) که شئ ما از آن مشتق شده را ذکر کنیم . البته معمولا اتوماتیک اضافه می شود .
1 ) در این قسمت نام شئ جدید را درج میکنید و بعد کلمه کلاس (Class) نام کلاسی که قرار است شئ ما از آن مشتق شود را درج می کنیم به عبارتی کلاس شئ پدر
2 ) در این بخش صفت ها ، توابع و روالهای محافظت شده را ایجاد می کنید . بدین معنی که با درج نام توابع و روالها در این قسمت به شما این اجازه را می دهد که از این توابع و روالها تنها در کلاس های فرزند برای ایجاد شئ ( Object ) جدید استفاده شود و در مابقی عملیات ها اجازه تغییر برای افراد دیگه وجود نداره ونمی توانند آنها را تغییر یا جای گزین کنند .
3 ) در این بخش توابع و روالهای مخصوص همین کلاس را ایجاد می کنیم . بدین معنی که در توابع و اشیاء جدید دیگر امکان دست رسی وجود ندارد .
4 ) در این بخش صفت ها ، توابع و روالهای سراسری را ایجاد می کنید . با درج توابع در این قسمت اجازه دست رسی به توابع و روالها و صفت ها را در تمام پروژه طادر می کنیم .
5 ) در این بخش مصفتها را درج میکنیم (اشتباه نکنید در این بخش توابع و پروسه ها را نمی توان نوشت بلکه ازآنها در ساخت وایجاد صفات استفاده می کنیم .)
6 ) این یک تابع برای ساخت و ایجاد پروژه است . که با فراخوانی آن پروژه نصب و برقرار می گردد .
7 ) این پروسه پروژه را در تب (Tab) دلخواه شما ایجاد می کند .
--------------------------------------------------------------------------------
در ساخت یک کامپوننت چگونه می بایست عمل شود ؟
برای فهم بیشتر برنامه کار را با مثال TSuperLabel ادامه می دهیم . خوب تصور کنید که می خواهیم لیبلی بسازیم که توانایی سایه زدن به متنی که در لیبل را داشته باشیم و در هنگام ورود و خروج موس (Mouse) بر روی خود حساسیت نشان داده و تغییر رنگ دهد . برای انجام این کار همانطور که در بالا پیش رفتیم میبایست از کلاس TLabel یک کامپوننت جدید ایجاد کنیم . پس از ساخت یونیت اولیه کافیست تا مطابق زیر و توضیحات پیش بروید .
یونیتهای مورد احتیاج را درج کنیم :
uses
SysUtils, Classes, Controls, messages,StdCtrls,Windows, Graphics, Dialogs, GraphUtil;
اضافه کردن پروسه ها ، توابع ، صفتها در هدر برنامه ( Header ) :
....
private
FInColor : TColor ; {1}
FSwichColor:TColor ;
FShadowActive : Boolean;
{ Private declarations }
protected
procedure SetInColor (Value:TColor); {2}
Function GetInColor :TColor ; {2}
procedure SetShadowActive (Value:Boolean);
Function GetShadowActive :Boolean ;
procedure Paint; override;{4}
procedure DoDrawText(var Rect: TRect; Flags: Integer); override; {5}
{--- > در صورتی که با کار کردن پیامهای ویندوز آشنا نیستید پیام ارسال کنید تا توضیح داده شود }
procedure CMMouseenter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseleave(var Message: TMessage); message CM_MOUSELEAVE;
{<---}
{ Protected declarations }
public
{ Public declarations }
published
property InColor : TColor read GetInColor write SetInColor default ClBlack; {3}
property ShadowActive : Boolean read GetShadowActive write SetShadowActive default True;
{ Published declarations }
end;
...
توضیحات برنامه ( قسمت هدر Header ) :
ابتدا یک متغییر در بخش پرایویت اضافه می کنیم تا رنگ سایه را از کاربر دریافت کند
سپس یک تابع و یک پروسیجر جدید نوشته تا با آن خاصیت رنگ را ذخیره کنیم .
سپس یک خاصیت جدید به نام این کالر تعریف می کنیم (هر نام دلخواهی که می خواهید )
بعد از انجام مراحل بالا میبایست پروسه Paint را از کلاس پدر فراخوانی و باز نویسی کنیم برای این کار نام و آرگومانهای پروسه را وارد کرده و پس از آن کلمه کلیدی Override را درج می کنیم تا پروسه ما باز نویسی شود و از پروسه کلاس پدر صرف نظر شود . (برای این کار میتوانید با زدن کلیدهای Ctrl + Space و درج تنها نام پروسه و انتخاب آن و زدن کلید Enter از ادامه راه خود داری کنید و درج ادامه مطالب را به سیستم وا گذار کنید )
پس از انجام 4 مرحله بالا حال پروسه DoDrawText همانند مرحله 4 از کلاس پدر فراخوانی می کنیم . (این پروسه مخصوص تبدیل خواص چاپی و چاپ متن در کلاس TLabel می باشد )
درج توابه و پروسه ها :
بعد از درج خطوط دستور بالا باید توابع رو درج و ست (Set) می کنیم .این کار رو نیز بعد از کلمه کلیدی implementation مانند مراحل زیر انجام می دهیم .
1- درج پروسه سازنده کامپوننت و اعمال تغییرات ( Create ) :
constructor TCustomSuperLabel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);{1}
FInColor := clSkyBlue ;
FSwichColor := Color ;
FShadowActive := True ;
end;
همینطور که مشاهده می کنید اولین مورد استفاه از Inherited در ابتدای کار در پروسه ساخت Object می باشد . در این نوع استفاده به برنامه می فهمانیم که می بایست قبل از انجام هر کاری دستورات ساخت کامپوننت را از کلاس پدر اجرا کند یعنی پروسیجر Create در کلاس پدر . سپس به اجرای خطوط بعدی پروسیجر بپردازد . فراخوانی همراه با مولفه و متغییر در این قسمت قابل مشاهده است .
توجه : هیچگاه در چنین پروسه هایی که از کلاس پدر مشتق شده بدون کلمه Inherited کار فراخوانی را پروسه پدر را انجام ندهید . این کار شما موجب می شود تا پروسه ی بازگشتی ایجاد شود که اینکار باعث از دست دادن فظای مورد استفاده می شود و با پیغام خطا و یا خروج از دلفی برخورد می کنید که در این صورت پروژه را در صورت Save نبودن از دست می دهید .
2- درج توابع گرفتن و ذخیره رنگ (برای تغییر رنگ با ورود و خروج موس Mouse ) :
procedure TCustomSuperLabel.SetInColor (Value:TColor);
begin
if Value <> FInColor then
begin
FInColor := Value ;
Invalidate ;
end;
end;
Function TCustomSuperLabel.GetInColor :TColor ;
begin
Result := FInColor ;
end;
3- پروسیجرهای نمایش یا عدم نمایش سایه ( Shadow ) :
procedure TCustomSuperLabel.SetShadowActive (Value:Boolean);
begin
if Value <> FShadowActive then
begin
FShadowActive := Value ;
Invalidate ;
end;
end;
Function TCustomSuperLabel.GetShadowActive :Boolean ;
begin
Result := FShadowActive;
end;
4- پروسه Paint را درج می کنیم :
procedure TCustomSuperLabel.Paint; {1}
{2 -->> }const
Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
WordWraps: array[Boolean] of Word = (0, DT_WORDBREAK);
var
Rect, CalcRect: TRect;
DrawStyle: Longint;
OldFontColor:TColor ;
begin
if (FSwichColor <> InColor ) and (FSwichColor <> Color) or
(csDesigning in TComponent(Self).ComponentState) then FSwichColor := Color;
with Canvas do
begin
if not Transparent then
begin
Brush.Color := FSwichColor;
Brush.Style := bsSolid;
FillRect(ClientRect);
end;
Brush.Style := bsClear;
Rect := ClientRect;
{ DoDrawText takes care of BiDi alignments }
DrawStyle := DT_EXPANDTABS or WordWraps[WordWrap] or Alignments[Alignment];
{ Calculate vertical layout }
if Layout <> tlTop then
begin
CalcRect := Rect;
DoDrawText(CalcRect, DrawStyle or DT_CALCRECT);
if Layout = tlBottom then OffsetRect(Rect, 0, Height - CalcRect.Bottom)
else OffsetRect(Rect, 0, (Height - CalcRect.Bottom) div 2);
end; {<<-- 2 }
DoDrawText(Rect, DrawStyle);
end;
end;
توضیحات برنامه ( قسمت تابع Paint ) :
درج نام پروسیجر ( Procedure ) همراه مشخصات کلاس آن بدون درج Override در انتهای Procedure .
اعلان متغییر ها ، ثابتها و نوشتن متن برنامه برای ست کردن نوع نمایش
فراخوانی تابع DoDrawText . با فرواخوانی تابع ذکر شده و باز نویسی آن توسط شما که در جلو تر به آن میپردازیم به شما این امکان را می دهد تا با استفاده از نوع نمایش و محدوده آن به عملیات چاپ متن بپردازید .
توجه : در این قسمت چون ما نمی خواهیم برنامه پروسیجر کلاس پدر پیت ( Paint ) را فراخوانی کند از نوشتن خط دستور Inherited Paint جدا خوداری کنید. فراخوانی آن باعث به هم ریختن شکل کلی نمایش متن می شود و اگر به برنامه تسلط نداشید در ابتدا دقیقا به صورت بالا عمل کنید تا بعد تغییرات دلخواه خود را انجام دهید .
5 - حالا با ید به درج و بازنویسی تابع DoDrawText بپردازیم :
procedure TCustomSuperLabel.DoDrawText(var Rect: TRect; Flags: Integer); {1}
{2-->>}
var
Text : string;
AFont :TFont;
begin
try
Inc(Rect.Top,2);
Inc(Rect.Left);
AFont := TFont.Create ;
AFont.Assign(Font);
Text := GetLabelText;
if (Flags and DT_CALCRECT <> 0) and ((Text = '') or ShowAccelChar and
(Text[1] = '&') and (Text[2] = #0)) then Text := Text + ' ';
if not ShowAccelChar then Flags := Flags or DT_NOPREFIX;
Flags := DrawTextBiDiModeFlags(Flags);
AFont.Color := GetShadowColor (Font.Color);
Canvas.Font := AFont;
if not Enabled then
begin
OffsetRect(Rect, 1, 1);
Canvas.Font.Color := clBtnHighlight;
DrawText(Canvas.Handle, PChar(Text), Length(Text), Rect, Flags);
OffsetRect(Rect, -1, -1);
Canvas.Font.Color := clBtnShadow;
DrawText(Canvas.Handle, PChar(Text), Length(Text), Rect, Flags);
end
else
DrawText(Canvas.Handle, PChar(Text), Length(Text), Rect, Flags);
finally
AFont.Free ;
end;
dec(Rect.Top,2);
dec(Rect.Left);
Canvas.Brush.Style := bsClear ;{<<--2}
inherited DoDrawText(Rect,Flags);{3}
end;
توضیحات برنامه ( قسمت تابع DoDarwText ) :
درج نام ومشخصات و مولفه های پروسیجر بدون Override .
نوشتن قسمت بدنه پروسیجر
نوشتن کلمه کلیدی inherited به همراه نام پروسیجر DoDrawText همراه با دو مولفه Rect, Flags برای رسم متن به وسیله کلاس پدر .
توجه : یک شکل دیگر استفاده از وراثت مطابق خط دستور بخش 3 توضیح برنامه DoDrawText می باشد . این شکل فراخوانی باعث می شود نه تنها قسمت بدنه این پروسیجر فراخوانی و اجرا شود بلکه پروسیجر DoDrawText در کلاس پدر نیز اجرا گردد . بدین شکل که بعد از ذکر کلمه inherited به برنامه این را می فهماند که باید پروسیجری را از کلاس پدر( Parent ) اجرا کند و با ذکر نام پروسیجر وانجام تغیررات دل خواه در ولفه ها و متغییرهای آن این امکان را داریم که قبل از فراخوانی یک پروسیجر تغییرات ما را اعمال کند و با شرایط جدید کار فراخوانی را صو.رت دهید . همان طور که ما در این تکه برنامه از آن استفاده کردیم .
6 - درج پروسیجرهای حساس به حرکت ماوس :
procedure TCustomSuperLabel.CMMouseenter(var Message: TMessage);
begin
inherited ;{1}
if not (csDesigning in TComponent(Self).ComponentState ) then
begin
FSwichColor := FInColor ;
Invalidate ;
end;
end;
procedure TCustomSuperLabel.CMMouseleave(var Message: TMessage);
begin
inherited;{1}
if not (csDesigning in TComponent(Self).ComponentState ) then
begin
FSwichColor := Color ;
Invalidate ;
end;
end;
توضیحات پروسه های دریافت رویدادهای ماوس :
1 ) همانطور که در این دو پروسیجر مشاهده می کنید شکل دیگری از کاربرد Inherited وجود دارد که به پروسه می فهماند بدون هیچ تغییری در متغییرها آن باید پروسیجر را درکلاس یا کلاسهای پدر اجرا کند . در این شکل شما دیگر به ذکر نام پروسه و ارسال متغییر به آن نمی پردازید .
--------------------------------------------------------------------------------
در نهایت چه کنیم ؟
خوب کامپوننت ما آماده اجراست تا ایجاد و برای استفاده آماده گردد . برای این کار شما می بایست پروژه را مجددا ساخته که این کار را می توانید با استفاده از پنجره Package و فشردن دکمه Compile درون پروژه انجام دهید . سپس وارد Tab انتخابی که در ابتدای ساخت از شما خواسته بود شوید و از کامپوننت ساخته شده توسط خودتان استفاده کنید .
+ نوشته شده در ساعت   توسط حسن سامی نسب
|
