Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft Access Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Цитата из статьи:

Можно инициировать событие Scroll, выпустив метод Scroll для формы, кадра или страницы. Пользователи могут генерировать события Scroll, перемещая ползунок.

Ссылка на эту статью:
[url=]https://msdn.microsoft.com/ru-ru/library/office/gg251461.aspx[/url]

Вопрос как инициировать событие Scroll?
3 сен 17, 21:35    [20768463]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
guest_rusimport
Guest
JavaStudent,
может из этого что пригодится
Считывание и установка позиции скроллбаров у формы Access
3 сен 17, 21:50    [20768491]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
guest_rusimport, код 14 летней давности пугает. Я пытался засунуть это в форму... Сходу не получилось...

Я хочу сделать, чтобы при движении scrolla вправо, двигалось поле в подчиненной форме вправо. В статье есть строка - "инициировать событие Scroll" ... Как его иницировать...?
3 сен 17, 21:56    [20768498]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
guest_rusimport
Guest
JavaStudent
Я хочу сделать, чтобы при движении scrolla вправо, двигалось поле в подчиненной форме вправо...

Так в чём проблема? См. приложенный пример с использованием приведенного кода по ссылке. (Не знаю, заработает ли в твоей версии Access ... ну, вот, заодно и проверишь)

К сообщению приложен файл (db1.zip - 19Kb) cкачать
4 сен 17, 01:12    [20768702]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Скачал, БОЛЬШОЕ спасибо. Работает. Попробую к себе прикрутить.
4 сен 17, 12:09    [20769364]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
2007 Access не работает. Не находит crossbar в форме:

If StrComp(s, "SCROLLBAR", vbTextCompare) = 0 Then

Сюда не заходит, т.е. нет в детях скроллбара.... и перебор всех детей формы их там не 3...

style& = GetWindowLong&(hwndChild, GWL_STYLE)
4 сен 17, 12:37    [20769461]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Поменял на дитя: NUIScrollbar заработал пример.

If StrComp(s, "NUIScrollbar", vbTextCompare) = 0 Then

Только вот таймер для проверки положения скролл устанавливать не красиво...

Как поймать событие движения скролла?

Двигается скролл вправо - двигается поле вправо.
4 сен 17, 12:52    [20769506]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
guest_rusimport
Guest
JavaStudent
2007 Access не работает. Не находит crossbar в форме:

If StrComp(s, "SCROLLBAR", vbTextCompare) = 0 Then

Сюда не заходит, т.е. нет в детях скроллбара.... и перебор всех детей формы их там не 3...

style& = GetWindowLong&(hwndChild, GWL_STYLE)


в комментарии к статье же было -
надо заменить на
If StrComp(s, "NUIScrollbar", vbTextCompare) = 0 Then

пробуй
4 сен 17, 12:53    [20769513]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
guest_rusimport
Guest
JavaStudent
Поменял на дитя: NUIScrollbar заработал пример.

If StrComp(s, "NUIScrollbar", vbTextCompare) = 0 Then

Только вот таймер для проверки положения скролл устанавливать не красиво...

Как поймать событие движения скролла?

Двигается скролл вправо - двигается поле вправо.


некрасиво, зато просто и надежно... другой путь - субклассирование , ловить сообщение окна формы WM_HSCROLL
4 сен 17, 13:00    [20769539]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
guest_rusimport
Guest
JavaStudent,

пример субклассирования 3367169 (переделай под свой случай)
4 сен 17, 13:06    [20769574]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Вакшуль Сергей
Member

Откуда: Харьков
Сообщений: 392
guest_rusimport,
guest_rusimport
другой путь - субклассирование , ловить сообщение окна формы WM_HSCROLL

а я как раз недавно подобным и занимался - 20774213


JavaStudent,

В общем, взял этот пример за основу, переделал на скорую руку за 1,5 часа. Вроде работает. Если что - можно подправить.
Но я бы, наверно, применял бы таймер. Куда более безопасней чем субклассирование. И там и там функции обратного вызова, какая по большому счету разница?

