Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / [VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса) / 25 сообщений из 46, страница 1 из 2
20.09.2010, 12:17
    #36855118
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Ну раз никто глупых вопросов не задает, тогда задам я


В общем задача понятна должна быть, но тезисы обрисую:

1) Есть юзерконтрол. У него должна быть некая функция, которая обеспечивает появление дополнительного окошка, в которое в идеале динамически грузится другой юзерконтрол с произвольным функционалом.

2) Окошко не должно ограничиться границами контейнера, на котором расположен базовый юзерконтрол (иначе можно было бы просто изменять размеры юзерконтрола)

3) Окошко должно реагировать на края экрана и выпадать сверху, если снизу оно не помещается до края экрана.

4) Окошко должно исчезнуть, если произошел клик мимо него (простая потеря фокуса не годится, так как если просто кликнуть по пустой части формы, активный контрол фокус не теряет), а также потеря фокуса основным контролом или базовым приложением.

Как я понимаю, п.2,3,4 без АПИ реализовать не удастся, подскажите плиз - какими функциями нужно воспользоваться.
...
Рейтинг: 0 / 0
20.09.2010, 12:48
    #36855213
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
...
Рейтинг: 0 / 0
20.09.2010, 12:54
    #36855239
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Antonariy,

Упс...
старый склеротик...
тогда не разобрал, не до этого было....

ща займусь.
...
Рейтинг: 0 / 0
20.09.2010, 14:00
    #36855450
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Antonariy,

А ты его после того не дорабатывал? Чтоб уж последнюю версию смотреть...
...
Рейтинг: 0 / 0
20.09.2010, 14:11
    #36855477
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Вот она.
...
Рейтинг: 0 / 0
20.09.2010, 14:25
    #36855520
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Ругается на отсутствие cUxTheme.dll
Это для чего? в той версии такого не было
...
Рейтинг: 0 / 0
20.09.2010, 15:22
    #36855625
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
c UxTheme это класс, а ругается наверное на отсутствие uxtheme.dll — "Библиотека тем UxTheme (Microsoft)". У меня XP SP3 и она есть в System32.
Она нужна для того, чтобы кнопка комбобокса рисовалась в соответствии с текущем стилем винды.
...
Рейтинг: 0 / 0
20.09.2010, 16:11
    #36855789
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Antonariy,

Я в данный момент на 2000к и стили мне не нужны, так как выпадания будут вызываться специфическими кнопками, поэтому пока ковыряю старую версию.

Пытаюсь курить код, тяжело, ибо стихи АПИ - нет беглости, а пока изучишь каждую функцию, забудешь с чего начинал. Так структуру примерно разобрал, просто много непонятно, почему именно так. К примеру, почему события Click и DblClick сделаны через отдельный класс? А вот само время жизни окна находится внутри цикла, в котором нет DoEvents - как же он обходится?
...
Рейтинг: 0 / 0
20.09.2010, 16:58
    #36855928
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Shocker.ProК примеру, почему события Click и DblClick сделаны через отдельный класс?
Кстати, для чего они вообще нужны?
По идее - требуется, чтобы по возникновению какого-то события в выпавшем фрагменте, сам выпавший фрагмент закрылся. Для этого, как я понимаю, нужно выставить fStop в True, но это делается через сообщения, почему? Только из-за того, чтобы работало на модальной форме?
...
Рейтинг: 0 / 0
20.09.2010, 19:10
    #36856173
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Shocker.ProК примеру, почему события Click и DblClick сделаны через отдельный класс?
Кстати, для чего они вообще нужны?Нужны для того, чтобы создать у контрола событие аналогичное Click у комбобокса. Зачем нужен даблклик? Затем, что по клику у дерева, например, распахиваются узлы, будет неприятно, если дропдаун закроется до того, как нужный узел будет найден. В отдельном классе просто потому что так сложилось. Можно и через сам юзерконтрол.

