Форум: "Основная";
Текущий архив: 2002.09.16;
Скачать: [xml.tar.bz2];
ВнизСхема передачи сообщений в VCL компоненте Найти похожие ветки
← →
Dmk (2002-08-24 12:50) [0]Желательно визуальную диаграмму. Адрес подскажите плз.
Можно на примере TForm. Книжек никаких нет.
← →
Юрий Зотов (2002-08-24 16:56) [1]> книжек никаких нет.
Тогда я тоже не берусь отвечать на этот вопрос. Просто у меня нет столько времени. Обещайте подумать, ладно?
← →
Dmk (2002-08-24 21:41) [2]Я имел ввиду, что у меня нет книг с желаемой диаграммой. Литературы у меня для изучения хватает, а чтению я отдаю предпочтение. Просто я неправильно задал вопрос.
Как работает компонент я понимаю, и как сообщения передаются тоже. Мне кажется, что я где-то, что-то мог пропустить. Проблема возникает только под Win2k server.
Если вы готовы общаться и не кипятитесь по поводу книг, я могу описать эту проблему.
Я прекрасно понимаю ваше негодование и занятость, но мне казалось:
1. Что кто-то уже составлял такие диаграммы.
2. Он намного опытнее меня.
3. Я допустил ошибку в коде.
4. Хотел проверить себя по искомой схеме.
Я чувствую себя виноватым за поставленный вопрос, но надеюсь кто-нибудь подскажет мне адрес.
← →
Dmk (2002-08-24 21:41) [3]... или книгу.
← →
Dmk (2002-08-24 21:52) [4]В дополнение к сказанному.
Я уже два месяца тщетно бьюсь над этой проблемой.
← →
Юрий Зотов (2002-08-25 04:18) [5]Давайте попробуем, может и получится. В чем проблема?
← →
Dmk (2002-08-25 13:41) [6]Управление прорисовкой клиентской части окна я передаю своим процедурам. Перекрыты WM_PAINT, WM_ERASEBKGND, WM_MouseMove. т.е. именно по этим сообщениям родитель не получает сообщения.
Проблема именно в WM_MouseMove.
За курсором мыши в ней происходит прорисовка клиентской части формы. Вроде прокрутки Изображения. Вроде все нормально. Ошибок в движении быть не может. Перепроверил раз 10.
Procedure TDrawForm.WMMouseMove(var m: TWMMouseMove);
begin
if LB_Down then
begin
mMovePosX := m.XPos;
mMovePosY := m.YPos;
ofsMouseX := (mDownPosX - mMovePosX);
ofsMouseY := (mDownPosY - mMovePosY);
If (ofsMouseX <> 0) or (ofsMouseY <> 0) then
begin
sPosX := sPosX + ofsMouseX;
sPosY := sPosY + ofsMouseY;
ClipImagePos(sPosX, sPosY);
HorzScrollBar.Position := sPosX;
VertScrollBar.Position := sPosY;
vpDraw(sPosX,sPosY,dtRegionRepaint);
mDownPosX := MouseX;
mDownPosY := MouseY;
end;
end;
end;
В функции прорисовки vpDraw ничего особенного. Простая BitBlt.
Вроде схема проста. Движение мыши - сдвиг изображения.
Но под Win2k server происходит вот что. Сдвигаем изображение
на 20 пикселов вправо и вниз (это к примеру). Курсор мыши вроде резко переместился на заданное положение. Должен быть один сдвиг и одно изменение координат. Но под вышеуказанной системой эта процедура может получить от 1 до 20 сообщений за сдвиг. Происходит медленное перемещение изображения по всем полученным координатам. Даже если отпустить кнопку мыши во время движения.
При разборе класса TForm и всех его предшественников синхронизации со временем я не обнаружил.
Вот такой прикол. Странно, что под win2k Prof такого не происходит. Скорее всего распределение сообщений под server происходит чаще чем в других. А може очередь при выборке из нее сообщения данного типа (WM_MouseMove) не очищается от остальных. Кстати в некоторых программах верстки (QuarkXPress, PageMaker) происходит тот же самый эффект на той же системе.
Вроде все описал. Благодарен за внимание.
← →
Игорь Шевченко (2002-08-26 11:21) [7]А зачем рисовать в событии MouseMove ? Может, вместо vpDraw просто сказать invalidateRect (или InvalidateRgn) ???
← →
Dmk (2002-08-26 22:38) [8]vpDraw рисует на внутреннем контексте формы. Там где все контролы рисуются при прокрутке. Просто скроллинг TForm я отключил. У меня свой InvalidateRect, т.к. вся прорисовка формы и ее содержимого реализуется собственными процедурами.
← →
Юрий Зотов (2002-08-26 23:23) [9]Да, ситуация непонятная. Попытался в MSDN найти какие-то особенности 2k server, и, конечно, не нашел. А в VCL синхронизации со временем нет, там "поступило - выбрали - обработали".
Но вот что пришло в голову. Функция GetQueueStatus позволяет выяснить, есть ли в очереди потока сообщения WM_MOUSEMOVE. Не сделать ли что-то в таком духе: при получении WM_MOUSEMOVE сначала проверить очередь, а потом уже обрабатывать - но только в том случае, если таких сообщений в очереди нет.
Таким образом, программа сможет реагировать лишь на последнее из серии WM_MOUSEMOVE, исключая промежуточные перерисовки. Не очень ясно, конечно, что считать "серией" (возможно, алгоритм принятия решения "обрабатывать или нет" придется усложнить), но попробовать, IMHO, стоит.
← →
Dmk (2002-08-27 01:34) [10]Спасибо Юрий. Действительно как я и ожидал очередь не полностью очищается от сообщений MouseMove. При начале движения возникает от 1 до 3 лишних сообщений даже под w2k prof. Просто при высокой скорости прорисовки лишние 1-3 BitBlt не так заметны как например 20. С помощью GetQueueStatus удается отсечь лишние. Завтра попробую на работе на Server"e.
Придется наверно еще и дома поставить. О результатах (если интересуют) обязательно сообщу.
← →
Dmk (2002-08-27 01:38) [11]Складывается впечатление, что под w2k server идет более интенсивный поток сообщений :|
Хотя может я что-нибудь и недопонял.
← →
Dmk (2002-08-28 00:05) [12]Ну и прикол! Ничего не понимаю. Поставил дома Server - все в порядке. Что за дребедень?!?
← →
Юрий Зотов (2002-08-28 00:17) [13]А нет ли различий в установках флажка "показывать окно при перетаскивании"? Может, при установке/снятии этого флажка механизм посылки/прохождения сообщений как-то меняется?
← →
Dmk (2002-08-28 03:17) [14]От этого флажка прорисовка никак не зависит.
Нашел еще одну "утечку" Messages.
-> HorzScrollBar.Position := sPosX;
После передачи Bar"у значения управление передается в WndProc и обратно в мой обработчик WM_MOUSEMOVE. Мне кажется, что если сообщение еще не стерто из переменной MESSAGE, то после этого происходит рекурсионный вызов WM_MOUSEMOVE обработчика до появления в очереди новых MOUSE сообщений. При этом переменные
mDownPosX := MouseX;
mDownPosY := MouseY;
стоящие после изменения позиции скролл-баров не получают новые значения координат мыши(они записываются в переменные класса при входе в процедуру)! Отсчет движения идет от старых. Поэтому наверно и получается эффект тянущегося хвоста изображений. Но происходить это может только в случае быстрого процессора!
На работе P4-2.0 GHz + 1Gb RIMM RAM, а дома PIII550 384DIMM RAM.
УФФ...!!! Надеюсь моя догадка верна хотябы на 51%
Завтра буду пробовать.
← →
Dmk (2002-08-28 03:24) [15]Извиняюсь за "рекурсионный". Следует читать "рекурсивный".
← →
Dmk (2002-09-02 23:13) [16]УРАААААААААААА! Нашел ГЛЮЧАРУ.
VCL недоделка. Не все на VCL сделать можно. :(
Все из-за передачи управления в WindProc. Как я и описывал выше.
Если напрямую к WinApi обращаться (SetScrollPos), то все в порядке!
Спасибо Юрию Зотову за поддержку.
:)
← →
Dmk (2002-09-02 23:15) [17]И Игорю Шевченко thx :) (навел на мысль новую)
← →
Dmk (2002-09-03 22:05) [18]Кстати !!!!!!!!!!!!!! Вниманию Юрия Зотова!
Я нашел в TControlScrollBar синхронизацию со временем!!!!!!!!!
Именно из за нее и был этот глюк. Переписал без синхронизации, все стало нормально.
Работа со временем тут -> procedure TControlScrollBar.ScrollMessage(var Msg: TWMScroll);
← →
passing_walker (2002-09-04 06:23) [19]Спасибо Dmk за освещение интересной проблемы. Пока не сталкивался, но вдруг придется.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.09.16;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.008 c