All Forums
 Категория Visio
 Форум Вопросы и ответы
 Undo неправильного действия
Author Previous Topic Topic Next Topic  

Евгений

88 Posts

Posted - 01/20/2005 :  16:50:51
Как это сделать? Скажем, юзер перенес шейп туда, куда не положено. Высвечиваю в этот момент messageBox, что так нельзя, и хочу вернуть все в прежнее положение. Просто Application.Undo бросает непонятный exception. Подскажите.

Евгений

88 Posts

Posted - 01/20/2005 :  16:58:02
В reference написано следующее:
quote:
The number of times that code can call the Undo method depends on whether or not the code is executing in the scope of an open undo unit. Code runs in the scope of an open undo unit if it is:

a macro or add-on invoked by the Visio user interface.
In an event handler responding to a Visio event other than the VisioIsIdle event.
In a user-created undo scope.
If code is not executing in the scope of an open undo unit, it can call the Undo method for each undo unit presently on the Visio undo stack. The maximum number of units on the undo stack is set in the Options dialog box on the General tab (20 is the default). If the number of calls to the Undo method exceeds the number of undo units on the stack, no action is taken and the Undo method raises no exception.

То есть, мне желательно или создать заранее user-created scope, или сделать так, чтобы мой код запускался извне open unit code. Как это возможно?
Go to Top of Page

Евгений

88 Posts

Posted - 01/20/2005 :  18:49:54
Блеснула надежда выполнить Application.DoCmd (1017), но ответ, что данная команда currently disabled...
Go to Top of Page

Tumanov

Russia
1198 Posts

Posted - 01/20/2005 :  20:49:26
Нехорошую операцию Вы пытаетесь сделать...
Когда изменяется формула, то CellChanged срабатывает на открытом Undo Unit по изменению этой самой формулы. В этом случае Вы можете отменять не Undo, находящиеся в стеке, а только операции, выполняемые в данном макросе. А их тут нет - вот и идет exception.
Более того, даже если бы и удалось отменить изменение формулы, то это действие тоже является изменением (хоть и обратным) и в свою очередь вызвало бы то же событие. То есть было бы зацикливание.
Там в хелпе на тему BeginUndoScope method есть хороший примерчик, поясняющий подобную вложенность.
Вот если бы дождаться завершения этого Scope, то Undo прошло бы нормально (при условии, что не вклинится какое-то незапланированное изменение).
Короче, в данном случае я посоветовал бы Вам не связываться с Undo, а просто по какому-то другому событию, например, по SelectionChanged (это когда пользователь ткнет мышкой в шейп) запомнить координаты шейпа, а в CellChanged отработать их обратно. Шейп естественно вернется на прежнее место.
Go to Top of Page

Евгений

88 Posts

Posted - 01/20/2005 :  23:23:21
quote:
Короче, в данном случае я посоветовал бы Вам не связываться с Undo, а просто по какому-то другому событию, например, по SelectionChanged (это когда пользователь ткнет мышкой в шейп) запомнить координаты шейпа, а в CellChanged отработать их обратно. Шейп естественно вернется на прежнее место.

Все гениальное - просто! :)
Go to Top of Page

Евгений

88 Posts

Posted - 01/21/2005 :  11:34:34
Все не так просто, как хотелось бы. Юзер может обозначить более чем один шейп одновременно - и сдвинуть их всех. Как теперь запомнить позиции всех обозначенных шейпов?... В качестве глобальной переменной теперь придется взять не пару x, y, а целую коллекцию пар. Как это сделать? Поискал в инете, нашел Queue, SortedList, но это видимо в VB, а как то же получить в VBA - без понятия...
Go to Top of Page

Евгений

88 Posts

Posted - 01/21/2005 :  17:45:11
Проблема тут еще такая, что если юзер введет неправильное значение проперти, я должен это отловить. То есть, при любом изменении проперти проверяю правильность значении, и если оно некорректно, я должен... что сделать? Вернуть прежнее! Неужели единственным выходом тут является записывание в переменные всех значений пропертей шейпа, которых много?
Go to Top of Page

Tumanov

Russia
1198 Posts

Posted - 01/21/2005 :  19:50:18
Тогда Вам не повезло. Придется разбираться с техникой Undo по всем правилам...
Кстати, если бы Вы изменяли Custom Properties не подручными средствами Visio, а на своей форме, то там проверять на допустимость введенного значения было бы проще. Значение вводится в другом месте (на форме), а в Properties Вы его пишете только в том случае, если оно допустимо.
В Вашем же случае можно попытаться, еще находясь в открытом Undo Unit, выставить какой-нибудь флаг, который можно проверить за пределами этого юнита, и уже там провести Application.Undo.
Важно найти событие, по которому можно проверять этот флаг. Напрашивается VisioIsIdle, но как-то уж очень мне не нравится это событие... А другие происходят несколько попозже, и пользователю может показаться, будто изменение произошло, а когда он куда-то переключится, то изменение откатится, но пользователь этого уже не будет видеть...
Короче, экспериментировать надо.
А чисто теоретически VisioIsIdle работает. Вот если в упомянутом примере BeginUndoScope в Private Sub Visio_Application_CellChanged вставить
If Visio_Application.IsInScope(m_lngScopeID) Then
Flag = 1
Debug.Print Cell.Name & " changed in scope "; m_lngScopeID
End If
и добавить обработчик
Private Sub Visio_Application_VisioIsIdle(ByVal app As IVApplication)
If Flag = 1 Then
Flag = 0
Application.Undo
End If
End Sub
то при выполнении макроса Sub ScopeActions() мы успеваем заметить, как изображение появляется на рисунке, а затем исчезает - это срабатывает Undo.
Go to Top of Page

Евгений

88 Posts

Posted - 01/21/2005 :  20:57:27
Не понимаю, чем Вам не нравится этот способ? Только что сделал пару тестов - все работает на ура, именно это и было нужно. Хотя когда появляется процедура XXX_VisioIsIdle, окно редактора VB начинает неприятно мигать (видимо, из-за постоянной обработки этой процедуры). Но юзер этого не увидит, так что все замечательно! В который раз огромное спасибо!
Go to Top of Page
  Previous Topic Topic Next Topic  
Данный сайт является архивом форума visio.artberg.ru, который был закрыт в связи с переходом на новую платформу visio.getbb.ru
Все материалы доступны только для чтения! Если у вас появились вопросы, или вы хотите что-то обсудить, связанное с Visio, обращайтесь на новый форум!
Архив был создан благодаря совместным усилиям Генадия Туманова @Tumanov (visio.artberg.ru), Александра ака @Surrogate (visio.getbb.ru), и Николая Белых @nbelyh (unmanagedvisio.com)