PDA

View Full Version : سوال: آیا راهی برای فراخوانی یک پروسیجر مشابه موجود در چند فرم با داشتن نام فرم هست؟



mbshareat
پنج شنبه 22 اردیبهشت 1390, 00:09 صبح
با سلام
من یک فرم دارم که برای Search تهیه کردم.توی این فرم یه متغیر مثلا به نام CallerForm دارم.
می خوام وقتی که این فرم OK میشه پروسیجر SearchText در فرمی که این فرم جستجو رو احضار کرده اجرا بشه.فرمی که پنجره جستجو رو بالا میاره ممکنه هر نامی داشته باشه.(فرض کنین برنامه جدیدی نیاز شد نمیخوام کد فرم جستجو رو دوباره دستکاری کنم)
سوالم اینه که راهی هست که بدون بررسی تک تک احتمالات متغیر CallerForm پروسیجر SearchText مربوط به فرم احضار کننده پنجره جستجو اجرا بشه.
خیلی بخوام سادش کنم باید بگم اگه چیزی مثل CallerForm.SearchText میشد استفاده کرد سوال نمی کردم!
لطفا اگه راهی سراغ دارین راهنماییم کنین.

Mask
پنج شنبه 22 اردیبهشت 1390, 12:39 عصر
با سلام
کد و پروسیجر مورد نظرتون رو تبدیل به یونید با پسوند pas کنید. سپس کامپایل و فایل dcu تشکیل شده رو به قسمت Lib کپی کنید.
حالا اسم یونیت رو در هر کدام از فرمهاتون uses کنید .میتونید با ارسال پارامتر برگشتی مورد نظرتون رو دریافت کنید.
موفق باشید.

mbshareat
پنج شنبه 22 اردیبهشت 1390, 14:44 عصر
با سلام و درود
ببخشید پروسیجر SearchText بر روی شیئ ListBox عمل میکنه.روش شما چه کمکی میتونه بکنه.
در ضمن روش شما اگر حرفه ای تر باشه ولی دلچسبتر نیست.چرا فقط برای یه پروسیجر بخوام یونست درست کنم بعدش Use کنم و آخرش هم باز مجبور بشم تک تک احتمالات CallerForm رو بررسی کنم.احتمال میدم شما منظور من رو نفهمیده باشید.
در هر صورت از اینکه تاپیکم رو خوندین ممنونم.اگه راه ساده تری سراغ دارین بفرمایین.

Felony
پنج شنبه 22 اردیبهشت 1390, 19:43 عصر
بهتره اون تابع رو در همون فرم جست و جو یا یک Thread جداگانه قرار بدید ، بعد فرم جست و جو رو به صورت Modal نمایش بدید ، وقتی فرم بسته شد و ModalResult با Ok یا گزینه مورد نظرتون مقدار دهی شده بود Thread جست و جو رو فراخوانی کنید یا اینکه تابع جست و جو رو از فرم جست و جو فراخوانی کنید .

البته اگر نخواستید فرم رو به صورت Modal نمایش بدید راه دیگری هم هست ولی در کل روند کاری همون هست که گفتم .

majidbestgame
پنج شنبه 22 اردیبهشت 1390, 20:31 عصر
ببخشید پروسیجر SearchText بر روی شیئ ListBox عمل میکنه
اگه کار این پروسیجر شما فقط جستجو در لیست باکسه و میخواید وقتی از یک فرم این فرم جستجو را احضار کند(اگه فرم احضار کننده دارای لیست باکسی است که میخواهید در آن جستجو کنید با استفاده از پروسیجرتون) میتونید یک آرگومان از نوع لیست باکس به پروسیجرتون اضافه کنید. مثال:

Procedure SearchText(MyListBox:TListBox);
اگرم یک خورده سوالتون واضح تر باشه شاید بتونیم درست تر راهنمایی کنیم

SAASTN
پنج شنبه 22 اردیبهشت 1390, 21:55 عصر
ببینید من اینطور متوجه شدم که یک فرمی میاد فرم جستجوی ما رو ShowModal میکنه، حالا ما می خوایم درست بعد از اتمام کار فرم جستجو یک تابعی در فرم فراخواننده صدا زده بشه. درسته؟ حالا اگر من درست متوجه شده باشم دیگه اهمیتی نداره که کی قراره اون تابع رو صدا بزنه (یا در واقع کجا قراره اون تابع صدا زده بشه). خوب توی این شرایط به نظر من سه تا کار مختلف میشه کرد. اولی اینکه اصلا به خودمون فشار نیاریم و خیلی ساده در محل ShowModal کردن فرم جستجو بنویسیم:
if SerchForm.ShowModal = mrOK then
Self.SearchText;

راه دوم، اگه به هر دلیلی برامون اهمیت داره که که فرم جستجو اون تابع SearchText رو فراخونی کنه، (که البته من دلیلی براش پیدا نمی کنم، بهتره یکم بیشتر در این مورد توضیح بدید)، کاری که می تونیم بکنیم اینه که تمام فرم هایی که قراره از این فرم استفاده بکنند رو بجای TForm از یک کلاس واسط خودمون مشتق کنیم که تابع SearchText در اون بصورت abstract تعریف شده. بصورت زیر:
TSearchCallerForm = class(TForm)
public
procedure SearchText; virtual; abstract;
end;

