Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Learning to use the Sender Object

Status
Not open for further replies.

lespaul

Programmer
Feb 4, 2002
7,083
0
0
US
Hello all! I have discovered the usefulness of the Sender Object, but am having a little problem! I only want the following code to run if the user presses the OK button on my form:

procedure TfrmVenMaint.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if Sender = ????? then
if JMSData.dsVenMaint.State = dsEdit then
If MessageDlg('Do you want to save your changes?',mtConfirmation, [mbYes, mbNo], 0) = mrNo then
JMSData.dsVenMaint.DataSet.Close
else
JMSData.qryVenMaint.Post;
end;

So, if they have entered a value and it hasn't posted and they press the OK button then ask for confirmation.
Form = frmVenMaint
bitbtn = btnOK (btnOKClick calls frmVenMaint.Close;)

So can anyone tell me what I need in the ????? to make this work? Thanks! Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
Assuming your ok button is a TButton then the following code would detrmine whether the sender was in fact the OK button or not.

procedure TfrmVenMaint.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if Sender = TButton then
begin
if TButton(Sender).Name = 'OKButton' then
begin
if JMSData.dsVenMaint.State = dsEdit then
If MessageDlg('Do you want to save your changes?',mtConfirmation, [mbYes, mbNo], 0) = mrNo then
JMSData.dsVenMaint.DataSet.Close else
JMSData.qryVenMaint.Post;
end;
end;
end;

Just subsitute the button type and the button name for whatever they are on your form. Arte Et Labore
 
So I followed the instructions:

procedure TfrmVenMaint.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if Sender = TBitBtn then
begin
if TButton(Sender).Name = 'btnOK' then
begin
if JMSData.dsVenMaint.State = dsEdit then
If MessageDlg('Do you want to save your changes?',mtConfirmation, [mbYes, mbNo], 0) = mrNo then
JMSData.dsVenMaint.DataSet.Close
else
JMSData.qryVenMaint.Post;
end;
end;
end;

and I get an error message: INCOMPATIBLE TYPES on Sender = TBitBtn?

Also, FYI, when I step through the code into this procedure Sender = ()?

Thanks! Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
You haven't changed the second instance of TButton to TBitBtn.

if TButton(Sender).Name = 'btnOK' then

should be

if TBitBtn(Sender).Name = 'btnOK' then Arte Et Labore
 
I noticed that too and changed it, and still get the same error message. Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
What about ...

procedure TFormFindSpecific.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
CanClose := false;
TRY
if ModalResult = mrOK then
begin
if JMSData.dsVenMaint.State = dsEdit then
begin
If MessageDlg('Do you want to save your changes?',mtConfirmation, [mbYes, mbNo], 0) = mrNo then
JMSData.dsVenMaint.DataSet.Close
else
JMSData.qryVenMaint.Post;
end;
Canclose := true;
exit; //leave this procedure
end;
:
 
What is TFormFindSpecific? Don't I need a FINALLY with a TRY? To use ModalResult does my form need to be called with a ShowModal? Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
TFormFindSpecific - sorry, that's cutting and pasting for you.

Yep, it will have to be showmodal I think to use modalResult.

Going back to your IF statements, does it work better with

if Sender IS TbitBtn then ???

 
..oh and

if sender is TBitBtn then
if (Sender as Tbitbtn).name = 'btnOK' then

Sorry for the messy answers, this is what happens when I'm jumping about from code to tek-tips. Try my best to be helpful but not succeeding very well %-)

Hope this is more helpful.
 
Normally you get to CloseQuery by calling
the Form's Close method.
CloseQuery calls OnCloseQuery passing the
FORM REFERENCE as the Sender. The original
reference to the button is lost.

A simple method is to declare an integer
variable private to the form. Set a
unique value for the button pressed and
test that value in OnCloseQuery.
 
Ok, so I don't get an error message when I use

If Sender IS TBitBtn

but...

it still doesn't run the code! When stepping through and viewing the variables I get Sender = (). Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
David, Thanks for the info, but I'm not sure what you mean.

OK Button:

procedure TfrmVenMaint.btnOkClick(Sender: TObject);
begin
frmVenMaint.Close;
end;

FormClose:

procedure TfrmVenMaint.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
JMSData.qryVenMaint.Active := False;
end;

procedure TfrmVenMaint.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if Sender is TBitBtn then
begin
if TBitBtn(Sender).Name = 'btnOK' then
begin
if JMSData.dsVenMaint.State = dsEdit then
If MessageDlg('Do you want to save your changes?',mtConfirmation, [mbYes, mbNo], 0) = mrNo then
JMSData.dsVenMaint.DataSet.Close
else
JMSData.qryVenMaint.Post;
end;
end;
end;

So what you're saying is in the btnOkClick I need to set the variable. And in the OnQueryClose I check it? Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
I apologize if this isn't helpful, but it might be easier to do whatever you want the OK button to do in the OK button event, and then call close.
 
BB - The FormCloseQuery event is there for the developer intercept the form's closing and prevent it from closing if necessary (by setting CanClose to T or F). So if the user has entered data, but it hasn't posted, I want to give them the opportunity to post the data before closing the form or close the dataset without posting. I am also trying to learn how the SENDER object works (I'm a Delphi newbie). Thanks though! Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
If find that the Sender is most useful when you are
sharing an event between visual components.
If you want to want test who the Sender was then
you can use the component reference as follows:-


if (Sender = btnOkay) then
showmessage( 'sender is button okay' )
else if (Sender = btnCancel) then
showmessage( 'sender is button cancel' )
else if (Sender = btnHelp) then
showmessage( 'sender is button help' );


you only need to test for the class type
if you want to do something with the sender
as that type.

For example:

if (Sender is TBitBtn) then
begin
showmessage( (Sender as TBitBtn).name;
end;

If you are sharing an event and you know the
type of the sender then the above if stmt
is unnecessary.

 
We also do that. One place that it is very useful for us is in date fields. If the user closes a form with an invalid date, it can cause a lot of errors, so we point all of our date fields at a common event handler for OnSetText:

procedure TDM1.tPersonBirthDateSetText(Sender: TField; const Text: String);
begin
TRY
if Text = ' / / ' then
Sender.Clear
else
begin
StrToDate(Text);
Sender.AsString := Text;
end;
EXCEPT
ON E:Exception Do
begin
AFLD_DateField.Clear;
end;
END;
end;

 
Thanks for all the response (I was out yesterday afternoon). Steven, that's the article that started my inquiry! David, thanks for that explanation, maybe I'll get all of this one day! BB - thanks for the code, I'll give it a shot (My only other experience with the SetText and related procedures was very frustrating!).
Leslie
landrews@metrocourt.state.nm.us

SELECT * FROM USERS WHERE CLUE > 0
No Rows Returned
 
Sender is realistically only useful when you have multiple things that might call a single event handler. An example: A page that lets the user enter the directories various things are stored in. Every such editor on the page has it's OnChanged property set to a routine that verifies what's entered. To paraphrase the event handler:

if sender is tedit then
if invaliddirectory(tedit(sender).text) then
tedit(sender).color := clred
else if not directoryexists(tedit(sender).text) then
tedit(sender).color := clyellow
else
tedit(sender).color := clwhite
else
assert(false, 'VerifyDirectory: Caller is not a tEdit');
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top