Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.10.22;
Скачать: CL | DM;

Вниз

повторяющееся событие MouseWheel   Найти похожие ветки 

 
_Guest_   (2006-09-08 09:31) [0]

На событие MouseWheel повешено масштабирование карты. Выполняется оно не очень быстро. Можно ли каким-либо образом не обрабатывать событие сразу после первого прокручивания колесика на один сегмент, а дождаться, когда пользователь закончит прокрутку и отмасштабировать все за один хлоп? Спасибо.


 
StriderMan ©   (2006-09-08 09:41) [1]

повесь Application.OnMessage, и в нем анализируй, закончилось ли масштабирование рисунка. если нет - просто проглатывай WouseWheel.


 
Сергей М. ©   (2006-09-08 10:15) [2]


> Выполняется оно не очень быстро


Есть резон вынести масштабирование в доп.код.поток.
При этом основной получит возможность оперативно реагировать на события колеса, анализировать частоту их возникновения, расчитывать требуемый масштаб и передавать доп.потоку расчетное значение для очередного пересчета им масштаба.


 
_Guest_   (2006-09-08 15:57) [3]


> Сергей М. ©   (08.09.06 10:15) [2]
> Есть резон вынести масштабирование в доп.код.поток.
> При этом основной получит возможность оперативно реагировать
> на события колеса

Да можно даже и не выносить в дополнительный. Вопрос как узнать в основном что колесико остановилось? Единственное, что приходит в голову - таймер, но это как-то не серьезно.


 
Сергей М. ©   (2006-09-08 16:12) [4]


> как узнать в основном что колесико остановилось? Единственное,
>  что приходит в голову - таймер, но это как-то не серьезно.
>


Оч даже серьезно.

Ибо иного способа нет и быть не может.


 
Loginov Dmitry ©   (2006-09-08 16:37) [5]

Заведи в основном потоке таймер. Запускай его при возникновении события скролла. Останавливай в обработчике OnTimer. Здесь же вызывай код перерисовки.


 
_Guest_   (2006-09-08 16:50) [6]


> Loginov Dmitry ©   (08.09.06 16:37) [5]
>
> Заведи в основном потоке таймер. Запускай его при возникновении
> события скролла. Останавливай в обработчике OnTimer. Здесь
> же вызывай код перерисовки.

Это уже все сделано. Спасибо. Думал еще как-то можно.


 
GrayFace ©   (2006-09-09 12:56) [7]

Можно. Например,

var WheelMove:integer; WheelMoving:boolean;

OnMouseWheel:

inc(WheelMoves, Delta);
if WheelMoving then exit;
WheelMoving:=true;
WheelMoves:= Delta;
try
  Application.ProcessMessages;
finally
  WheelMoving:=false;
end;
if WheelMoves<>0 then ScaleMap(WheelMoves);


 
sniknik ©   (2006-09-09 23:54) [8]

> Думал еще как-то можно.
добавить событие EndWheel... чегото лишнее чегото не хватает... но рабочий, на основе TMemo, думаю понятно будет

1000 это секунда (примерно), надо подобрать, здесь зато времени хватает увидеть.

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TTmtpMemo = class(TMemo)
 private
   FCountPoint: DWORD;
   FThread: THandle;
   FEndWheel: TNotifyEvent;
   procedure WMMouseWheel(var Message: TWMMouseWheel); message WM_MOUSEWHEEL;
 public
   property OnEndWheel: TNotifyEvent read FEndWheel write FEndWheel;
 end;

 TMemo = class(TTmtpMemo);

 TForm1 = class(TForm)
   Memo1: TMemo;
   Label1: TLabel;
   procedure FormCreate(Sender: TObject);
 private
   procedure EndWheel(Sender: TObject);
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

function WaitWheel(Par: TTmtpMemo): Integer;
begin
 result:= 0;

 with Par do begin
   while (GetTickCount() - FCountPoint) < 1000 do
     Sleep(100);

   FThread:= 0;
   FEndWheel(Par);
 end;

 EndThread(0);
end;

