Question

In a Delphi 7 application, I want to move a component following the mouse. I'm doing something like this:

procedure MyComponent.MouseMove(Sender: TObject;Shift: TShiftState; X, Y: Integer);
begin
  AnotherComponent.Top := X;
  AnotherComponent.Left := Y;
end;

When I move the mouse the CPU usage for the main core goes up to 100% on a recent PC.

Any idea or tick to reduce the CPU usage in this case ?

Was it helpful?

Solution 3

Finally I've change my code for this one:

procedure MyComponent.MouseMove(Sender: TObject;Shift: TShiftState; X, Y: Integer);
begin
  if GetTickCount-LastMoveTick>50 then begin
    AnotherComponent.Top := Y;
    AnotherComponent.Left := X;
    LastMoveTick := GetTickCount;
  end;
end;

Really easy to implement (2 lines added), no timer, works well for me...

OTHER TIPS

You could create a TTimer that polls the current mouse position every 0.10 seconds or so, then positions "AnotherComponent" according to the current mouse position.

Then you wouldn't fire your event for every pixel of mouse movement- you won't need any OnMouseMove event on your controlling component at all.

On my computer, this basically has no performance impact at all.

procedure TForm1.Timer1Timer(Sender: TObject);
var
  pt: TPoint;
begin
  //Is the cursor inside the controlling component?  if so, position some
  //other control based on that mouse position.

  GetCursorPos(pt);
  if MouseWithin(pt.x,pt.y,MyComponent,Form1.Left,Form1.Top) then begin
    //replace with whatever real positioning logic you want
    AnotherComponent.Top := pt.y;
    AnotherComponent.Left := pt.x;
  end;
end;

function TForm1.MouseWithin(mouseX, mouseY: integer;
  const comp: TWinControl; const ParentWindowLeft: integer;
  const ParentWindowTop: integer): boolean;
var
  absoluteCtrlX, absoluteCtrlY: integer;
begin
  //take a control, and the current mouse position.
  //tell me whether the cursor is inside the control.
  //i could infer the parent window left & top by using ParentwindowHandle
  //but I'll just ask the caller to pass them in, instead.

  //get the absolute X & Y positions of the control on the screen
  //needed for easy comparison to mouse position, which will be absolute
  absoluteCtrlX := comp.Left + ParentWindowLeft;
  absoluteCtrlY := comp.Top + ParentWindowTop +
    GetSystemMetrics(SM_CYCAPTION);

  Result := (mouseX >= absoluteCtrlX)
    and (mouseX < absoluteCtrlX + comp.Width)
    and (mouseY >= absoluteCtrlY)
    and (mouseY <= absoluteCtrlY + comp.Height);
end;
  1. It has nothing to do with the Mouse Move itself.
  2. Unless it's what you intended, you are mismatching X, Y with Top, Left. Top is the Y coord and Left the X one.
  3. The problem is the actual moving of AnotherComponent.

To try and understand it, I suggest that you write a TestMove routine that moves your AnotherComponent automatically with adjustable repetition/delays to monitor the CPU.
I bet it triggers a costly repaint or some other CPU intensive calculation.
So Examine closely if you have any event handler on this component first, then go with the inherited behavior...

Maybe, instead of moving the component itself you move a 'shadow' and only move the component once the user lets the mousebutton go. Sort of like drag&drop.

It can't be the move itself that needs so much cpu power, most probably the move causes the component to redraw itself somehow. Can you avoid that AnotherComponent is redrawn on each move? It should not be necessary, unless it is a movie container.

Anything tied to the mouse move event will be called very frequently as mice are a high resolution input device. I wouldn't worry about the cpu usage though because your handler only gets fired as fast as possible based on how busy the system is. In other words, it's only maxing the CPU because nothing else is.

From MSDN:

The mouse generates an input event when the user moves the mouse, or presses or releases a mouse button. The system converts mouse input events into messages and posts them to the appropriate thread's message queue. When mouse messages are posted faster than a thread can process them, the system discards all but the most recent mouse message.

Now there may be some exceptions to this. You could do some testing to be sure by running some other processing intensive activity and see how much the mouse move stuff impacts it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top