powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
12 сообщений из 12, страница 1 из 1
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38400935
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Допустим у меня есть MainMenu1:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
File
...
Edit 'menu_Edit
...Item1
...Item2
...Item3
View
...



Допустим есть Toolbar1 и контекстное меню (при нажатии правой кнопкой мыши) должно быть:
Код: vbnet
1.
2.
3.
Item1
Item2
Item3


(т.е. пункты меню Edit)

В VB6 я бы сделал так:
Код: vbnet
1.
2.
3.
Private Sub Toolbar1_MouseUp...
  If Button = vbRightButton Then PopupMenu menu_Edit
End Sub



В .Net на первый взгляд проще:
Код: vbnet
1.
    Me.ToolBar1.ContextMenu = ContextMenu_Edit


и все дела.
Но я типа должен рисовать дублирующее ContextMenu_Edit
Чего я делать естественно не хочу т.к. ContextMenu_Edit == menu_Edit

Как быть?
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38400940
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
  Private Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As IntPtr,
   ByVal uFlags As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nReserved As Integer, _
   ByVal hwnd As IntPtr, Optional ByRef prcRect As RECT = Nothing) As Boolean

  Private Sub ToolBar1_MouseUp(ByVal sender As Object,
   ByVal e As System.Windows.Forms.MouseEventArgs) Handles ToolBar1.MouseUp
    If e.Button = MouseButtons.Right Then TrackPopupMenu(menu_Edit.Handle, 0,
     Control.MousePosition.X, Control.MousePosition.Y, 0, Me.Handle)
  End Sub


Ничего умнее и короче не придумал.
Хотя в VB6 эту API никогда не использовал.

Вообще это ляп, если ContextMenu нельзя связать с MainMenu -у них одна природа.
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38401845
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

комрад, я вот сколько смотрю твои темы, имхо, ты фигнёй страдаешь. Да, у тебя большой опыт в VB и WinAPI. Однако, при переходе на .NET и WinForms нужно перебороть себя, и отказаться от старых привычек. Практически всё, что ты реализуешь через жопу WinAPI/вызов WndProc/сабклассинг легко можно реализовать стандартными средствами винформ.

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

И я не понял, почему ты используешь устаревшие MainMenu и ToolBar вместо рекомендуемых MenuStrip и ToolStrip. Вроде в другой теме ты писал, что внешний вид нужен современный. Ну дык более новые компоненты обеспечивают его.

В другой теме ты юзаешь сабклассинг через WndProc. Опять же, это неправильный подход для дотнета. Нужно создавать новый компонент, унаследовав его от одного из имеющихся. Можно создать UserControl, который может комбинировать сразу несколько других.
Конечно, не всегда стандартный способ подходит. Хотя бы по причине производительности. Но в большинстве случаев годится.

Удачи!
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38401856
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Но я типа должен рисовать дублирующее ContextMenu_Edit
Чего я делать естественно не хочу т.к. ContextMenu_Edit == menu_Edit

Как быть?

У контрола может быть только один родитель.
В принципе, можно в событии открывания контекстного меню - Opening - программно добавлять в него нужные toolStripMenuItem. А в событии закрытия контекстного меню - Closed - возвращать эти итемы в главное меню.
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38401929
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikВ принципе, можно в событии открывания контекстного меню - Opening - программно добавлять в него нужные toolStripMenuItem. А в событии закрытия контекстного меню - Closed - возвращать эти итемы в главное меню.

только не говори что это не косяк в дизайне
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38401962
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилтолько не говори что это не косяк в дизайне

Косяк конечно :).
Но человеку очень хочется одни и те же итемы использовать в разных местах...
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38402143
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikИ я не понял, почему ты используешь устаревшие MainMenu и ToolBar вместо рекомендуемых MenuStrip и ToolStrip. Вроде в другой теме ты писал, что внешний вид нужен современный. Ну дык более новые компоненты обеспечивают его.
Меню: глянь сюда (попробую приложить картинку вниз) 14324197
"стрип" не поддерживает стандартный (системный) вид меню. Первая картинка (Vista/7/8). Это есть современный нормальный вид. А "стрип" это видимо от слова "стриптиз". В "стрип" есть стиль System, но он годится только для классики, для Висты и выше он ни фига не систем. Стрип (внешний вид) выигрывает только на классике.
Если я ошибаюсь и можешь стрипом сделать такой же вид меню,
то Net. код в студию (рисование не принимается).