procedure TTmtpMemo.WMMouseWheel(var Message: TWMMouseWheel);
begin
 if Assigned(FEndWheel) then begin
   if FThread = 0 then begin
     Form1.Label1.Caption:= "Start";
     FCountPoint:= GetTickCount();
     FThread:= BeginThread(nil, 0, Addr(WaitWheel), Self, 0, FThread);
   end;

   FCountPoint:= GetTickCount();
 end;
 inherited;
end;

procedure TForm1.EndWheel(Sender: TObject);
begin
 Label1.Caption:= "End";
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Memo1.OnEndWheel:= EndWheel;
end;

end.


 
_Guest_   (2006-09-11 10:33) [9]


> sniknik ©   (09.09.06 23:54) [8]
> .. но рабочий,

Вы павы !!!

> думаю понятно будет

А вот тут Вы ошибаетесь, Мастер :)
Я половины слов таких не знаю :) Но как работает !!! - просто песня.
Субъективно производительность на масштабировании на порядок выросла.
Ночами спать не буду, но разберусь, чтоб в следующий раз не отвлекать :) Спасибо!


 
GrayFace ©   (2006-09-12 11:42) [10]

sniknik ©   (09.09.06 23:54) [8]
А TTimer чем не угодил? Он бы был гораздо лучше! И при каждом WM_MOUSEWHEEL можно было бы перевзводить таймер.
В твоем случае код не рабочий, т.к. периодически возможны неожиданные ошибки. Из второго потока надо отправлять сообщение и обрабатывать формой (или вызывать Synchronize в случае TThread).

А лучше всего было бы при рисовании периодически вызывать Application.ProcessMessages и перезапускать процесс рисования, если было прокручено колесико. (рисовать надо на TBitmap, а не на форму). Есть возможность вставить в цикл отрисовки Application.ProcessMessages?


 
GrayFace ©   (2006-09-12 11:45) [11]

Кстати, в этом коде FCountPoint:= GetTickCount(); лучше вытащить из if FThread = 0. Тогда не будет промежуточных отрисовок.


 
sniknik ©   (2006-09-12 13:28) [12]

> А TTimer чем не угодил? Он бы был гораздо лучше!
на вкус на цвет...
я не считаю, что таймер тут лучше. по одной простой причине, это легко оформить в виде законченного компанента, в отличие от с таймером.
и потом, разговора про то, что лучше/хуже не было, был ответ на "как сделать по другому"

> В твоем случае код не рабочий, т.к. периодически возможны неожиданные ошибки.
> Из второго потока надо отправлять сообщение и обрабатывать формой (или вызывать Synchronize в случае TThread).
синхронизация/сообщение это как раз то, про что говорил, что чегото не хватает.
но я и не ставил целью написать "конечный" код, цель была показать принцип, и как можно проще (и даже это показалось сложным > [9]). разберется, будут вопросы, можно перейти и к тому чего не хватает.

кстати, неожиданных ошибок не будет, если не рисовать на этом же компаненте паралельно еще откуда нибудь, (еще поток/таймер), и для гаранти этого делать при начале отрисовки локирование канваса (что кажется обычная практика).

> Кстати, в этом коде FCountPoint:= GetTickCount(); лучше вытащить из if FThread = 0. Тогда не будет промежуточных отрисовок.
оно есть и "вытащенное", а то на что ты обратил внимаение это начальная инициализация (предотвратить первое случайное срабатывание), возможно лишняя/неоптимальная по количеству строк...
можно было бы так (если оптимизировать) вместо
if Assigned(FEndWheel) then begin
  if FThread = 0 then begin
    Form1.Label1.Caption:= "Start";
    FCountPoint:= GetTickCount();
    FThread:= BeginThread(nil, 0, Addr(WaitWheel), Self, 0, FThread);
  end;

  FCountPoint:= GetTickCount();
end;

так
if Assigned(FEndWheel) then begin
  FCountPoint:= GetTickCount();

  if FThread = 0 then begin
    Form1.Label1.Caption:= "Start"; //ну это думаю и так понятно тоже лишнее, просто паказать процесс визуально
    FThread:= BeginThread(nil, 0, Addr(WaitWheel), Self, 0, FThread);
  end;
end;


 
GrayFace ©   (2006-09-12 20:04) [13]

