Form OnClick event handler - How to overlap other event handlers? - delphi

I'm having a little trouble writing a validation function to my Form.
I have a GroupBox within my Form, on this GroupBox a couple buttons, and a StatusBar at the bottom of this Form. I've written a function to display the validation messages in a StatusBar panel. I have a Timer and the messages are visible in the StatusBar for five seconds, like a hint to the user.
But I would like that if before the message disappears for itself the user happen to click at any object within the Form (GroupBox, Panel, Button... anywhere), that i could use the form OnClick to clear the validation message.
I don't want to work with every control possible to interact, clearing the message if the control was clicked. I want to do this only one time at the Form OnClick, however, the objects OnClick event handler override the parent (Form) OnClick event handler.
I don't know if i was clear enough, but is there any way i could do this? Writing code just one time to every click within the form?
Thank you in advance, and sorry for my English and any orthographic or grammatical mistake.

Add a TApplicationEvents component to your form. And implement a handler for its OnMessage event like this:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if Msg.message=WM_LBUTTONDOWN then
ClearStatusBarMessage;
end;
where ClearStatusBarMessage is your code to clear the hint.
This event handler will get called every time the application processes a queued event on the main UI thread. So, this may be more far-reaching than you might imagine. I'm not sure exactly how your application is designed, but you may need to tweak the code a little to get the exact behaviour that you desire.

I recently had to solve a similar problem.. I handled the form event
OnMouseActivate
Copy&Paste from the help:
Occurs when the user presses a mouse button with the mouse pointer over a control and the parent form is not active.
I use Delphi 2007

Related

How to close an FMX TFrame shown in a TPopup from event handlers inside the TFrame

I use a frame that is shown by calling TPopup.Popup(true); method. If the frame contains a button with the ModalResult property set (to, for example, mrOK) it closes automatically when clicked by the user. But I need to close the frame in an OnClick event of a TListBox in it.
Frame does not have Close method.
I would like to avoid using message posting to the parent form as it might cause future problems when the application is ported to Android as well as I would prefer not to declare the OnClick event handler for the Frame.ListBox in the parent Form because the frame might be shown by several different forms and it will worsen the quality of parent Form code making it heavy and difficult to read.
I would highly appreciate suggestions how to do this.
I found the following way out. I call
(GetParentComponent as TPopup).IsOpen:=false;
When you inherit from TPopUp like explained here (How to make my own dialog component from Firemonkey TPopUp?) then you can call ClosePopup when an event is trigerred in your frame.

How to tell a non-modal has lost/regained focus

I have a main form and a secondary form both with some DBAware controls from a common database. Currently I am using ShowModal but I would like to be able to use Modal to go back to the main form and navigate the database.
In the secondary I can replace the TDBEdits with TEdits and stuff them with data when I Show the secondary form. There is no means of navigating the database in the secondary form, but, if the user can go back to the main form where they can navigate, I will need to reset the database cursor when they return to the secondary.
How can I tell that the secondary form has just lost focus? I can grab the database cursor position.
How can I tell when the secondary form gets focus again? So I can reset the database cursor if it was moved before returning.
Thanks
p.s. Please no questions on why and/or alternative suggestions. It is an existing application and I really do not want to have to fix miles of code. As crappy as it is, it has been working for years and the customer wants the change of possible. :)
Use the form's OnActivate and OnDeactivate events. OnActivate is called when the form gains focus, and OnDeactivate is called when it loses it.
Note that these events are only triggered when focus is transferred within your own application. If you need to know when your application itself loses or gains focus, use TApplication.OnActivate and TApplication.OnDeactivate instead.
You can take a look at the onActivate and onDeactivate events of the secondary form. I think they are what you need.
Note: OnDeactivate works only if focus is switched to another form of project. For example I have project1.exe which creates 2 forms Form1 and Form2 . So Form1 OnDeactivate event triggers if I ckick Form2. But it will not be trigger if I click Notepad window.

Is there a workaround for something like "Form1.MousePreview:=true"?