و تمام، و این کد رو توی یک یونیت خشک و خالی قرار می دیم و تنها همین یونیت رو در یونیتی که فرم جستجو تعریف شده use می کنیم. حالا اون پارامتر یا مشخصه CallerForm رو بجای اینکه از نوع TForm تعریف کنید از نوع TSearchCallerForm تعریف می کنید و دیگه از این به بعد CallerForm.SearchText معنی داره. فقط توجه داشته باشید که متد SearchText رو حتما برای تک تک فرمهایی که از TSearchCallerForm مشتق میشن پیاده سازی کنید که با خطا روبرو نشید:
TForm1 = class(TSearchCallerForm)
public
procedure SearchText; override;
end;

implementation

{ TForm1 }

procedure TForm1.SearchText;
begin
// Do Something ...
end;

راه سومی که به ذهنم میرسه اینه که برای فرم جستجوتون یه Event جدید تعریف کنید و قبل از ShowModal کردنش اون رویداد رو مقدار دهی کنید، و در هنگام بسته شدنش اون رویداد رو فراخونی کنید:
TSearchFormOnSearchText = procedure (Sender: TObject;
SomeParameter: Integer) of object;

TSearchForm = class(TForm)
private
FOnSearchTex: TSearchFormOnSearchText;
{ Private declarations }
public
property OnSearchTex: TSearchFormOnSearchText read FOnSearchTex write FOnSearchTex;
function ShowModal: Integer; override;
end;

var
SearchForm: TSearchForm;

implementation

{$R *.dfm}

{ TSearchForm }

function TSearchForm.ShowModal: Integer;
begin
if (inherited = mrOk) and Assigned(FOnSearchTex) then
FOnSearchTex(Self, 1);
end;

و برای فراخوانی:
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure SearchText(Sender: TObject; SomeParameter: Integer);
public
{ Public declarations }
end;


var
Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
SearchForm.OnSearchTex := SearchText;
SearchForm.ShowModal;
end;

procedure TForm1.SearchText(Sender: TObject; SomeParameter: Integer);
begin
// Do Something ...
end;

mbshareat
جمعه 23 اردیبهشت 1390, 13:06 عصر
سلام و خدا قوت
از تمامی سروران گرانقدر کمال تشکر رو دارم.
راهی که جناب majidbestgame ارائه دادند ساده و جالب بود.
از استاد تاجیک هم ممنونم ولی ظاهرا مشکل بنده رو متوجه نشده بودند(البته ببخشید اینقدر راحت اظهار نظر می کنم)
جناب SAASTN دوست عزیز راه اولتون به نظرم به دردم بخوره.
من به زور می تونم از مفاهیم کلاس و ارث بری و Abstract سر در بیارم.
من نه دوره آموزشی رفتم نه کتاب قطور خوندم.تنها مقاله جناب آقای کشاورز رو در مورد Interface نصفه نیمه خوندم.
راستش تا حالا نیازی هم به دونستن این چیزها نداشتم(مگر زمانی که به سرم زد دکمه طراحی کنم!!)
فکر می کنم تست کردن دو سه حالت فرم خیلی راحت تر و قابل فهم تر از ایجاد کلاس و Use کردنشه.ولی بدم نمی اومد یه برنامه آماده هم میذاشتین که بفهمم چی میگین.(البته توقع اضافه هم ندارم)

M_Maskout
جمعه 23 اردیبهشت 1390, 17:12 عصر
سلام
برای اینکه دو تا یونیت (فرم) به محتویات همدیگه دسترسی داشته باشن، باید نام دومی رو تو بخش Uses از قسمت interface اولی، و نام اولی رو تو بخش Uses از قسمت implementation وارد کنید. حالا تو یونیت دوم (در اینجا فرم Search) به محتویات یونیت فراخوان، دسترسی دارین.
یه روش این هست که یه رویه (=procedure) یا تابع (حسب نیاز) با نام خاصی (مثلاً SearchText) بصورت سراسری تو یونیت فراخوان تعریف کنید، بعد تو بدنه‌ی اون رویه یا تابع، عملیات لازم رو انجام بدین.



Unit MainForm;

interface

uses
Search;

type
TfrmMainForm = class(TForm)
.
.
.
end;

procedure SearchText;

var
frmMainForm: TfrmMainForm;

implementation

{$R *.dfm}

procedure SearchText;
begin
with frmMainForm do
begin
.
.
.
end;
end;


این روش، همون روش ماژولار قدیمیه و احتمالاً باب پسند دوستان حرفه‌ای نیست.

mbshareat
جمعه 23 اردیبهشت 1390, 23:58 عصر
با سلام و عرض ادب
جناب M_Maskout گفتم چیز درست و حسابی بلد نیستم ولی می دونم Use کردن به چه درد می خوره!تو جواب شما چیز تازه ای ندیدم.
راه حلهای قبلی خوب بود.