Toolbar:
Еще раз рассказываю.
В стандарном (современном) стиле Toolbar идет в паре с Rebar (он же Coolbar).
Rebar может иметь тематическую стандартную стилистическую подложку (Виста и выше), например:
"Communication" (темно синий)
Код: vbnet
1.
2.
SetWindowTheme g_hwndRebar, StrPtr("Communications"), 0 'синий системный градиент
SetWindowTheme g_hwndToolbar, StrPtr("Communications"), 0 'белые буквы на кнопках - системно

Открой "Windows Fax and Scan", либо глянь сюда 14840756
"Media" (черный) (Windows Media Player)

1)Сделай мне то же самое с ToolStrip
или хотя бы
2) Вставь тулстрип в Parent-Rebar (API) -у меня не получилось
Если сделаешь, то .Net Код в студию.(рисование не принимается).



petalvikНа мой взгляд, совсем не сложно (и не долго) пару раз клацнуть мышкой и настучать на клаве те же самые названия итемов повторно. Ну а обработчики событий назначить те же. Это будет быстрей и проще, чем ты возишься сейчас.
У контрола может быть только один родитель.
Да мне не сложно продублировать. А про родителя ты правильно заметил. Он у контекстного меню должен быть Form.Handle, обрати внимание на Me.Handle в TrackPopupMenu. А я подозреваю что с интерпретацией ContextMenu вообще что-то не так.
Куда ContextMenu шлет сообщения. Есть подозрение что не в Form, и здесь возникают определенные сложности. Хотя буду еще играться с ContextMenu - не все ж контекстные меню "дублированные".

petalvikтолько не говори что это не косяк в дизайне.
Конечно косяк, тупейший нетовский "наворот". ContextMenu и MainMenu это один и тот же контрол. И использовать сабменю главного меню в качестве контекстного для чего-нибудь - вполне стандартный подход.
Я уже про это написал.
petalvikВообще это ляп, если ContextMenu нельзя связать с MainMenu -у них одна природа.
==========
petalvikВ другой теме ты юзаешь сабклассинг через WndProc. Опять же, это неправильный подход для дотнета.
Хорошо, ответь по-Net-овски на вот этот вопрос для начала:
Как сделать событие Handle на "все элементы одного типа"
Код в студию (перечисление Handles через запятую или добавление через Handles (конкретный контрол) не принимается).
.Net-овский код где конкретные контролы (а их может сотня) перечисляются через запятую, я уже привел.
Я могу делать так:

Код: vbnet
1.
2.
3.
4.
  Private Sub AnyMenuItem_DrawItem(ByVal sender As Object,
   ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles menu_FileNew.DrawItem,
   menu_FileEdit.DrawItem,
   ...

, где AnyMenuItem_DrawItem -название ф-ции обработчика, при этом должен тупо и явно перечислять Handles.

Ради бога, я за .Net методы.
Только я сначала слышу фразу ".Net 100% может все"
а как спрашиваю
Как сделать конкретно то-то и то-то?
то мне в ответ в 99% тишина.

Подкрепляйте ваши ответы .Net примерами, если делаете такие утверждения.
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38403303
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77"стрип" не поддерживает стандартный (системный) вид меню. Первая картинка (Vista/7/8). Это есть современный нормальный вид. А "стрип" это видимо от слова "стриптиз". В "стрип" есть стиль System, но он годится только для классики, для Висты и выше он ни фига не систем. Стрип (внешний вид) выигрывает только на классике.

Каюсь, у меня со времён WinXP всегда стоит стиль Classic (типа средний на картинке), поэтому я и не знал о существовании проблемы :).

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

Ну, тут только удалять сабменю из дочерней коллекции одного контрола, и добавлять в другой контрол, как я уже предлагал. Это всего лишь перекинуть указатель (ссылку). С точки зрения дотнета - косяк, зато просто, и не нужно WinAPI/pinvoke.

Дмитрий77Хорошо, ответь по-Net-овски на вот этот вопрос для начала:
Как сделать событие Handle на "все элементы одного типа"

Тут дело в том, что использование Handle - не дотнетовский подход. Нужно полностью отказывать от этого.
Хотя и мне приходилось делать сабклассинг, когда не получалось по "дотнетному", поэтому ничуть не осуждаю.
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38403331
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikНу, тут только удалять сабменю из дочерней коллекции одного контрола, и добавлять в другой контрол, как я уже предлагал. Это всего лишь перекинуть указатель (ссылку). С точки зрения дотнета - косяк, зато просто, и не нужно WinAPI/pinvoke.

