Doevents своими руками

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Doevents своими руками

Сообщение arthur2 » 16.04.2010 (Пт) 19:15

Собственно, вопрос к Хакеру:

Хакер писал(а):
есть ли альтернатива DoEvents?

PeekMessage->TranslateMessage->DispatchMessage
<...>
DoEvents делает то же самое в числе прочего.

Хакер писал(а):GetMessage->(TranslateMessage)->DispatchMessage
<...>
DoEvents делает то, что я написал + кучу лишнего.

Так как всё-таки правильней: PeekMessage или GetMessage?
Последний раз редактировалось arthur2 16.04.2010 (Пт) 22:06, всего редактировалось 1 раз.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents

Сообщение Хакер » 16.04.2010 (Пт) 19:22

Смотря какая цель.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents

Сообщение arthur2 » 16.04.2010 (Пт) 19:27

Я имею ввиду, как это происходит внутри Doevents? И чего ещё там есть в "куче лишнего" и "числе прочего" - тоже интересно :D
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents

Сообщение Хакер » 16.04.2010 (Пт) 19:30

Логически, пик, хотя можно сделать и через гет.


В числе прочего всякие COM/RPC-штуки. Ну и Sleep, конечно же.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents

Сообщение arthur2 » 16.04.2010 (Пт) 19:48

Поискал разницу :)
Через гет не получается - такой дуеэвентс остановит программу, если ничто не происходит. Так что, наверно, всё-таки пик :)

Кстати, а почему цикл с дуеветсом грузит систему на 100%, а с дуэвентсем + слипом - не грузит, если слип уже есть в дуэвентсе?

всякие COM-штуки
какие, интересно?
RPC - Remote Procedure Call. Удалённый вызов процедур — класс технологий, позволяющих компьютерным программам вызывать функции или процедуры в другом адресном пространстве
А это ещё там зачем?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents

Сообщение Хакер » 16.04.2010 (Пт) 20:04

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

Пока не придёт сообщение. Кто тебе сказал, что оно не придёт? :)

какие, интересно?

Уже не помню.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents

Сообщение arthur2 » 16.04.2010 (Пт) 20:42

Хакер писал(а):Пока не придёт сообщение. Кто тебе сказал, что оно не придёт?

Сам попробовал. Если ничего не двигать и не нажимать, то с гетом код замрёт, а с пиком - естественно - нет, как и с дуэвентсем.

arthur2 писал(а):Кстати, а почему цикл с дуеветсом грузит систему на 100%, а с дуэвентсем + слипом - не грузит, если слип уже есть в дуэвентсе?


И ещё - на сколько я понимаю, дуевентс даёт обработаться ВСЕМ сообщениям, успевшим накопиться в очереди. Значит, пик тоже нужно прогнать в цикле, пока в очереди есть сообщения (если есть)? Так?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents

Сообщение Хакер » 16.04.2010 (Пт) 21:21

arthur2 писал(а):
Хакер писал(а):Пока не придёт сообщение. Кто тебе сказал, что оно не придёт?

Сам попробовал. Если ничего не двигать и не нажимать, то с гетом код замрёт, а с пиком - естественно - нет, как и с дуэвентсем.

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

Ну ладно, раскрою: можно запустить таймер, который сработает через 100 мс и пришёл сообщение и вызвать GetMessage.

И ещё - на сколько я понимаю, дуевентс даёт обработаться ВСЕМ сообщениям, успевшим накопиться в очереди.

Не знаю, всем ли. Наверное всем.

Значит, пик тоже нужно прогнать в цикле, пока в очереди есть сообщения (если есть)? Так?

Кому нужно? Когда и где нужно? Мне, вот, сейчас — так вообще не нужно.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents

Сообщение arthur2 » 16.04.2010 (Пт) 21:49

Хакер писал(а):Кому нужно?
Нужно, чтобы сделать свой дуэвентс :)

Про гет и таймер как постовщик сообщений я тоже думал (пока не наткнулся на вариант с пиком - так что нужды в гете теперь, вроде, нет)

