How works the OnMouseDown event on my MainForm with Firemokey? - firemonkey

I am using Tmainform.OnKeyDown and it fires always correctly, besides the controls or frames added to the form.
I need the same behavior for OnMouseDown.
My goal is to track activity of the user. After x minutes with no keyboard nor mouse clicks I want to close the application.
Edit: TMainForm.OnMouseDown never gets fired. I don't want to do anything with the event, just know that the user is alive and clicking.

For the Form to see keystrokes prior to the active control you need to set the KeyPreview property within the forms Object Inspector.
You can also do this via code: Form1.KeyPreview := True;
There is a substantial explanation in the accepted answer here: How does Delphi's KeyPreview work?
Regarding your mouse query, how do you know it isn't working if you're not doing anything there?
Put this code into your forms OnMouseDown event;
PROCEDURE TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
BEGIN
CASE Button OF
mbLeft: showmessage('Left Mouse Button!');
mbRight: showmessage('Right Mouse Button!');
mbMiddle: showmessage('Middle Mouse Button!');
END;
END;
I hope this is helpful and answers your question.

Related

Hiding Taskbar Button works, but not when second form is shown [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I managed to hide my winforms application taskbar button using
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
This i call on timer 1 second after the form is created. The taskbar button remain hidden through out the application usage, but until I click a button on the form to show another form, with the Form1 as the owner.
I try to use the same code to hide the second form but not able to work.
Edit: Adding more codes:
Codes in Form1:
// this fires every 1 second and works well.
procedure TForm1.scanTimerTimer(Sender: TObject);
begin
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
end;
// when a user press Settings button on the Form1
// I open another form.
procedure TForm1.SettingsBtnClick(Sender: TObject);
var
settings: TSettingsForm;
begin
settings := TSettingsForm.Create(Form1);
settings.Show;
end;
Codes in SettingsForm
// this fires every 1 second and DOESNT WORK!
procedure TSettingsForm.scanTimerTimer(Sender: TObject);
begin
ShowWindow(GetParent(SettingsForm.Handle),SW_HIDE);
end;
That's all there is for the codes. So when I open SettingsForm, immediately the taskbar button reappears and never disappears anymore. I want taskbar to remain hidden no matter how many other forms I open from the main form.
I tried a "OS specific API" for windows which is
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
Which works after FormCreate, but after the main window opens a secondary window,
the taskbar button reappears. So if your app just have one window, you can use this. But for multiple windows/forms app, it will not work!
Also I tried Non OS Specific API:
SettingsForm.ShowInTaskBar := stNever;
Tried putting this in FormCreate, and also just before Show in Caller form, but still it doesn't work. The taskbar button still appears.
Finally I found in lazarus forum the answer using a OS Specific API:
You need to add 2 imports:
InterfaceBase, Win32Int
And put this is FormCreate:
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
EXStyle: Long;
AppHandle: THandle;
begin
AppHandle := TWin32WidgetSet(WidgetSet).AppHandle;
EXStyle:= GetWindowLong(AppHandle, GWL_EXSTYLE);
SetWindowLong(AppHandle, GWL_EXSTYLE, EXStyle or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
end;

Missing keyboard input on custom VCL control [duplicate]

I've built a custom control that I'm trying to send input to. It will accept mouse input and report MouseDown, MouseMove and MouseUp correctly, but for whatever reason, it won't accept keyboard input. When I click on it, it doesn't receive focus, and any keys I press get interpreted by whatever control had the focus already.
This is probably something really simple. The first place I thought to look was in the ControlStyle property, but the only thing I can see in the helpfile about keyboard input is csNoStdEvents, which disables it, and my control doesn't have that. So what do I need to do to make it so my control can receive input focus?
A few things to try:
On MouseDown, call Windows.SetFocus(Handle). In my experience, the WinAPI function SetFocus often works better than the VCL's SetFocus method.
In response to the WM_GETDLGCODE message, reply with Message.Result := Message.Result or DLGC_WANTCHARS or DLGC_WANTARROWS or DLGC_WANTTAB or DLGC_WANTALLKEYS;
Could it be as simple as calling SetFocus on mouse down?
procedure TYourCustomControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer);
begin
inherited;
if CanFocus then
SetFocus;
end;
Do you have WS_TABSTOP set? You don't have input focus without that, I believe. But this is based on a recollection from nearly 10 years ago, when I was writing my own syntax-highlighting code editor, for which I have long since lost the source.
{TWinControl.}TabStop := True; ought to do. A quick test app with a do-nothing component derived from TWinControl and displaying a dialog for key events seems to show that it makes all the difference.
I've checked the code for my control and I can't see anything that might stop this working. Are you calling "inherited" in the Create procedure?
I do handle the following, but nothing special:
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
Is the keystroke available at form level? That is, is KeyPreview turned on, and can you see the keystroke in the form's OnKeypress event? You can follow it from there in the debugger. Is the control (as Dan indicated) suitable for keyboard input? For instance, a TLabel, although it displays text, is a graphical control.

How to pass keystrokes onto a second active form in Firemonkey

I encountered some behavior in FMX that is different in VCL. This relates to how main menu shortcuts are processed. It seems that an FMX application will intercept all shortcut keystrokes in the main form such that any other active forms do not see these keystrokes.
This means for example if you have a TMemo on a second form and the main form uses the Ctrl-V main menu short cut, it's not possible to paste text into the memo using Ctrl-V. This is unique to FMX, VCL works as expected where a second form receives all keystrokes irrespective of shortcuts on a main form.
An answer in this question How to intercept Menu shortcut event in Firemonkey explains how to intercept shortcuts in the main form.
The question here is how to get these intercepted keystrokes from the main form to the currently active form, so that controls such as TMemo or TEdit on the second form work as expected?
Based on the answer in How to intercept Menu shortcut event in Firemonkey, one way to pass on the mainmenu shortcut keystrokes, eg Ctrl-A, to the currently active form is to use this code in the main form:
TMenuItem = class(FMX.Menus.TMenuItem)
protected
procedure DialogKey(var Key: Word; Shift: TShiftState); override;
end;
procedure TMenuItem.DialogKey(var Key: Word; Shift: TShiftState);
var ch : char;
begin
if (ssCtrl in Shift) and (Key = 65){A} then
begin
ch := #0;
Screen.ActiveForm.KeyDown(Key, ch, Shift);
exit;
end;
inherited;
end;
An alternative answer to the first one, it's works but not everyone might like it, plus it has limitations. For simple cases is should work.
Before showing the second form, remove the shortcuts from the mainform, then restore the shortcuts when the form returns control to the mainform. Works ok if the second form is shown using showmodal. Pity there isn't a form OnShortCut event as we have in VCL. Eg rough example:
(MainMenu.Items[0] as TMenuItem).Items[0].ShortCut := TextToShortCut('');
FormTwo.ShowModal;
(MainMenu.Items[0] as TMenuItem).Items[0].ShortCut := TextToShortCut('Ctrl+V');

How do I put a form in to help mode?

I am trying to put form into "help mode" in Delphi 2010.
I have a button which the user clicks, and I want the cursor to change to the help cursor, then when a user clicks onto a control, the help for the control is displayed
Is there a window message that I can send?
Send a WM_SYSCOMMAND message to the form passing SC_CONTEXTHELP as lParam.
Changes the cursor to a question mark with a pointer. If the user then clicks a control in the dialog box, the control receives a WM_HELP message.
Write something like this in your button OnClick event handler:
procedure TMyForm.Button1Click(Sender: TObject);
begin
SendMessage(Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
end;

Windows Vista and 7 motion effects are applied only once when my form is shown. Why?

I created an application with two forms. First one is the main form and second one is hidden.
I placed a button on Form1 and I made it ShowModal the second form. On Win7 the form appears with an animation. Then I close the appeared form (Form2) and I click the button once again. Form2 appears without the animation. I want the animation every time. What should I do?
The only thing I can think of right now is to create the form manually each time you want to display it modally. To do this, go to the project options and make sure that the form isn't automatically created. Then do
procedure TForm1.Button1Click(Sender: TObject);
begin
with TForm2.Create(self) do
try
ShowModal;
finally
Free;
end;
end;
In my opinion, most often modal forms should in fact be created manually.
Well, you could just elect not to worry about it! Alternatively a very quick hack would be to free the form each time it closes since the animation appears to run only on the first time the form is shown.
EDIT: Another approach would be to call DestroyHandle on your form whenever it closes. I'm guessing now, but I imagine that Windows records somewhere in the window a flag indicating that the animation has been shown. Once this flag has been set the animation is never shown again.
As an alternative way it's possible to fool windows by sending a notification that form's style has been changed, that will make windows reset "secret flag" for current form's handle. Thus, on showing already created form the cool show effect animation will be applied again. However, I can't say what negative effects can be caused by doing this way.
uses
Winapi.Windows, Vcl.Controls;
type
TFormHelper = class helper for TForm
public
procedure Show;
end;
implementation
procedure TFormHelper.Show;
begin
SendMessage(Handle,CM_CUSTOMSTYLECHANGED,0,0);
inherited Show;
end;
Note: code featured with a class helper, this feature/keyword might be not available in older IDEs.

Resources