Shocker.ProДля этого, как я понимаю, нужно выставить fStop в TrueНет, в старой версии это была заплатка от краша при потере фокуса, в последней версии она не нужна, как и условие If fStop. Вообще большинство "почему именно так" это заплатки от вылета программы в астрал. Делаю какое-то действие, получаю вылет, нахожу событие или их последовательность, приводящую к вылету, ищу пути обхода. В одних местах это перевод фокуса, в других — уничтожение окна.

Shocker.Pro А вот само время жизни окна находится внутри цикла, в котором нет DoEvents - как же он обходится?GetMessage ожидает событий, блокируя поток. Пока их нет, цикл стоит.
...
Рейтинг: 0 / 0
21.09.2010, 16:06
    #36858281
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
фух, отодрал работу со стилями, ща буду курить дальше уже новую версию...

WorobjoffЕсть еще один маленький клопик:
Если форма внизу экрана, фрейм дропается вникуда (за пределы экрана, а не вверх).
А это ты не стал исправлять делать, как я понимаю?
...
Рейтинг: 0 / 0
21.09.2010, 17:17
    #36858575
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Не стал.
...
Рейтинг: 0 / 0
22.09.2010, 00:54
    #36859117
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
AntonariyShocker.Pro А вот само время жизни окна находится внутри цикла, в котором нет DoEvents - как же он обходится?GetMessage ожидает событий, блокируя поток. Пока их нет, цикл стоит.
Но, получается, при этом спокойно отрабатываются события в другом потоке? То есть в "выпавшем" контроле я могу делать что хочу?

В принципе, получается такая цепочка, если я все правильно понял:
1) TargetProc перехватывает сообщения окну "выпавшего" контрола
2) Если находит WM_LBUTTONDBLCLK, посылает контейнеру "выпавшего" окна сообщение на уничтожение
3) ...Одновременно с этим запускает таймер для генерации события
4) Окно контейнера уничтожается, GetMessage получает WM_QUIT, цикл завершается, завершая работу "выпадения"
5) тем временем таймер генерит событие в классе, которое получает базовый контрол.

В общем-то, я хочу несколько переиначить это дело, то есть наплевать на Click, DblClick - у выпадающего юзерконтрола могут быть задачи посерьезнее и я делегирую ему полномочия решить, когда ему закрыться (например пользователь нажал определенную кнопку). То есть пункты 2,3,5 я могу смело ликвидировать.
Если я опять же правильно понял, когда выпавший контрол решит, что его миссия выполнена, он должен сделать это:
Код: plaintext
1.
2.
PostMessage gDropWindow, WM_USER +  1 ,  0 ,  0 
PostMessage gDropWindow, WM_CLOSE,  0 ,  0 
PostMessage gDropWindow, WM_DESTROY,  0 ,  0 
(разумеется gDropWindow должно оказаться в его области видимости)
и цикл завершит свою работу. При этом сам факт завершения цикла будет событием для базового контрола, что выпавшая часть завершила свою работу, а если нужна дополнительная информация - ее можно взять через свойства выпадающего контрола.
Правильный подход?

ЗЫ: твой текущий пример можно загнать в астрал следующим образом - раскрыть выпадающий список и нажать Alt+F4
...
Рейтинг: 0 / 0
22.09.2010, 11:15
    #36859527
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Shocker.ProНо, получается, при этом спокойно отрабатываются события в другом потоке? То есть в "выпавшем" контроле я могу делать что хочу?Это не другой поток, это другой обработчик событий другого окна. Они работают по очереди, но так быстро, что кажется, как бы одновременно. Сначала событие обрабатывает контрол, потом оно добирается до GetMessage, если контрол его не зарубит, и цикл продолжает свой неспешный бег.

Shocker.ProЕсли я опять же правильно понял,Правильно.

Shocker.ProПри этом сам факт завершения цикла будет событием для базового контрола, что выпавшая часть завершила свою работу, а если нужна дополнительная информация - ее можно взять через свойства выпадающего контрола.Собственно, у меня так и сделано.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Private Sub Command1_Click()
    …
    CreateDD ObjPtr(cPrivate), cControl.hWnd, …
    cControl.Visible = False
    RaiseEvent Click( 0 )
    Exit Sub
