Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.10.22;
Скачать: [xml.tar.bz2];

Вниз

повторяющееся событие 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.042 c
1-1157899111
Kolan
2006-09-10 18:38
2006.10.22
Управление свойством Point TChart.


15-1159184655
Samael6
2006-09-25 15:44
2006.10.22
Формат данных Word


2-1160066923
Любитель мп3-шек
2006-10-05 20:48
2006.10.22
Проиграть мп3


15-1159783394
Slider007
2006-10-02 14:03
2006.10.22
С днем рождения ! 30 сенября


2-1159730643
Изучающий_
2006-10-01 23:24
2006.10.22
CloseHandle(hLib) для Kernel32.dll





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский