Помогите со всплывающей менюхой!

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
holmik
Начинающий
Начинающий
 
Сообщения: 4
Зарегистрирован: 29.07.2004 (Чт) 12:39

Помогите со всплывающей менюхой!

Сообщение holmik » 30.07.2004 (Пт) 12:15

Помогите со всплывающей менюхой!
Из кода программы создаётся всплывающее многоуровневое меню из базы данных. Основное меню - категория - группа - элемент. Я могу отловить
щелчок по конечному элементу, но не знаю, как отловить его путь (группу и категорию). Подскажите, что делать! Уже несколько месяцев мучаюсь, но на том же Relib.com никто ответа не дал. :(

natcap
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 234
Зарегистрирован: 25.06.2003 (Ср) 13:15
Откуда: Москва

Сообщение natcap » 30.07.2004 (Пт) 12:42

а может пойти самым примитивным путем???
в тег каждого элемента заноси путь...
например

Категория 1 tag=1
группа 1 tag=1-1
элем 1 tag=1-1-1
элем 2 tag=1-1-2
элем 3 tag=1-1-3
группа 2 tag=1-2
элем 1 tag=1-2-1
элем 2 tag=1-2-2
элем 3 tag=1-2-3

вот и будет путь.. строку то разобрать на путь элементарно :)
Медленно переезжаю с 6.0 на 2008 .... задавая тонны глупых вопросов :)

holmik
Начинающий
Начинающий
 
Сообщения: 4
Зарегистрирован: 29.07.2004 (Чт) 12:39

Сообщение holmik » 03.08.2004 (Вт) 13:22

А как синтаксически пользоваться свойством Tag? Мне вот это непонятно :?

natcap
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 234
Зарегистрирован: 25.06.2003 (Ср) 13:15
Откуда: Москва

Сообщение natcap » 03.08.2004 (Вт) 13:33

.tag=string
кавычки было лениво писать :)
Медленно переезжаю с 6.0 на 2008 .... задавая тонны глупых вопросов :)

holmik
Начинающий
Начинающий
 
Сообщения: 4
Зарегистрирован: 29.07.2004 (Чт) 12:39

Сообщение holmik » 11.08.2004 (Ср) 21:33

Дык я вкурсе, что доступ к свойствам объекта через точку :wink:
Только куды ж её ставить? :?:

Код: Выделить всё
Private Sub Command1_Click()
    Const maxLen As Long = 255&
    Dim cmdRect As RECT
    Dim menuX As Long, menuY As Long
    Dim menuId As Long, menuText As String
'
    ' Получаем координаты нижнего левого угла кнопки Command1:
    GetWindowRect Command1.hWnd, cmdRect
    menuX = cmdRect.Left
    menuY = cmdRect.Bottom
'
    'Показываем всплывающие меню и определяем, по какому элементу щЈлкнули:
    menuId = TrackPopupMenu(hMenu, TPM_LEFTALIGN Or TPM_RETURNCMD, menuX, menuY, 0, Me.hWnd, ByVal 0&)
    If menuId <> 0& Then
        ' был сделан щелчок по элементу с id = menuId
        menuText = Space$(maxLen)
        GetMenuString hMenu, menuId, menuText, maxLen, 0&
        menuText = Left$(menuText, InStr(1, menuText, vbNullChar) - 1)
        MsgBox "Вы выбрали пункт меню:" + vbCr + menuText, vbInformation, "Информация:"
    End If
End Sub
'
Private Sub Form_Load()
    Dim dataArr(1 To 2, 0 To 3) As String
    Dim i As Integer, j As Integer
    Dim groupMenu As Long, elementMenu As Long
'
    Command1.Caption = "Список элементов"
    Command1.Width = 2000
    Command1.Height = 500
'
    ' СоздаЈм пустое всплывающее меню
    hMenu = CreatePopupMenu()
'
    ' Заполняем меню двухуровневой иерархией ваших элементов. Для определЈнности
    ' предполагаем, что все элементы читаются из БД в двумерный строковый массив,
    ' в нулевом элементе второго индекса которого хранится имя группы элементов.
    ' Чтобы не писать здесь код работы с базой (формат которой неизвестен), просто
    ' присвоим значения элементам массива напрямую:
'
    dataArr(1, 0) = "Каши"
    dataArr(1, 1) = "Овсяная"
    dataArr(1, 2) = "Гречневая"
    dataArr(1, 3) = "Манная"
'
    dataArr(2, 0) = "Фрукты"
    dataArr(2, 1) = "Яблоки"
    dataArr(2, 2) = "Груши"
    dataArr(2, 3) = "Апельсины"
'
    ' Заполняем меню данными из массива dataArr():
    For i = LBound(dataArr, 1) To UBound(dataArr, 1)
        For j = LBound(dataArr, 2) To UBound(dataArr, 2)
            If j = 0 Then
                ' надо создать меню с именем группы:
                groupMenu = CreatePopupMenu
                InsertMenu hMenu, i - 1, MF_STRING Or MF_BYPOSITION Or MF_POPUP, groupMenu, dataArr(i, j)
            Else
                ' надо заполнить созданное меню именами элементов из группы:
                elementMenu = i * 1000& + j
                AppendMenu groupMenu, MF_STRING, ByVal elementMenu, dataArr(i, j)
            End If
        Next j
    Next i
'
End Sub

holmik
Начинающий
Начинающий
 
Сообщения: 4
Зарегистрирован: 29.07.2004 (Чт) 12:39

Сообщение holmik » 23.08.2004 (Пн) 15:41

Люди! Помогите! Вишу с этим вопросом уже несколько месяцев! Хоть малюсенький примерчик, попробую разобраться! :cry:

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.08.2004 (Пн) 16:16

Вот пример:

Код: Выделить всё
Option Explicit
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
Private Type MENUITEMINFO
    cbSize As Long
    fMask As Long
    fType As Long
    fState As Long
    wID As Long
    hSubMenu As Long
    hbmpChecked As Long
    hbmpUnchecked As Long
    dwItemData As Long
    dwTypeData As String
    cch As Long
End Type
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function TrackPopupMenu Lib "user32.dll" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, lprc As Any) As Long
Private Declare Function GetMenuString Lib "user32.dll" Alias "GetMenuStringA" (ByVal hMenu As Long, ByVal wIDItem As Long, ByVal lpString As String, ByVal nMaxCount As Long, ByVal wFlag As Long) As Long
Private Declare Function CreatePopupMenu Lib "user32.dll" () As Long
Private Declare Function InsertMenu Lib "user32.dll" Alias "InsertMenuA" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
Private Declare Function AppendMenu Lib "user32.dll" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Function GetMenuItemInfo Lib "user32.dll" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Boolean, lpMenuItemInfo As MENUITEMINFO) As Long
Private Const TPM_LEFTALIGN As Long = &H0&
Private Const TPM_RETURNCMD As Long = &H100&
Private Const MF_STRING As Long = &H0&
Private Const MF_BYPOSITION As Long = &H400&
Private Const MF_POPUP As Long = &H10&
Private Const MIIM_SUBMENU As Long = &H4
Dim hMenu As Long

Private Sub Command1_Click()
    Const maxLen As Long = 255&
    Dim cmdRect As RECT
    Dim menuX As Long, menuY As Long
    Dim menuId As Long, menuText As String
'
    ' Получаем координаты нижнего левого угла кнопки Command1:
    GetWindowRect Command1.hwnd, cmdRect
    menuX = cmdRect.Left
    menuY = cmdRect.Bottom
'
    'Показываем всплывающие меню и определяем, по какому элементу щ_лкнули:
    menuId = TrackPopupMenu(hMenu, TPM_LEFTALIGN Or TPM_RETURNCMD, menuX, menuY, 0, Me.hwnd, ByVal 0&)
    If menuId <> 0& Then
        ' был сделан щелчок по элементу с id = menuId
        Dim i As Long, j As Long, hSubMenu As Long, mnuPath As String
        Dim mii As MENUITEMINFO
        For i = 0 To GetMenuItemCount(hMenu) - 1
            mii.cbSize = LenB(mii)
            mii.fMask = MIIM_SUBMENU
            GetMenuItemInfo hMenu, i, True, mii
            hSubMenu = mii.hSubMenu
            For j = 0 To GetMenuItemCount(hSubMenu) - 1
                If GetMenuItemID(hSubMenu, j) = menuId Then
                    menuText = Space$(maxLen)
                    GetMenuString hMenu, hSubMenu, menuText, maxLen, 0&
                    menuText = Left$(menuText, InStr(1, menuText, vbNullChar) - 1)
                    mnuPath = menuText & "\"
                   
                    menuText = Space$(maxLen)
                    GetMenuString hMenu, menuId, menuText, maxLen, 0&
                    menuText = Left$(menuText, InStr(1, menuText, vbNullChar) - 1)
                    mnuPath = mnuPath & menuText
                   
                    MsgBox "Вы выбрали пункт меню:" + vbCr + mnuPath, vbInformation, "Информация:"
                End If
            Next
        Next
    End If