Пытаюсь сделать так:
Код: Выделить всё
For i = 0 To 1000000
Caption = i
myDoEvents
Next i
Код: Выделить всё
Sub myDoEvents()
    Static MSG As MSG
    PeekMessage MSG, 0&, 0&, 0&, PM_NOREMOVE
    TranslateMessage MSG
    DispatchMessage MSG
End Sub

Заголовок обновляется, но так, как в моём дуэвентсе обрабатывается всего одно сообщение, больше ничего не происходит - и окно не перерисовывается и мышкой его подвинуть не получается
Пробую так:
Код: Выделить всё
Sub myDoEvents()
  Static MSG As MSG
  Do While PeekMessage(MSG, 0&, 0&, 0&, PM_NOREMOVE)
    TranslateMessage MSG
    DispatchMessage MSG
  Loop
End Sub

Получается совсем плохо: паузы в пиках не возникает, видимо, потому что обработка одних сообщений порождает новые.

Решить, на сколько я понимаю, можно так: узнать, сколько сообщений накопилось в очереди, и дать обработаться только им, а вновь поступающие проигнорировать. Вопрос - как?
Артур
 
   

0xy
Бывалый
Бывалый
 
Сообщения: 223
Зарегистрирован: 14.06.2006 (Ср) 2:34

Re: Doevents своими руками

Сообщение 0xy » 16.04.2010 (Пт) 22:35

A чем не устраивает msvbvm60.rtcDoEvents?

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 16.04.2010 (Пт) 22:45

Тем, что так я сам смогу решать, какие эвентс будут ду, а какие не будут ду :)
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 16.04.2010 (Пт) 23:11

PM_NOREMOVE то зачем?

Вариант с циклом верный, проблему искать нужно где-то ещё.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 17.04.2010 (Сб) 19:37

Хакер писал(а):PM_NOREMOVE то зачем?
я просто недопонял механизм этоих флагов, нужно было как раз PM_REMOVE :oops:

Всё заработало! Спасибо огромное :D

Код: Выделить всё
Sub myDoEvents()

  Dim MSG As MSG
  Do While PeekMessage(MSG, 0&, 0&, 0&, PM_REMOVE)
    TranslateMessage MSG
    DispatchMessage MSG
  Loop
 
End Sub



А что бы ты посоветовал, чтобы не загружать циклом систему на сто процентов? Вставить-таки в мой дуэевентс sleep 1 ? Или может есть способ покрасивей?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 17.04.2010 (Сб) 19:43

Ты, вероятно, собираешь вызывать DoEvents в каком-то цикле?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 17.04.2010 (Сб) 20:46

Мне просто нужен был дуэвентс, который бы не позволял обрабатываться клавишам и мыши, но позволял отрисовываться окнам. Это у меня теперь уже есть.

Ещё мне нужен свой слип, но, опять же, без заморозки отрисовок. Так что хотел сделать как раз через цикл.

Пока такая мысль:
Код: Выделить всё
Sub mySleep(ByVal dwMillisecond As Long)
    Dim idTm As Long, MSG As MSG, start As Long
    Dim endInterval As Long
   
    endInterval = GetTickCount + dwMillisecond 'когда закончить интервал
    idTm = SetTimer(fm.hWnd, 1&, dwMillisecond, 0&) 'генерируем событие на случай, если оно не произойдёт само
    Do
      GetMessage MSG, 0&, 0&, 0& 'получаем все сообщения, если они есть (по истечении интервала событие будет от таймера, на случай, если других не произошло)
      'тут ещё нужны условия, какие из сообщений проигнорировать
      TranslateMessage MSG
      DispatchMessage MSG
   
      If MSG.Time >= endInterval Then Exit Do
    Loop
   
    KillTimer fm.hWnd, idTm
End Sub

Пойдёт?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 17.04.2010 (Сб) 21:11

В чём смысл обрабатывать отрисовку, но не обрабатывать ввод?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 18.04.2010 (Вс) 5:25

