This code is not working for me on Delphi XE:
http://delphi.about.com/cs/adptips2000/a/bltip0800_5.htm
procedure TForm1.FormDeactivate(Sender: TObject) ;
begin
ReleaseCapture;
end;
procedure TForm1.FormMouseMove
(Sender: TObject; Shift: TShiftState; X,Y: Integer) ;
begin
If GetCapture = 0 then
SetCapture(Form1.Handle) ;
if PtInRect(Rect(Form1.Left,
Form1.Top,
Form1.Left + Form1.Width,
Form1.Top + Form1.Height),
ClientToScreen(Point(x, y))) then
Form1.Caption := 'Mouse is over form' else
Form1.Caption := 'Mouse is outside of form';
end;
No errors - it just has no effect.
Please help.
EDIT 1
It turned out the problem is not with the code, even mouse FormMouseEnter and FormMouseLeave are not working because I'm passing the form to a Unit I created with a function like this:
procedure Slide(Form: TForm; Show: Boolean);
I'm calling the Show method from inside this procedure. How can I overcome this problem?
Thanks.
EDIT 2
I don't want to use the function I posted now. I want to use what the people suggested below (FormMouseEnter and FormMouseLeave) but it's not working in my case as well.
You could use OnMouseEnter and OnMouseLeave events to keep track of whether the mouse is over the form or not without capturing the mouse cursor.
This is just a matter of entering the necessary code in the OnMouseEnter and OnMouseLeave events of the corresponding form. In my case, all I did was :
Create a new project in Delphi
Select the form you are working with
Go to the Object Inspector
Switch to the Events tab in the object inspector if necessary
Scroll down to the OnMouseEnter event, double click in the white space next to it which will generate an EventHandler. Make sure you end up with the following code in the event handler :
procedure TForm1.FormMouseEnter(Sender: TObject);
begin
Self.Caption := 'Mouse in form';
end;
Go to the Object Inspector again
Find the OnMouseLeave event and double click in the white area to the right of it to generate a new event handler, and add the following code to it
procedure TForm1.FormMouseLeave(Sender: TObject);
begin
Self.Caption := 'Mouse outside form';
end;
Run the app ... move your mouse over the form and the caption will change to 'Mouse inside form', move it outside the form and the caption will say 'Mouse outside form'
Works as a charm (Tested in Delphi 2010)
As far as I understand, using SetCapture for this is a bad idea. If it functioned like you wish, you would be robbing everyone else of the mouse messages just because you don't know a better way to track mouse.
But MSDN says (http://msdn.microsoft.com/en-us/library/ms646262(VS.85).aspx) that even with SetCapture, mouse messages from outside would not be redirected to your window unless mouse button is down (probably a measure to prevent exactly what are you trying to achieve: stealing mouse without a valid reason).
It doesn't matter where are you calling Show() from, so your problem is not in that.
I needed a form (frmTasks) with a heavily modified Caption. So I created a form with a hidden Caption. I simulate the Caption with a TImage (imgRedLogo) on which I draw the stuff I need.
This code lets the user to click the fake caption (the image) and move the form around. Works like a charm WITHOUT capturing the mouse. It works even with the right mouse button (you have to test the 'Button' parameter in imgRedLogoMouseDown if you want to disable this 'feature').
FULL WORKING CODE:
VAR
Dragged : Boolean= FALSE;
IsOverImg: Boolean= FALSE; { True if mouse if over the image }
OldPos : TPoint;
procedure TfrmTasks.imgRedLogoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Dragged:= True;
GetCursorPos(OldPos);
end;
procedure TfrmTasks.imgRedLogoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
VAR NewPos: TPoint;
begin
if Dragged AND IsOverImg then
begin
GetCursorPos(NewPos);
frmTasks.Left:= frmTasks.Left- OldPos.X + NewPos.X;
frmTasks.Top := frmTasks.Top - OldPos.Y + NewPos.Y;
OldPos:= NewPos;
end;
end;
procedure TfrmTasks.imgRedLogoMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Dragged
then Dragged:= False;
end;
procedure TfrmTasks.imgRedLogoMouseEnter(Sender: TObject);
begin
IsOverImg:= TRUE;
end;
procedure TfrmTasks.imgRedLogoMouseLeave(Sender: TObject);
begin
IsOverImg:= FALSE;
end;
Enjoy.
Related
How can I disable the mouse wheel scroll on a FMX TComboBox when hovering over it?
I've tried overriding the MouseWheel method without any luck. I'm most likely doing it wrong as I'm not experienced with overriding. REF: MouseWheel
I've gone ahead and removed Inherited:
type
TComboBoxOverride = class(TComboBox)
procedure MouseWheel(Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); override;
end;
// I've tried changing the control on the class overriding the method. No luck
cbbServerMap: TComboBoxOverride;
{ TComboBoxOverride }
procedure TComboBoxOverride.MouseWheel(Shift: TShiftState; WheelDelta: Integer;
var Handled: Boolean);
begin
Handled := True;
end;
I've found the following SO post for VCL and DevEx but I'm struggling to convert it to FMX, Ref: How to suppress mouse wheel in TcxComboBox
When setting a breakpoint on the TCustomComboBox.MouseWheel method I can see that it ignores my override.
In the OnMouseWheel event, simply put Abort;.
For example:
procedure TfrmMinorInjury.cboDischargetypeMouseWheel(Sender: TObject;
Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
begin
Abort;
end;
I solved the same task but for memos in scrollbox.
My solution is
handle mouse wheel in scrollbox.OnMouseWheel. Set Handle := true there.
call directly scrollbox.OnMouseWheel in memo's OnMouseWheel
I wanna display hint just on mouse move, like in Winamp. No need to have focus on app. Thanks for help.
You can make the hint popup, but I'm not sure if you can do that if the application is not the focussed application.
This will show the hint for anything where the hint is set and ShowHint = True. But only if it is the focusseed Application. (As Sertac Akyuz said in a comment on the original post, VCL only does this for the currently active form).
procedure TForm1.ControlMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
aPoint: TPoint;
aControl: TControl;
begin
aControl := TControl(Sender);
if aControl.ShowHint = true then
begin
aPoint.X := X;
aPoint.Y := Y;
if Assigned(aControl.Parent) then
aPoint := aControl.ClientToParent(aPoint);
aPoint := ClientToScreen(aPoint);
Application.ActivateHint(aPoint);
end;
end;
Hope this helps.
There is a way you can detect if mouse cursor position is over some controll by periodically checking mouse cursor position in relation of that controls client rectangle. You can do this using Timer and next code:
procedure TForm4.Timer1Timer(Sender: TObject);
if Panel1.ClientRect.Contains(Panel1.ScreenToClient(Mouse.CursorPos)) then
begin
Form4.Caption := 'Panel1';
end
else if Panel2.ClientRect.Contains(Panel2.ScreenToClient(Mouse.CursorPos)) then
begin
Form4.Caption := 'Panel2';
end
else if Panel3.ClientRect.Contains(Panel3.ScreenToClient(Mouse.CursorPos)) then
begin
Form4.Caption := 'Panel3';
end
else if Panel4.ClientRect.Contains(Panel4.ScreenToClient(Mouse.CursorPos)) then
begin
Form4.Caption := 'Panel4';
end
else Form4.Caption := 'None';
There is probably some better solution by iterating through your forms component list or even better creating your own specific list for this.
Now the only problem is that hint is shown only for active applications. So if you want for hints to be shown even when your application isn't active you will have to make your own hint system (Creating a small form with hint text shown).
Finally it works now. I copied VCL.Forms.pas to project directory
removed there ForegroundTaskCheck like Sertac Akyuz said
var
HintInfoMsg: TCMHintInfo;
{$ENDIF}
begin
FHintActive := False;
HintInfo.ReshowTimeout := 0;
if FShowHint and (FHintControl <> nil) {and ForegroundTaskCheck(EnumAllWindowsOnActivateHint)} and
and most important thing is to add {$B-} in VCL.Forms.pas (without it many AV and crash)
unit Vcl.Forms;
{$B-}
In Delphi 7's TMemo control, an attempt to do the key combo Ctrl + A to select all does not do anything (doesn't select all). So I've made this procedure:
procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
C: String;
begin
if ssCtrl in Shift then begin
C:= LowerCase(Char(Key));
if C = 'a' then begin
Memo1.SelectAll;
end;
end;
end;
Is there a trick so that I don't have to do this procedure? And if not, then does this procedure look OK?
This is more elegant:
procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
if Key = ^A then
begin
(Sender as TMemo).SelectAll;
Key := #0;
end;
end;
While the accepted answer by Andreas Rejbrand is correct, it is not the expected Windows visual behavior. It leaves the cursor position unchanged. Ctrl-A (Select All) should leave the cursor at the bottom of the text and scroll the control so the cursor is in view.
If this is not done, the control exhibits odd behavior. For example, assume there is more text than fits the window, and the window is not scrolled to the bottom. You press Ctrl-A, and all text is Selected. Ctrl-C will now copy all text to the clipboard. Although you can't see it the cursor is now at the bottom of the View, which has not scrolled. If you now press Ctrl-Down the Selected Text becomes just the text in view, then the cursor moves down and window scrolls down one line. The new bottom line is not selected. This makes it look like the Select All only selected the visible text.
The fix is simply to move the caret to the end of text before SelectAll.
procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
if Key = ^A then begin
With Sender as TMemo do begin
SelStart := Length(Text);
Perform(EM_SCROLLCARET, 0, 0);
SelectAll;
end;
Key := #0; //Eat the key to suppress the beep
end;
end;
Note that 'Eat the key' only works in the OnKeyPress event, not the OnKeyDown or OnKeyUp events.
I used the previous answer and discussion to create a standalone component which handles the KeyPress event which I use in small test programs.
TSelectMemo = class(TMemo)
protected
procedure KeyPress(var Key: Char); override;
end;
...
procedure TSelectMemo.KeyPress(var Key: Char);
begin
inherited;
if Key = ^A then
SelectAll;
end;
Another way of adding "select all" behavior to all components on a form is to add an action list to your form with a standard select all action.
I want to remove the caret from a TEdit control in Delphi. I have made the component Enabled := False but the caret still appears.
My question is how to remove the caret from a disabled TEdit control?
I assume that you mean TEdit control.
The solution is HideCaret function, the only problem is where to call it. The 2 event handlers below worked fine for me:
procedure TForm18.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
HideCaret(Edit1.Handle);
end;
procedure TForm18.Edit1MouseEnter(Sender: TObject);
begin
HideCaret(Edit1.Handle);
end;
Place a TApplicationEventscontrol on the form and in the OnIdle event, hide the caret, as follows. Set the event to nil so it only fires once.
procedure TFormMain.AppEventsIdle(Sender: TObject; var Done: Boolean);
begin
AppEvents.OnIdle := nil;
HideCaret(Memo1.Handle);
end;
I want a TPageControl and some TTabSheets, with 'per tabsheet' tooltip hints visible as I hover over each tab in turn.
Is there any way of getting this effect in Delphi 2009?
Just hook the Page Control's Mouse Move event and use the TabAtPos property to determine which tab the mouse is hovering over. Then assign that tab's Hint to the Page Control's hint property.
procedure TForm.PageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
var
tabindex: integer;
begin
tabindex := PageControl.IndexOfTabAt(X, Y);
if (tabindex >= 0) and (PageControl.Hint <> PageControl.Pages[tabindex].Hint) then
begin
Application.CancelHint;
PageControl.Hint := PageControl.Pages[tabindex].Hint;
PageControl.ShowHint := true;
end;
end;
CancelHint/ShowHint will take care of updating the hint window when mouse moves directly from one tab to another.
Improved but ugly version below also temporarily changes HintPause to 0 when mouse is moved directly from tab to tab so that the hint is redisplayed immediately. (The "ugly" part of the solution goes to the Application.ProcessMessages call which forces hint messages to be processed before HintPause is restored.)
procedure TForm.PagesMouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
var
hintPause: integer;
tabindex: integer;
begin
tabindex := PageControl.IndexOfTabAt(X, Y);
if (tabindex >= 0) and (PageControl.Hint <> PageControl.Pages[tabindex].Hint) then
begin
hintPause := Application.HintPause;
try
if PageControl.Hint <> '' then
Application.HintPause := 0;
Application.CancelHint;
PageControl.Hint := PageControl.Pages[tabindex].Hint;
PageControl.ShowHint := true;
Application.ProcessMessages; // force hint to appear
finally Application.HintPause := hintPause; end;
end;
end;
To hide the hint on the main page body, assign the following method to the page control's OnMouseLeave event.
procedure TForm.PageMouseLeave(Sender: TObject);
begin
PageControl.Hint := '';
PageControl.ShowHint := false;
end;
In Raize Components, this can be accomplished by setting the trzpagecontrol.tabhints property to true. Good components can save you a lot of time (therefore money).
(just a happy customer, btw)
Update (in response to comment from #Rigel) from raize.com FAQ (Raize Components tab):
What happened to Raize Components?
Back in 2015 Embarcadero acquired Raize Components from us and
rebranded the product as the Konopka Signature VCL Controls (KSVC).
Initially they sold the product separately, but for the past several
releases of RAD Studio, the components have been available for free
through the GetIt Package Manager. Simply open the GetIt Package
Manager from the Delphi or C++Builder Tools menu and search for
“Konopka” to locate the installer. The component names, units, and
packages are the same as they were in Raize Components, just the
product name is different.
1 - fill in the .Hint property, and set the .ShowHint property to True for the PageControl (assuming each tabsheet has ParentShowHint set to true; otherwise you'll have to set each page individually).
2 - Assign this event to the PageControl's OnChange event handler:
procedure TForm1.PageControl1Change(Sender: TObject);
begin
PageControl1.Hint := PageControl1.ActivePage.Hint;
end;
After you do that, the hint will be whatever the active tab is. I am not sure how to make it change the hint based on where the mouse is hovering - that's an interesting phenomenon I've never noticed before, actually.
On the tPageControl.OnMouseMove find TabIndex by Pgctrl.IndexOfTabAt( X, Y ) and assign TabSheet hint to the tPageControl hint
Look here:
http://www.delphigroups.info/2/9/321680.html
Originally working on a C++ Builder 6 (!) project (so please forgive any typo in this transcript), I started with the answer of Gerard[1] and reduced the code as much as possible. To better control the calls of Application.CancelHint, I introduced the member FLastHintTabIndex, it must be initialized with -1.
procedure TForm1.PageControl1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var
TabIndex: Integer;
begin
TabIndex := PageControl1.IndexOfTabAt(X, Y);
if FLastHintTabIndex <> TabIndex then
Application.CancelHint;
if TabIndex <> -1 then
PageControl1.Hint = PageControl1.Pages[TabIndex].Hint;
FLastHintTabIndex := TabIndex;
end;
[1]
my answer doesn't contain much new, but I find all that code and text too distracting.