Страницы: 1
RSS
VBA Как увидеть имя контекстного меню
 
Всем привет,  
 
В процессе выполнения процедуры по DoEvents возможно вызвать контектное меню.    
Вопрос1: Как перехватить имя этого меню.  
 
Вопрос2: Есть ли оператор в коллекции Application, который выключает-включает все стандартные контекстные меню при выполнениии процедуры.  
 
 
Заранее благодарен,  
 
Владимир.
 
For Each x In CommandBars  
   Debug.Print x.Visible  
Next
 
Не так все просто аноним, x.Visible надо ставить в проверку,  
но и в этом случае эта процедура выгрузит все видимые на данный момент видимые меню.  
 
Меня же интересует активное (имеющее фокус) в данный момент...
 
ну перед запуском запоминаете видимые, потом ищете прибавку..  
 
в любом случае можете промазать - окно может закрыться до осуществления проверки.  
 
может лучше объявить все меню, невидимые до запуска, как недоступные?
Живи и дай жить..
 
Сделать все недоступным циклом не сложно. Как потом также просто восстановить?  
Запоминать состояние до выполнения цикла еще более муторная задача.  
 
Беда еще в том, что при вызове меню приостанавливается выполнение процедур и нет возможности опросить свойства ActiveControl...
 
ничего муторного:  
 
Sub t()  
   Dim x As CommandBar, r As New Collection  
   For Each x In CommandBars  
       If Not x.Visible Then  
           r.Add x  
           x.Enabled = False  
       End If  
   Next  
   Do  
   ' тут ваш код  
   DoEvents  
   Loop Until [a1] = 1
   For Each x In r  
       x.Enabled = True  
   Next  
End Sub  
 
обратите внимание на условие выхода из цикла, если будете пробовать :)
Живи и дай жить..
 
Не понятно, для чего это нужно.  
Отключения панелей, скорее всего, не достаточно, потому что можно зайти в редактирование ячейки и тем самым остановить цикл с DoEvents.  
Кроме того, для Excel 2007/2010 убрать панели мало - там лента.  
 
Если цель в использовании DoEvents для перерисовки экрана, но при этом еще требуется  запретить пользователю что-либо делать, то можно использовать Application.Interactive.  
 
Пример:  
Sub Test()  
 Dim t!  
 t = Timer + 5 ' <-- цикл на 5 секунд  
 Application.Interactive = False  
 While Timer < t  
   DoEvents  
   'Application.StatusBar = Now ' <-- что-то делаем    
 Wend  
 Application.StatusBar = False  
 Application.Interactive = True  
End Sub
 
Спасибо Владимир, что откликнулись.  
 
Задача в следующем: Создал собственное контекстное меню, которое вызывается API-функцией GetKeyState по правому клику мышы. Срабатывание нечеткое в некоторых мне непонятных случаях вызываются стандартные меню, поэтому и появилась идея подавить только эти контекстные меню, имен которых я не знаю...  
 
Владимир, не могли бы Вы по подробнее раскрыть действие свойства Application.Interactive. Будет ли работать меню пользователя?
 
Слэн, спасибо. Идея понятна...
 
Application.DisplayAlerts = False полностью блокирует клавиатуру и мышку, работает только код макроса.  
 
Для озвученной цели можно обойтись без API.  
Чтобы подавить все контекстные меню по правому клику мышки и вызвать свое меню, например, только на листе с кодовым именем Лист1, подойдет такой макрос в модуле ЭтаКнига:  
 
' Код в модуле ЭтаКнига  
Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)  
 If Not Sh Is Лист1 Then Exit Sub  
 With Application.CommandBars.Add(Name:="Custom", Position:=msoBarPopup, Temporary:=True)  
   .Controls.Add Type:=msoControlButton, ID:=3, Temporary:=True  
   .Controls.Add Type:=msoControlComboBox, Temporary:=True  
   .ShowPopup  
   .Delete  
 End With  
 Cancel = True  
End Sub  
 
Панель с 2-мя контролами приведена для примера, нужно вписать свой код.
 
Спасибо Владимир,  
Но контекстное меню вызывается не на листе, а на диаграмме. Здесь пример:  
http://www.planetaexcel.ru/forum.php?thread_id=29647  
 
Я сейчас отлаживаю эту надстройку и пытаюсь устранить все недоработки, (надстройка корректно работает на Excel 2007,с Excel 2003 сразу не пошло и я не стал заморачиваться)...
 
Владимир, в коде, который я привел выше, достаточно сначала определить, есть ли под курсором диаграмма. Если есть, то выполнить код, иначе - Exit Sub.  
При этом будет подавлено только контекстное меню диаграмм.
 
Всем привет,  
 
На примере во вложении пытаюсь выключить все без исключения контекстные меню.  
Запускаю, действительно все меню листа заблокированы, проверяю на диаграмме - не тут то было...  
 
Вопрос: Как достучаться до контекстных меню диаграмм и заблокировать их процедурой?  
 
Заранее благодарен,  
 
Владимир.
 
Прошу прощения, забыл вложение...
 
\у меня оно отключается...
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Саш, правый клик на диаграмме - контекстное меню доступно...
 
2003. После длинной кнопки по ПКМ нет ни одного меню
 
Ну  это понятно. В 2003 диаграммы организованы иначе нежели в 2007.    
 