Пример во вложении. Три версии: Scroll_2000.mdb, Scroll_32-bit.accdb, Scroll_64-bit.accdb
Запустите на выполнение не открывая редактор кода. В ролике поста, на который сослался выше и в самом коде файла объяснил почему придется соблюдать более жесткие правила, субклассируя форму. Нельзя открывать редактор IDE, если в этот момент идет субклассирование. Откроете - завесите Access. Если хотите посмотреть код или редактировать, сначала закройте формы, по которым запущено субклассирование, а только потом открывайте среду IDE. В этом примере я тоже ввел константу, определяющую режим отладки. Здесь она называется Scroll_DebugMode. Если хотите отлаживать и писать свой код, установите ее значение в True. Тогда Access будет работать стабильно, т.к. перехвата событий прокрутки не будет. А чтобы посмотреть как работает ваш код, установите Scroll_DebugMode = False, закройте проект и запустите, помня, что теперь редактор кода открывать нельзя. Захотите открывать - снова закройте все формы, по которым запущено субклассирование и тогда открывайте. Но открыв среду IDE хоть раз, запускать проект на выполнение, если Scroll_DebugMode = False нельзя, - завесите Access.

Я обращался и на Stackoverflow и на Social.msdn:
https://stackoverflow.com/questions/45854403/i-cant-subclass-ms-access-form-if-the-window-of-ide-has-been-opened?noredirect=1#comment78705743_45854403
https://social.msdn.microsoft.com/Forums/office/en-US/4cf1d113-d905-4cdf-9f82-eb2c8d3666ed/setwindowlong-on-a-ms-access-form-what-happens-if-ide-window-is-open?forum=accessdev
в надежде, что подскажут, как работать без риска краха, но ответа нет.

На Stackoverflow мое внимание обратили на нежелательность использования SetWindowLong, с предпочтением в пользу применения SetWindowSubclass. Мне сложно это комментировать. Я просто решил сделать как советуют:
IInspectable
Subclassing controls using SetWindowLong has been wrong since the first 64-bit Windows OS (Windows XP 64-Bit Edition, released in 2001). Likewise, subclassing controls using SetWindowLongPtr has been wrong for more than a decade and a half (see Subclassing Controls for the safe and sane alternative). – IInspectable Aug 24 at 19:56

И адресовали меня вот сюда:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb773183.aspx?f=255&MSPPError=-2147217396
А тут действительно Microsoft ратует за использование SetWindowSubclass.

Хотя, что интересно. Когда в тестах я использовал SetWindowLong, то в этом случае не нужно было ждать пока форма загрузится полностью. Там не нужны были вот эти финты с таймером - 20780320, в то время как используя SetWindowSubclass субклассировать форму можно только, как я говорил, тогда, когда она полностью загружена, иначе, Access падает.
Но я все равно остановился на SetWindowSubclass, почитав, что многие расхваливают эти API функции, мол, это безопасный подход, к тому же примеры с SetWindowLong, которые я видел, все используют Lib "user32", а как это будет работать на 64-bit, да, и вообще, что там дальше с судьбой этой Lib "user32", не понятно.

У меня вообще-то есть еще мысли как можно было бы попробовать сделать по-другому. Если найду время - попробую, расскажу.

К сообщению приложен файл (Scroll.7z - 56Kb) cкачать
8 сен 17, 01:58    [20780341]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
13-й квартал
Guest
Относительно прокрутки и сабклассинга - думается, 10808021 можно доработать, инфраструктура там есть. Там часть вопросов, с которыми Вакшуль Сергей столкнулся, решена с помощью низкоуровневой фильтрации сообщений (прикол, однако, в том, что для .mde/.accde таких ухищрений не нужно, достаточно простых вариантов типа упомянутого 3367169).
Ещё несколько комментариев для понимания, какие могут быть проблемы (часть) и как решать:
7280562 п. 4)
8512604.
8 сен 17, 17:48    [20782737]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Вакшуль Сергей
Member