Меню вообще штука непростая.
Я сейчас наверно на другом языке буду объяснять.
У главного меню формы есть hMenu -handle
У каждого сабменю (файл, правка, справка) есть свой hSubMenu -handle
В VB6 контекстное всегда вызывается как сабменю главного (ну или сабменю от сабменю наверно тоже можно), нет понятия контекстного.
И я могу сказать следующюю вещь (благо смотрел на все это сквозь API призму).

Если в VB6 главному меню поставить =Visible,
то при вызове PopupMenu (VB6)==TrackPopupMenu(API),
всегда будет вылезать окно с одним и тем же hSubMenu, равном hSubMenu сабменю из которого мы его делаем, т.е. это оно и есть, просто ему сделали Show() в нужном месте.
А вот если в VB6 главному меню поставить Visible=false,
то всегда будет вылезать окно каждый раз с новым hSubMenu, то бишь окно меню (контекстного) каждый раз будет создаваться заново и потом удаляться. Поэтому например Blend-картинки (см. мой левый рисунок) на вистах статически (при лоад_form) итемам этого меню присвоить нельзя и только сабклассинг (ну или InitMenu событие - я кстати оценил что в .Net с этим значительно лучше).

petalvikДмитрий77Хорошо, ответь по-Net-овски на вот этот вопрос для начала:
Как сделать событие Handle на "все элементы одного типа"

Тут дело в том, что использование Handle - не дотнетовский подход. Нужно полностью отказывать от этого.
Хотя и мне приходилось делать сабклассинг, когда не получалось по "дотнетному", поэтому ничуть не осуждаю.
Ай-яй. Невнимательно читал.
Ты счас говоришь про Handle== Hwnd (окна),

а в теме которую ты процитировал говорится о Handles которая подписывает Net контролы под обработку события (можно через запятую).
Хотя, сорри, я опечатался (похоже звучит) имелось ввиду
Handles и AddHandler ,
но это значит что ты даже поглядел туда.

Код: vbnet
1.
2.
3.
4.
5.
  Private Sub AnyMenuItem_DrawItem(ByVal sender As Object,
   ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles menu_FileNew.DrawItem,
   menu_FileEdit.DrawItem,

AddHandler menu_subitem.DrawItem, AddressOf DrawMenuItem



Т.е. вопрос то был как сделать "по-нетовски", при этом подробно описано что мне не нравится.
Потому что все чего мне нужно сделать с меню (например картинки) можно как раз думаю сделать по нетовси через события, нужные для этого события .Net предоставляет, но мне нужна "массовая обработка" всех итемов Я могу и ручками перечислить поименно, но я например через год накидал в конструкторе еще 2 итема, и я хочу чтоб они автоматически были "подписаны" на событие, понимаешь о чем я?
И кстати,
вариант по типу
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
    'menu
    For Each menu_item As MenuItem In MainMenu1.MenuItems
      If (menu_item.Text = "&File") Or (menu_item.Text = "&Help") Then
        For Each menu_subitem As MenuItem In menu_item.MenuItems
          AddHandler menu_subitem.DrawItem, AddressOf DrawMenuItem
        Next
      End If
    Next


ужасен, т.к. сабменю могут иметь свои сабменю, и For Each без вложенной хитро-выдуманной рекурсии безполезен (посмотри на мое описание с hMenu -> hSubmenu->hSubSubmenu и поймешь почему).
А через API у меня один единственный
Код: vbnet
1.
Case WM_DRAWITEM


на ВСЕ итемы.
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38403375
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77на ВСЕ итемы.

ну и откажись полностью от нетовских меню, рисуй на API
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38403595
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилну и откажись полностью от нетовских меню, рисуй на API
Не, извини. Полностью точно не надо. Рисовать итемы проще в конструкторе. И простые действия, типа обработка нажатия item естественно тоже удобней без API.
По поводу "на все итемы" тоже вопрос неоднозначный.
Я ведь и в API начинаю выяснять что за item, напр. чтобы присвоить разные картинки разным итемам.
И если в среде это делается через .Text например, то в API надо бабахать еще кучу API в обработчике и т.д.
Но с другой стороны, чтобы воткнуть те же картинки на "классике", надо менять размеры для всех итемов включая те, что без картинок (минимум в данном подменю), и здесь уже выяснять что за итем не надо, т.е. "типизация", и здесь конечно перечисление через запятую начинает бесить.
...
Рейтинг: 0 / 0
MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
    #38403632
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77и здесь конечно перечисление через запятую начинает бесить.
не надо беситься, инструмент осваивай
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / MainMenu и ContextMenu (не стрипы) -а если у меня ContextMenu=Submenu(MainMenu)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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