Пытался увидеть через Watch, но безрезультатно...
 
Безнадега какая-то с этим меню... Воспользовался советом Владимира(ZVI):  
 
On Error Resume Next  
If obj.Type = msoChart Then  
   Application.Interactive = False  
      DoEvents  
   Application.Interactive = True  
Else  
   DoEvents  
End If  
 
НО, при клике на мышь система издает противный "блям"  
Вопрос:  
Как систему заставить молчать?
 
Не знаю поможет это вам или нет (а может это и есть в Вашем коде), но как вариант "щлепнуть" все  
 
Sub io()  
Dim x As Object  
For Each x In CommandBars  
   If x.Type = msoBarTypePopup Then  
Debug.Print x.Name  
       x.Enabled = False ' True  
   End If  
Next  
End Sub  
 
 
Вот тут еще один интересный вопрос, мож Вы знаете ответ?)  
http://www.planetaexcel.ru/forum.php?thread_id=31716&page_forum=5&allnum_forum=124
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
вот еще (пальцем в небо)    
 
Sub io()  
Dim x As Object  
For Each x In CommandBars.FindControls(Type:=msoBarTypePopup)  
   MsgBox x.Caption  
Next  
End Sub
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
{quote}{login=VovaK}{date=18.10.2011 09:20}{thema=}{post}Безнадега какая-то с этим меню... Воспользовался советом Владимира(ZVI)...{/post}{/quote}  
Владимир, я же потом, когда выяснил назначение, предложил использовать событие.  
Приложил пример кода с модулем класса для пользовательского меню на выделенной диаграмме.
 
А вот так можно еще заблокировать и контекстное меню невыделенной диаграммы
 
Бог мой, как красиво, задыхаюсь от восторга. Владимир низкий поклон. Только вот появился вопрос. Проверяю дома и  у меня и на выделенной и на не выделенной диаграмме отрабатывает класс, предварительно выделив диаграмму. Второй вариант гасит уже пользовательское меню (отрабатывает oChart_Activate).  
Вопрос: Владимир, почему все таки меню диаграмм в локализации Excel 2007 (где диаграммы это - объекты типа Shape) не доступны для редактирования через коллекцию Application.CommandBars? Ну к примеру вставить дополнительную команду в меню "Chart" или "Cure", или те же попытки заблокировать их посредством .Enabled = True.  
Очень запал этот вопрос, потому как уже давно изучаю диаграммы и вижу на каждом шагу различия в организации диаграмм версий Excel 2003 и 2007 года. Но прочитать про эти различия нигде не могу, в инете просто нет этой информации.    
 
Еще раз огромное спасибо,  
 
Владимир.
 
{quote}{login=VovaK}{date=19.10.2011 08:33}{thema=}{post}...почему все таки меню диаграмм в локализации Excel 2007 (где диаграммы это - объекты типа Shape) не доступны для редактирования через коллекцию Application.CommandBars?{/post}{/quote}  
Не изучал этот вопрос. Но совершенно очевидно, что, начиная с Excel 2007, интерфейс и графические объекты претерпели существенные изменения.  
 
Что касается диаграмм, то их объектная модель вполне очевидная в любой версии Excel и доступна из VBA. Не сложно также заметить, что контекстные меню диаграмм возникают и при нажатии на кнопку мышки, и при её отпускании, а также при удержании.  
 
Перехватив событие нажатия кнопки мышки, можно корректно и эффективно заблокировать встроенные контекстные меню диаграмм и отобразить своё.  
Приложил такой вариант кода.
 
Спасибо Владимир,  
 
Пытался использовать Ваш Вариант, но из цикла по DoEvents события почему-то не отрабатываются.  
 
Нашел подходящее решение средствами WinAPI (подсказал знакомый системщик):  
 
Private Const APPCOMMAND_VOLUME_MUTE As Long = &H80000  
Private Const WM_APPCOMMAND As Integer = &H319  
Declare Function SendMessageW Lib "user32.dll" (ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long  
...  
On Error Resume Next  
If Not(obj.Type = msoChart) Then  
DoEvents  
Else  
SendMessageW Application.hwnd, WM_APPCOMMAND, Application.hwnd, APPCOMMAND_VOLUME_MUTE  
Application.Interactive = False  
DoEvents  
Application.Interactive = True  
SendMessageW Application.hwnd, WM_APPCOMMAND, Application.hwnd, APPCOMMAND_VOLUME_MUTE  
End If  
...  
Всем еще раз спасибо,  
 
Владимир.
 
Владимир, может здесь найдется полезная информация:  
http://www.rondebruin.nl/contextmenu.htm  
 
 
в т.ч:  
Excel 97-2003  
You can add controls to every context menu with VBA code    
Not possible to change context menus with RibbonX  
 
Excel 2007  
You can add controls to almost every contextmenu with VBA code  
Not possible to change for example the Shapes and Picture contextmenu with VBA  
Not possible to change Context menus with RibbonX  
 
Excel 2010  
You can add controls to almost every contextmenu with VBA code  
Not possible to change for example the Shapes and Picture toolbar with VBA  
But you can add buttons/menus to every ContextMenu with RibbonX but if you want  
to disable or re-purpose controls you may not be able to find the correct idMso
Страницы: 1
Наверх