Search code examples
delphiwinapicursorcursor-position

SetCursorPos malfunctions?


I wanted to write a procedure in delphi to simulate a moving mouse pointer with a specific speed (similar to the AutoIT MouseMove function). Either my code is wrong or SetCursorPos malfunctions after it gets called too many times. Here is the function I have:

procedure MoveMouse ( X, Y, Speed : Integer);
var
  P     : TPoint;
  NewX  : Integer;
  NewY  : Integer;
begin
  if X < 0 then exit;
  if Y < 0 then exit;
  if X > Screen.Height then exit;
  if Y > Screen.Width then Exit;
  repeat
    GetCursorPos(P);
    NewX := P.X;
    NewY := P.Y;
    if P.X <> X then begin
      if P.X > X then begin
        NewX := P.X - 1;
      end else begin
        NewX := P.X + 1;
      end;
    end;
    if P.Y <> Y then begin
      if P.Y > Y then begin
        NewY := P.Y - 1;
      end else begin
        NewY := P.Y + 1;
      end;
    end;
    sleep (Speed);
    SetCursorPos(NewX, NewY);
  until (P.X = X) and (P.Y = Y);
end;

I use it like this:

procedure TForm1.btn1Click(Sender: TObject);
var
  X : Integer;
  Y : Integer;
begin
  for X := 0 to Screen.Width do begin
    for Y := 0 to Screen.Height do begin
      MouseClick (X, Y, 1);
    end;
  end;
end;

For some reason the mousepointer gets stuck at a certain X point and then jumps back to 0,0 but why is that?


Solution

  • You code is stuck , because in the repeat loop, the condition

    until (P.X = X) and (P.Y = Y);
    

    is never satisfied when you pass the values X=0 and Y=Screen.Height, so you must modify your loop to pass only valid screen coordinates values

      for X := 0 to Screen.Width-1 do
        for Y := 0 to Screen.Height-1 do
          MoveMouse (X, Y, 1); 
    

    Also you can improve your method checking the result of the GetCursorPos and SetCursorPos functions.

    procedure MoveMouse ( X, Y, Speed : Word);
    var
      P     : TPoint;
      NewX  : Integer;
      NewY  : Integer;
    begin
      if X > Screen.Width-1  then Exit;
      if Y > Screen.Height-1 then Exit;
      repeat
        if not GetCursorPos(P) then RaiseLastOSError;
        NewX := P.X;
        NewY := P.Y;
        if P.X <> X then
        begin
          if P.X > X then
            NewX := P.X - 1
          else
            NewX := P.X + 1;
        end;
    
        if P.Y <> Y then
        begin
          if P.Y > Y then
            NewY := P.Y - 1
          else
            NewY := P.Y + 1
        end;
        Sleep (Speed);
        if not SetCursorPos(NewX, NewY) then RaiseLastOSError;
      until (P.X = X) and (P.Y = Y);
    end;