PDA

View Full Version : افزودن EventHandel به شی ای که در کلاس تعریف شده



ayub_coder
پنج شنبه 08 تیر 1391, 20:03 عصر
دوستان من کلاسم ی شی از نو TQuery برگشت میدم
و تو فرمم یه TQuery می سازم و خروجی کلاسم رو به این انتصاب می دم.

حالا می خوام به این Query که تو فرم تعریف کردم و برابر Query که از کلاس برمیگرده هست می خوام به Event با نام AfterOpen یه EventHandler اضافه کنم.
یعنی موقعی این اجرا می شه تابعی که خودم تعریف کردم اجرا شه. ولی اینکار انجام نمیشه.
واسه کنترل هایی که رو فرم قرار می دم درست کار می کنه ولی واسه شی ای که تو کلاس ساختم درست عمل نمیکنه!
Help

Felony
پنج شنبه 08 تیر 1391, 20:10 عصر
کلاست چه جوری یک شئ رو برمیگردونه ؟! تابعی داره که این کار رو میکنه ؟
کدی که نوشتی رو به صورت کامل قرار بده .

ayub_coder
پنج شنبه 08 تیر 1391, 20:25 عصر
این کدیه که TUniQuery برمیگردونه . اون اضافاتشم از همون کلاس تو تاپیک قبلیمه.

function DBClass.GetQueryResult(Query: String): TUniQuery;
begin

Self._UniQuery := TUniQuery.Create(nil);
Self._UniQuery.SQL.Text := Query;
Self._UniQuery.Connection := Self._UniConnection;
Self._UniQuery.Open;


self._DataSource.DataSet := Self._UniQuery;

Result := Self._UniQuery;

end;

حالا تو فرم برنامه ام یه Query از نوع TUniQuery تعریف می کنم و اونو مساوی خروجی این تابعی که بالا نوشتم قرار میدم



Query := TUniQuery.Create(nil);

Query := MyConnection.GetQueryResult('SELECT * FROM table');




حالا اینو هم اضافه می کنم


Query.AfterOpen := QueryAfterOpen;



اینم کد QueryAfterOpen

procedure TForm1.QueryAfterOpen(DataSet: TDataSet);
begin
ShowMessage('After Open Called');
end;


ولی پیغام نمایش داده نمیشه. یعنی اون متد اصلا Call نمیشه.
ولی اگه Query رو تو همون فرم مقدار دهی کنم و کانکشن و SQL رو تنظیم کنم و Open کنم درست کار میکنه.
:افسرده:

ayub_coder
پنج شنبه 08 تیر 1391, 21:28 عصر
یه تشکر به خودم
درست شد
مشکل من اینجا بوده

Self._UniQuery.Open;

که من این رو درون کلاس گذاشته بودم.
این دستور باید بعد از


Query.AfterOpen := QueryAfterOpen;


می بود . چون دستورات مربوط ب تابع QueryAfterOpen; من بیرون از کلاس و درون فرم بود مجبور شدم دستور Open رو بیرون از کلاس و در فرم اجرا کنم. که با این کار مشکل حل شد تابع هندل کننده فراخوانی شد.:تشویق:

ayub_coder
پنج شنبه 08 تیر 1391, 21:33 عصر
ولی سوال اساسی
آیا میشه این تابع هندل کننده رو به درون کلاس پاس داد تا از درون کلاس اجرا بشه؟ یعنی من اون دستور Open رو هم دیگه تو فرم ننویسم و تو کلاس بنویسمش؟
الان سوالم اینه تابع کنترل کننده من یعنی QueryAfterOpen درون فرم نوشته شده. آیا میشه کاری کرد که این تابع به صورت پارامتری چیزی ارسال بشه به درون کلاس و از داخل کلاس EventHandler به این تابع QueryAfterOpen انتصاب داده بشه و این تابع رو اجرا کنه؟

Felony
پنج شنبه 08 تیر 1391, 21:41 عصر
اون کدهایی که نوشتی خیلی خطرناک هستن ، فکر مدریت حافظه این کدها رو کردی ؟!
برای برگردوندن یک شئ کار فنی این هست که شئ رو به عنوان پارامتر و به صورت ارجاع به مرجع به روال ارجاع بدید تا تابع مستقم با شئ کار کنه ، میشه همچین چیزی :

proceudre DBClass.GetQueryResult(Query: String; var aQuery: TUniQuery);
begin
aQuery.SQL.Text := Query;
aQuery.Connection := Self._UniConnection;
aQuery.Open;
end;