Откуда: Харьков
Сообщений: 392
20780341 код в этом примере чего-то конечно ловит, но только процентов 15 возможных ситуаций. И эти 15% требуют доработки.
Вакшуль Сергей
У меня вообще-то есть еще мысли как можно было бы попробовать сделать по-другому. Если найду время - попробую, расскажу.

Я сделал по-другому. Без субклассирования окна формы. Т.е. редактор кода может быть открыт.
Перехватываются и обрабатываются:
- прокрутка формы при клике по полосе прокрутки
- прокрутка формы колесиком мыши
- прокрутка формы при использовании middle button(нажатие на колесико и удерживание)
- прокрутка формы в результате смены фокуса, как при использовании клавиатуры(tab, стрелки и т.п.), так и мыши. Тот случай, когда прокручивание происходит в результате получения фокуса контролом, который частично или полностью не виден, выходя за границы формы

Не обрабатывается:
- горизонтальная прокрутка формы, вызываемая наклоном колесика в сторону(tilt) мыши Microsoft
События мыши перехватываются с помощью SetWindowsHookEx. Особенность функции в том, что системные сообщения о наклоне колесика мыши в сторону(tilt) эта функция не перехватывает. К сожалению. Во всяком случае сообщения моей мыши Microsoft не перехватываются.

Плохо обрабатывается:
- прокрутка формы при использовании middle button(нажатие на колесико и удерживание). В принципе работает, но возможна ситуация, когда клики вниз и вверх уже отработали, а форма "разогнавшись" продолжает прокручивание и останавливается когда ей заблагорассудится. Я заложил для борьбы с этим определенное время ожидания, но, как уже сказал, событие может не перехватится.

В целом пример рабочий, но как и предлагал guest_rusimport, гораздо проще просто обойтись таймером.

Во вложении два файла: accdb32-bit и mdb2000. mdb2000 на XP не работает. Там низкоуровневые сообщения мыши не перехватываются. Но на семерке mdb2000 работает.

К сообщению приложен файл (ScrollWindow.7z - 74Kb) cкачать
15 сен 17, 02:40    [20797575]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Вакшуль Сергей, Я не смотрел еще код, но выглядит красиво. Не разобрался почему h=2 при крайнем левом положении бегунка, но то, что удалось отловить самый левый номер столба и самый верхний номер строки в зависимости от положения ползунка, которые видны прикольно.

Выглядит так. Лифт(бегунок) поехал вниз, а лампочка горит на 12 этаже. Лифт(бегунок) остановился лампочка загорелась сразу на 1 этаже...

Но пример, мне очень понравился. Спасибо.
1 ноя 17, 23:50    [20920612]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Вакшуль Сергей
Member

Откуда: Харьков
Сообщений: 392
JavaStudent,
JavaStudent
Не разобрался почему h=2 при крайнем левом положении бегунка
Это просто факт. Не знаю есть ли тут логика. У подчиненной формы крайнее значение, считываемое функцией GetScrollPos, действительно не равно нулю, но очень близко. А вот у основной формы крайние значения полос прокрутки таки равны нулю. Остается только констатировать это явление :)

JavaStudent
то, что удалось отловить самый левый номер столба и самый верхний номер строки в зависимости от положения ползунка, которые видны
тут не понял. Вы имеете ввиду, что вы у себя реализовали такой функционал?

Вакшуль Сергей
Плохо обрабатывается:
- прокрутка формы при использовании middle button(нажатие на колесико и удерживание). В принципе работает, но возможна ситуация, когда клики вниз и вверх уже отработали, а форма "разогнавшись" продолжает прокручивание и останавливается когда ей заблагорассудится. Я заложил для борьбы с этим определенное время ожидания, но, как уже сказал, событие может не перехватится.

