Как прокручивать Scroll Bar колесиком?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Как прокручивать Scroll Bar колесиком?

Сообщение Gigahard » 16.01.2006 (Пн) 18:00

У меня MDI форма со скролбаром. Нужно добавить возможность прокрутки скролбара колесиком мышки, а в идеале еще и а ля IE с зажатой средней кнопкой. Вопрос как это сделать?

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 16.01.2006 (Пн) 18:23

Стандартными методами - никак. Сабклассить, отлавливая WM_MOUSEWHELL и посылать нужные сообщение родительскому окну.
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 18.01.2006 (Ср) 16:17

Ну вращение колесика я отловил. А вот к чему его превязывать, чтобы сделать прокрутку содержимого MDI формы?
Старый глюк лучше новых двух!

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 18.01.2006 (Ср) 16:22

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

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 18.01.2006 (Ср) 16:27

Ну поэкспериментировать нужно, наверное. Для начала возьми Spy++, посмотри кому какие сообщения приходят при обычном скроллинге. Найди нужные и эмулируй их.
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 18.01.2006 (Ср) 16:43

Да... если бы я еще умел этим инструментом пользоваться
:oops: :roll:
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 18.01.2006 (Ср) 16:56

Дык... Учиться, учиться и еще раз учиться. Тем более, что тулза весьма и весьма полезная ;)
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 18.01.2006 (Ср) 17:36

Ну если поможете сообразить что к чему... :) В общем запускаю я этот Spy++, ставлю отслеживание сообщенией, в групах сообщений ставлю отслеживание scrollBar'a. Запускаю. При скроле показывается, что в скроллбару шлется nScrollCode:SB_THUMBTRACK nPos:1 (это видимо и есть положение прокрутки скроллбара) hwndscrollbar:(null).
Почему hwnd у этого скроллбара нулевой, не понятно. Хотя возможно потому, что он встроен в MDIформу. Но вообще что теперь со всей этой веселухой делать? 8)
Теперь я так понимаю, нужно сделать операцию обратную хуку, т.е. не отследить событие, а сэмулировать его выполнение. Вопрос как это сделать?

Вся гдость заключается, в том, что этот самый скролл бар сидит в части Mdi формы под названием MDIClient и достучатся до нее проблематично.
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 18.01.2006 (Ср) 17:55

Ладно, в общем так.
Для начала при запуске приложение тебе нужно определить хендл MDIChild основного окна. Потом при прокручивании колесика (ты ж уже научился его ловить?) посылаеш вот этому чайлду сообщения WM_VSCROLL с нужными параметрами. Объявляеш вот это у себя:

Код: Выделить всё
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_HSCROLL = &H114
Private Const WM_VSCROLL = &H115
Private Const SB_LINEDOWN = 1
Private Const SB_LINEUP = 0

Dim hWndClient As Long


MDIChild находится так:

Код: Выделить всё
hWndClient = FindWindowEx(Me.hwnd, 0, "MDIClient", "")


При прокручивании вверх:

Код: Выделить всё
SendMessage hWndClient, WM_VSCROLL, SB_LINEUP, 0


Вниз:

Код: Выделить всё
SendMessage hWndClient, WM_VSCROLL, SB_LINEDOWN, 0


Вроде так. Там еще нужно определять нужно ли прокручивать вообще. То есть, вылезло что-то за пределы окна. Ну это уже совсем другая тема ;)
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 10:52

Круто! Спасибо :) А я думал, как же ентот MDIClient найти :) Буду пробовать :)
Старый глюк лучше новых двух!

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 11:19

Проверку на то, что вылезло ли что из окна, делать не надо. Это делается автоматически. Т.к. когда нет скролл бара, то нет и прокрутки. А вот условие на сролл если мышка за пределами формы нужно сделать :).
В общем спасибо огромное! Все заработало. Приложению добавилось функциональности!
-----
Проверку на вылезание из окна все же надо делать :)
Старый глюк лучше новых двух!

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 11:49

Проверку, вылезает содержимое за пределы окна или нет, можно в принципе двумя способами сделать. Или смотреть свойство visible элемента scrollbar, либо смотреть высоту окна MdiClient и сравнивать ее со scaleHeight родительской MDI формы. Каким способом лучше пойти и как достучаться до свойств MDIClient или ScrollBar?
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 19.01.2006 (Чт) 13:26

Не, не в ту сторону смотриш... В общем подскажу - копай в сторону стилей окна. Стиль узнается с помощью GetWindowLong с параметром GWL_STYLE. Ну а в стиле тебя должно интересовать наличие/отсутствие полос прокрутки. Это соответственно в стиле WS_HSCROLL и WS_VSCROLL.
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 14:55