Query.AfterOpen := QueryAfterOpen;
MyConnection.GetQueryResult('SELECT * FROM table', Query);

Felony
پنج شنبه 08 تیر 1391, 21:54 عصر
ولی سوال اساسی
آیا میشه این تابع هندل کننده رو به درون کلاس پاس داد تا از درون کلاس اجرا بشه؟ یعنی من اون دستور Open رو هم دیگه تو فرم ننویسم و تو کلاس بنویسمش؟
الان سوالم اینه تابع کنترل کننده من یعنی QueryAfterOpen درون فرم نوشته شده. آیا میشه کاری کرد که این تابع به صورت پارامتری چیزی ارسال بشه به درون کلاس و از داخل کلاس EventHandler به این تابع QueryAfterOpen انتصاب داده بشه و این تابع رو اجرا کنه؟
بله میشه ، این یک نمونه کد که با ADOQuery براتون نوشتم :

TTest = class
private type
AfteOpenProc = procedure(DataSet: TDataSet) of object;
public
procedure GetTest(var aQuery: TADOQuery; AfterOpenProceure: AfteOpenProc);
end;

procedure TTest.GetTest(var aQuery: TADOQuery;
AfterOpenProceure: AfteOpenProc);
begin
with aQuery do
begin
Close;
ConnectionString :=
'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Data Source=.';
SQL.Text := 'SELECT ''Mojtaba''';
AfterOpen := AfterOpenProceure;
Open;
end;
end;

نمونه استفاده :

with TTest.Create do
try
GetTest(ADOQuery1, ADOQuery1AfterOpen);
finally
Free;
end;

ayub_coder
پنج شنبه 08 تیر 1391, 22:02 عصر
:تشویق: بسیار عالی.
خیلی از شما تشکر می کنم که به تازه کارایی مثل من میرسین و جواب سوالات پیش پا افتاده ی ما رو میدین.

SAASTN
پنج شنبه 08 تیر 1391, 22:08 عصر
جواب تکراری شد ولی بخاطر بخش دم حذفش نکردم...
-------------------------------------------------------------

ولی سوال اساسی
آیا میشه این تابع هندل کننده رو به درون کلاس پاس داد تا از درون کلاس اجرا بشه؟ یعنی من اون دستور Open رو هم دیگه تو فرم ننویسم و تو کلاس بنویسمش؟
الان سوالم اینه تابع کنترل کننده من یعنی QueryAfterOpen درون فرم نوشته شده. آیا میشه کاری کرد که این تابع به صورت پارامتری چیزی ارسال بشه به درون کلاس و از داخل کلاس EventHandler به این تابع QueryAfterOpen انتصاب داده بشه و این تابع رو اجرا کنه؟
بله میشه:
function DBClass.GetQueryResult(Query: String; AfterOpen: TDataSetNotifyEvent): TUniQuery;
begin

Self._UniQuery := TUniQuery.Create(nil);
Self._UniQuery.SQL.Text := Query;
Self._UniQuery.Connection := Self._UniConnection;
Self._UniQuery := AfterOpen;
Self._UniQuery.Open;


self._DataSource.DataSet := Self._UniQuery;

Result := Self._UniQuery;

end;

Query := MyConnection.GetQueryResult('SELECT * FROM table', QueryAfterOpen);


البته اگر منظور اینه که بعد از Open شدن Query یه متدی ران بشه با این تکنیک میشه کارای قشنگتری هم کرد. مثلا میشه یه سری پارامتر هم برای یه تابع ارسال کرد که بدنش در جای دیگه ای قرار داره:
type
TMyMethod = procedure (Param1: Integer; Param2: string) of object;

DBClass = class
private
function GetQueryResult(Query: String; AfterOpen: TMyMethod): TQuery;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure MyMethod(Param1: Integer; Param2: string);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

type

function DBClass.GetQueryResult(Query: String; AfterOpen: TMyMethod): TQuery;
begin

Self._UniQuery := TQuery.Create(nil);
Self._UniQuery.SQL.Text := Query;
Self._UniQuery.Connection := Self._UniConnection;
Self._UniQuery.Open;
AfterOpen(25, 'Ali')


self._DataSource.DataSet := Self._UniQuery;

Result := Self._UniQuery;

end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
Query := MyConnection.GetQueryResult('SELECT * FROM table', MyMethod);
end;

procedure TForm1.MyMethod(Param1: Integer; Param2: string);
begin
// Do something
end;