Уже потом, когда описывал плюсы и минусы решения, понял как можно устранить описанный выше недостаток. Если очень, очень надо могу доработать код в этом плане. Просто так - не хочется.
2 ноя 17, 00:30    [20920668]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Вакшуль Сергей,

VScroll = False HScroll = True fsbSub_ScrollPos v = 5, h = 3

v=5 - это 1 видимая строка
h=3 - это 1 видимый столб

Ваш пример оценил и понравился. Пока не реализовал у себя. В идеале ловить v = 5, h = 3 при движении бегунка, а не при его отпускании. Позже поковыряюсь в вашем коде.

Но себе взял на вооружение.
2 ноя 17, 22:09    [20923239]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Вакшуль Сергей
Member

Откуда: Харьков
Сообщений: 392
JavaStudent,
вы правы, там действительно оказывается :) есть связь между значениями v/h и номерами видимых строк/столбцов
я даже не обратил на это внимание. Вернее, напрочь забыл.
3 ноя 17, 02:45    [20923556]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Вывод такой. Поймать событие скролл нельзя. Более того при перемещении мышки вдоль линии прокрутки, событие перемещение не происходит. Ни события click, ничего. Мышка попадает в пустоту.

Использовать Hook не хочется. Я как понял он грузится и начинает слушать все события, я не разбирался только в форме или вообще
все приложение.

Использовать таймер, надо знать координаты ползунка (для определения взял код из примера Сергея Вакшуль)

Запускаю в событии таймер так

Dim v As Long
Dim h As Long
Call GetScrollBarPos(Me("Экран").Form.hWnd, v, h)
If Me("Экран")("region").Left = PixelToTwip(h) Then
Else
   Me("Экран")("region").Left = PixelToTwip(h)
End If


Координаты выплевывает в Пикселях, нужно переводить в Твипы
Определяет очень точно.

Недостаток, то что каждую секунду запускается таймер, который проверяет положение ползунка...

Не ожидал такого от Access.... Везде есть работа с ползунком, а в Access Нету...

Очень хороший подводный камень Access. Ударился больно.
10 ноя 17, 19:58    [20944830]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
MrShin
Member

Откуда:
Сообщений: 1103
JavaStudent,

Увы и ах. Таймер - смерть условному форматированию и вычисляемым полям, начинают работать просто ужасно - ну нет в Аксе многозадачности. Хуки - нормальное обходное решение, особого влияния на производительность не оказывается, так что не гнушайтесь
10 ноя 17, 20:28    [20944883]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Панург
Member

Откуда: настоящему индейцу завсегда везде ништяк
Сообщений: 3649
JavaStudent
Вывод такой. Поймать событие скролл нельзя.
Ээмуляция табличной формы
10 ноя 17, 20:46    [20944916]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Вакшуль Сергей
Member

Откуда: Харьков
Сообщений: 392
JavaStudent
Использовать Hook не хочется. Я как понял он грузится и начинает слушать все события, я не разбирался только в форме или вообще все приложение.
Насчет примененной у меня функции SetWindowsHookEx.
Используемый тип процедуры фильтра - WH_MOUSE_LL, т.е. мониторятся не все сообщения, а только "low-level mouse input events".
Этот же тип определяет и область мониторинга: "Global only", т.е. слушаются клики не только внутри приложения.
Также нужно иметь ввиду, что перехватив сообщение, долго тянуть с его обработкой нельзя. MSDN на этот счет говорит следующее:
автор
The hook procedure should process a message in less time than the data entry specified in the LowLevelHooksTimeout value in the following registry key:
HKEY_CURRENT_USER\Control Panel\Desktop
The value is in milliseconds. If the hook procedure times out, the system passes the message to the next hook. However, on Windows 7 and later, the hook is silently removed without being called. There is no way for the application to know whether the hook is removed.