End Sub
'
Private Sub Form_Load()
    Dim dataArr(1 To 2, 0 To 3) As String
    Dim i As Integer, j As Integer
    Dim groupMenu As Long, elementMenu As Long
'
    Command1.Caption = "Список элементов"
    Command1.Width = 2000
    Command1.Height = 500
'
    ' Созда_м пустое всплывающее меню
    hMenu = CreatePopupMenu()
'
    ' Заполняем меню двухуровневой иерархией ваших элементов. Для определ_нности
    ' предполагаем, что все элементы читаются из БД в двумерный строковый массив,
    ' в нулевом элементе второго индекса которого хранится имя группы элементов.
    ' Чтобы не писать здесь код работы с базой (формат которой неизвестен), просто
    ' присвоим значения элементам массива напрямую:
'
    dataArr(1, 0) = "Каши"
    dataArr(1, 1) = "Овсяная"
    dataArr(1, 2) = "Гречневая"
    dataArr(1, 3) = "Манная"
'
    dataArr(2, 0) = "Фрукты"
    dataArr(2, 1) = "Яблоки"
    dataArr(2, 2) = "Груши"
    dataArr(2, 3) = "Апельсины"
'
    ' Заполняем меню данными из массива dataArr():
    For i = LBound(dataArr, 1) To UBound(dataArr, 1)
        For j = LBound(dataArr, 2) To UBound(dataArr, 2)
            If j = 0 Then
                ' надо создать меню с именем группы:
                groupMenu = CreatePopupMenu
                InsertMenu hMenu, i - 1, MF_STRING Or MF_BYPOSITION Or MF_POPUP, groupMenu, dataArr(i, j)
            Else
                ' надо заполнить созданное меню именами элементов из группы:
                elementMenu = i * 1000& + j
                AppendMenu groupMenu, MF_STRING, ByVal elementMenu, dataArr(i, j)
            End If
        Next j
    Next i
'
End Sub


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

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

Сообщение GSerg » 23.08.2004 (Пн) 17:07

Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.08.2004 (Пн) 17:20