Хакер писал(а):В чём смысл обрабатывать отрисовку, но не обрабатывать ввод?
Иногда - надо. Ну, например, чтобы визуально показать, что пару секунд ввод невозможен :) Или вот: viewtopic.php?p=6726243#p6726243

Ты скажи: код mySleep - пойдёт? Есть там грабли?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 18.04.2010 (Вс) 10:08

От лукавого всё это.

Если не нужно принимать ввод, надо трогать свойство Enabled, а не фильтровать сообщения.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: Doevents своими руками

Сообщение Денис » 19.04.2010 (Пн) 8:28

Хакер писал(а):надо трогать свойство Enabled, а не фильтровать сообщения.


[offtop]Падажжи! "Свой" Enabled у него - следующим пунктом идет в его грандиозном плане.[/offtop] :lol:
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 19.04.2010 (Пн) 13:27

Хакер писал(а):Если не нужно принимать ввод, надо трогать свойство Enabled, а не фильтровать сообщения.


Ну что ты, честное слово :) Случаи бывают разные. Если ввод перекрыть на пару минут - тогда да (всегда, кстати, так и делаю), а вот если просто на пару секунд...

Допустим, юзер набирает текст по образцу - бац, ошибка, юзер слышит бряньк, видит, как сгорает один бонус (мультиком) и его отбрасывает на начало слова - всё это он должен внятно разглядеть, и в этот момент не должны ловится удары по клавишам, которые наверняка будут по инерции тарабанить дальше. Раньше я делал это громоздкой системой флагов, теперь - просто своим новым дуэвентом.

И ещё раз на бис: Что ты скажешь за мою неблокирующую mySleep?

Денис писал(а):[offtop]Падажжи! "Свой" Enabled у него - следующим пунктом идет в его грандиозном плане.[/offtop]
Ага, а третьим пунктом - захват почты и телеграфа и мир во всём мире.
Артур
 
   

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: Doevents своими руками

Сообщение Денис » 19.04.2010 (Пн) 13:42

arthur2 писал(а):
Денис писал(а):[offtop]Падажжи! "Свой" Enabled у него - следующим пунктом идет в его грандиозном плане.[/offtop]
Ага, а третьим пунктом - захват почты и телеграфа и мир во всём мире.


На самом деле, я неспроста эту фразу написал. Мне припомнилось, что ранее кто-то спрашивал на форуме, как изменить имя класса для формы VB, ему ответили, что невозможно такое, да и ни к чему, при этом показали, как создать в VB на API полностью свое окно, со своим именем класса (отображаемым в диспетчерах задач всевозможных). Такое окно было бы полностью управляемо только на одних оконных сообщениях. Вот это окно я и имел ввиду.

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

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 19.04.2010 (Пн) 18:28

Идея с фильтрацией всё равно плоха. Делай нормально.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 19.04.2010 (Пн) 20:31

Ты сам предложил заменить дуэвентс на последовательность PeekMessage->DispatchMessage. В чём смысл такой замены, если не использовать те дополнительные возможности, которые она даёт? Только в том, что такой самодельный дуэвентс - быстрее?
Хакер писал(а):Например, при использовании DoEvents может «схаваться» какое-нибудь ненужное событие, например клик по кнопке, и неизвестно, к чем может это привести.
А может ему нужно нажимать на кнопки.
И что? Разве предложенный мною вариант не даёт ему выбор? Разве предложенный тобою — даёт?

И всё-таки - четвёртый раз: каков на предмет наличия граблей этот код: viewtopic.php?p=6740624#p6740624
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 19.04.2010 (Пн) 20:44

Cмысл таков, что у меня в одном проекте DoEvents вешал код на 5 секунд, и этот висяк был явно в COM/RPC-части DoEvents-а.

DoEvents делал то, что мне не требовалось. Делал лишние действия. Это нарушало принцип лени.

В mySleep много граблей.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 19.04.2010 (Пн) 22:08

Хакер писал(а):В mySleep много граблей.
Ну же???
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 19.04.2010 (Пн) 23:08

Предполагалось, что ты напряжёшь мозги и сам проанализируешь. А я уж поправлю. Не-а?

