יצירת רכיב חדש בלזרוס חלק ראשון

ללזרוס יש תכונה מאוד מעניינת, הוא מאפשר ליצור רכיבים (או פקדים) גרפיים חדשים לגמרי במערכת ולהשתמש בהם בתוך התוכנה שלנו.

יש רשימה די גדולה של רכיבים ללזרוס (חלקם אפילו רכיבים מסחריים), אבל כאשר אנחנו מפתחים תוכנה גרפית רצינית בעצמנו, סביר להניח שנרצה או להרחיב פקד קיים, או ליצור פקד חדש לגמרי משל עצמנו. בכל מקרה, גם אם נרחיב פקד קיים, נהיה צריכים ליצור אותו בתור רכיב חדש, אחרת הוא יתפוס רק בנקודה שאותה שינינו וזה לא ישפיע בשאר התוכנה שלנו.

בפוסטים הקרובים, אני אנסה להסביר כיצד בעצם מרחיבים פקד קיים (אני לא הולך ללמד אותכם ליצור ממש מ0, כי זה דורש מאיתנו הכירות טובה יותר של ה FCL [הספרייה שמגיעה עם FPC ומספקת תמיכה בהרבה מחלקות, שיגרות ופונקציות לא גרפיות המרחיבות את הRTL. ראשי התיבות של הFCL הינם Free Component Library] בנוסף ל LCL [הרכיבים הגרפיים של לזרוס. ראשי התיבות הינם Lazarus Component Library] ובהרחבה של פקד רגיל, בד"כ לא נהיה צריכים להכיר לעומק את התמיכה הזו). במקרה הזה נרחיב את הפקד TCustomEdit שאחראי על 2 פקדים אחרים: הראשון הוא TMemo שזה בעצם סוג של עורך טקסט לקבצי טקסט "רגילים" ללא תכונות מיוחדות מעבר. הפקד השני הוא TEdit והוא הפקד שמאפשר לנו לקבל שורה של טקסט לרשום בה.

שימו לב שהרחבת הפקדים אינה דורשת מאיתנו עבודה עם ספרייה גרפית ספציפית, ולכן השינויים שלנו יתפסו בכל מקום בו ניתן להדר את התוכנית לזרוס שלנו, וזאת בניגוד ליצירת פקד מ0, אשר הרבה פעמים תדרוש מאיתנו התאמה זו או אחרת לספרייה הגרפית איתה אנחנו משתמשים (תלוי כמובן במה אנחנו רוצים ליצור).

עד כאן להקדמה, אז בואו נתחיל:

אחרי שהרצנו את לזרוס, ניצור תוכנה חדשה ע"י הליכה לתפריט "קובץ". ומשם ל"חדש …", ונבחר בתוכנה.

הסיבה שאני מתחיל בפרוייקט חדש היא שהרבה יותר קל ליצור רכיב כאשר מנסים את הדברים מאשר שעובדים בצורה עיוורת. יותר מאוחר, נוכל להעביר את המחלקה שלנו להיות רכיב, וזה יהיה רק בפוסט האחרון.

נקבל עכשיו טופס חדש בצבע ברירת המחדל של הסביבה הגרפית שלכם. בעורך הטקסט נקבל יחידה חדשה בשם Unit1.pas. ניכנס לעורך הטקסט, ונוסיף בשורת ה uses את היחידה StdCtrls.

היחידה מכילה את כל הרכיבים הגרפיים שאנחנו מוצאים בלשונית הרכיבים שנקראת Standard ומכאן השם.

לאחר שהוספנו לשורת ה uses שלנו את StdCtrls, ניצור מחלקה חדשה מעל המחלקה של TFrom1 וניתן לה את השם TExtendedEdit.

אתם כמובן יכולים לתת לה כל שם שתרצו, אך בפוסט זה ובקרובים, זוהי שם המחלקה שאני משתמש בה.

לאחר מכן, ניצור את המבנה הבא:

TExtendedEdit = class ( TCustomEdit )
private
protected
public
published
end;

שימו לב שאנחנו לא באמת צריכים כל חלק וחלק כאן. אבל ככול שנוסיף עוד קוד, ככה יש סיכוי שהוא יכנס לאחת מהמחלקות הבאות, ולכן אני נוהג ליצור את כולן בהתחלה. כאשר נראה בסיום שאנחנו לא השתמשנו בחלק מסויים, אנחנו נמחק אותו, כי אין בו צורך אמיתי. שימו לב שאתם יכולים להגדיר רק את השורה של המחלקה ולסיים אותה ב end; אם אתם מעוניינים, ולהרחיב את המחלקה בהתאם לצורך. שימו לב שככה גם אפשר להגדיר הגדרת foreword למחלקה ולשים את ההגדרות האמיתיות מתחת למחלקה של הטופס. אך במקרה הזה אין צורך בכך.

בפסקל מונחה עצמים, יש כמה מקדמים להגדרות אשר אומרות לנו איפה הוגדרה ההגדרה. T בתור מקדם אומר שמדובר בטיפוס. כלומר type.

את ההגדרה הבאה נשים (כרגע) בחלק ה public של המחלקה TForm1. ההגדרה היא:

MyEdit : TExtendedEdit;

וזה יראה ככה:

TForm1 = class ( TForm )
private
{ private declarations }
public
{ public declarations }
MyEdit : TExtendedEdit;
end;

השלב הבא שלנו יהיה לגשת לObject Inspector או OI בקיצור, וכאשר ווידאנו שאנחנו מראים את התכונות של הטופס (היות והוא הפקד הגרפי היחיד, הוא בכל מקרה מה שהOI יציג, אך מומלץ להתרגל להסתכל ולוודא בכל מקרה.

נלך בOI ללשונית שנקראת אירועים, ונלחץ לחיצה כפולה על האירוע של OnCreate.

השיטה העיקרית בה אנחנו עובדים בפסקל מונחה עצמים (אם כי היא לא מחייבת), היא באמצעות אירועים. כלומר יש לנו לולאה גדולה שמריצה את התוכנה שלנו, וכל פעם שאנחנו מקבלים אירוע כלשהו, והשתמשנו בcallback, אז הוא יורץ לנו ונוכל לשים בו קוד המתאים לאירוע.

במקרה הזה, אנחנו אומרים לLCL שברגע שהוא מתחיל ליצור את הטופס, שיגיד לנו, בשביל שנוכל להשפיע על דברים בעת היצירה שלו.

בתוך הפרוצדורה שנוצרה לנו (FormCreate) אנחנו נכתוב את הקוד הבא. שימו לב שחלק מהקוד ילך איתנו בשלב הבא דווקא לרכיב שאנחנו יוצרים, אך כאן אנחנו מתחילים לבדוק מה אנחנו מקבלים בשביל לדעת איך להמשיך לעבוד.

הקוד שיש לכתוב כרגע הוא כזה:

MyEdit        := TExtendedEdit.Create(Self);
MyEdit.Parent := Self;
MyEdit.Left   := 20;
MyEdit.Top    := 50;
MyEdit.Width  := 80;
MyEdit.Height := 23;

יצרתי כאן את הרכיב שלנו בשורה של:

MyEdit := TExtendedEdit.Create(Self);

בפסקל מונחה עצמים ליוצר אנחנו תמיד קוראים Create ולכן אנחנו נאתחל את האובייקט שלנו עם Create. במקרה הזה הוא מקבל פרמטר של הבעלים שלו. אמרנו לו שהבעלים שלו זה אנחנו (כלומר Form1). זה אומר בעצם מי מטפל ברכיב מבחינת ניהול. במידה ונגיד לו nil, אנחנו צריכים לטפל בו בעצמנו. אבל היות ויש לנו Garbage Collector לרכיבים גרפיים, אשר יהרסו את הרכיב עבורינו, ניתן לטופס לעשות את מה שהוא יודע לעשות.

השורה הבאה:

MyEdit.Parent := Self;

אומרת מי הבעלים הגרפי שמכיל את הרכיב. כלומר יכול להיות שנרצה תת פקד שיכול להכיל בתוכו פקדים ונרצה שהשורת עריכה שלנו תהיה שייכת לו ולא לטופס עצמו (אם כי בהיררכיה עדיין הטופס מכיל את כל הפקדים), ואז נשנה את Parent בהתאם. שימו לב שמאוד מומלץ לשים גם ביוצר וגם ב Parent את אותם הבעלים. כי אם הפקד נהרס לפני פקד האב, אך הפקד אב לא קיבל על כך מידע, נקבל חריגה שאומרת לנו שהפקד אינו קיים.

השורות הבאות אומרות לנו את המיקום והגודל של הפקד שלנו. בכל מה שקשור לרוחב ואורך, נהוג להעביר ליוצר של הפקד עצמו וזה מה שנעשה עכשיו.

אבל קודם נריץ את התוכנית שלנו ונראה שיש לנו שורת עריכה על הטופס שלנו. לאחר שנסגור את הטופס שהרצנו ונסיים בעצם את הריצה, ניגש לחלק ה public של הפקד שלנו ונכתוב את הקוד הבא:

constructor Create(AOwnder : TComponent); override;

ועכשיו נלחץ בלזרוס על צירוף המקשים CTRL+Shift+C ונגלה שהוא לקח את ההגדרה הזו ויצר לנו את היוצר בחלק הביצוע של היחידה שלנו (בנוסף לעוד כמה דברים כמו חילק לנו את המיקום של המחלקות השונות).

שימו לב לשורה של

inherited Create ( AOwner ) ;

בניגוד לשפות כדוגמת ג'אווה ו ++C בהן לא ניתן לרשת יוצרים קודמים, בפסקל מונחה עצמים ניתן לעשות זאת ואנחנו מקבלים את כל הקוד של היוצר הקודם ביוצר שלנו.

בחלק הביצועי של constructor TExtendedEdit.Create נכתוב את הקוד שלנו של האורך והרוחב של הפקד שלנו:

constructor TExtendedEdit.Create ( AOwner : TComponent ) ;
begin
inherited Create ( AOwner ) ;
SetInitialBounds(0, 0, GetControlClassDefaultSize.X, GetControlClassDefaultSize.Y);
end;

ונוכל למחוק את הגדרות הרוחב והאורך שאירוע של יצירת הטופס אלא אם נרצה לשנות את האורך והרוחב שלנו.

הפרוצדורה SetInitialBounds שייכת לאב קדמון שלנו שנקרא TControl, והוא בעצם מזין את ההגדרות שלנו של המיקום והגודל לתכונות שלנו.

הפונקציה GetControlClassDefaultSize מחזירה ערכים קבועים של האורך והרוחב שלנו. שימו לב שבמקרה הספציפי הזה, היות והערכים זהים ל TCustomEdit, לא היינו צריכים להגדיר אותם ביוצר שלנו, אבל אם נשנה את הערכים ב GetControlClassDefaultSize, אז הקוד שלנו לא יהיה צריך להשתנות מעבר לכך, ולכן הכנסתי את הנתון הזה לכאן, אם כי במקרה הספציפי הזה, אין מקום אמיתי לקוד הזה, היות וירשנו גם אותו מהיוצר הקודם.

עכשיו האירוע שלנו של הטופס צריך להראות ככה:

procedure TForm1.FormCreate ( Sender : TObject ) ;
begin
MyEdit        := TExtendedEdit.Create(Self);
MyEdit.Parent := Self;
MyEdit.Left   := 20;
MyEdit.Top    := 50;
end;

עכשיו נגדיר את הפונקציה GetControlClassDefaultSize ונשנה לה את הערכים.

ניגש להגדרת המחלקה שלנו של TExtendedEdit ונכתוב את ההגדרה הבאה:

TExtendedEdit = class ( TCustomEdit )
private
protected
class function GetControlClassDefaultSize: TPoint; override;
public
constructor Create(AOwner : TComponent); override;
published
end;

ושוב נלחץ על CTRL+Shift+C ונקבל את הקוד הבא:

class function TExtendedEdit.GetControlClassDefaultSize : TPoint;
begin
Result := inherited GetControlClassDefaultSize;
end;

כמו שניתן לראות לזרוס חושב שאנחנו רוצים לרשת את הערכים שפונקציית האב רוצה להחזיר לנו. אבל אנחנו לא רוצים את זה, ולכן נמחק את השורה הזו (אפשר להשתמש ב CTRL+Y למחיקת שורה).

לפני שנמשיך, הגדרה של מתודה עם מקדם של class אומר שזו מתודה סטטית. בגלל שהמתודה שלנו נמצאת ב protected היא משפיעה על כל היורשים של המחלקה, אבל אינה גלוייה אל מחוץ למחלקות המכילות את המתודה.

עכשיו נכתוב בפונקציה שלנו את הקוד הבא:

class function TExtendedEdit.GetControlClassDefaultSize : TPoint;
begin
Result.X := 120;
Result.Y := 25;
end;

המשתנה Result הוא משתנה המקבל את הטיפוס החזרה שלנו וכאשר הפונקציה מסיימת את הריצה שלה, זה הערך שהיא תחזיר. במקרה הזה, יש לנו רשומה שמכילה X ו Y. ולכן אנחנו צריכים לתת ערכים לכל שדה ברשומה. יש פונקציה שיכולה לעזור לנו, אבל עדיף לרשום את זה בצורה שכתבתי.

השלב הבא יהיה שוב פעם להריץ את התוכנה שלנו ונראה את השינויים של האורך והרוחב שהגדרנו לפקד.

עד כאן לחלק הזה. בחלק הבא, כבר נתחיל להיות טיפה יותר רציניים.

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s