Я собственно ни к чему не призываю. Решайте сами. В реальном бою свой код не проверял, а комментарии MrShin насчет использования таймера вы видели.

По поводу области действия, "Global only". Да, хотелось бы, что бы фильтр был наложен внутри потока, но, увы. Я немного поэксперементировал с другими типами фильтра: WH_MOUSE, WH_MSGFILTER и, по-моему, WH_CALLWNDPROC, область действия которых "Thread or global", но ничего там толком не добился, использовать их в решении у меня не получилось. А вот с WH_MOUSE_LL все как по маслу. Ну да, он глобальный, но посмотрите код, там в два коротких шага(WindowFromPoint и GetAncestor) проверяется пришелся ли клик на окно Access или на другое приложение. Если в другое, сразу выход. Работая не в Access, а снаружи, влияния эти двух шагов на действия мыши, я не заметил. Вообще было ощущение, что приоритет Access ушедшего в фон резко понижен, установленный фильтр никак себя не проявлял. Хотя работая внутри Access я заметил некоторое подтормаживание при попытке выделения текста мышкой(в самом начале этого движения).
В принципе, в момент переключения в другое приложение, фильтр можно снять, а при возвращении - восстановить. Например, поставив еще один хук :), отслеживающий переключения между приложениями/окнами. Я даже сделал набросок, но потом, взвесив, решил, что преимущества ничтожны и вообще спорны (вы действительно не заметите работая извне, что Access, находящийся в фоне, фильтрует сообщения мыши).

Но вот о чем, действительно, мне кажется, нужно позаботится, так это о том, чтобы handle установленного фильтра, сохраненный в переменной, не был потерян, если в результате неперехваченной ошибки выполнения глобальные переменные "слетят". Если его сохранять в Tempvars, то проблем не будет. Я проверял. Tempvars работает железобетонно. В коде не использовал Tempvars только потому, что думал о совместимости с предыдущими версиями Access. А зря. На XP в 2000-ом применить SetWindowsHookEx все равно не получилось.
Если опасаетесь, что ваша программа зависнет, процесс придется снять, а установленный фильтр по-прежнему будет мучить систему, то опасения напрасны. Фильтр будет снят системой.
У меня в коде фильтр на сообщения устанавливается и удерживается ровно столько, сколько открыта форма, чья прокрутка отслеживается. Вы можете сделать еще жестче и снимать фильтр, если форма деактивируется(хотя если форма всплывающая, то отследить это проблемно), и устанавливать при ее активации.

Остальные комментарии по теме я оставил тут: 20797575 20897125 20899090 20899392.
11 ноя 17, 02:48    [20945273]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
Predeclared
Member

Откуда: And God I know I'm one
Сообщений: 694
JavaStudent
... Двигается скролл вправо - двигается поле вправо.

Никак не соображу цель этого перемещение.
Скриншотом формы не поделитесь?
11 ноя 17, 11:46    [20945483]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
JavaStudent
Member

Откуда:
Сообщений: 75
Подчиненная ленточная форма. 31 квадратик (2 см на 2 см) в строке. 44 строки. 1 колонка, например, наименование стран. Двигаю бегунок.
Наименование стран пропадает. Определяю положение бегунка - двигаю первый столбик. Но таймер очень плохое решение...
Другого, пока нет...
12 ноя 17, 19:09    [20947290]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
_гурД
Guest
JavaStudent,
если, как вы пИшите, плохо работает только в подчинённой форме -
то, может, переделать её на главную?..
12 ноя 17, 19:40    [20947337]     Ответить | Цитировать Сообщить модератору
 Re: Как в форме поймать событие Scroll?  [new]
_гурД
Guest
Что касается наименований государств в международных и внутренних документах,
по у каждой страны есть "нормативный алиас" (даже вроде два). Не помню, как это наз в документе, на практике стречались: Russia - RU, RUS...
??
12 ноя 17, 19:45    [20947346]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Microsoft Access Ответить