errh:
    MsgBox "Control does not have a window handle or invisible at run time!", vbExclamation
End Sub
Тебе нужно только заменить обработку WM_LBUTTONUP и WM_LBUTTONDBLCLK на WM_USER + 4, например, и снабдить юзерконтрол методом, отправляющим это сообщение контролу, который используешь для выпадения.

Shocker.ProЗЫ: твой текущий пример можно загнать в астрал следующим образом - раскрыть выпадающий список и нажать Alt+F4Да уж, до этого я не додумался — закрывать программу в самый разгар работы в ней. :)
...
Рейтинг: 0 / 0
22.09.2010, 11:28
    #36859554
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Shocker.ProВ общем-то, я хочу несколько переиначить это дело, то есть наплевать на Click, DblClick - у выпадающего юзерконтрола могут быть задачи посерьезнее и я делегирую ему полномочия решить, когда ему закрыться (например пользователь нажал определенную кнопку). Кстати, здесь есть громадная засада. Контрол спроектирован так, чтобы исключить возможность появления вообще в системе обновременно более одного выпадающего окна, потому что глобальные переменные модуля разделяются всеми экземплярами контрола во всех процесах.
Если же процедуру закрытия будет регламентировать не DDControl, а кто попало, то потенциально возможна попытка показать более одного дропдауна, что приведет к краху программы.
...
Рейтинг: 0 / 0
22.09.2010, 11:30
    #36859563
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Как минимум нужно прятать дропдаун изнутри DDControl'а, если фокус получил другой его экземпляр.
...
Рейтинг: 0 / 0
22.09.2010, 13:12
    #36859856
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
AntonariyКстати, здесь есть громадная засада. Контрол спроектирован так, чтобы исключить возможность появления вообще в системе обновременно более одного выпадающего окна, потому что глобальные переменные модуля разделяются всеми экземплярами контрола во всех процесах.

Я тоже поначалу не понял, почему это модуль, а не класс.
Что причина, а что следствие -
1) ТЗ на то, что нельзя получить два выпадающих списка одновременно => реализация в виде модуля
или
2) Реализация в виде модуля - как следствие невозможность получить два выпадающих контрола
?
А если изолировать модуль в класс - будут работать два?

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

AntonariyЕсли же процедуру закрытия будет регламентировать не DDControl, а кто попало, то потенциально возможна попытка показать более одного дропдауна, что приведет к краху программы.
Ну, собственно, вариант с отсылкой WM_USER + 4 это решает? или ты что-то другое имеешь ввиду?
...
Рейтинг: 0 / 0
22.09.2010, 14:57
    #36860217
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Shocker.ProЧто причина, а что следствиеНи то ни другое. Хотелось полной имитация работы комбобокса, а из того, что двух открытых комбобоксов не бывает, следует ненужность поддержки нескольких открытых дропдаунов. В любом случае, в виде класса это сделать не получится без ассемблерных вставок, а оно разве надо?

Shocker.ProНасколько я понимаю, увод фокуса автоматически закроет выпадающую часть, так что второй выпадающий контрол может появиться только если это будет по инициативе программы, а не пользователя.Все верно, упустил это из виду.

Shocker.ProКстати, а что будет, если приложение по своей инициативе уведет фокус на другую форму (есть у меня такое - приход сверхважного сообщения)?Потеря фокуса есть потеря фокуса, неважно как это произошло.

Shocker.ProНу, собственно, вариант с отсылкой WM_USER + 4 это решает? или ты что-то другое имеешь ввиду?Проблему решает потеря фокуса, а WM_USER + 4 призвано закрывать дропдаун альтернативным потере способом.
...
Рейтинг: 0 / 0
22.09.2010, 18:20
    #36860940
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
AntonariyВ любом случае, в виде класса это сделать не получится без ассемблерных вставок, а оно разве надо?