GSerg писал(а):Чиииивоооооо???? :shock: :( :cry:

http://bbs.vbstreets.ru/viewtopic.php?p=39489#39489

User-defined type not defined: MenuItemDrawer
User-defined type not defined: MenuClickCatcher
User-defined type not defined: PopupMenuDrawItemAction
User-defined type not defined: PopupMenuDrawItemState
и ещё, ещё, ещё...


1. Чего мне нехватает, чтобы насладиться этой изумительной красотой?
2. И где это взять?
3. И зачем это, вообще, надо? Чтоб тормозило сильнее?
Меня бесит, когда у пустяковых программ из-за изумительной красотищи многомеговые дистрибутивы. Офису это простительно - там кроме красоты ещё и огромная, уникальная функциональность. Кто-то готов с ним соревноваться в этом отношении?
Передирать офисную красотищу "шоб було" - верхоглядство и пижонство.

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

Сообщение GSerg » 23.08.2004 (Пн) 17:27

1. Всё должно быть там, странно, перепроверю.
2. Там всё!
3. НЕ ТОРМОЗИТ (28 вскл. зн.)

Меня тоже это бесит. Дистрибутив отсутствует, никаких библ, всё в exe...
Передирать красотищу - это мы "шоб знали как", и токмо ради этого...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

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

Сообщение GSerg » 23.08.2004 (Пн) 17:32

Не проверяя старой, закачал новую версию :roll:
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.08.2004 (Пн) 17:39

На случай, если я сгоряча сформулировал мысль не вполне чётко...

Необходимость использования изумительной красотищи в болльшинстве тех программ, где я её видел, очень и очень спорна. Девелоперы увлекаются красотищей и забывают, что их программа - не скринсейвер, а рабочий инструмент, где рюшечки, даже если и не тормозят, что бывает редко, - то по крайней мере отвлекают.

Ты и подобные тебе люди процируете девелоперов на такие вот глупости. Если пример чисто демонстративный, рядом с ним надо класть жирный дизклеймер: "НЕ ВЗДУМАЙТЕ юзать это в реальных программах! Поиграйте и бросьте".

Вкратце: торт с кремом - хорошо, крем с тортом - нет. Красота должна иметь меру.

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

Сообщение GSerg » 23.08.2004 (Пн) 17:42

Я и подобные мне люди порой занимаемся вопросом ради самого изучения процесса.
Пример не чисто демонстративный.
А если кастомная отрисовка не нужна, то:
  • Не использовать параметр CustomDrawer при создании пункта
  • Установить SubClasserPresent = False.

И тогда это будет обычная менюшка, только объектно-ориентированная...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.08.2004 (Пн) 18:15

GSerg писал(а):Я и подобные мне люди порой занимаемся вопросом ради самого изучения процесса.

Я тебе не об этом говорил. Если ты до чего-то дошёл и хочешь поделиться - безусловно, все в выигрыше.
Просто конкретно этим примером ты имхо развращаешь морально нестойких девелоперов. Они увидят, что так можно сделать, - и пожалуйста, вставят сине-зелёный градиент в свои меню. А юзеры потом будут удивляться - что это за панк прогу писал?

Ещё одна аналогия. Если ты рассылаешь исходники вирусов по почте - с целью поделиться достижениями в области программирования - кто-нибудь может воспользоваться ими не так, как тебе бы хотелось. И получится, что ты ничьи диски не форматировал, но из-за тебя они были отформатированы. И тут так же.

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

Сообщение GSerg » 23.08.2004 (Пн) 18:57

:shock:
Вообще-то я хотел показать, как это делается в принципе. Сине-зелёному градиенту в нужной мне софтине я сильно не обрадовался бы.
И вообще, я верю в морально устойчивых девелоперов... Хоть рисовалку в почти стиле офиса 97 ты не будешь ругать? :roll: :(
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

A.A.Z.
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3035
Зарегистрирован: 30.06.2003 (Пн) 13:38

Сообщение A.A.Z. » 23.08.2004 (Пн) 19:01

Народ, сорри, что влезаю, но, ИМХО, здесь оба в своём правы, tyomitch в том, что излишняя красота в мелких прогах обычно не нужна, GSerg в том, что делится своим опытом с другими.
Вообще-то говоря, вы уже давно залезли в оффтоп, как в топике про +/- .NET. Поэтому предлагаю вам остановиться во избежание ругани.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.08.2004 (Пн) 19:15

GSerg писал(а)::shock:
Вообще-то я хотел показать, как это делается в принципе.

Или я плохо объясняю, или ты не можешь понять, о чём я говорю.
Ну, скажем, если бы химик-энтузиаст написал на форуме с 5000+ подписчиками, как "в принципе" приготовить взрывчатку из подручных материалов, ты бы как к этому отнёсся?
Против меню я ничего не имею, когда их употребляют к месту и с умом. Твоя реализация - ну, любопытная вещь, хотя едва ли когда-нибудь воспользуюсь сам.

Морально устойчивых девелоперов имхо меньшинство. Я, когда мне только VB попался в руки, естественно начал с того, чтобы налепить цветастых мигающих кнопок, всплывающих с соответствующим звуком меню, и т.д. Не прога, а карусель, одним словом. Тех же, кто этот этап ещё не прошёл, я очень хочу от него предостеречь.

2AAZ: я не про то, что опытом делиться не надо, а про то, что делать это надо осторожно. А ругани никакой не будет :-)

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

Сообщение GSerg » 23.08.2004 (Пн) 19:18

Ругани точно не будет :)
Моя реализация - любопытная для меня вещь, и ею я воспользуюсь...

И я могу понять, о чём ты говоришь :)
Но скажи мне тогда, как определить грань между "надо поделиться" и "а вдруг не созрели"? :)


ЗЫ: Присоединяюсь к твоим предостережениям.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.08.2004 (Пн) 22:41

GSerg писал(а):Но скажи мне тогда, как определить грань между "надо поделиться" и "а вдруг не созрели"? :)

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

Теперь конструктив. Чтобы картинки в меню-97 были правильного цвета, можно строчку
Код: Выделить всё
DrawState hdc, 0, 0, ByVal hPic, 0, Left + 2, Top + 2, 16, 16, DST_BITMAP Or DSS_NORMAL

заменить на
Код: Выделить всё
TransparentBlt hdc, Left + 2, Top + 2, 16, 16, Picture2.hdc, 0, 0, 16, 16, Picture2.BackColor

Совместимость: Win98+/Win2000+
Объявление:
Код: Выделить всё
Private Declare Function TransparentBlt Lib "msimg32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nWidthSrc As Long, ByVal nHeightSrc As Long, ByVal crTransparent As Long) As Long

+ надо задать Picture2.BackColor (в твоём случае, &HC0C0C0)

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

Сообщение GSerg » 23.08.2004 (Пн) 22:56

Ого! :)
Вот он, критерий, оказывается :)

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


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

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

Сейчас этот форум просматривают: AhrefsBot, Yandex-бот и гости: 22

    TopList