Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> отловить отпускание левой кнопки мышки, везде 
V
    Опции темы
nns2009
Дата 6.2.2009, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 1.2.2009

Репутация: нет
Всего: 1



Я заметил одну вещь:
WM_LBUTTONUP посылается окну только если мышка отпущена в его области(на окне),
а мне нужно как-то узнавать что мышка отпущена, где бы она ни была.
Подскажите, как это сделать?
PM MAIL   Вверх
SenkraD
Дата 6.2.2009, 23:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: 4
Всего: 23



nns2009, вы правила читали? Поиска нет или как?
Я по форуму щас не искал, но google дал этоэто и это


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
nns2009
Дата 7.2.2009, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 1.2.2009

Репутация: нет
Всего: 1



Спасибо за ссылки, но правила я читал(и если б я не пользовался поиском, то моих сообщений было в два раза больше).
Ставить ловушки слишком заумно, а в моём случае буду считать, что если пользователь увёл мышку за пределы окна, то он её отпустил,
в моём приложении это не слишком принципиально.
Буду искать нужное событие.
PM MAIL   Вверх
GremlinProg
Дата 7.2.2009, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(nns2009 @  7.2.2009,  23:12 Найти цитируемый пост)
в моём случае буду считать, что если пользователь увёл мышку за пределы окна, то он её отпустил

т.е. WM_LBUTTONDOWN, все таки происходит в твоем приложении, т.е. тебе для своего приложения  нужно узнавать что мышка отпущена?

если так, то, хуки здесь не нужны, достаточно использовать механизм "захвата мыши": SetCapture и ReleaseCapture

После вызова SetCapture, все мышиные сообщения начнут приходить в твое окно до тех пор, пока мышь не будет выпущена другим SetCapture или ReleaseCapture, независимо от того, проходит курсор по нему или нет.

подробнее - смотри в поиск по этим ключам, тема не новая


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 9.2.2009, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Capture - это слишком мощно, его захват "портит" логику многих процессов, иак что лучше не использовать всуе...
Разве что это свяано с тащением чего-либо или типа того, тогда да, Capture. В противном случае вопрос, насколько синхронно тебе нужно знать, что мышка вышла за пределы окна\отпустила кнопку. Если  это нужно "не очень синхронно" - то поставь таймер и проверяй, не вышла ли мышь за пределы окна. Строго говоря, ставить таймер нужно, только если мышь приползла в окно (т.е. по первому MouseMove), а как только ты увидел (по таймеру), что мышь уползла - снимай. Диапазон подбери органолептически, чтобы хорошо смотрелось...
Ну а если нужно синхронно - то только хук. И почему, собственно, хук слишком заумный?


--------------------
...
PM   Вверх
GremlinProg
Дата 10.2.2009, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



ну, тут я уже просто предполагаю, что nns2009, организует какую-то сенсорику на залипании мыши, поэтому и предложил механизм захвата, конечно, если нужно только определяты выход за пределы клиентской/неклиентской области, то захват не нужен, как, впрочем, и таймер, поскольку этот механизм реализован в системе: TrackMouseEvent + WM_MOUSELEAVE/WM_NCMOUSELEAVE

Добавлено @ 14:15
хук, кстати, не слишком заумный, это крайний механизм перехвата всего и вся, здесь-то он зачем, когда можно обойтись более дипломатично, тем более, хук - узкое горлышко, ничего не стоит его просто перегрузить, в обоих смыслах ))

Это сообщение отредактировал(а) GremlinProg - 10.2.2009, 14:16


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 10.2.2009, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(GremlinProg @  10.2.2009,  15:08 Найти цитируемый пост)
TrackMouseEvent + WM_MOUSELEAVE/WM_NCMOUSELEAVE

Это дело, к сожалению, звучит соблазнительно, но работает так себе. Во всяком случае, при тестировании мне довольно быстро удавалось получить ситуацию, когда MOUSELEAVE не приходил - просто быстро двигая мышкой. И я на этот способ забила. А таймер работает железно (ну, почти...) Впрочем, должна оговориться: дело было давно, уж не помню в каком виндоус. Возможно, сейчас этот способ работает стабильнее. Но осадок остался... smile 


--------------------
...
PM   Вверх
GremlinProg
Дата 10.2.2009, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Earnest @  10.2.2009,  16:43 Найти цитируемый пост)
Это дело, к сожалению, звучит соблазнительно, но работает так себе

да нет, нормально работает, о замечаниях к TrackMouseEvent я уже писал, правда давно, но, тем не менее, работает она до тех пор, пока очередь сообщений потока, владеющего окном, не пуста

это ключевой момент