Для общего развития - а что там такого, что не может быть размещено в классе?
...
Рейтинг: 0 / 0
22.09.2010, 23:12
    #36861254
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Оконные процедуры. AddressOf понимает только те, что объявлены в модуле.
...
Рейтинг: 0 / 0
23.09.2010, 13:56
    #36862354
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
AntonariyОконные процедуры. AddressOf понимает только те, что объявлены в модуле.

Ну обойти, конечно, можно, разместив оконные процедуры в модуле и делая реестр hwnd и соответствующих им объектов.... но незачем, конечно же....
...
Рейтинг: 0 / 0
14.11.2010, 20:09
    #36955725
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Блин.
БЛИН.

Antonariy,

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

Как только я пытаюсь нажать кнопку, у окна gTarget возникает сообщение WM_KILLFOCUS и мое окошко DD уничтожается, не дав мне даже получить событие от кнопки. А нужно, чтобы оно в этом случае вообще не закрывалось.


В общем, методом тыка и грубой силы сделал следующим образом: при получении WM_KILLFOCUS, DD не уничтожается, а запускается таймер. Вот обработчик таймера:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Private Sub Timer1()
    
Dim Par As Long
KillTimer  0 , hTimer
            
Par = GetFocus
Do Until Par =  0 
  If Par = gDropWindow Then
    SetFocus gTargetWindow
    Exit Sub
  End If
  Par = GetParent(Par)
Loop

PostMessage gDropWindow, WM_USER +  1 ,  0 ,  0 
PostMessage gDropWindow, WM_CLOSE,  0 ,  0 
PostMessage gDropWindow, WM_DESTROY,  0 ,  0 

End Sub

Ничего другого в голову не пришло, прошу совета, а то мне кажется это как-то слишком грубо. Кроме того, теоретически ведь я могу щелкнуть по другому контролу с выпадающим списком. И тогда возникнет та самая ситуация, когда открывается следующий DD, а предыдущий не закрыт. Я даже пока не стал пробовать такую ситуацию, конечно, можно сделать контрольные проверки, но пока не делаю, надеюсь, что будет идея получше.
...
Рейтинг: 0 / 0
14.11.2010, 20:35
    #36955745
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
он еще и не рабочий этот метод
если убрать строку
Код: plaintext
SetFocus gTargetWindow
то работает, но перестает закрываться по потере фокуса по понятным причинам.
а с этой строкой - события кнопки не возникают
...
Рейтинг: 0 / 0
14.11.2010, 20:51
    #36955760
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Ситуацию исправил добавлением процедуры обработки потери фокуса для любого контрола, находящегося в подчинении DD. Выглядит ужасно:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Private Sub Timer1()
    
Dim l As Long, Par As Long
KillTimer  0 , hTimer1
            
l = GetFocus
Par = l
Do Until Par =  0 
  If Par = gDropWindow Then
    If lpPrevAnyControlhWnd <>  0  Then
      SetWindowLong lpPrevAnyControlhWnd, GWL_WNDPROC, lpPrevAnyControlProc
    End If
    lpPrevAnyControlhWnd = l
    lpPrevAnyControlProc = SetWindowLong(lpPrevAnyControlhWnd, GWL_WNDPROC, AddressOf AnyControlProc)
    Exit Sub
  End If
  Par = GetParent(Par)
Loop

PostMessage gDropWindow, WM_USER +  1 ,  0 ,  0 
PostMessage gDropWindow, WM_CLOSE,  0 ,  0 
PostMessage gDropWindow, WM_DESTROY,  0 ,  0 

End Sub
...
Рейтинг: 0 / 0
14.11.2010, 21:02
    #36955772
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса)
Самый первый вариант контрола поддерживал нажатия на кнопки.
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / [VB6] Как организовать свой контрол с выпадающим окошком (типа комбобокса) / 25 сообщений из 46, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]