Windows Control Panel's Mouse applet features a "snap to" option in the Pointer Options section. The "Automatically move pointer to the default button in a dialog box" specifies whether the mouse pointer snaps to the default button (i.e. Ok or Apply) in dialog boxes.
Some users find this option valuable as it speeds up their work. In word processing application, for example, if you want to close an unsaved document, a dialog box would popup and ask you something like "would you like to save the changes". If "mouse snap to" is on, the mouse pointer will jump and be positioned in the center of the default button of the dialog box. The default button is the one that has the input focus when the dialog is displayed. Having the focus a user can simply hit the Enter key to "click" it.
Unfortunately for your Delphi application users, this feature is not handled by your Delphi application. The mouse pointer will not jump for Delphi dialog boxes like InputBox, MessageBox, ShowMessage or any custom made modal form / window.
The actual snapping is implemented by the mouse driver. The implementation looks for a default button that has a class name "button" on a window implementing the default dialog class. Since only TOpenDialog, TSaveDialog and alike from the Dialogs section on the Tool Palette and also the Application.MessageBox are recognized by the mouse driver - all your custom dialogs and also InputBox, MessageDlg, ShowMessage will not be recognized and therefore mouse snapping will not work.
Fix For Mouse Snap-To For Your Delphi Application
Luckily, you can easily fix this problem "internally" by implementing the snap-to functionality in your own modal dialog forms by positioning the mouse over the default button.The TScreen's OnActiveFormChange event is the ideal candidate to handle this. The OnActiveFormChange event is raised immediately after a new form becomes active in a multi-form application.
Of course, before you move the mouse pointer you need to check if the "snap-to" option is turned on. A call to Windows API SystemParametersInfo function which retrieves (or sets) the value of one of the system-wide parameters, by providing it with the SPI_GETSNAPTODEFBUTTON flag, the result determines whether the snap-to-default-button feature is enabled.
What's left is to define a procedure for the TScreen's OnActiveFormChange event handler.
To use OnActiveFormChange event, define a procedure in the unit of your application's main form, like this:
typeNext, assign this procedure to the global Screen variable's OnActiveFormChange event in the MainForm's OnCreate event handler:
TMainForm = class(TForm)
public
procedure OnActiveFormChange(Sender: TObject) ;
end;
//MainForm's OnCreateFinally, here's the code that implements the "move move pointer to the default button in dialog boxes":
procedure TMainForm.FormCreate(Sender: TObject);
begin
Screen.OnActiveFormChange := OnActiveFormChange;
end;
//center the mouse over the default button on a modal dialogYou now have the mouse snapping working in all your Delphi modal dialogs that have the default button set.
//Screen.OnActiveFormChange
procedure TMainForm.ScreenOnActiveFormChange(Sender: TObject);
var
af : TCustomForm;
cp : TPoint;
function SnapMouseToDialogDefaultButton : boolean;
var r: Bool;
begin
result := SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, @r, 0) AND r;
end;
begin
af := Screen.ActiveCustomForm;
if (af = nil) OR (af.ActiveControl = nil) then Exit;
if (fsModal in af.FormState) AND af.ActiveControl.InheritsFrom(TButton) AND SnapMouseToDialogDefaultButton then
begin
cp := af.ActiveControl.ClientOrigin;
Inc(cp.X, af.ActiveControl.ClientWidth div 2);
Inc(cp.Y, af.ActiveControl.ClientHeight div 2);
Mouse.CursorPos := cp;
end;
end;
Note that you want the mouse snapping to work only when it is turned on in Windows (SnapMouseToDialogDefaultButton function), only when a modal dialog is displayed (fsModal in af.FormState) and also only when the default control is actually a "button". The code than uses the global Mouse object and its CursorPos property to position the mouse pointer in the center of the default button.