З.Ы. Ты ЛС вообще читаешь?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 19.04.2010 (Пн) 23:32

Так ты скажи, идея-то хоть верная?

Ну, я вижу только одну граблю - в момент, когда обнуляется системное время.

А установку таймера, кстати, вообще переделал на отправку в никуда: idTm = SetTimer(0&, 0&, dwMillisecond, 0&)Всё равно сообщение отправляется и гетом отлавливается :)

Хакер писал(а):DoEvents делал то, что мне не требовалось. Делал лишние действия.

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

З.Ы. Пропустил :) Сейчас отпишусь
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 19.04.2010 (Пн) 23:58

«Идея-то хоть» как раз неверная. Совсем.

Смысл в своём ML — затормозить выполнение кода, заблокировать его внутри нужной процедуры пока не произойдёт что-то. Заблокировать UI — совсем другая опера, и решается не своим ML, а Disable-ингом.


Ну, я вижу только одну граблю - в момент, когда обнуляется системное время.

Вот такой грабли как раз нет. Чтобы понять это, попытайся объяснить мне природу проблем при обнулении счётчика тиков.

Есть другая проблема со временем: если на момент вызова функции счётчик тиков будет иметь значение из промежутка от (0x7fffffff - SpecifiedDelay; 0x7fffffff], то тебя ждёт Overflow со стороны VB. Если бы это был код на С/С++, произошло бы переполнение, которые не нарушило бы арифметику. Решения: кривое — отключить в настройках оптимизации проверку переполнений, правильное — складывать не VB-шным оператором сложения, а чем-то внешним, например функцией InterlockedExchangeAdd.

Даже если ты сделаешь такую замену, от оператора >= тоже придётся избавиться, ибо он сразу же выкинет тебя из цикла, хотя время ещё не настало.

Другие бывшие грабли: указание идентификатора таймера. При указании идентификатора, если таймер с таким идентификатором уже был, произойдёт замена, вместо добавления. С учётом того, что функция mySleep может быть вызвана из самой себя, это плохо.

Другие бывшие стилевые грабли: использование глобальной переменной со ссылкой на экземпляр формы.

Принципиальные грабли: при обработке какого-то сообщения обработчик породит свой ML, который случайно обработает твоё таймерное событие. Тогда тебе придётся ждать нового таймерного события, но и его может кто-нибудь съесть.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Doevents своими руками

Сообщение arthur2 » 20.04.2010 (Вт) 0:55

Хакер писал(а):Смысл в своём ML — затормозить выполнение кода, заблокировать его внутри нужной процедуры пока не произойдёт что-то. Заблокировать UI — совсем другая опера, и решается не своим ML, а Disable-ингом.
Переведи :) Хотя бы аббревиатуры. А то я даже не очень понял, о чём речь :oops:

В остальном - вот проба устранить те грабли, которые понял:
Код: Выделить всё
Sub mySleep(ByVal dwMillisecond As Long)
    Dim idTm As Long, MSG As MSG
    Dim endInterval As Long
    On Error GoTo errH
    endInterval = GetTickCount + dwMillisecond
    On Error GoTo 0
   
'   idTm = SetTimer(0&, 0&, dwMillisecond, AddressOf TimerProc)
    idTm = SetTimer(0&, 0&, dwMillisecond, 0&)
   
    Do
      GetMessage MSG, 0&, 0&, 0&
      TranslateMessage MSG
      DispatchMessage MSG
      If MSG.Time < 0 Then If endInterval >= 0 Then Exit Do
      If MSG.Time >= endInterval Then Exit Do
    Loop
   
    KillTimer 0&, idTm
Exit Sub
errH:
   If Err.Number = 6 Then 'переполнение
     endInterval = &H80000000 + dwMillisecond - (&H7FFFFFFF - GetTickCount)
   End If
   Resume Next
End Sub
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Doevents своими руками

Сообщение Хакер » 20.04.2010 (Вт) 1:09

ML — message-loop.
UI — user inteface.
Код оценю завтра.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот, Yandex-бот и гости: 53

    TopList