execute an event but the coding from my own class [duplicate] - delphi

I have one button on my form. Following is the click event of that button
procedure Form1.btnOKClick(Sender: TObject);
begin
//Do something
end;
This event will be called only when I click the button, right?
How can I call this event automatically without any user intervention?

The best way to invoke the OnClick event handler attached to a control is to call the Click method on the control. Like this:
btnOK.Click;
Calling the event handler directly forces you to supply the Sender parameter. Calling the Click method gets the control to do all the work. The implementation of the windows message handler for a button click calls the Click method.
But I second the opinion expressed in whosrdaddy's answer. You should pull out the logic behind the button into a separate method.

Do not put your businesslogic into event handlers. This will make your code unreadable when the application grows larger.
Normally you would do this:
procedure TForm1.DoSomething;
begin
// do something
end;
procedure TForm1.btnOKClick(Sender: TObject);
begin
DoSomething;
end;
then all you need to do is call DoSomething from other parts in your code

You can call this event in code like any other method.
...
btnOkClick(Self.btnOk); // Sender in this case is the btnOk
...
The Sender can be whatever object you like or nil.

Related

Get return value of an item clicked

I am trying to figure out how to get a TObject (TLabel or TCard) as a returned value after a player has clicked on the object.
Goes like this
Player plays a spell //
Spell says hey i need a target //
spell calls get a target //
player selects a target //
target is returned to spell//
spell does xx with target//
Here is an example of code.
procedure TSpell.Spell;
var
secondTarget : Tobject;
begin
if true then
begin
secondTarget := GetSecondTarget(); //how??
if SecondTarget.classname = TCard then
begin
showmessage('you selected a TCard');
end
if SecondTarget.classname = TLabel then
begin
showmessage('you selected a label');
end
end
GetSecondTarget() : TObject;
begin
showmessage('Select a Target');
//wait for user to click something
//return the TObject to TSpell.spell
end;
I have no idea on how to do the GetSecondTarget... how to wait for user to click on something then return it to TSpell.Spell Any help on how to do this?
Windows GUI programs are event driven. You should not contemplate calling a function on the main thread that will block until an event happens.
What's more, your call to ShowMessage results in a modal dialog. And modal dialogs disable their owning windows which means that the user is not able to click on the object that you are hoping they will click on. If you wish to show a form with an instruction, then at the very least it needs to be a modeless dialog.
The bottom line here is that you need to adapt your ideas to the concepts of event-driven programming. When the user clicks on an object, an OnClick event will be raised. Attach a handler to that event and respond to it when that handler executes. If you need to behave differently to the OnClick event at different times, you'll need to maintain some state in your program to determine that behaviour switching.

Implementing Button Click in Firemonkey

I am missing TButton.Click Method in FireMonkey TButton.
Is there any way to fire click event in the code in fire monkey? If there is no such event, just use the click method to fire the action assigned to the button?
Well, you can simply write:
Button1.OnClick(Button1);
If there is an action attached to the button you can invoke it with
Button1.Action.Execute;
But that is not really to be recommended. The right way to do this is to create a method to do the work. Then call that method from either your OnClick event handler, or the other location in your code that wants to invoke this action. Like this:
procedure TForm1.DoSomething;
begin
// do whatever it is
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DoSomething;
end;
Then anywhere in your code you can just call DoSomething. It's best to leave GUI event handlers just for handling GUI events.
You can use this method :
first declare this new type to access TButton Click procedure :
type
TButtonHack = type TButton;
Then caste your button to TButtonHack class and call Click procedure :
TButtonHack(Button1).Click;

How to intercept user defined message twice?

I'm using a component that internally has a KeyDown handler, which sends a user defined PostMessage(WM_GROUPUNGROUP), and also has a custom message handler to handle WM_GROUPUNGROUP.
I want my app to do something after this message handler has executed, without modifying the component code.
(How) Can this be done?
One way to achieve this is via the WindowProc property.
Simply supply your own window procedure by assigning to WindowProc on the instance you want to hook. You'll need to take a copy to the previous value of WindowProc so that you can make sure that the original handling is carried out.
Roughly it goes like this:
type
TMyClass = class
....
FOldWindowProc: TWndMethod;
procedure NewWindowProc(var Message: TMessage);
....
end;
To redirect the window procedure you do this:
FOldWindowProc := SomeControl.WindowProc;
SomeControl.WindowProc := NewWindowProc;
Then implement the new window procedure like this:
procedure TMyClass.NewWindowProc(var Message: TMessage);
begin
FOldWindowProc(Message);
if Message.Msg = WM_GROUPUNGROUP then
....
end;
When you are done with the control, put the old window procedure back in place:
SomeControl.WindowProc := FOldWindowProc;
Another way to do it is to take advantage of the fact that the message is queued. You can add an Application.OnMessage handler, most likely by using a TApplicationEvents object. This will get a look at all queued messages. However, OnMessage fires before the message is dispatched to the control which sounds like it may be the wrong way round for you.

