Jump to content
Sign in to follow this  
Linuxuser1234

How to have a component that follows Mouse Pointer

Recommended Posts

Im trying to get TCalloutPanel to follow the mouse pointer but i cant find any code examples on this here is the code i have so far 

procedure TForm1.Button22Click(Sender: TObject);
var
Marker : TCalloutPanel;
begin
//
Marker := TCalloutPanel.Create(Self);
Marker.Width := 209;
Marker.Height := 41;
Marker.RotationAngle := 180;
Marker.Visible := True;
Marker.Parent := Self;
end;

 

Edited by Linuxuser1234

Share this post


Link to post

Sorry, but my "Math" it's not so good than Eistein... :classic_cheerleader:

  • you can move your Form for any place and my code can find the "Form-center"...
  • in fact, you dont need use all code... it's only a sample!
  • NOTE: use CallOutPanel .HitTest = false...  then, you can to click on form!

 

type
  TForm1 = class(TForm)
    CalloutPanel1: TCalloutPanel;
    LineVert: TLine;
    LineHorz: TLine;
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  Winapi.Windows {SetCursorPos(...) on screen-center-form ... to Mobile can not works  } ,
  System.Math;

var
  LCalculatingMouseAngle: boolean = false;
  LCrossPos             : TPointF;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
var
  LCalloutPanelPointF : TPointF;
  LCalloutPanelCenterF: TPointF;
  LFormCenter         : TPointF;
  A, B                : TPointF;
  C                   : TPointF;
begin
  LCalloutPanelPointF := CalloutPanel1.Position.Point;
  //
  // find Form center in any place on the screen...
  LFormCenter := TPointF.Create((Width / 2), (Height / 2));
  LFormCenter := ClientToScreen(LFormCenter);
  //
  A                   := TPointF.Create(LFormCenter.X, LFormCenter.Y - (LineVert.Height / 2));
  A                   := ScreenToClient(A);
  LineVert.Position.X := A.X;
  LineVert.Position.Y := A.Y;
  //
  B                   := TPointF.Create(LFormCenter.X - (LineHorz.Width / 2), LFormCenter.Y);
  B                   := ScreenToClient(B);
  LineHorz.Position.X := B.X;
  LineHorz.Position.Y := B.Y;
  //
  // center found!
  LCrossPos.X := LineVert.Position.X;
  LCrossPos.Y := LineHorz.Position.Y;
  //
  // cursor position
  C := ClientToScreen(TPointF.Create(LCrossPos.X, LCrossPos.Y));
  SetCursorPos(Trunc(C.X), Trunc(C.Y));
  //
  // CalloutPanel on form-center
  LCalloutPanelCenterF.X := CalloutPanel1.Width / 2;
  LCalloutPanelCenterF.X := LineVert.Position.X - LCalloutPanelCenterF.X;
  //
  LCalloutPanelCenterF.Y := CalloutPanel1.Height / 2;
  LCalloutPanelCenterF.Y := LineHorz.Position.Y - LCalloutPanelCenterF.Y;
  //
  CalloutPanel1.Position.X := LCalloutPanelCenterF.X;
  CalloutPanel1.Position.Y := LCalloutPanelCenterF.Y;
  //
  LCalculatingMouseAngle := true;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
var
  LArcTan2            : Double;
  LMousePos           : TPointF;
  LCalloutPanelCenterF: TPointF;
begin
  if LCalculatingMouseAngle then
    begin
      LMousePos := TPointF.Create(X, Y);
      LArcTan2  := ArcTan2(LMousePos.Y - LCrossPos.Y, LMousePos.X - LCrossPos.X);
      //
      if (LArcTan2 < 0) then
        begin
          if (LArcTan2 > -1.5) then
            CalloutPanel1.RotationAngle := 225 // 45
          else
            if (LArcTan2 < -1.5) then
              CalloutPanel1.RotationAngle := 135; // 315;
        end else if (LArcTan2 > 0) then
        begin
          if (LArcTan2 < 1.5) then
            CalloutPanel1.RotationAngle := 315 // 135
          else
            if (LArcTan2 > 1.5) then
              CalloutPanel1.RotationAngle := 45; // 225;
        end;
      //
      LCalloutPanelCenterF.X := CalloutPanel1.Width / 2;
      LCalloutPanelCenterF.X := X - LCalloutPanelCenterF.X;
      //
      LCalloutPanelCenterF.Y := CalloutPanel1.Height / 2;
      LCalloutPanelCenterF.Y := Y - LCalloutPanelCenterF.Y;
      //
      CalloutPanel1.Position.Y := LCalloutPanelCenterF.Y;
      //
      CalloutPanel1.Position.X := LCalloutPanelCenterF.X;
    end;
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  LCalculatingMouseAngle := false;
end;

end.

image.thumb.png.fb10c96ce42253508fac6891da93576e.png

Edited by programmerdelphi2k

Share this post


Link to post

@programmerdelphi2k also do you know how to set the TCalloutpanel visibilaty to true when you click on the earth

im trying to do this 

procedure TForm1.Button22Click(Sender: TObject);
var
Marker : TCalloutPanel;
Coord: TLabel;
MarkerBool: Boolean;
begin
if MarkerBool then begin
  Marker := TCalloutPanel.Create(Self);
  Marker.Width := 209;
  Marker.Height := 41;
  Marker.RotationAngle := 180;
  Marker.Visible := False;
  Marker.Parent := Self;
  Coord := TLabel.Create(Self);
  Coord.Width := 120;
  Coord.Visible := False;
  Coord.Parent := Self;
  Coord.Height:= 17;
  Coord.Text := '00.00000 -00.00000';
end else begin
Earth.OnClick := Marker.Visible:=True; //<--Code Doesnt work keep getting incompatible types TNotiftEvent and procedure untyped pointer or untyped parameter

 

Share this post


Link to post

Normally, the "event" (like OnClick) is type:  procedure(....) OF OBJECT;

Which means it belongs to an instance of an object. That is, it will be defined to the class that instantiates the object.
I don't know what type of object the "Earth" is?
So I'll give an example of the general form of use:

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure MyHello(Sender: TObject);
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TMyEventNofitication = procedure(Sender: TObject) of object;

  TMyClass = class
  private
    FMyEvent: TMyEventNofitication;
  public
    property MyEvent: TMyEventNofitication read FMyEvent write FMyEvent;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  try
    MyClass.MyEvent := MyHello; // MyHello is a "procedure" of a Object/Instance (in case, "Form1") = compatible!
    //
    // MyClass.MyEvent := true; // not compatible, because "true" is a boolean type, not a "procedure of a object"
  finally
    MyClass.Free;
  end;
end;

procedure TForm1.MyHello(Sender: TObject);
begin
  // ...
end;

 

Share this post


Link to post

in your case, you are trying to do this:

Quote

   Earth.CanReceiveClicks := true / false;   ???

//

then use (if "Earth" (classs) is allowed)

   Earth.HitTest := true / false;

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×