View Full Version : بخشی از ویژگیهای جدید Borland Developer Studio 2006
m-khorsandi
سه شنبه 25 مهر 1385, 11:46 صبح
بخشی از ویژگیهای جدید محیط BDS 4.0
Method Navigation
حرکت/پرش بین متدها با استفاده از ترکیب کلیدهای :
Ctrl+Alt+Up متد قبل
Ctrl+Alt+Down متد بعد
Ctrl+Alt+End آخرین متد
Ctrl+Alt+Home اولین متد
• Class Lock
برای حرکت بین متدهایی که در یک یونیت در کلاسهای مختلف تعریف شده اند از روش بالا میتوانید استفاده کنید،
حالا برای اینکه حرکت بین متدها را به یک کلاس خاص محدود کنید ، میتوانید روی هر متدی که هستید
(که متعلق به یک کلاس خاص هست) کلید های Ctrl+Q+L را فشار دهید تا از این به بعد با استفاده از روش مذکور
فقط در این کلاس حرکت کنید و با استفاده دوباره همین کلیدها (Ctrl+Q+L) این محدودیت را از بین ببرید.
• زمانیکه یک فایل سورس را باز کنید شماره خطوط را در کنار ادیتور می بینید که تغییر میکند.
• به جای اینکه کنار هر خط و همه خطوط "عدد" ببینید، شماره خط را در کنار هر 10 خط خواهید دید. به این معنی که
خطوط به صورت 10 خط به 10 خط شماره گذاری شده اند با یک خط فاصله در خط پنجم و یک نقطه کنار هر خط.
این قاعده برای خطی که کرسر در آن است استثناست، یعنی برای خطی که کرسر در آن ست شماره خط نیز نمایش
داده میشود. شماره خط در محلی که علامت Bookmark و Breakpoint قرار میگیرد نمایش داده نمیشود و محلی جداگانه دارد.
• در سمت چپ ادیتور خطوطی را به رنگهای مختلف میبینید که :
رنگ زرد : تغییرات جاری
رنگ سبز : آخرین تغییرات که ذخیره هم شده اند.
• اگه در Code Editor روی هر کدام از Tabها دکمه سمت راست ماوس را فشار دهید میتوانید با استفاده
از گزینه Close all other pages به غیر از این Tab ، سایر Tab ها رو ببندید.
• با فشار دادن دکمه میانی ماوس روی هر Tab میتوانید آن Tab رو ببندید.
• اگه در جایی بخواهید مقدار رشته ای را به یک ثابت (Const) یا به یک متغیر تخصیص دهید که جمله نسبتا" طولانی هم برای
آن در نظر گرفتید ، میتوانید این جمله را به چندین خط تقسیم کنید و برای نوشتن این جمله از ویژگی جدید BDS 2006
استفاده کنید به این صورت که بعد از تعریف نام ثابت و قرار دادن علامت مساوی و کوتیشن بخشی از جمله مورد نظر را
بنویسید و به جای قرار دادن کوتیشن و عملگر + و زدن کلید Enter (برای نوشتن ادامه جمله در خط بعدی ) ، فقط کلید Enter
را بزنید و بقیه کار را به Editor بسپارید.
Const
S = ' This is ' +
' my String';
• برای تعریف یک کلاس جدید ، میتوانید از ویژگی جدید BDS 2006 استفاده کنید به این صورت که:
در قسمت Type یعنی در جایی که ساختار یک کلاس تعریف میشود یک خط جدید باز کنید و در آن خط فقط کلمه Class
را بنویسید و بعد کلید Tab را بزنید، میبینید که قالب عمومی یک کلاس ایجاد میشود و فقط کافیست نام کلاس و وراثت آن
را تعیین کنید، که مطمئنا" انجام این دو کار هم با استفاده از کلیدهای Shift+Tab مشکل نخواهد بود.
• وقتی در یک متد در حال کار هستید و نیاز به یک متغیر دارید ، حتما" لازم نیست که به ابتدای متد رفته و متغیر مورد نیاز را
در بخش var تعریف کنید، میتوانید در جایی که هستید یک خط جدید باز کنید و کلمه var را بنویسید و کلید
Tab را بزنید ، که در این صورت تعریف یک متغیر با نام Lvar از نوع Integer را در همان خط ملاحظه خواهید کرد،
حالا میتوانید با استفاده از کلیدهای Shift+Tab بین نام متغیر و نوع متغیر حرکت کنید و متغیر را با نام و نوع مورد نیاز
خود تعریف کنید و در آخر هم کلید Enter را بزنید تا تعریف متغیر در سر جای خود قرار گیرد.
• فراموش نکنید که IDE جدید دلفی شامل Error Insight و Help Insight و SyncEdit نیز هست.
Error Insight : نمایشگر خطای زمان طراحی ست ، برای نمونه اگر شما از متغیری استفاده کنید که تعریف نشده باشد
یک خط قرمز رنگ در زیر آن کشیده خواهد شد.
Help Insight : راهنمایی که با قرار دادن اشاره گر ماوس روی یک کلمه نمایش داده خواهد شد.
(این ویژگی را با Code Hints اشتباه نگیرید)
SyncEdit یاSynchronized Editing : اگر یک بخش از کد را انتخاب کنید که در آن کلمات تکراری وجود داشته باشد
در قسمت سمت چپ Editor ، آیکون دو قلم نمایش داده خواهد شد ، با انتخاب این آیکون یا استفاده از
کلیدهای Shift+Ctrl+J میتوانید SyncEdit را فعال کنید . پس از فعال شدن SyncEdit ، زیر تمام کلمات تکراری یک خط آبی قرار میگیرد
که نشان میدهد با تغییر یک کلمه از هر گروه ، مابقی گروه نیز تغییر میکنند. برای این کار میتوانید کلمه مورد نظر
(که خط آبی رنگ زیر آن وجود دارد) را انتخاب کنید و شروع به ویرایش کلمه کنید و نتیجه را ببینید.
(آیکون SyncEdit زمانی ظاهر میشود که در بلاک انتخاب شده کلمه تکراری وجود داشته باشد)
• UML Designer (همان Together هست که در BDS 2006 جا داده شده)
ورژن 1.5 و 2.0 UML را پشتیبانی میکند و اگر نرم افزاری را با Rational Rose مدل کرده باشید ، مبدل(Rational Rose to Together)
آن را در اختیارتان قرار میدهد.
UML Designer سابقا" در نسخه 2005 توسعه داده شده و ویژگی جدید آن live code synchronization میباشد ،
که شما میتوانید کد را تغییر دهید و همین تغییر را در Diagram ببینید یا Diagram را تغییر دهید و نتیجه را در کد مشاهده کنید.
میتوانید یک کلاس جدید ایجاد کنید و به آن Field و Property و Method را اضافه کنید. در کنار Class Diagram با سایر
دیاگرامهای UML نیز میتوانید کار کنید ، مانند : Use Case, Sequence Collaboration, State Chart و ... .
با استفاده از Together میتوانید مستندات کاملی را برای پروژه تهیه کنید.
• وقتی یک کنترل را روی فرم قرار میدهید در گوشه ها و مرکز هر طرف کنترل ، یک دایره کوچک به رنگ آبی روشن مشاهده میکنید.
این علامات ، بخشهایی هستند که شما میتوانید از آنها برای تغییر سایز کنترل استفاده کنید.
• اگر یک کنترل دیگر روی فرم قرار دهید ، میتوانید از ویژگی جدید و مفید Design Guidelines استفاده کنید.
این ویژگی یک راهنمای بصری خوب برای تراز کردن کنترل های روی یک فرم هست (خط آبی رنگ). این راهنما نه تنها برای
تراز کردن کناره های کنترلهاست بلکه شما میتوانید کنترل ها را با توجه به متن موجود در آنها تراز کنید(خط صورتی رنگ).
• Form Positioner
ویژگی دیگریست که در سمت راست پائین Designer قرار دارد. توسط این ویژگی میتوانید موقعیت فرم جاری در صفحه نمایش را
در زمان اجرای برنامه ببینید و آن را تغییر دهید. برای راحتی کار میتوانید با دوبار کلیک روی آن ، سایز Form Positioner را بزرگتر کنید.
• Block Completion
با استفاده از این ویژگی در Code Editor میتوانید بلاکهای خود را تکمیل کنید برای نمونه اگر در خطی از برنامه
کلمه End را بنویسید و بعد کلید Enter را بزنید این بلاک با قرار دادن یک End و یک Semicolon در انتهای آن تکمیل میشود .
این ویژگی شما را در تکمیل بلاکهای Beginو Try و Case و Record و Class و Repeat و If کمک خواهد کرد.
به غیر از بلاک If ، در انتهای مابقی بلاکها Semicolon قرار میگیرد.
• Live (Code) Templates
این ویژگی واژه نامه ای شامل کدهای از قبل نوشته شده را در اختیار شما قرار میدهد که میتوانید از این کدها در برنامه
استفاده کنید (البته زمانیکه در Code Editor هستید) تا از بخشی از مقدار تایپی را که روزانه میبایست انجام دهید بکاهد.
Live Template قابل تغییر نیز هست.
• Block Comments
زمانیکه در Code Editor هستید با استفاده از ترکیب کلیدهای /+Ctrl میتوانید خطی که در آن هستید را Comment
کنید (Comment یی که با // ایجاد میشود ) یا اینکه بخشی از کد (که میتواند شامل چندین خط باشد) را انتخاب کنید
و با /+Ctrl همه را یکدفعه Comment کرد. توسط همین ترکیب هم میتوانید Comment هایی را که ایجاد کرده اید حذف کنید.
m-khorsandi
شنبه 29 مهر 1385, 09:32 صبح
بخش دوم
• Code Folding and Region
با استفاده از علامت – و + در کنار هر تعریف، متد یا تمام بخشها مانند بخش Implementation یک یونیت که وجود دارد
میتوانید آن را ببندید یا باز کنید(این علامات به صورت خودکار در کنار هر بخشی ایجاد میشود).
Ctrl+Shift+K+O : غیرفعال/فعال کردن Code Folding
Ctrl+Shift+k+E : بستن کد
Ctrl+Shift+K+U : باز کردن کد
Ctrl+Shift+K+A باز کردن همه کد
ویژگی که به محیط Code Editor اضافه شده، تعریف شخصی چنین بخشی ست ، به این معنی که شما میتوانید با
استفاده از یک رهنمود کامپایلر (compiler directives) این بخش را ایجاد کنید و آن را نامگذاری کنید.
{$REGION 'your region name'}
......
.....
....
...
{$ENDREGION}
{$REGION 'extra code}
procedure TestMessage;
begin
ShowMessage('Test');
end;
{$ENDREGION}
• Refactoring
تکنیکی ست برای دوباره ساختن و اصلاح کد جاری تا رفتار کد جاری به همان صورت باقی بماند.
سه نوع Refactoring در دلفی تعریف شده ست :
یکی استفاده از ترکیب کلیدهای Ctrl+Shift+V، برای تعریف متغیر محلی و دیگری برای تعریف فیلد
(یا همان متغیر در ساختار کلاس جاری ست) که با ترکیب کلیدهای Ctrl+Shift+D ست. خوب، این مراحل را که خودم هم
میتوانستم با رفتن به بخش تعریف کلاس یا Begin متد انجام بدهم !!؟؟ بله، Refactoring امکان مفید دیگری که در کنار
کدنویسی سریعتر به شما میدهد اینست که نیازی نیست وقفه ای را ایجاد کنید و سرتاسر سورس را برای تعریف
یک متغیر طی کنید، نیازی نیست که به Begin متد بروید و کلمه var را اگر وجود نداشته باشد تایپ کنید و بعد هم متغیر
مورد نظر را تعریف کنید یا به کلاس یک متد بروید تا در آنجا فیلدی را تعریف کنید.
نمونه :
خط زیر را در Code Editor بنویسید و از قبل مطمئن باشید که متغیری به نام i وجود ندارد :
For I := 0 to
به موقعیت i برگردید و تعریف متغیر (Declare Variable) را فعال کنید (با Ctrl+Shift+V یا از منوی اصلی و گزینه Refactor
یا با استفاده از context menu که همان کلیک راست در Code Editor و گزینه Refactoring). فرمی باز میشود که اگر
در جلوی متغیر := و مقدار را قرار نداده باشید ، نوع پیشنهادی خود را نمایش میدهد. اگر در این فرم دقت کنید، میبنید که
میتوانید یک آرایه نیز تعریف کنید، همچنین میتوانید یک مقدار اولیه (initial value) نیز برای متغیر در نظر بگیرید که در این
صورت دلفی یک خط جدید بعد از Begin متد ایجاد میکند و مقدار را به متغیر تخصیص میدهد.
تعریف فیلد (Declare Field)نیز شباهت خیلی زیادی به تعریف متغیر دارد.
Extract Resource String
دومین Refactoring یی که در دلفی وجود دارد راه ساده ایست برای انتقال یک متغیر رشته ای به بخش resource string.
بخش resource string در قسمت code segment برنامه کامپایل نمیشود ولی مانند یک resource به فایل اجرایی لینک میشود.
به این شکل میتوان بخشی از حافظه را که همیشه درگیر متغیرهای رشته ای هست را آزاد کرد.
نکته :
تعریف resource string مانند تعریف Const است :
resourcestring
rsTest = 'this is my resource string'
استفاده از resource string ها واقعا خسته کننده ست؛ باید از رشته مورد نظر کپی بگیرید ، از محل فعلی به قبل از
بلاک جاری(حداقل) حرکت کنید ، resource string را تعریف کنید ، رشته مورد نظر را قرار دهید ، به موقعیت قبلی برگردید
و از نام resource string یی که در بالا تعریف کرده اید استفاده کنید. ولی حالا فقط با یک دستور همه این کارها انجام میشود، Ctrl+Shift+L .
فرض کنید متدی مانند متد زیر دارید :
procedure TForm1.Button1Click(Sender: Tobject);
var
strTest: string;
begin
strTest := 'Hello';
end;
کرسر متن را داخل رشته Hello ببرید (لازم نیست که متغیر را انتخاب کنید یا این خط را انتخاب کنید) سپس کلیدهای Ctrl+Shift+L
را فشار دهید. فرمی نمایش داده میشود که در آن نام پیشنهادی resource string وجود دارد که میتوانید آن را تغییر دهید و تائید کنید،
تمام مراحلی که در بالا ذکر کردم انجام میشود. (نام resource string برگرفته از رشته مورد نظر به اضافه کلمه Str ست).
پس Extract Resource String با استفاده از :
Ctrl+Shift+L
یا از منوی اصلی گزینه Refactor و بعد هم گزینه Extract Resource String
یا کلیک راست در Code Editor ، گزینه Refactoring و بعد هم Extract Resource String
نکته :
سه نوع Refactoring یی که توضیح دادم Declare Variable) و Declare Field و Extract Resource String) در دلفی وجود دارد
و جزء لیست رسمی Refactoring نیست ، ولی به هر حال پیاده سازی را ساده تر میکند.
Rename Refactoring
یکی از مهمترین انواع Refactoring است که جزء لیست رسمی Refactoring نیز هست. Rename بسیار قدرتمند است و میتواند
روی خیلی از موارد مانند متغیرها، procedure ها، type ها(شامل کلاسها)، فیلدها، functionها کار کند.
فعال کردن Rename Factoring :
ترکیب کلیدهای Ctrl+Shift+E
یا از منوی اصلی گزینه Refactor و بعد گزینه Rename
یا کلیک راست در Code Editor و گزینه Refactoring و بعد هم گزینه Rename
کافی ست کرسر متن را روی چیزی که میخواهید تغییر نام دهید بگذارید(لازم نیست که آن را انتخاب کنید) ، Rename را فعال کنید.
اطلاعاتی از قبیل نام کلاس یا یونیت و نام فعلی و نام جدید نمایش داده می شود که میتوانید نام جدید را وارد کنید.
اگر گزینه View reference before refactoring انتخاب شده باشد، قبل از تغییر نام ، لیستی از تغییرات در یک پنجره جدید
نمایش داده می شود ، پس از مرور میتوانید عملیات را ادامه دهید یا لغو کنید.
اگر نوعی (منظور فیلد ، شئی، متغیر و ...) را تعریف کرده اید و از آن در چندین یونیت مختلف استفاده کرده اید و حالا
قصد تغییر نام آن را دارید ، Rename تمام یونیتها را برای این تغییر مرور میکند.
حقیقتا" زیبایی Rename Refactoring اینست که نه فقط در تعریف و اعلان یک کلاس یا متد موثر هست، بلکه روی همه
ارجاعات به متد یا کلاس نیز تاثیر گذار هست.
یکی دیگر از تفاوتهای Search و Replace با Rename refactoring در اینست که اگر در یک کلاس پدر، متد virtual یی
را تغییر نام دهید ، Rename در کلاسهای فرزند نام متد را تغییر خواهد داد.
اگر که فرضا" با نام جدید شئی ، شئی دیگری وجود داشته باشد، Rename refactoring با خطا متوقف خواهد شد.
موردی که بوسیله Rename نمیتوانید تغییر دهید، Property ست، البته نه نام Property، بلکه متدهای setter و getter آن.
به این صورت که اگر نام یک Property را تغییر دهید، متدهای مربوط به آن که معمولا" ترکیبی ست از نام Property و پیشوندهای get و set،
تغییر نخواهند کرد. که البته برای این مورد میتوانید به صورت جداگانه از Rename استفاده کنید.
Extract Method Refactoring
یکی دیگر از Refactoring های رسمی Extract Method هست. Extract Method یک قطعه کد را تبدیل به یک متد میکند
که نام متد نشان دهنده هدف متد هست.
ممکن است همین کار را زمانی انجام دهید که متد برای درک خیلی پیچیده شده یا نیاز شما به چنین کدی که
در متد دیگری پیاده سازی شده باعث انجام این کار شود. فرض کنید دو متد مجزا دارید که بخشی از کد در هر دو مشترک هست، در چنین مواقعی بهترست که در صورت امکان بخش مشترک تبدیل به یک متد شود تا هر دو متد بتوانند از آن استفاده کنند.
برای فعال کردن Extract Method Refactoring ابتدا بخشی از کد را که میخواهید تبدیل به یک متد شود انتخاب کنید
سپس یکی از سه روش زیر را اجرا کنید :
ترکیب کلیدهای Ctrl+Shift+M
یا از منوی اصلی گزینه Refactor و بعد هم گزینه Extract Method
یا کلیک راست روی Code Editor و گزینه Refactoring و بعد گزینه Extract Method
در ابتدا Extract Method کد مورد نظر شما را تجزیه میکند و اگر قابل تبدیل نباشد به شما هشدار میدهد. اگر کد مورد نظر قابل
تبدیل باشد آن را تبدیل به یک متد خارج از متد جاری میکند.
نکته جالبی که در Extract Method وجود دارد اینست که اگر در قطعه کدی که انتخاب شده متغیری وجود داشته باشد ،
به صورت خودکار آن را به عنوان پارامتر در نظر میگیرد.
بعد از باز شدن فرم Extract Method ، اطلاعاتی از قبیل نام متد جاری ، نام متد جدید و ساختار کامل متد نمایش داده میشود
که میتوان نامی را برای متد در نظر گرفت. فراموش نکنید که در بخش new method name فقط نام متد را بنویسید و از قرار دادن
پرانتز و تعریف پارامتر خودداری کنید.
نمونه :
این کد ، کد اصلی ما هست که میخواهیم بخش داخلی حلقه for را تبدیل به یک متد کنیم:
1)
procedure TForm1.Button2Click(Sender: TObject);
var
i: Integer;
outstr: string;
begin
for I := 1 to 10 do
begin
outstr := inttostr(i);
ListBox1.Items.Add(outstr);
end;
end;
2)
بخش داخلی حلقه را انتخاب کنید( به غیر از begin و end)، یعنی :
outstr := inttostr(i);
ListBox1.Items.Add(outstr);
3)
یکی از روشهای فراخوانی Extract Method را انجام دهید، مثلا" Ctrl+Shift+M، بعد از باز شدن فرم، NumberToString را
در قسمت نام متد تایپ و تائید کنید. میتوانید با مرور سورس نتیجه را ببینید.
نکته:
هر کدی را نمیتوان تبدیل به یک متد کرد. کد حتما" باید بدون خطا باشد و شامل with و متدهای محلی/تو در تو
(متدی که داخل یک متد دیگر ایجاد شده) و دستور inherited نباشد.
m-khorsandi
شنبه 06 آبان 1385, 12:03 عصر
بخش سوم
Change Parameters
توسط این Refactoring میتوانید نوع پارامتر(های) موجود یک متد را تغییر دهید، یک پارامتر جدید به متد اضافه کنید، پارامتری را حذف کنید یا ترتیب پارامترها را تغییر دهید. تغییری که حاصل میشود هم بر روی تعریف(declaration) متد هست و هم روی پیاده سازی (implementation) متد.
اگر پارامتر متدی که به صورت virtual تعریف شده را تغییر دهید، این تغییر روی تمام کلاسهای فرزند که این متد را override کرده اند نیز اعمال می شود.
فراخوانی Change Parameters :
ترکیب کلیدهای Ctrl+Shift+A
یا از منوی اصلی ، گزینه Refactor و بعد هم Change Params
یا کلیک راست روی Code Editor ، گزینه Refactoring و بعد Change Params
فرمی که باز میشود اطلاعاتی مانند نام یونیت، نام کلاس و لیستی از پارامترها (اگر وجود داشته باشد) به همراه نوع داده ، مقدار پیش فرض و نوع پارامتر (var, const, out) نمایش میدهد.
کاربرد دکمه ها :
Add برای اضافه کردن پارامتر
Edit برای تغییر نوع پارمتر موجود
Remove حذف پارامتر
Move up و Move Down تغییر ترتیب پارمترها در متد
بعد از ایجاد تغییرات روی پارامترهای متد و زدن کلید OK ، لیستی از تغییراتی که اعمال خواهند شد نمایش داده می شود که شما می توانید این تغییرات را مرور کنید و نهایتا" تائید کنید.
Extract Interface
خارج کردن یک متد از یک کلاس و قرار دادن آن در یک Interface . با فعال کردن Extract Interface فرمی باز میشود که میتوانید نام Interface و نام یونیتی که میخواهید این Interface در آن قرار گیرد را وارد کنید. بعد از تائید فرم، لیستی از مواردی که تغییر خواهند کرد نمایش داده می شود که پس از مرور میتوانید آن را تائید یا لغو کنید.
اگر نام Interface یی که وارد میکنید از قبل وجود داشته باشه، این متد به Interface موجود اضافه خواهد شد.
اگر نام یونیتی که میخواهید Interface در آن ساخته شود وجود نداشته باشد، ابتدا یونیت ساخته شده و سپس Interface در آن قرار میگیرد.
Introduce Variable و Introduce Field
Introduce Variable
در نگاه اول شباهت زیادی به declare variable دارد، در صورتیکه declare variable ، تعریف متغیری ست که در کد استفاده شده ولی جایی تعریف نشده و introduce variable ، انتخاب یک عبارت برای تعریف یک متغیر جدید و تخصیص عبارت به آن متغیر هست.
فراخوانی Introduce Variable :
منوی اصلی ، گزینه Refactor ، گزینه Introduce Variable
یا کلیک راست در Code Editor ، گزینه Refactoring ، گزینه Introduce Variable
نمونه :
procedure TForm5.DisplayPosition;
begin
ShowMessage (IntToStr (Left + Top));
end;
در این مثال می توانید عبارت Left + Top را انتخاب کنید و Introduce Field را فراخوانی کنید. فرمی باز میشود که فقط باید نام متغیر جدید (فرضا" Position) را در آن وارد و تائید کنید. می بینید که یک متغیر در بخش var تعریف میشود و کد به صورت زیر تغییر میکند :
procedure TForm5.DisplayPosition;
var
Position: Integer;
begin
Position := Left + Top;
ShowMessage (IntToStr (Position));
end;
Introduce Field شباهت زیادی به Introduce Variable دارد با این تفاوت که فیلدی(متغیری) که در ساختار کلاس تعریف می شود ، ویژگیهایی از قبیل مقدار اولیه (intitialize) و میدان دید (visibility) ... را باید در مورد آن مشخص کرد که با فراخوانی فرم Introduce Field ، این امکان فراهم میشود.
فراخوانی Introduce Field :
منوی اصلی ، گزینه Refactor ، گزینه Introduce Field
یا کلیک راست در Code Editor ، گزینه Refactoring ، گزینه Introduce Field
- Find Unit Refactoring
آخرین Refactoring یی که دلفی 2006 در اختیار شما میگذارد، توانایی اضافه کردن خودکار یونیت به دستور uses هست. بعضی مواقع ممکن ست که از توابع ، پروسیجرها یا هر تعریفی از یونیتی دیگر استفاده کنید ولی آن یونیت در لیست uses اضافه نشده باشد.
نمونه :
DateUtils.MinuteOf(x)
DateUtils.MinuteOfTheDay(x)
در اینصورت توسط Find Unit میتوانید نام یونیت مربوطه را در لیست uses اضافه کنید.
Find Unit به صورت زیر فراخوانی میشود :
Ctrl+Shift+A
یا از منوی اصلی گزینه Refactor و بعد گزینه Find Unit
یا کلیک راست در Code Editor و گزینه Refactoring و بعد گزینه Find Unit
بعد از باز شدن فرم Find unit میتوانید تعیین کنید که یونیت مورد نظر در کدام uses میبایست قرار گیرد، uses بخش Interface یا بخش Implementation .
m-khorsandi
دوشنبه 15 آبان 1385, 19:55 عصر
بخش چهارم
• دستور for…in
مایکروسافت ویژوال بیسیک دستوری برای پیمایش از ابتدا تا انتهای یک مجموعه دارد که for..each نامیده میشود. قبلا" چنین ایده ای
در #C نیز پیاده شده است. شرکت بورلند در دلفی نسخه 2005 تصمیم گرفت که پشتیبانی بهتری از این نوع کد را انجام دهد. البته نه فقط برای کامپایلر دات نت بلکه هم برای کامپایلر Win32 و هم برای دات نت. الان این دستور برای استفاده آماده است، البته نه تنها برای یک کلاس Container بلکه برای :
- کاراکترهای موجود در یک رشته
- مقادیر یک مجموعه
- آیتم های یک آرایه داینامیک یا استاتیک ، شامل آرایه های دو بعدی
شکل کلی :
For element in collection do
به مثال های زیر توجه کنید :
- کاراکترهای موجود در یک رشته
var
s: String;
ch: char;
begin
s := 'Hello world';
for ch in s do
ListBox1.Items.Add(ch);
end;
در این مثال، حلقه به تعداد ch های موجود در s اجرا خواهد شد، یا به عبارتی حلقه به تعداد کاراکترهای موجود در s اجرا میشود.
- آیتم های یک آرایه
var
iArray: array[1..5] of integer;
i: integer;
begin
iArray[1] := 1;
iArray[2] := 2;
iArray[3] := 3;
iArray[4] := 4;
iArray[5] := 5;
for i in iArray do
ListBox1.Items.Add(IntToStr(i));
End;
در این مثال، حلقه به تعداد i موجود در iArray تکرار خواهد شد. اگر فرضا" برای دو خانه آخر آرایه مقداری در نظر نگیرید ، چون آرایه به صورت استاتیک تعریف شده، باز هم حلقه 5 بار تکرار خواهد شد که در مورد آرایه های داینامیک ، به خاطر ماهیتشان، چنین اتفاقی نمی افتد.
- مقادیر یک مجموعه
type
TNumber = (one, two, three);
TNumberSet = set of TNumber;
var
Number: TNumberSet;
myNumber: TNumber;
begin
Number := [one, two, three];
for myNumber in Number do
// do something
Number := [one, three];
for myNumber in Number do
// do something
end;
در این مثال، حلقه به تعداد عنصرهای موجود در مجموعه تکرار میشود، یعنی برای حلقه اول 3 بار و برای حلقه دوم 2 بار.
procedure TForm1.Button2Click(Sender: TObject);
var
c: TComponent;
begin
for c in self do
ListBox1.Items.Add(c.Name);
end;
در این مثال، حلقه به تعداد کامپوننتهای موجود در فرم اجرا خواهد شد و نام آنها را به لیست اضافه خواهد کرد.
• Advanced Record
رکوردها همیشه بخشی از زبانهای برنامه نویسی هستند. اما در این نسخه به رکوردها میدان بیشتری داده شده چونکه از این به بعد برای رکورد میتوان هم "متد" تعریف کرد و هم از مفهوم نهان سازی یا Encapsulation استفاده کرد ( البته فقط از public و private).
یک رکورد به همراه متد تا حدی شبیه به یک کلاس است. بیشترین تفاوت (به غیر از مفاهیم Inheritance و Polymorphism) این است که :
رکورد از حافظه محلی (از Stack frame) استفاده میکند.
رکورد را میتوان به عنوان پارامتری از نوع By Value ارسال کرد.
رکورد در زمان تخصیص یک متغیر رکورد به یک متغیر رکورد دیگر رفتار "value copy" دارد. به این معنی که محل دیگری از حافظه با محتویات رکورد مبدا مقدار دهی میشود.
از کلمات کلیدی مانند dynamic و virtual و message در تعریف رکورد نمی توانید استفاده کنید.
در مقابل متغیری از نوع کلاس :
در حافظه Heap قرار میگیرد.
به عنوان پارامتر به صورت By Reference ارسال میشود.
در هنگام تخصیص یک متغیر کلاس به یک متغیر کلاس دیگر رفتار "reference copy" دارد. به این معنی که متغیر مقصد هم به همان محل از حافظه اشاره میکند که متغیر مبدا اشاره میکند، در واقع عمل "کپی" صورت نمی گیرد بلکه آدرس حافظه به متغیر مقصد تخصیص داده می شود.
برای مثال :
وقتیکه متغیری از نوع رکورد تعریف میکنید ، متغیر مربوطه در Stack ایجاد میشود و میتوانید بلافاصله از آن استفاده کنید .یک متغیری از نوع رکورد نسبت به متغیر نوع کلاس کمتر به سمت مدیر حافظه و Garbage Collector میرود.
Type
TpersonInfo: Record
Fname: String;
Lname: String;
End;
Var
myInfo: TpersonInfo;
در این حالت ، به محض تعریف متغیر myInfo از نوع TpersonInfo ، محلی از حافظه به myInfo اختصاص داده میشود و میتوانید از آن استفاده کنید. در صورتیکه در مورد کلاس این مراحل یک قدم اضافه میشود :
Type
Tfoo = Class
End;
Procedure DoIt;
Var
myFoo: Tfoo;
Begin
myFoo:= Tfoo.Create(Self);
End;
اینها دلایل کلیدی برای استفاده از Record به جای Class هستند.
رکورد میتواند یک Constructor نیز داشته باشد، اما این Constructor حتما" باید یک پارامتر داشته باشد ، در غیر اینصورت پیغام خطای "parameterless constructors not allowed on record types" را دریافت می کنید. چرا بورلند این شرط را لازم دانسته است؟ رکورد به طور خودکار ساخته میشود ، یعنی یک constructor بدون پارامتر دارد، پس زمانی که برنامه نویس ، constructor دیگری تعریف میکند، باید یکی یا بیشتر پارامتر نیز برای آن در نظر بگیرد تا تفاوتی بین constructor پیش فرض و constructor یی که برنامه نویس تعریف کرده بوجود بیاد.
نمونه :
تعریف :
TmyRecord = Record
Private
one: string;
two: integer;
three: char;
public
procedure print;
constructor Create(aString: string);
procedure Init(aValue: Integer);
end;
پیاده سازی :
procedure TmyRecord.Print;
begin
showmessage (one, ' - ' , two, ' - ', three);
end;
constructor TmyRecord.Create(aString: string);
begin
showmessage ('TMyRecord.Create called');
one := aString;
two := 2;
three := '3';
end;
procedure TmyRecord.Init(aValue: Integer);
begin
two := aValue;
one := IntToStr (aValue);
end;
استفاده :
var
myrec: TmyRecord;
begin
myrec := TmyRecord.Create('hello');
myrec.Print;
end;
وقتی در این زبان برنامه نویسی کلاس وجود دارد، مطمئنا" تعجب می کنید که چه دلیلی دارد که رکورد "متد" داشته باشد ؟ گذشته از کمبود ویژگیهای جدید و پیشرفته در کلاس، فرق اصلی بین رکورد و کلاس، روش استفاده آنها از حافظه ست.
m-khorsandi
دوشنبه 22 آبان 1385, 19:35 عصر
بخش پنجم
• Sealed Class
در Net framework. همچون معماری جاوا، راهی برای جلوگیری از ارث بری بیشتر از یک کلاس وجود دارد. Sealed Class ها، کلاسهایی هستند که شما نمی توانید از آنها برای کلاس دیگری به ارث ببرید. این ویژگی الان در دلفی Win32 نیز وجود دارد.
شکل کلی :
TinheritedClass = class sealed (TbaseClass)
…
end;
به این معنی ست که از کلاس TinheritedClass ، کلاس دیگری نمیتواند به ارث ببرد .
مثال :
type
TBase = class
procedure A; virtual;
end;
TBaseDeriv = class sealed (TBase)
procedure A; override;
end;
از این به بعد نمی توانیم کلاس دیگری را از کلاس TBaseDeriv به ارث ببریم.
TDeriv = Class (TBaseDeriv)
End;
در این صورت با پیغام خطای کامپایلر مواجه خواهید شد : "Cannot extend sealed class TbaseDeriv" .
فراموش نکنید که Abstract و Sealed را با هم نمی توانید به کار ببرید.
• Final Method
با Sealed class میتوانید یک کلاس را به صورت کامل از ارث بری محروم کنید. بعضی مواقع هم نیاز دارید که از ارث بری متدی که به صورت virtual تعریف شده است جلوگیری کنید.
برای این کار میتوانید از Final Method ها استفاده کنید.
مثال :
TBaseDeriv = class (TBase)
procedure A; override; final;
end;
از این به بعد کلاسی که از کلاس TbaseDeriv به ارث ببرد ، نمیتواند متد A را override کند. در غیر اینصورت با پیغام خطای کامپایلر مواجه میشود : "Cannot override a final method" .
خوب، حالا ممکن است که از خودتان سئوال کنید که چه دلیلی پشت سر این دو مفهوم وجود دارد؟ ممکن ست بخواهید سایرین را از ارث بری کلاس به صورت عمومی منع کنید و مخصوصا" میخواهید که از ارث بری کلاسهای Security یا Cryptography توسط دیگران جلوگیری کنید، در این زمان این دو مفهوم به شما کمک میکنند.
از نظر من تا جای ممکن باید از استفاده از این ویژگی در یک کتابخانه خودداری کرد و اجازه دهیم که برنامه نویسان از کلاسهای موجود نهایت استفاده را بکنند، مگر در شرایط خاص که مطمئنا" پیش خواهد آمد.
با این حال اگر نگاهی به کتابخانه های مایکروسافت برای دات نت بیاندازید ، sealed class و final methodهای بیشماری را پیدا خواهید کرد.
• Class Helper
زمانیکه بورلند کار بر روی دلفی دات نت را آغاز کرد، یکی از مشکلاتی که ظاهر شد؛ نیاز به تطبیق برخی از کلاسهای پایه دلفی (مانند Tobject، Exception) با کلاسهای .Net Framework بود. بعد از کمی تحقیق ، ایده ای متحیر کننده به نام Class Helper عرضه شد. Class Helper چیزی نیست به جز نوعی کلاس که موقعیکه در کلاس دیگری شرکت کند ، متدها و ویژگیهای بیشتری را مطرح میکند که ممکن ست شما در متن کلاس اصلی از این متدها و ویژگیهای اضافه تر استفاده کنید. Class Helper راهی ست برای توسعه کلاس، بدون استفاده از مفهوم وراثت یا همان Inheritance. به عبارت دیگر ، شما یک Class Helper ایجاد میکنید تا متدهای آن به کلاس موجود اضافه شود. این قابلیت به غیر از دلفی .Net در دلفی Win32 نیز قابل استفاده هست.
شکل کلی :
type
ClassHelperName = class helper for ExistingClassType
methods
end;
نمونه :
تعریف ساختار کلاس اصلی :
TMyObject = class
private
Value: Integer;
Text: string;
public
procedure Increase;
end;
تعریف Class Helper برای کلاس TmyObject که در بالا تعریف شده است :
TMyObjectHelper = class helper for TMyObject
public
procedure Show;
end;
پیاده سازی کلاس اصلی :
procedure TMyObject.Increase;
begin
Inc (Value);
end;
پیاده سازی Class Helper :
procedure TMyObjectHelper.Show;
begin
ShowMessage (Text + ' ' + IntToStr (Value) + ' -- ' + ClassName);
end;
استفاده از کلاس TmyObject :
procedure TForm1.Button6Click(Sender: TObject);
var
obj: TMyObject;
begin
obj := TMyObject.Create;
obj.Text := 'test';
obj.Value := 100;
obj.Show;
end;
می بینید که متد Show که در Class Helper یی با نام TmyObjectHelper تعریف شده به سادگی توسط کلاس اصلی قابل استفاده هست. بعد از اجرای متد Show به مقداری که ClassName توسط ShowMessage نمایش می دهد دقت کنید.
m-khorsandi
شنبه 18 آذر 1385, 10:54 صبح
اگه مطلبی اضافه کنم، هم به این صفحه و هم به فایل ضمیمه اضافه میکنم.
فایل موجود در پست شماره 9، شامل بخشهای 1 تا 7 هست.
m-khorsandi
شنبه 09 دی 1385, 23:18 عصر
بخش ششم
• Class Data
یادآوری :
تعریف class method ها همواره در دلفی وجود داشته، class method ها ، متدهایی هستند که محدود به یک شئی بخصوص نیستند و در اختیار کلاس قرار دارند. به بیان دیگر متدهایی که نیازی به یک نمونه شئی ساخته شده از یک کلاس ندارند.
تعریف بالا را به این جهت یاد آوری کردم که در نسخه جدید دلفی ، ویژگی اضافه شده که خیلی زیاد شبیه به class method هاست. این ویژگی "داده" را در بین اشیائی که از یک کلاس خاص ساخته میشوند به اشتراک میگذارد.
البته شما این قابلیت را میتوانستید (در نسخه های قدیمی) و میتوانید! با تعریف یک متغیر عمومی در قسمت implementation یونیت شبیه سازی کنید ولی به این طریق کد خیلی تمیزی ننوشتید و همچنین ممکن ست در جایی با کلاس های مشتق شده به درد سر بیفتید و زحمت و هزینه مرور و بازنویسی این کد نه چندان تمیز را متحمل شوید. فکر کنم الان که نامی از "متغیر" به میان آمد ، موضوع را بهتر درک کنید، دقیقاً قرار ست متغیری تعریف کنیم تا اشیائی از یک کلاس ، به آن به صورت مشترک دسترسی داشته باشند.
چطور میتوان یک class data تعریف کرد؟
خیلی ساده، با استفاده از کلمه کلیدی class var میتوانید بلاکی را برای تعریف یک یا چند class data ایجاد کنید. تمام فیلدهایی (متغیرهایی) که بعد از این کلمه تعریف شوند دارای خاصیت ذخیره سازی ایستا (Static) هستند.
(منظورم از بلاک چیزی مثل begin و end هست)
با استفاده از کلمه کلیدی class var بلاک تعریف class data آغاز میشود و با استفاده از یکی از موارد زیر این بلاک خاتمه پیدا میکند :
تعریف یک var یا class var دیگر ، اگر از var استفاده کنید با متغیرهایی که بعد از آن تعریف میشوند مانند متغیرهای معمولی رفتار میشود.
تعریف یک Property که میتواند شامل class property ها نیز باشد .
تعریف یک متد (procedure یا function ) که شامل class function یا class procedure نیز هست.
تعریف constructor یا destructor .
و در نهایت اینکه حوزه تعریف خاتمه پیدا کند (فرضاً class var را در public تعریف کرده اید و حالا به کلمه کلیدی published رسیده اید) .
نمونه :
TmyData = class
private
class var
Green: integer;
Blue: integer;
Red: Integer;
Var
Fcounter: integer
end;
کدی که از این کلاس استفاده میکند :
Var
myObject: TmyData;
begin
TmyData.Green := 10;
TmyData.Red := 20;
TmyData.Blue := 30;
myObject := TmyData.Create;
ShowMessage(IntToStr(myObject.Green + myObject.Blue));
myObject.Blue := 100;
myObject.Free;
ShowMessage(IntToStr(TmyData.Blue));
end;
نکته :
این موضوع را باید زودتر مطرح میکردم ولی متاسفانه فراموش شد. کلمه کلیدی var را میتوانید در تعریف ساختار کلاس استفاده کنید. در دلفی 7 ، هنگام تعریف ساختار کلاس (فرضاً در public) بعد از تعریف اولین متد ، دیگر نمیتوانستید فیلد یا متغیری را تعریف کنید. اما در دلفی 2006 با استفاده از کلمه کلیدی var بعد از متد میتوانید فیلد/متغیری را تعریف کنید.
نمونه :
TTestVarKeyWord = class
private
FName: string;
procedure FullName();
var
LName: string;
function dotest: string;
var
FPhone: String;
end;
m-khorsandi
جمعه 15 دی 1385, 06:37 صبح
بخش هفتم
• شرح class method :
class method ها ، متدهایی هستند که بدون اینکه شیئی از آن کلاس ساخته شود اجرا میشوند. مطمئناً تا به حال با contructor ها سر و کار داشته اید و مجبور بودهاید که با متد Create یک کلاس کار کنید. متد Create یا همان constructor، یک نوع class method هست . به نمونه کد زیر توجه کنید :
with Tlabel.Create(nil) do
begin
Caption := 'Load…';
With := 20;
Height := 10;
Parent := Form1;
End;
** اگر به اولین خط دقت کنید، میبینید که متدی از یک کلاس فراخوانی شده و نه از یک شیئ
فرض کنید که در حال نوشتن کلاسی برای فراخوانی فایل های گرافیکی هستید و این کلاس قابلیت فراخوانی فرمتهای خاصی از فایلهای گرافیکی را دارد.
خوب ،
یک راه حین پیاده سازی کلاس مورد نظر این ست که کلاس را طوری پیاده سازی کنید که برنامه نویس مجبور باشد یک شیئ از کلاس بسازد ، مقدار دهی اولیه را انجام دهد و سپس نام فایل را به متدی که فایل های گرافیکی را نمایش میدهد پاس دهد و حالا اگر کلاس قابلیت نمایش این نوع فرمت را نداشت ، با پیغامی کاربر را آگاه سازد.
این روش ، روش هزینه بریست و دلیل آن هم مشخص ست.
راه دیگر اینست که class method یی را تعریف کنید تا برنامه نویس بتواند قبل از انجام هر کاری ، فایل مورد نظر را به آن پاس دهد و تست کند که کلاس قابلیت نمایش فایل را دارد یا خیر؟
مانند :
type
TMyGraphicClass = class
class function Supports( Format: String): Boolean;
...
end;
class function TmyGraphicClass.Support(Format: String): Boolean;
begin
// do something
end;
و به شکل زیر از آن استفاده کنید :
if TMyGraphicClass.Supports( 'myimagefile.wmf' ) then
...
به این صورت برنامه نویس ابتدا قابلیت نمایش فایل مورد نظر را توسط کلاس تست میکند و بعد از آن میتواند یک شئی از کلاس مورد نظر ایجاد و استفاده کند.
Self : یک متغیر مخفی در تمام متدهای یک شیئ و سبب ارجاع متد به شیئ هست. فرقی نمیکند که در یک متد از یک کلاس ، از کلمه کلیدی Self استفاده کنید یا نه ، به این دلیل که به صورت ضمنی به آن اشاره شده ست.
فرض کنید فرمی را ایجاد کرده اید و میخواهید Caption فرم را مقدار دهی کنید ، به کد زیر دقت کنید :
procedure Tform1.FormCreate(Sender: Tobject);
begin
Self.Caption := 'for Test';
end;
procedure Tform1.FormCreate(Sender: Tobject);
begin
Caption := 'for Test';
end;
اینکه Self را "بنویسید" یا "ننویسید" تاثیری در مقدار دهی "عنوان" فرم ندارد. این توضیحات به این خاطر هست که بدانید کلمه کلیدی Self در متدهای معمولی و class method ها رفتار متفاوتی دارد. در یک متد معمولی توسط Self میتوانید به فیلدها (متغیرها) ، Property ها و متدهای معمولی دیگر دسترسی داشته باشید در صورتیکه در class methodها توسط Self ، دسترسی به constructor و سایر class method ها امکان پذیر هست.
m-khorsandi
جمعه 20 بهمن 1385, 22:33 عصر
این فایل شامل بخشهای 1 تا 7 هست.
m-khorsandi
پنج شنبه 17 اسفند 1385, 16:28 عصر
بخش هشتم
• ویژگیهای بیشتر برای کلاس
Strict Private و Strict Protected
همانطور که میدانید زمانی که در یک یونیت، کلاسی را تعریف میکنیم و در آن کلاس از میدان دید private و protected استفاده میکنیم، و وقتی کلاسی را از کلاس تعریف شده مشتق میکنیم(در واقع کلاس فرزندی را میسازیم) در کلاس فرزند و در همان یونیت، متغیر/فیلدهای تعریف شده در Private قابل رویت هستند، در صورتیکه منطقاً وقتی فیلد یا متغیری را در بخش private تعریف میکنیم، انتظار این ست که فقط در همان کلاس بتوان به آن دسترسی داشت و نه کلاسهای مشتق شده از آن. همینطور وقتی از protected استفاده میکنیم، فیلد یا متغیرهای تعریف شده فقط همان کلاس و کلاسهای فرزند قابل دسترسی باشند و در کلاس دیگری دیده نشود و از شگردی که اغلب Protected Hack نامیده میشود هم نتوان برای دسترسی به آنها استفاده کرد(این موارد بخشی از قابلیتهای کامپایلر دلفی ست.).
برای رسیدن به این دو هدف میتوان از Strict Protected و Strict Private بهره برد.
با strict private شروع میکنیم و ابتدا مثالی را برای Private سنتی مرور میکنیم :
نام یونیت : Unit1
TTest = class(TObject)
private
AField: String;
end;
با اینکه فیلد AField در بخش Private تعریف شده، اما اگر کلاسی را از TTest مشتق کنیم، به فیلد Afield هم دسترسی خواهیم داشت، به این صورت :
TDerivedTest = class(TTest)
private
Procedure Add();
end;
procedure TDerivedTest.Add;
begin
AField := 'Private member';
end;
اما اگر به جای Private از Strict Private استفاده کنیم، فیلد AField در میدان دیدِ کلاس مشتق شده قرار نمیگیرد:
TTest = class(TObject)
Strict private
AField: String;
end;
TDerivedTest = class(TTest)
private
Procedure Add();
end;
procedure TDerivedTest.Add;
begin
AField := 'Private member';
end;
با مقداردهی فیلد AField پیغام خطای 'Undeclared Identifier :'AField را مشاهده میکنید. به این شکل ما واقعاً فیلدی داریم که فقط در کلاس تعریف شده به آن دسترسی داریم و در کلاسهای فرزند دیده نمیشود.
بخش Strict Protected
وقتی فیلد یا متدی را در بخش Protected تعریف میکنید، این فیلد یا متد در کلاسهای فرزند و همینطور در سایر کلاسهای موجود در همان یونیت دیده میشود. اما اگر بخواهید این تعاریف فقط در همان کلاس و کلاسهای فرزند دیده شود میتوانید از Strict Protected استفاده کنید.
مثال زیر را ببینید :
نام یونیت : Unit1
TTest1 = class(TObject)
protected
AField: String;
end;
TTest2 = class(TObject)
protected
procedure Add();
end;
این دو کلاس، دو کلاس مجزا هستند و هیچ ارتباطی به هم ندارند، به پیادهسازی متد Add که در کلاس Test2 هست دقت کنید :
procedure TTest2.Add;
var
a: TTest1;
begin
a.AField := 'Protected Field';
end;
ابتدا متغیری از کلاس TTest1 تعریف میکنیم و سپس فیلد AField را مقداردهی میکنیم، دقت کنید، فیلدی را مقداردهی میکنیم که ظاهراً مخصوص کلاس TTest1 و مشتقات آن هست!
چه کار کنیم که این فیلد در فقط در همان کلاس و کلاسهای مشتق شدهی آن در دسترس باشد، راه حل Strict Protected هست.
TTest1 = class(TObject)
strict protected
AField: String;
end;
TTest2 = class(TObject)
protected
procedure Add();
end;
procedure TTest2.Add;
var
a: TTest1;
begin
a.AField := 'Protected Field';
end;
بعد از کامپایل این مثال، پیغام خطای Cannot access protected symbol TTest1.AField مشاهده میکنید، به این شکل فیلد AField فقط در حوزه دید کلاس TTest1 و کلاسهای مشتق شده از آن قرار دارد.
در این دو مثال من فقط در مورد فیلدها توضیح دادم در صورتیکه این روند برای متدها یا همان Procedureها و Functionها نیز صادق هست.
استفاده توام Protected و Strict Protected مشکلی ندارد و همینطور Private و Strict Private .
m-khorsandi
دوشنبه 21 اسفند 1385, 08:14 صبح
بخش نهم
• VCL در دلفی 2006
کتابخانهی VCL در دلفی 2006 واقعاً پیشرفت کرده و میتوان گفت این مجموعه از تغییرات، تغییرات قابل توجهی در طی این چند سال هست.
توضیحی دربارهی VCL : VCL سرنام Visual Component Library ست، مجموعهای از کامپوننتهای ویژوال برای توسعهی سریع برنامههای کاربردی تحت ویندوز در زبان دلفی که از قابلیتهای مهم و اساسی دلفی نیز هست . VCL شامل تنوع وسیعی از کلاسهای ویژوال، غیر ویژوال و مفید برای کارهایی مانند ساختن برنامههای ویندوزی، برنامههای تحت وب، برنامههای دیتابیسی و برنامههای کنسول هست. همه کلاسها از TObject مشتق میشوند. TObject، معرف متدهایی ست که رفتارهای بنیادی و پایه (که لازمهی هر کلاسی هست) مانند construction و destruction و کنترلکنندهی پیغامها را پیادهسازی میکنند.
در دلفی 2006 سه کامپوننتِ TTrayIcon و TGridPanel و TFlowPanel اضافه شده ست. کلاسهای TCustomTransparentControl و TMargins و TPadding نیز اضافه شدهاند.
ویژگیهای Margins و Padding
برای تعریفِ موقعیتهای نسبی دربین کنترلهایی که روی فرم هستند، دلفی 2006 دو ویژگی جدید به نامهای Margins و Padding به کلاس TControl اضافه کرده و در طبقهبندی Layout در Object Inspector قرار میگیرد.
Margins (که نام کلاس آن TMargins و دارای چهار ویژگی ست که به هر کنترل اضافه میشود) فراهمکنندهی فضای لازم پیرامون هر کنترل هست. این توضیح اشارهای بود به اینکه اگر یک کنترل با یک ضلع فرم هم تراز شود، کنترل لبههای فرم را لمس نخواهد کرد. البته Margins یک ویژگی ست که فقط 4 عدد (تعداد پیکسلها) را میگیرد و زمانی به صورت خودکار عمل میکند که ویژگی AlignWithMargins را فعال کنید و برای ویژگی Align نیز مقداری به غیر از alNone و alCustom قرارداده باشید به غیر از این اگر در حال نزدیک کردن کنترل به لبههای فرم باشید، به محض اینکه فاصله کنترل (از هر جهتی) با لبهی فرم برابر با تعداد پیسکلهای تعریف شده باشد، خط نازک سیاه رنگی در وسط ضلع کنترل، حد فاصل کنترل و لبهی فرم ظاهر میشود.
یک فرم خالی را در نظر بگیرید، یک Panel روی آن بگذارید و ویژگی Margins را به ترتیب با عدد 5 مقداردهی کنید. ویژگی AlignWithMargins را True کنید و برای ویژگی Align مقدار alTop را در نظر بگیرید. Panel به بالای فرم رفته ولی فاصله آن با 3 طرف به اندازهی 5 پیکسل هست. حالا Margins.Top را با 10 مقداردهی کنید و نتیجه را ببینید.
Panel دیگری روی فرم بگذارید و فقط ویژگی Align آن را با alTop مقداردهی کنید، میبینید که باز هم فاصله رعایت میشود.
Padding (که نام کلاس آن TPadding هست) در کنترلهایی که میتوانند در برگیرندهی کنترلهای دیگر باشند استفاده میشود مانند Form، Panel، PageControl. با اینکه Padding را در این سری از کامپوننتها تنظیم میکنیم اما در واقع Padding برای سایر کامپوننتها استفاده شود، به این صورت که اگر تمام ویژگیهای زیر مجموعه Padding دارای مقدار 10(پیکسل) باشند، هر کامپوننتی که روی آن میگذاریم مجبور به پیروی از فواصلی ست که Padding تعیین کرده، یعنی فاصله 10 پیکسلی با لبهها. البته این ویژگی نیز مانند ویژگی Margins باید به همراه Align استفاده شود.
یک Panel روی فرم قرار دهید و Width آن را با 360 و Height آن را با 145مقدار دهید، دو Button روی فرم Panel قرار دهید. ویژگی Align مربوط به Button1 را با alTop و Align مربوط به Button2 را با alBottom مقدار دهید، میبینید که یک Button به لبهی پائینی و Button دیگر به لبهی بالایی میچسبد. حالا، ویژگی Padding.Bottom و Padding.Top را با 10 مقدار دهید.
سئوال : 10 به چه معنی ست؟
جواب : میخواهم از این بعد هر کامپوننتی که روی این پنل قرار میگیرد و ویژگی Align آن مقدار خاصی دارد، از حداقل فاصلهای که پنل تعیین کرده که همان 10(پیکسل) هست، تبعیت کنند.
خوب، میبینید که بعد از مقداردهی، فاصلهی 10 پیکسلی با لبههای پائینی و بالایی ایجاد میشود و هنوز هر دو Button به لبههای چپ و راست چسبیدهاند. Padding.Left و Padding.Right را تنظیم کنید و نتیجه را ببینید.
m-khorsandi
سه شنبه 29 اسفند 1385, 00:04 صبح
تا دلفی 2005، VCL دارای گزینههایی برای قرار دادن کامپوننتها در موقعیتهای ثابت (ویژگیهای Top و Left)، یا در موقعیتهای که با حاشیهی فرم در ارتباط هستند (ویژگی Anchors) یا به صورت خودکار تنظیم میشوند(ویژگی Align)، بود. فقط بعضی از کامپوننتهایی که میتوان روی آنها کامپوننتهای دیگری را قرار داد(مانند RadioGroup یا ButtonGroup) میتوانستند موقعیت کامپوننتها را به صورت خودکار مدیریت کنند.
دلفی 2006، دو کامپوننتِ شبیه به Panel را در VCL خود معرفی میکند : FlowPanel و GridPanel
کامپوننت FlowPanel
کامپوننتهایی که روی آن قرار میگیرند به ترتیب اولویت قرارگیری نمایش داده میشوند، بدون در نظر گرفتن موقعیتشان اما سایز کامپوننتها اهمیت دارند و FlowPanel با توجه به سایز کامپوننتها آنها را منظم میکند. مورد جالبی که دیدم، اگر یک کامپوننت را روی FlowPanel قرار دهید، ویژگیهای Left و Top آن حذف! خواهند شد. حتی اگر مقدار ویژگیهای Left و Top را در زمان اجرا تغییر دهید، هیچ اثری ندارد. فاصله کامپوننتها با لبهها را توسط Padding و Margin میتوانید تنظیم کنید.
کامپوننت FlowPanel ویژگی دارد به نام FlowStyle که شامل 6 مقدار ترکیبشده از Left و Right و Top و Bottom هست، که میتوانید توسط آن ترتیب قرارگیری کامپوننتها روی آن را تعیین کنید. مقدار پیشفرض آن هم fsLeftRightTopBottom هست.
یک FlowPanel روی فرم قرار دهید و مثلاً 10 عدد CheckBox روی آن بگذارید، ویژگی Align مربوط به FlowPanel را با alTop مقدار دهید و برنامه را اجرا کنید، سایز فرم را تغییر دهید و نتیجه را ببینید.
کامپوننت GridPanel
یک Grid با سلولهایی را ارائه میکند که میتوان روی آنها کامپوننتهایی را قرارداد. هر کامپوننت در یک سلول، زمانیکه اولین کامپوننت را قرار دادید، کامپوننت دوم به صورت خودکار در سلول دوم قرار میگیرد. میتوان ردیف یا ستون نیز به آن اضافه کرد یا اینکه محتویات آن را ثابت نگه داشت با استفاده از ویژگی ExpandStyle. جزئیات ستونها و ردیفهای اضافه شده را نیز میتوان توسط ویژگیهای ColumnCollection و RowCollection مشاهده کرد.
در کنار ویژگیهای بزرگ، VCL در دلفی 2006 شامل پیشرفتهای کوچکی نیز هست:
همه کنترلها از رویداد OnMouseEnter و OnMouseLeave پشتیبانی میکنند، با اینکه این دو رویداد برای بعضی از کنترلها در ویندوز! نوشته نشده اما به صورت داخلی در VCL پیادهسازی شده ست.
از این پس میتوانید Toolbar و CoolBar را با پسزمینه Gradient داشته باشید.
مجموعهای از توابع Overload شدهی جدید که بعضاً انتظارات ما را برآورده میکنند، مانند MessageDlg که میتوان Button پیشفرض برای آن تعیین کرد.
میتوان پشتیبانی از Mouse Wheel را در بیشتر کامپوننتها با اضافه کردن یونیت IMouse به لیست Uses فعال کرد. رفتار Wheel روی کامپوننتهایی که از ویژگی Panning برخوردار هستند عمل میکند (Panning ویژگی جدیدی ست که به بعضی از کامپوننتهای دلفی اضافه شده).
کامپوننت TrayIcon
برای اولین بار، VCL در دلفی 2006 شامل کامپوننتی به نام TrayIcon برای اضافه کردن Icon در ناحیه Windows Tray هست. البته چندین کامپوننت رایگان خارجی (منظور خارج از VCLدلفی) برای این منظور وجود دارد، اما این کامپوننت، کامپوننت رسمی در مجموعه کامپوننتهای VCL هست.
استفاده از این کامپوننت بسیاز ساده ست. این کامپوننت را روی فرم برنامه خود قرار دهید(اگر بیشتر از یکی را روی فرم قرار دهید، فقط اولین کامپوننت نمایش داده میشود و مابقی نادیده گرفته میشوند)، ویژگی Visible این کامپوننت را True کنید، Iconیی را برای نمایش انتخاب کنید، Hintیی را برای نمایش به کاربر اضافه کنید(برای وقتی که کرسر ماوس روی Icon حرکت میکند)، یک Popup Menu برای زمانیکه کاربر روی TrayIcon کلیک میکند نیز اضافه کنید.
اگر میخواهید برنامهای که نوشتید در زمان اجرا هیچ فرمی را نمایش ندهد و فقط یک Icon در Windows Tray داشته باشد، میتوانید از کد زیر استفاده کنید :
Application.ShowMainForm := False;
کامپوننت TrayIcon ویژگیهایی مربوط به Balloon Hint با نامهای BalloonFlags، BalloonHint، BalloonTimeout، Balloon Title دارد. اما این ویژگیها فقط زمانی عمل میکنند که کاربر تنظیم خاصی را در Windows Explorer فعال کرده باشد. این تنظیم از طریق Registry در دسترس هست، در آدرس زیر مقدار کلید EnableBalloonTips میبایست برابر با 1 باشد.
HKEY_CURRENT_USER\Software\Microsoft\Windows\Curre ntVersion\Explorer\Advanced
• Inlining
این ویژگی از ویژگیهایی ست که از دلفی 2005 قابل استفاده ست، این ویژگی شرح واقعاً جالبی دارد. ابتدا، توضیحی در مورد Inlining : بطور کلی وقتی یک متد را فراخوانی میکنید، کامپایلر کدی را برای حرکت برنامه به آن نقطهی اجرایی تولید میکند. بنابراین چهارچوب Stack سازماندهی و کارهای دیگری نیز انجام میشود و ممکن ست که یک دو جین کد ماشین هم هزینهی اجرای آن باشد. هر چند که این متد میتواند خیلی ساده و کوچک باشد و با هربار فراخوانی، چند فیلد را مقداردهی کند یا مقدار آنها را برگرداند. اگر این متد، از متدهایی باشد که زیاد آن را فراخوانی میکنیم این حس بوجود میآید که ای کاش میشد کد واقعی را داشته باشم تا کامپایلر هربار آن را تولید نکند تا برنامه دائماً سرباری داشته باشد. برای رسیدن به این هدف، میتوان از Inline استفاده کرد تا سربار از بین برود.
با حذف این سربار، برنامه سریعتر اجرا میشود. اگر متد برای استفاده از inlining مناسب باشد، کامپایلر کد را مستقیماً به برنامه الحاق میکند به جای اینکه کد را هربار در زمان فراخوانی تولید کند.
Inlining موجب میشود تا کارایی بهبود یافته و برنامه سریعتر اجرا شود اما هزینهی این اجرای سریعتر، مصرف فضای بیشتر هست؛ inlining باعث میشود تا حجم فایل اجرایی بیشتر شود.
پس بسته به نیاز و با توجه افزایش حجم میتوان متدهایی که با آنها زیاد سر و کار داریم را به صورت inline تعریف کنیم.
از رهنمود inline باید در تعریف procedure و function استفاده کرد و نیازی به تکرار آن در پیادهسازی نیست.
procedure MyProc(x:Integer); inline;
begin
// ...
end;
function MyFunc(y:Char) : String; inline;
begin
// ..
end;
خیلی از توابع دلفی از رهنمود inline استفاده میکنند مانند تابع Max در یونیت Math :
Function Max(const A, B: Integer): Integer; overload; inline;
برای تست تاثیر واقعی تابع Max، من حلقهی زیر را نوشتم :
var
ttt: TTimeTest;
I, J: Integer;
begin
J := 0;
ttt := TTimeTest.Create;
try
for I := 0 to LoopCount do
J := Max (I, J);
memo1.Lines.Add ('Off ' + ttt.Elapsed + '[' + IntToStr (J) + ']');
finally
FreeAndNil (ttt);
end;
TTimeTest یک کلاس خیلی سادهست که با استفاده از تابع Now()، زمان سیستم را میگیرد. با این مثال میتوان فهمید که سرعت متد Inline دوبرابر متد معمولی ست.
نکات :
Inline را نمیتوان در متدهایی که به صورت virtual یا dynamic تعریف شدهاند، استفاده کرد.
Inline را نمیتوان در متدهای که برای کنترل پیغامها (MessageMethods) استفاده میشوند به کاربرد.
متدهایی که شامل کدهای اسمبلی هستند از Inline نمیتوانند استفاده کنند.
Constructorها و Destructor ها نمیتوانند از Inline استفاده کنند.
از Inline نمیتوان در بلوک اصلی برنامه استفاده کرد.
متدهایی که هدر آنها تعریف نمیشوند، نمیتوانند از Inline استفاده کنند.
متدهایی که پارامترهایی به صورت Open Array دارند نمیتوانند از Inline استفاده کنند.
از Inline میتوان در کد Packageها استفاده کرد.
اگر متد Inlineیی را تغییر دادید، تمام یونیتهایی که از این متد استفاده میکنند میبایست دوباره کامپایل شوند.
vBulletin® v4.2.5, Copyright ©2000-1403, Jelsoft Enterprises Ltd.