sniknik ©   (12.09.06 13:28) [12]
я не считаю, что таймер тут лучше. по одной простой причине, это легко оформить в виде законченного компанента, в отличие от с таймером.

Почему?

sniknik ©   (12.09.06 13:28) [12]
кстати, неожиданных ошибок не будет, если не рисовать на этом же компаненте паралельно еще откуда нибудь, (еще поток/таймер), и для гаранти этого делать при начале отрисовки локирование канваса (что кажется обычная практика).

Будет.
В потоке: FThread:= 0; и начинается рисование.
В это время крутанули колесо, создается новый поток, который начинает новое рисование.

sniknik ©   (12.09.06 13:28) [12]
оно есть и "вытащенное"

Не заметил :)

P.S. О, оказывается не я один отбиваю := пробелом с 1 стороны. Правда, я это делаю не вседа.


 
sniknik ©   (2006-09-12 20:44) [14]

> Почему?
ну куда ты будеш таймер лепить если нужно все в один компонент уложить (вместо одной простой функции потока), не, можно конечно и в сам компонент но тогда нужно и create перекрывать и destroy, заморочено и неудобно. (сам попробуй сделать проще чем ниже показано, с таймером)

> В это время крутанули колесо, создается новый поток, который начинает новое рисование.
возможно, но я в общемто не отрицаю, что нормально лучше доделать с событием например.
например вот так
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;

const
 WM_RUNEDNWEEL = WM_USER + 111;

type
 TTmtpMemo = class(TMemo)
 private
   FCountPoint: DWORD;
   FThread: THandle;
   FEndWheel: TNotifyEvent;
   procedure WMMouseWheel(var Message: TWMMouseWheel); message WM_MOUSEWHEEL;
   procedure WMRunEndWheel(var Message: TMessage); message WM_RUNEDNWEEL;
 public
   property OnEndWheel: TNotifyEvent read FEndWheel write FEndWheel;
 end;

 TMemo = class(TTmtpMemo);

 TForm1 = class(TForm)
   Memo1: TMemo;
   Label1: TLabel;
   procedure FormCreate(Sender: TObject);
 private
   procedure EndWheel(Sender: TObject);
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

function WaitWheel(Par: TTmtpMemo): Integer;
begin
 result:= 0;

 with Par do begin
   while (GetTickCount() - FCountPoint) < 1000 do
     Sleep(100);

   FThread:= 0;
   PostMessage(Handle, WM_RUNEDNWEEL, 0, 0);
 end;

 EndThread(0);
end;

procedure TTmtpMemo.WMMouseWheel(var Message: TWMMouseWheel);
begin
 if Assigned(FEndWheel) then begin
   FCountPoint:= GetTickCount();

   if FThread = 0 then begin
     Form1.Label1.Caption:= "Start";
     FThread:= BeginThread(nil, 0, Addr(WaitWheel), Self, 0, FThread);
   end;
 end;
 inherited;
end;

procedure TTmtpMemo.WMRunEndWheel(var Message: TMessage);
begin
 FEndWheel(self);
end;

procedure TForm1.EndWheel(Sender: TObject);
begin
 Label1.Caption:= "End";
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Memo1.OnEndWheel:= EndWheel;
end;

end.


но только хотелось бы чтобы это делал уже не я...


 
sniknik ©   (2006-09-12 20:47) [15]

кстати, тогда уж и в  WMRunEndWheel проверку на Assigned(FEndWheel) надо добавить, а то мало ли кто куда какие события шлет...



Страницы: 1 вся ветка

Текущий архив: 2006.10.22;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.041 c
15-1159707086
Real
2006-10-01 16:51
2006.10.22
WebViewFolderIcon - уязвимость то нашли, а что пока с этим делать


15-1159886848
ferr
2006-10-03 18:47
2006.10.22
Визальный редактор графов.


15-1159512544
IMHO
2006-09-29 10:49
2006.10.22
Самый лучший коллектив -


3-1156772682
novill
2006-08-28 17:44
2006.10.22
Кто знает где IBExpert хранит рег. информация по базам?


3-1155732451
BBCHa
2006-08-16 16:47
2006.10.22
Экспорт в Excel