ладно, добью таки до конца уже начатое, чтобы было понятно, когда необходимо дополнить любые сенсорные проверки на мышь
кстати, это касается не только TrackMouseEvent, так же, любые проверки на WM_NCHITTEST или просто на WM_MOUSEMOVE, в общем - на любые проверки, которые производятся в ответ на оконные сообщения, зависимые от внешних устройств

вот, к примеру, главный цикл окна:
Код

while (GetMessage(&msg, NULL, 0, 0)) 
{
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

что он делает? GetMessage - это "ядерная" функция, которая "спит" до тех пор, пока очередь пустая, т.е. этот вариант для TrackMouseEvent неудобен, поскольку нужное нам время GetMessage отдает другим процессам
ок, теперь другой вариант:
Код

do{
    fPeek    = ::PeekMessage(&m_Msg,0,0,0,PM_REMOVE);
    if(fPeek == TRUE){
        if(!::TranslateAccelerator(m_TranslateWindow,m_Accel,&m_Msg)){
            ::TranslateMessage(&m_Msg);
            ::DispatchMessage(&m_Msg);
        } 
    }else if(fPeek == FALSE){
        //    время Idle
        ::WaitMessage();
    }else{
        //    обработать ошибку
    }
}while(m_Msg.message != WM_QUIT);


PeekMessage - это более гибкий вариант GetMessage, который не отдает автоматом время другим процессам, вместо этого, она возвращает TRUE, если сообщение было успешно извлечено из очереди, и FALSE - когда извлекать из очереди просто нечего, она пустая
при успешном возврате из PeekMessage, мы делаем то же самое, что и в примере выше, т.е. это обычная обработка сообщения, а вот в случае, когда PeekMessage возвращает FALSE, как раз и наступает время простоя(Idle), которое мы теперь можем использовать по своему

есть 2 варианта
1. самим отдать время простоя в систему, т.е. дать возможность поработать другим задачам в этот период
2. сделать не слишком долгосрочную обработку чего-либо, пока сообщения в очереди вновь не появятся

WaitMessage - первый вариант, эта функция будет просто "спать", пока очередь не активируется
второй вариант - как раз то, что нам и нужно, т.е. мы сами можем здесь поставить необходимую нам обработку (допустим проверку текущих координат курсора на предмет присутствия его в нужной нам области и, в случае отсутствия - снять какие-либо флаги состояния, или напрямую вывести компонент в неактивный режим, вобщем, это уже непосредственно модель простоя, которую программист может реализовывать по своему вкусу и предубеждениям), после чего, если более время Idle нам не нужно, вызвать WaitMessage

если не вызывать WaitMessage, или нагружать слишком много проверок в этот момент, то нагрузка на процессор будет 100% на протяжении всей работы приложения, так что не стоит этим злоупотреблять, поскольку обычная работа приложений уже будет нарушена + начнут вылезать различные артефакты, которым не было места при нормальной работе

ну вот, теперь, похоже добил )


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 11.2.2009, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



GremlinProg, спасибо, интересная информация. Насчет того, что очередь сообщений не должна быть пуста, не знала. Я пыталась использовать TrackMouseEvent с MFC, а там свой цикл выборки сообщений (тоже PeekMessage + Idle-обработка).
Вмешаться, конечно, можно, но тогда я так далеко не влезала.
 


--------------------
...
PM   Вверх
GremlinProg
Дата 11.2.2009, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



ну, вобщем-то ничего нового я не открыл, на сколько я знаю, все средства разработки, будь то Delphi, MFC, WTL и т.п. - все предоставляют возможность обрабатывать время простоя, просто информации по поводу "как его использовать?" не слишком много. Большинство считают, что это аппендикс, который нужен только для расширения функционала программы

наверняка, каждый видел это магическое OnIdle с булевым параметром Done, так вот Done - как раз признак завершения времени простоя, который обычно упрощено раскрывается так:
Код

BOOL Done;
do{
  Done = TRUE;
  OnIdle(&Done);
}while(!Done);
::WaitMessage();

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

Done = (::PtInRect(...) == FALSE);

и
Код

if(::PtInRect(...) == FALSE){
  Done = TRUE;
}

совершенно разные логические манипуляции
в цепочке OnIdle, такого рода, нельзя использовать первый вариант, только второй - условная установка флага.
Ситуацию можно легко поправить, если Done будет счетчиком Repeat:
Код

int Repeat = 0;
do{
  OnIdle(&Repeat);
}while(Repeat);
::WaitMessage();

Код

if(::PtInRect(...) != FALSE){
  ++Repeat;
}

и логически - понятно и соблазна поискать другой путь для решения, не возникает
но я ни разу не встречал в onIdle явного счетчика, видимо из-за накладных расходов по документированию, благо, c WinAPI мы можем эти условности опустить и делать то, что нам действительно нужно.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1239 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.