Как уменьшить загрузку процессора при перемещении компонента в событии OnMouseMove в Delphi 7?

StackOverflow https://stackoverflow.com/questions/682451

Вопрос

В приложении Delphi 7 я хочу переместить компонент вслед за мышью.Я делаю что-то вроде этого:

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

Когда я перемещаю мышь, загрузка процессора для основного ядра возрастает до 100% на последнем компьютере.

Есть какая- нибудь идея или галочка, чтобы уменьшить загрузку процессора в этом случае?

Это было полезно?

Решение 3

Наконец-то я изменил свой код для этого:

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;

Действительно прост в реализации (добавлено 2 строки), без таймера, у меня хорошо работает...

Другие советы

Вы могли бы создать TTimer, который опрашивает текущее положение мыши каждые 0,10 секунды или около того, затем позиционирует "AnotherComponent" в соответствии с текущим положением мыши.

Тогда вы не запускали бы свое событие для каждого пикселя движения мыши - вам вообще не понадобилось бы никакого события OnMouseMove в вашем управляющем компоненте.

На моем компьютере это практически никак не влияет на производительность.

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. Это не имеет никакого отношения к самому перемещению мыши.
  2. Если это не то, что вы задумали, вы не соответствуете X, Y с Верхним, Левым.Вверху находится координата Y, а слева - X.
  3. Проблема заключается в фактическом перемещении другого компонента.

Чтобы попытаться понять это, я предлагаю вам написать процедуру TestMove, которая автоматически перемещает ваш AnotherComponent с регулируемым повторением / задержками для мониторинга процессора.
Бьюсь об заклад, это вызывает дорогостоящую перекраску или какие-то другие вычисления с интенсивным использованием процессора.
Поэтому сначала внимательно изучите, есть ли у вас какой-либо обработчик событий в этом компоненте, а затем используйте унаследованное поведение...

Возможно, вместо перемещения самого компонента вы перемещаете "тень" и перемещаете компонент только после того, как пользователь отпустит кнопку мыши.Что-то вроде перетаскивания.

Это не может быть само перемещение, требующее такой большой мощности процессора, скорее всего, перемещение приводит к тому, что компонент каким-то образом перерисовывает себя.Можете ли вы избежать этого AnotherComponent перерисовывается при каждом движении?В этом не должно быть необходимости, если только это не контейнер для фильма.

Все, что связано с событием перемещения мыши, будет вызываться очень часто, поскольку мыши - это устройство ввода с высоким разрешением.Однако я бы не стал беспокоиться об использовании процессора, потому что ваш обработчик запускается как можно быстрее в зависимости от того, насколько загружена система.Другими словами, это только максимальная загрузка процессора, потому что больше ничего нет.

Из MSDN:

Мышь генерирует событие ввода когда пользователь перемещает мышь или нажимает или отпускает кнопку мыши.Система преобразует события ввода с помощью мыши в сообщения и отправляет их в очередь сообщений соответствующего потока.Когда сообщения мыши отправляются быстрее, чем поток может их обработать, система отбрасывает все, кроме самого последнего сообщения мыши.

Теперь из этого могут быть некоторые исключения.Вы могли бы провести некоторое тестирование, чтобы убедиться, запустив какое-нибудь другое интенсивное действие по обработке, и посмотреть, насколько сильно на это влияет перемещение мыши.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top