m-khorsandi
سه شنبه 15 خرداد 1386, 11:20 صبح
CreateParams
در حین اجرای فرآیند ایجاد یک شئ فرم، یا چنانکه سبک پیشفرض یک پنجره بر اساس نیاز شما تغییر میکند، این متد اجرا میشود. فرمهای شفاف، فرمهای بدون عنوان و... از این دست هستند.
زمانیکه دلفی یک کنترل از روی TWinControl(کلاس پایه برای همهی کنترلهای پنجرهای) میسازد، مانند یک EditBox یا Button یا Form، متد Create آن شئ، تابع APIیی با نام CreateWindowEx را برای ساختن یک پنجرهی حقیقی فراخوانی میکند. اگر چه، قبل از فراخوانی CreateWindowEx، متد CreateParams فراخوانده شده است. CreateParams یک متد virtual از کلاس TForm هست. به این معنی که میتوانید این متد را override کنید تا سبک پیشفرض پنجره را تغییر دهید. در این متد، یک پارامتر با ساختار دادهای از نوع TCreateParams با اطلاعاتی پر میشود که در فراخوانی CreateWindowEx استفاده خواهد شد. برای تغییر دادن تعدادی مختلفی چیز در مورد فرم(مانند نمایش، عنوان، پدر و...)، به ارثبری CreateParams راه مناسبی هست.
برای مثال، یک کامپوننتنویس، برای تنظیم سبک خاصی از پنجره، متد CreateParams را override میکند.
ساختار TCreateParams :
type
TCreateParams = record
Caption: PChar; {the window text or caption}
Style: DWORD; {style flag}
ExStyle: DWORD; {extended style flag}
X, Y: Integer; {Left and Top property}
Width, Height: Integer; {Width and Height property}
WndParent: HWND; {Parent window}
Param: Pointer {additional data}
WindowClass: TWndClass; {window calss information}
WinClassName: array[0..63] of Char; {class name}
end;
همانطور که در بالا توضیح داده شد، زمانیکه دلفی یک فرم را میسازد، رکورد CreateParams مقدار دهی میشود. بیشتر این مقادیر در این رکورد (ساختار)، متناظر با ویژگیهایی ست که در زمان طراحی تنظیم کردهاید. برای مثال فیلدهای Caption، Width و Height در CreateParams مقادیرشان را از Caption، Width و Heightیی که ما با استفاده از Object Inspector تنظیم کردهایم، میگیرند. سایر ویژگیهای فرم نیز در این فرآیند ایجاد استفاده میشود. برای مثال، اگر biHelp در BorderIcons فعال باشد، ExStyle دارای مقدار WS_EX_CONTEXTHELP خواهد بود، که شامل علامت سئوال در عنوان یک پنجره هست.
اما موارد خاصی نیز وجود دارد، مانند شفاف کردن فرم در فرآیند ایجاد.
Override کردن متد CreateParams :
موقعیکه میخواهید از پارامترهای اضافی در زمان ایجاد استفاده کنید، میبایست که متد CreateParams را override کنید(شباهت نام متد و نام نوع پارامتر تا حدودی گیج کننده است).
در بخش private کلاس مربوطه تعریف زیر را قرار دهید :
private
procedure CreateParams(var Params: TCreateParams); override;
در بخش implementation نیز خط زیر را قرار دهید :
procedure TForm.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
{code to alter the CreateParams values}
end;
اولین خط در متد بالا، inherited CreateParams(Params)، همیشه باید وجود داشته باشد. این خط برای پر کردن پارامتر، با مقادیر پیشفرض در کلاس TForm استفاده میشود. حالا میخواهم مواقعی که نیاز به override کردن متد CreateParams دارید را به شما نشان دهم :
TaskBar button for every Delphi form
button TaskBar برای هر فرم دلفی
به صورت پیشفرض، هر فرم دلفی فقط یک دکمه در Task Bar ویندوز برای کل برنامه دارد. برای مثال، زمانیکه فرم اصلی برنامهتان را minimize میکنید، دلفی فرم اصلی برنامه را minimize میکند و سپس، تمام پنجرههای برنامه minimize میشود. اگر میخواهید برای هر فرمی یک دکمهی جداگانه در Taskbar داشته باشید، باید پارامتر ExStyle را تغییر دهید. به این صورت که مقدار WS_EX_APPWINDOW را به ExStyle بدهید. به این شکل، وقتیکه فرم اصلی برنامه را minimize کنید، این فرم minimize نخواهد شد(برای هر فرمی که میخواهید taskbar button مجزا داشته باشد، باید متد CreateParams آن را override کنید) :
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
این روش، یک اثر جانبی دارد. زمانیکه برنامهی دیگری فعال هست، اگر بر روی دکمهی taskbar یکی از فرمهای دوم کلیک کنید، تمام فرمهای برنامه در جلو قرار میگیرند و نه فقط فرم مربوط به دکمه. دلیل این رفتار این هست که در واقع تمام فرمهای دوم به فرم اصلی برنامه به عنوان پدر اشاره میکنند. WndParent نام یکی از فیلدهای رکورد TCreateParams هست. این پارامتر مشخص کنندهی هندل پنجرهی پدر(Parent) هست. با تنظیم هندل پنجرهی پدر فرم دوم به Desktop، میتوانید پیوندی که باعث میشود وقتی یک فرم را فراخوانی میکنید، تمام برنامه فراخوانی شود را حذف کنید:
procedure TForm1.CreateParamsvar Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
ExStyle := ExStyle or WS_EX_APPWINDOW;
WndParent := GetDesktopwindow;
end;
end;
نکته:
شاید فکر کنید که تنظیم ExStyle := WS_EX_APPWINDOW کافی باشد، اما اشتباه میکنید. ExStyle از قبل شامل مقدار پیشفرضی هست که ما نباید آن مقدار را از بین ببریم، بنابراین میبایست مقدار WS_EX_APPWINDOW را به مقدار پیشفرض یا قبلی با عملگر OR اضافه کنیم.
Stay on TOP
هرچند با تنظیم FormStyle با fsStayOnTop میتوان یک فرم را در بالای تمام فرمهای پروژه در Desktop نگه داشت، بجزء سایر فرمهایی که FormStyle آنها نیز برابر با fsStayOnTop هست.
برای بالا نگه داشتن یک فرم (Stay on Top) از سایر فرمها در Desktop، باید هم پدر فرم را Desktop قرار دهید و هم از مقدار fsStayOnTop استفاده کنید. برای فرم اصلی برنامه این حالت وجود دارد، اما برای همهی فرمهای پروژه، چنین نیست. برای انجام این مورد باید متد CreateParams را با اضافه کردن مقدار WS_EX_TOPMOST به ExStyle ، override کنید :
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
ExStyle := ExStyle or WS_EX_TOPMOST;
WndParent := GetDesktopwindow;
end;
end;
راههای زیادی برای حذف Caption فرم وجود دارد. یکی از این راهها تغییر فیلد Style در متد CreateParams هست. یعنی اینکه SW_CAPTION باید از فیلد Style حذف شود. هر چند که تغییر این پارامتر تاثیری نخواهد داشت مگر اینکه ما BorderStyle را با bsNone مقداردهی کنیم :
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style AND NOT WS_CAPTION;
end;
Form with a raised edge - فرم با لبهی برجسته
وقتی که یک برنامهی MDI را توسعه میدهید، فرم اصلی برنامه (FormStyle := fsMDIForm) دارای لبههای برجسته هست که تداعی کنندهی یک ظرف برای سایر فرمها هست و در واقع چنین نیز هست. اگر میخواهید یک فرم معمولی دلفی (که از نوع MDIForm نیست) با لبهی برجسته داشته باشید. باید تغییری در ساختار CreateParams بدهید :
procedure TForm3.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle OR WS_EX_OVERLAPPEDWINDOW;
end;
Transparent form – فرم شفاف
به صورت عادی، برای ساختن یک فرم شفاف میبایست دو خط زیر را در رویداد OnCreate فرم قرار دهید :
procedure TForm1.FormCreate(Sender: TObject);
begin
Form4.Brush.Style := bsClear;
Form4.BorderStyle := bsNone;
end;
به تنهایی چنین روشی درست هست، اما اگر چیزی روی این فرم حرکت کند، فرضاً یک پنجره از برنامهی دیگری روی این فرم باز و بسته شود، تصویر این پنجره در فرم شفاف ما باقی خواهد ماند و فرم ما دیگر شفاف نیست. برای حل این مسئله، باید مطمئن باشید که متد Paint فرم شفاف به صورت مداوم فراخوانی خواهد شد. برای انجام آن، میبایست متد CreateParams را override کنید و مقدار WS_EX_TRANSPARENT را به فیلد ExStyle اضافه کنید :
procedure TForm4.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle OR WS_EX_TRANSPARENT;
end;
پس برای شفاف کردن کردن یک فرم هم باید از رویداد OnCreate فرم استفاده کرد و هم باید متد CreateParams را override کرد، در واقع با همکاری این دو متد میتوان یک فرم شفاف داشت.
سخن آخر
تمام مثالهای قبل، چگونگی ایجاد تغییر در نمایش و رفتار کلاس TForm در دلفی را به شما نشان دادند. در ابتدای این مقاله، عبارتی بود که " همهی کنترلهای مشتق شده از TWinControl که با تابع APIیی به نام CreateWindowEx ساخته شدهاند، دارای متد CreateParams هستند". معنی این جمله این هست که در کنار تغییراتی که میتوان توسط متد CreateParams بر روی فرمها داد، میتوان از همان تکنیکها برای افزایش قابلیتهای یک Edit Box یا یک Button یا... نیز استفاده کرد.
برای مثال، اگر میخواهید TButton با Caption چند خطی داشته باشید، باید یک کلاس جدید از TButton به عنوان یک کامپوننت دکمهی جدید بسازید و مقدار BS_MULTILINE را به فیلد Style آن در CreateParams بدهید. دقت کنید که کنترلهای مختلف(window, button, listbox, …) یک مجموعه از Style ها یا ExStyleهای خاص خود را دارند.
فایل PDF همین مقاله را میتوانید از لینک زیر دریافت کنید:
در حین اجرای فرآیند ایجاد یک شئ فرم، یا چنانکه سبک پیشفرض یک پنجره بر اساس نیاز شما تغییر میکند، این متد اجرا میشود. فرمهای شفاف، فرمهای بدون عنوان و... از این دست هستند.
زمانیکه دلفی یک کنترل از روی TWinControl(کلاس پایه برای همهی کنترلهای پنجرهای) میسازد، مانند یک EditBox یا Button یا Form، متد Create آن شئ، تابع APIیی با نام CreateWindowEx را برای ساختن یک پنجرهی حقیقی فراخوانی میکند. اگر چه، قبل از فراخوانی CreateWindowEx، متد CreateParams فراخوانده شده است. CreateParams یک متد virtual از کلاس TForm هست. به این معنی که میتوانید این متد را override کنید تا سبک پیشفرض پنجره را تغییر دهید. در این متد، یک پارامتر با ساختار دادهای از نوع TCreateParams با اطلاعاتی پر میشود که در فراخوانی CreateWindowEx استفاده خواهد شد. برای تغییر دادن تعدادی مختلفی چیز در مورد فرم(مانند نمایش، عنوان، پدر و...)، به ارثبری CreateParams راه مناسبی هست.
برای مثال، یک کامپوننتنویس، برای تنظیم سبک خاصی از پنجره، متد CreateParams را override میکند.
ساختار TCreateParams :
type
TCreateParams = record
Caption: PChar; {the window text or caption}
Style: DWORD; {style flag}
ExStyle: DWORD; {extended style flag}
X, Y: Integer; {Left and Top property}
Width, Height: Integer; {Width and Height property}
WndParent: HWND; {Parent window}
Param: Pointer {additional data}
WindowClass: TWndClass; {window calss information}
WinClassName: array[0..63] of Char; {class name}
end;
همانطور که در بالا توضیح داده شد، زمانیکه دلفی یک فرم را میسازد، رکورد CreateParams مقدار دهی میشود. بیشتر این مقادیر در این رکورد (ساختار)، متناظر با ویژگیهایی ست که در زمان طراحی تنظیم کردهاید. برای مثال فیلدهای Caption، Width و Height در CreateParams مقادیرشان را از Caption، Width و Heightیی که ما با استفاده از Object Inspector تنظیم کردهایم، میگیرند. سایر ویژگیهای فرم نیز در این فرآیند ایجاد استفاده میشود. برای مثال، اگر biHelp در BorderIcons فعال باشد، ExStyle دارای مقدار WS_EX_CONTEXTHELP خواهد بود، که شامل علامت سئوال در عنوان یک پنجره هست.
اما موارد خاصی نیز وجود دارد، مانند شفاف کردن فرم در فرآیند ایجاد.
Override کردن متد CreateParams :
موقعیکه میخواهید از پارامترهای اضافی در زمان ایجاد استفاده کنید، میبایست که متد CreateParams را override کنید(شباهت نام متد و نام نوع پارامتر تا حدودی گیج کننده است).
در بخش private کلاس مربوطه تعریف زیر را قرار دهید :
private
procedure CreateParams(var Params: TCreateParams); override;
در بخش implementation نیز خط زیر را قرار دهید :
procedure TForm.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
{code to alter the CreateParams values}
end;
اولین خط در متد بالا، inherited CreateParams(Params)، همیشه باید وجود داشته باشد. این خط برای پر کردن پارامتر، با مقادیر پیشفرض در کلاس TForm استفاده میشود. حالا میخواهم مواقعی که نیاز به override کردن متد CreateParams دارید را به شما نشان دهم :
TaskBar button for every Delphi form
button TaskBar برای هر فرم دلفی
به صورت پیشفرض، هر فرم دلفی فقط یک دکمه در Task Bar ویندوز برای کل برنامه دارد. برای مثال، زمانیکه فرم اصلی برنامهتان را minimize میکنید، دلفی فرم اصلی برنامه را minimize میکند و سپس، تمام پنجرههای برنامه minimize میشود. اگر میخواهید برای هر فرمی یک دکمهی جداگانه در Taskbar داشته باشید، باید پارامتر ExStyle را تغییر دهید. به این صورت که مقدار WS_EX_APPWINDOW را به ExStyle بدهید. به این شکل، وقتیکه فرم اصلی برنامه را minimize کنید، این فرم minimize نخواهد شد(برای هر فرمی که میخواهید taskbar button مجزا داشته باشد، باید متد CreateParams آن را override کنید) :
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
این روش، یک اثر جانبی دارد. زمانیکه برنامهی دیگری فعال هست، اگر بر روی دکمهی taskbar یکی از فرمهای دوم کلیک کنید، تمام فرمهای برنامه در جلو قرار میگیرند و نه فقط فرم مربوط به دکمه. دلیل این رفتار این هست که در واقع تمام فرمهای دوم به فرم اصلی برنامه به عنوان پدر اشاره میکنند. WndParent نام یکی از فیلدهای رکورد TCreateParams هست. این پارامتر مشخص کنندهی هندل پنجرهی پدر(Parent) هست. با تنظیم هندل پنجرهی پدر فرم دوم به Desktop، میتوانید پیوندی که باعث میشود وقتی یک فرم را فراخوانی میکنید، تمام برنامه فراخوانی شود را حذف کنید:
procedure TForm1.CreateParamsvar Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
ExStyle := ExStyle or WS_EX_APPWINDOW;
WndParent := GetDesktopwindow;
end;
end;
نکته:
شاید فکر کنید که تنظیم ExStyle := WS_EX_APPWINDOW کافی باشد، اما اشتباه میکنید. ExStyle از قبل شامل مقدار پیشفرضی هست که ما نباید آن مقدار را از بین ببریم، بنابراین میبایست مقدار WS_EX_APPWINDOW را به مقدار پیشفرض یا قبلی با عملگر OR اضافه کنیم.
Stay on TOP
هرچند با تنظیم FormStyle با fsStayOnTop میتوان یک فرم را در بالای تمام فرمهای پروژه در Desktop نگه داشت، بجزء سایر فرمهایی که FormStyle آنها نیز برابر با fsStayOnTop هست.
برای بالا نگه داشتن یک فرم (Stay on Top) از سایر فرمها در Desktop، باید هم پدر فرم را Desktop قرار دهید و هم از مقدار fsStayOnTop استفاده کنید. برای فرم اصلی برنامه این حالت وجود دارد، اما برای همهی فرمهای پروژه، چنین نیست. برای انجام این مورد باید متد CreateParams را با اضافه کردن مقدار WS_EX_TOPMOST به ExStyle ، override کنید :
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
ExStyle := ExStyle or WS_EX_TOPMOST;
WndParent := GetDesktopwindow;
end;
end;
راههای زیادی برای حذف Caption فرم وجود دارد. یکی از این راهها تغییر فیلد Style در متد CreateParams هست. یعنی اینکه SW_CAPTION باید از فیلد Style حذف شود. هر چند که تغییر این پارامتر تاثیری نخواهد داشت مگر اینکه ما BorderStyle را با bsNone مقداردهی کنیم :
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style AND NOT WS_CAPTION;
end;
Form with a raised edge - فرم با لبهی برجسته
وقتی که یک برنامهی MDI را توسعه میدهید، فرم اصلی برنامه (FormStyle := fsMDIForm) دارای لبههای برجسته هست که تداعی کنندهی یک ظرف برای سایر فرمها هست و در واقع چنین نیز هست. اگر میخواهید یک فرم معمولی دلفی (که از نوع MDIForm نیست) با لبهی برجسته داشته باشید. باید تغییری در ساختار CreateParams بدهید :
procedure TForm3.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle OR WS_EX_OVERLAPPEDWINDOW;
end;
Transparent form – فرم شفاف
به صورت عادی، برای ساختن یک فرم شفاف میبایست دو خط زیر را در رویداد OnCreate فرم قرار دهید :
procedure TForm1.FormCreate(Sender: TObject);
begin
Form4.Brush.Style := bsClear;
Form4.BorderStyle := bsNone;
end;
به تنهایی چنین روشی درست هست، اما اگر چیزی روی این فرم حرکت کند، فرضاً یک پنجره از برنامهی دیگری روی این فرم باز و بسته شود، تصویر این پنجره در فرم شفاف ما باقی خواهد ماند و فرم ما دیگر شفاف نیست. برای حل این مسئله، باید مطمئن باشید که متد Paint فرم شفاف به صورت مداوم فراخوانی خواهد شد. برای انجام آن، میبایست متد CreateParams را override کنید و مقدار WS_EX_TRANSPARENT را به فیلد ExStyle اضافه کنید :
procedure TForm4.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle OR WS_EX_TRANSPARENT;
end;
پس برای شفاف کردن کردن یک فرم هم باید از رویداد OnCreate فرم استفاده کرد و هم باید متد CreateParams را override کرد، در واقع با همکاری این دو متد میتوان یک فرم شفاف داشت.
سخن آخر
تمام مثالهای قبل، چگونگی ایجاد تغییر در نمایش و رفتار کلاس TForm در دلفی را به شما نشان دادند. در ابتدای این مقاله، عبارتی بود که " همهی کنترلهای مشتق شده از TWinControl که با تابع APIیی به نام CreateWindowEx ساخته شدهاند، دارای متد CreateParams هستند". معنی این جمله این هست که در کنار تغییراتی که میتوان توسط متد CreateParams بر روی فرمها داد، میتوان از همان تکنیکها برای افزایش قابلیتهای یک Edit Box یا یک Button یا... نیز استفاده کرد.
برای مثال، اگر میخواهید TButton با Caption چند خطی داشته باشید، باید یک کلاس جدید از TButton به عنوان یک کامپوننت دکمهی جدید بسازید و مقدار BS_MULTILINE را به فیلد Style آن در CreateParams بدهید. دقت کنید که کنترلهای مختلف(window, button, listbox, …) یک مجموعه از Style ها یا ExStyleهای خاص خود را دارند.
فایل PDF همین مقاله را میتوانید از لینک زیر دریافت کنید: