2009-03-25 3 views
6

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

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

Когда я двигаю мышь использование процессора для основного ядра идет до 100% на современных ПК.

Любая идея или галочка для уменьшения использования ЦП в этом случае?

+0

Не могли бы вы добавить ли компонент и элемент управления под ним - это оконные элементы управления или нет? У них сложный код рисования? – mghie

ответ

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 строки, добавленные), не таймер, работает хорошо для меня ...

+0

Проверьте X и Y там, где Left - X, Top - Y. Если это работает на вас, то хорошо, но кажется неправильным. – mj2008

+0

Исправлено. благодаря ! –

+0

Мне это нравится лучше, чем мое решение :) – JosephStyons

4

Вы можете создать 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; 
0

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

0

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

Из MSDN:

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

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

+0

Голосов без объяснения не так конструктивны, как могли бы быть. Если вы можете определить что-то не так, сообщите нам об этом. Я с радостью сделаю поправку на мой ответ. –

+0

Я не уменьшал вас, однако ваш POV не является многозадачным. Поток GUI будет иметь нормальный приоритет, поэтому он будет полностью голодать от всех потоков с меньшим приоритетом и отнимать циклы из потоков с одинаковым приоритетом. Оптимизация для минимальной загрузки процессора важна, даже если немодно. – mghie

+0

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

3
  1. Это не имеет никакого отношения к Движению мыши.
  2. Если это не так, вы несовместимы с X, Y сверху, слева. Верх - координата Y и слева X.
  3. Проблема заключается в фактическом перемещении AnotherComponent.

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

1

Возможно, вместо того, чтобы перемещать компонент, вы перемещаете «тень» и перемещаете компонент только после того, как пользователь отпустит мышью. Вид, как перетащить & падение.