I have two 100% overlapping panels with different contents on a form.
The first (static display of information) should be visible by default, but the other (user interaction) should replace it if the user moves the mouse near the two - and if the mouse moves away, it should switch back.
Something like this:
if (*the mouse is near*) then
begin
Panel1.Hide;
Panel2.Show;
end
else
begin
Panel2.Hide;
Panel1.Show;
end;
My problem is: where to capture mouse movement?
Each component has its own OnMouseMove handler - of course I could forward each of them to the forms handler, but I'd rather have something a bit more elegant (and easier to maintain).
The perfect solution would be something like Form1.MousePreview := true;.
Another solution would be assigning a generic handler that translates coordinates and calls the forms handler; The assigning could be done in FormCreate.
But that's not as easy as it seems, because one TImage already has its own mouse event handlers.
I have tried OnMouseEnter and OnMouseLeave of the two panels but it didn't work; #1 disappeared, but #2 did not appear. I guess that's because if the mouse leaves Panel2, it should disappear - but it also leaves it if it enters a button on it.
That's why I'd like to use a coordinate based approach to make the check more reliable.
Maybe the two panel method is completely wrong?
Update: Yes, it is, as Remy said.
I am now using a TJVPageList because a TPageControl has visual tabs.
The OnMouseEnter handler of the PageList sets one page, the OnMouseLeave sets the other; But once the mouse moves over the PageList, both pages start flickering.
I have tried adding the event handlers to each page, too, but that made no difference.
Should I check all OnMouseEnter / Leave events to filter out the PageList, the two pages and all components sitting on the pages?
Another update: I am using a TPageControl now, but the behaviour is similar.
It doesn't flicker, but if I move the mouse ontop the TPageControl, no TTabSheet is displayed at all.
Only if I press down the left mousebutton, the UI sheet is displayed. The other sheet is displayed normally if I move away the mouse. (The TJVPageList displays the UI page if I press the left mousebutton, too.)
I have used the mouse event handlers (enter/leave) of the TPageControl and both TTabSheets.
Update 3:
Done it.
The static Panel / TabSheet / JvStandardPage (#1) must not trigger the OnMouseLeave handler.
What you describe might be better served using a single TPageControl instead of two TPanel controls. Use the TPageControl's own OnMouseEnter/Leave events (or intercept the CM_MOUSEENTER/LEAVE messages) to switch the TPageControl.ActivePage as needed.

Handle changes to a big form. Alert before closing modal

I am currently working on a Customer Management application made in SmartGWT 2.0.
The Add Customer form is a fairly big one with multiple tabs and each tab has lot of fields. This form is opened in a modal window which have a save and a close button at the bottom.
Since this is a huge form, sometimes the rep accidentally hits Close without noticing that there is some information in one of the tabs.
We want to add some kind of alert when user tries to close the form after he has made changes to it.
I saw that there is ChangeHandler on text items which can flag a change which can be evaluated before firing the close event. However currently doing this for so many fields is a little bit cumbersome. Is there a way of achieving this on a DynamicForm level or even better on the Window level?
I am looking for a SmartGWT equivalent of this jquery code:
$("input:text, select, input:checkbox, input:radio, input:password").change(function(){
unloadRoutineFlag = true;
});
Take a closer look at this handler at the dynamicForm level.
addItemChangedHandler(ItemChangedHandler handler)
Handler fired when there is a changed() event fired on a FormItem
within this form.
Typically, when a formItem fires the changed() event, the form gets notified. Let us know if this works.

How to Detect that the Mouse is unmoved and button still pressed?

In Delphi, I've added a Scrollbar component (oriented vertical) to the right side of my form.
I've added a Scrollbar OnChange event so I can change the view of the form and the position of the scrollbar thumb when the user clicks on the UpArrow or DownArrow button with his mouse, and this works fine.
But the OnChange event only seems to get triggered when the mouse button is initially pressed on the arrow.
I notice all scrollbar controls repeat the command and continue scrolling while the mouse remains pressed on the arrow, and I'd like to implement this behavior.
So how can I easily detect if the user has not moved the mouse and continues to press the mouse button while the mouse remains over the arrow?
Conclusion. Somehow something in the scrollbar in my project got corrupted. After I deleted the ScrollBar, and added it again, the problem vanished.
This is one of those tricky ones that took me a lot of time to solve. Thanks for your help. I'm closing this question.
Use the OnScroll event.
The following code adds 'xxx' to a memo as long as the mouse is held down on the scrollbar arrow button. Tested with Delphi 6.
procedure TForm1.ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
begin
Memo1.Lines.Add( 'xxx' );
end;
The usual way to handle auto-repeating is to enable a TTimer and check in the OnTimer() event handler whether the action needs to be performed again, and to deactivate the timer if not. If you need sample code, I seem to remember that the SynEdit control used a similar technique for autoscrolling in drag and drop operations.
If a component does not encapsulate the behaviour you are looking for and you can't easily simulate the behaviour with the methods available you should really subclass the closest component that does most of what you need and add the behaviours that are missing.
I know that some extra work is involved but it really is the better way to go. Now with Delphi, I seem to recall that subclassed components needed a bit of extra work as well to be able to be used from the IDE for form design, maybe this has changed since version 7.

Resources