Да с размерами MDIClient действительно не вышло. Они оказались привязаны к высоте самой MDI формы и напрямую зависят от нее. Разобрался, что кроме сообщения SB_LINEDOWN и SB_LINEUP, желательно еще отправлять SB_ENDSCROLL. Сейчас буду разбиратся со стилями.

З.Ы. Запрограмировать скролл оказалось сложней, чем написать основной код программы :)
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 19.01.2006 (Чт) 15:02

Ну бывает :) Да, забыл сказать - стили нужно узнавать тоже MDIClient, есстественно...
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 16:32

Так. Появление отстутствие скролла отслеживаю... Посмотрим что дальше можно сделать :)
Получилось! Все работает!:) Это по истине надо в кирпичи добавить :)
Спасибо за помощь камрады! :D
Старый глюк лучше новых двух!

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 17:34

Да... Самое последнее... Тут такая вещь... Собственно содержимое MDI теперь колесиком скролится даже когда курсор вне пределов самой формы. Я так понимаю, что чтобы это исправить, нужно отследить положение курсора. Попробовал добавить к хуку WM_MOUSELEAVE, но оно почему то не срабатывает... А вот WM_MOUSEMOVE работает. В общем теперь осталось заставить работать WM_MOUSELEAVE и привязать к этому делу запрет скролла. Как победить WM_MOUSELEAVE? :oops:
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 19.01.2006 (Чт) 17:46

Добавь-добавь. Тут скорее интересно не прокручивание MDI, так как это весьма специфичная задача, а работа с колесом ;) Думаю, будет полезно многим.
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 17:48

Все. Разобрался :) Работает WM_NCMOUSELEAVE.
Старый глюк лучше новых двух!

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 19.01.2006 (Чт) 17:51

Ну работа с колесом, это не так сложно отследить. Вот привязывать это к сроллбару MDI, было действительно интересно. Спасибо тебе Odrick за неоценимую помощь. Узнал много нового и полезного.
Старый глюк лучше новых двух!

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 20.01.2006 (Пт) 12:04

Да... Все же с отслеживанием положения мыши на MDI форме проблемы. Из за ее неоднородности не удается обработать события WM_MOUSEMOVE и WM_MOUSELEAVE. Если ставить хук на саму MDI форму, то эти события вообще ей не воспринимаются. Т.к. рабочим полем является MDIClient. Ставлю хук на MDIClient, все работает, но только пока мышь находится непосредственно над областью MDIClient. Почему то ни MDIForm, ни MDIClient не ведут себя в этом плане как контейнеры. Теперь наипоследний вопрос который поможет довести задуманное до конца, это как же все таки отследить присутствие/отсутствие курсора на MDI форме.
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 20.01.2006 (Пт) 13:07

Э-э-э... Вопрос не совсем понятен. Тебе что нужно, определить в некий момент времени, находится ли курсор над MDI-формой, или обрабатывать события захода/ухода мыши на саму форму?
То, что для одних константа, для других только переменная...

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 20.01.2006 (Пт) 14:40

Ну это же практически одно и то же... Если курсор ушел из формы, то значит он не на форме, тогда нужно запретить скролл, грубо говоря поставить некий флаг в False. А если курсор вернулся в форму, то тогда скролл разрешить, поставить флаг в True. Это конечно не принципиально, но хотелось бы все по красивому сделать.
Старый глюк лучше новых двух!

Gigahard
Бывалый
Бывалый
 
Сообщения: 253
Зарегистрирован: 24.07.2002 (Ср) 11:15
Откуда: Russia

Сообщение Gigahard » 20.01.2006 (Пт) 15:07

Возникла идея! Отслеживать координаты формы с помощью getWindowRect и сравнивать с позицией курсора getCursorPos. Сейчас буду испытывать.

Заработало!!! :) Все. Сделал :)
Старый глюк лучше новых двух!

Odrick
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 503
Зарегистрирован: 28.09.2003 (Вс) 2:04

Сообщение Odrick » 20.01.2006 (Пт) 16:09

Та вот в том-то все и дело, что не одно и то же. Определить, находится ли курсор внутри какого-нить окна довольно просто. Да ты и сам уже это понял. А вот ловить событие ухода курсора за пределы формы немного посложнее будет ;)
То, что для одних константа, для других только переменная...


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

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

Сейчас этот форум просматривают: AhrefsBot, SemrushBot и гости: 187

    TopList