How to call events in delphi without user intervention?

I have one button on my form. Following is the click event of that button
procedure Form1.btnOKClick(Sender: TObject);
begin
//Do something
end;
This event will be called only when I click the button, right?
How can I call this event automatically without any user intervention?
The best way to invoke the OnClick event handler attached to a control is to call the Click method on the control. Like this:
btnOK.Click;
Calling the event handler directly forces you to supply the Sender parameter. Calling the Click method gets the control to do all the work. The implementation of the windows message handler for a button click calls the Click method.
But I second the opinion expressed in whosrdaddy's answer. You should pull out the logic behind the button into a separate method.
Do not put your businesslogic into event handlers. This will make your code unreadable when the application grows larger.
Normally you would do this:
procedure TForm1.DoSomething;
begin
// do something
end;
procedure TForm1.btnOKClick(Sender: TObject);
begin
DoSomething;
end;
then all you need to do is call DoSomething from other parts in your code
You can call this event in code like any other method.
...
btnOkClick(Self.btnOk); // Sender in this case is the btnOk
...
The Sender can be whatever object you like or nil.

How to identify the Tobject type for sender in Delphi?

i am creating code for a dialog with a radio group as part of a preferences form. Part of our code is that when the preferences form is opened, the radio group is clicked, which configures a bunch of stuff (ie if the radio button is 'off' then a bunch of config stuff is hidden).
What I want is to know when the user actually clicks the radio group as opposed to it being fired when the preferences dialog opens.
So the code looks like this:
(open preferences)...
rgMyGroupClick(nil)
procedure TdlgPreferences.rgMyGroupClick(Sender:TObject)
if sender <> nil then
begin
//do something useful
end;
But this code is also executed when the preferences dialog is opened. What should I put in there to only execute when the user actually clicks the mouse on the button?
Thanks
Testing your sender
You can test the sender in two ways:
procedure TdlgPreferences.rgMyGroupClick(Sender:TObject)
begin
if sender = RadioButton1 then //do action
else if sender = RadioButton2 then ....
or you can test the type of a sender.
procedure TdlgPreferences.rgMyGroupClick(Sender:TObject)
begin
if sender is TRadioButton then //do action
else if sender is TForm then ....
The is keyword tests to see if an object is of a certain type.
Note that the test if AObject is TObject is always true because every object is derived from TObject.
More fun with typecasting
The fact that is tests for the object type and all ancestors can be used for other purposes as well:
procedure TdlgPreferences.rgMyGroupClick(Sender:TObject)
begin
//TObject does not have a 'tag' property, but all TControls do...
if (sender is TControl) and (TControl(Sender).Tag = 10) then ....
Because of short-circuit boolean evaluation Delphi will first check (sender is TControl) and only continue if that is true. Making the subsequent test (TControl(Sender).Tag = 10) safe to use.
If you don't understand the construct TControl(Sender) you can read up on typecasting.
here: http://delphi.about.com/od/delphitips2007/qt/is_as_cast.htm
and here: http://delphi.about.com/od/oopindelphi/a/delphi_oop11.htm
If I'm understanding you correctly you are clicking your radiogroup programatically to set up the initial state of the form, but you have extra code in the click handler that you don't want to run?
If that's the case you might want to consider removing the code that sets the state of the form to its own method and then call it from both the radio click event and from the initialze/show/create of your form.
That way you can use the same code to set the form to your required state from a user click and programatically set it without doing any extra logic required when a user is interacting with the dialog. Or maybe I've completely misunderstood your problem...
something like this:
// (open preferences)...
SetStateOfFormForSelectedGroup();
procedure TdlgPreferences.SetStateOfFormForSelectedGroup()
begin
//do all setting of form for selected group here.
end;
procedure TdlgPreferences.rgMyGroupClick(Sender:TObject)
begin
SetStateOfFormForSelectedGroup();
//do something useful
end;
Try some functions or properties, as:
Sender.classtype
InheritedFrom()
Note: when using the obj SENDER of the ButtonClick( sender:TObject ) (for example)
Sender = class of button on the click => TButton
So, TButton(Sender).properties or methods etc...

Resources