M_Maskout
شنبه 24 اردیبهشت 1390, 00:30 صبح
...گفتم چیز درست و حسابی بلد نیستم ولی می دونم Use کردن به چه درد می خوره!
سلام
دوست عزیز، پاسخ دادن به تاپیک‌های ایجاد شده و پست‌های ارسال شده توی اون‌ها، به هیچ عنوان به این معنی نیست که سوال کننده و یا پست دهنده، چیزی بلد نیست و بنده هم با این فرض پست #8 رو ارسال نکردم.
من اغلب تو پست‌هایی که ارسال می‌کنم، سعی می‌کنم خود اون پست به قدر کافی مفهوم داشته باشه تا در صورتیکه بعدها کسی فقط اون پست رو خوند، متوجه محتوای پست بشه و مجبور نباشه کل یه تاپیک رو زیر و رو کنه.
بنده فکر می‌کنم روشی که ارائه دادم، با سایر روش‌ها فرق داره و البته در انتهای پست به قدیمی بودن این روش تأکید نمودم.
موفق باشید.

SAASTN
شنبه 24 اردیبهشت 1390, 00:54 صبح
راه اولتون به نظرم به دردم بخوره.
منم فکر می کنم برای همچین منظوری در همین حد کفایت می کنه.

من به زور می تونم از مفاهیم کلاس و ارث بری و Abstract سر در بیارم.
من نه دوره آموزشی رفتم نه کتاب قطور خوندم.تنها مقاله جناب آقای کشاورز رو در مورد Interface نصفه نیمه خوندم.
اینا مسائل شاقی نیستند، با یکمی مطالعه و تمرین می تونید بهشون اشراف پیدا کنید. راه دوم در مورد ارث بری و راه سوم در مورد تعریف رویداد برای کلاس هاست. اگر بخشیش براتون مبهم هست می تونید در موردش تحقیق کنید یا تو همین سایت بپرسید.

راستش تا حالا نیازی هم به دونستن این چیزها نداشتم(مگر زمانی که به سرم زد دکمه طراحی کنم!!)
هیچ نگران نباشید، اینجا همه چیز ممکنه، من با برنامه نویسهایی برخورد کردم که بیشتر از 10 سال سابقه دارند، اما تو تفاوت شیء و کلاس مشکل دارن. دونستن اینجور چیزا کاملا به نگاه خودتون نسبت به کارتون بستگی داره. اگر می خواید اصولی کار کنید ناگزیر باید برید سراغ درک این جور مفاهیم. اینجور چیزا هم مفهومند، توی تمام زبان ها با یکم تفاوتای جزیی وجود دارن. تفاوت یه کد قابل نگهداری و خوانا با یه کد شلوغ و پیچیده که هرچندوقت یه بار نیاز به جراحی و بازنویسی داره در استفاده صحیح از ابزار ها و رعایت اصول برنامه نویسی هست. زعمای قوم هم با دردهایی در دل و آرزوهایی در سر این اصول رو وضع کردند.

mbshareat
شنبه 24 اردیبهشت 1390, 15:35 عصر
با سلام
جناب M_Maskout من تو جواب شما دقیق نشده بودم حالا خوندم.اما راستش درست متوجه نشدم معنی این کد چیه؟
procedure SearchText;

var
frmMainForm: TfrmMainForm;

implementation

{$R *.dfm}

M_Maskout
یک شنبه 25 اردیبهشت 1390, 08:43 صبح
سلام
تو روش برنامه نویسی ماژولار، برای اینکه یونیت‌های دیگه بتونن به روتین‌های یه یونیت دسترسی داشته باشن، لازمه نام اون روتین‌ها تو بخش interface یونیت تعریف بشه. و بعداً تو قسمت implementationکد بدنه‌ی روتین وارد بشه.
تو شبه کدی که بنده تو پست #8 نوشتم، عبارت ;procedure SearchText، قبل از بخش implementation، رویه SearchText رو به عنوان یه procedure سراسری تعریف می‌کنه و باعث می‌شه هر جا (تو یونیت‌های دیگه) که نام یونیت در بر دارنده‌ی SearchText تو قسمت uses، آورده بشه، اونجا به پروسجر SearchText دسترسی ایجاد بشه.
اما روش پیشنهادی من این بود که شما یه فرم Search ایجاد کنید و تو قسمت تأیید نهایی اون پروسجری رو صدا کنید که نام اون رو از قبل تو فرم فراخوانِ فرم Search به عنوان procedure سراسری تعریف کردین. در اینجا شما مجبورین نام یونیت فراخوانِ فرم Search و نام روتین SearchText رو ثابت نگه دارین و با اونا رفتار کلمه‌های رزرو شده رو بکنید. این همون چیزیه که باعث قدیمی شدن روش می‌شه و علی القاعده امروزه دیگه روش اصولی‌ای نیست ولی جواب می‌ده.
69928