Форум пользователей Visio

Форум по вопросам применения и программирования в Visio
Текущее время: 29 мар 2024, 06:38

Часовой пояс: UTC + 3 часа [ Летнее время ]


Правила форума


При размещении файлов предпочтительным является формат vsd (а не vsdx/vsdm)
Размещая ваши вложения на форуме не используйте имена файлов содержащих кириллицу, в противном случае файл будет иметь имя .<расширение файла> !

Для форматирования ваших сообщений используйте BBCodes, описание используемых на форуме BBCodes.



Начать новую тему Ответить на тему  [ Сообщений: 5 ] 
Автор Сообщение
 Заголовок сообщения: Окна Ancor в Visio
СообщениеДобавлено: 15 сен 2020, 18:58 
Не в сети
Бывалый

Зарегистрирован: 19 июн 2015, 22:18
Сообщений: 114
Использую Visio c: 2013
Очков репутации: 21

Добавить очки репутацииУменьшить очки репутации
Делаю Add-In на C#.

Нужно сделать окно, которое ведет себя так же как окна Visio - докается к сторонам внутри окна, имеет возможность скрываться и т.д.
Такие возможности описаны в MSDN:
https://docs.microsoft.com/en-us/previous-versions/office/developer/office2000/aa140261(v=office.10)?redirectedfrom=MSDN
и современный вариант, который содержит ошибку:
https://docs.microsoft.com/en-us/office/vba/api/visio.windows.add
(В современном варианте немного перепутали: в функцию поиска окна нужно искать заголовок формы frmMain).

Но не в этом суть. Вот код:
Сначала об]являем функции WinAPI, которые будем использовать
Код:
public static class WinAPI
    {
       
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SetParent(IntPtr hWndChild, int hWndNewParent);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SetWindowLongPtrA(IntPtr hwnd, int nIndex, int dwNewLong);


а затем используем

Код:
public void Command1(object sender)
        {
            const int GWL_STYLE = (-16);
            const int  WS_CHILD = 0x40000000;
            const int WS_VISIBLE = 0x10000000;

            frm = new Form1(sender);

            var vsoWindow = this.Application.ActiveWindow.Windows.Add(
                bstrCaption: "My New Window",
                nFlags : Visio.VisWindowStates.visWSVisible | Visio.VisWindowStates.visWSDockedRight,
                nType : Visio.VisWinTypes.visAnchorBarAddon,
                nWidth : frm.Width, nHeight : frm.Height);

            var s1 = WinAPI.SetWindowLongPtrA(frm.Handle, GWL_STYLE, WS_CHILD | WS_VISIBLE);
            var s2 = WinAPI.SetParent(frm.Handle, vsoWindow.WindowHandle32);

            frm.Top = 0;
            frm.Left = 0;
            frm.Show();


1) Я создаю пустое окно с возможностью докаться, и докаю его вправо:

var vsoWindow = this.Application.ActiveWindow.Windows.Add(
bstrCaption: "My New Window",
nFlags : Visio.VisWindowStates.visWSVisible | Visio.VisWindowStates.visWSDockedRight,
nType : Visio.VisWinTypes.visAnchorBarAddon,
nWidth : frm.Width, nHeight : frm.Height);

2) я создаю форму (на которую накидал button)
frm = new Form1(sender);

3) Я объявляю стиль этой формы как дочерний и делаю ее видимой:
var s1 = WinAPI.SetWindowLongPtrA(frm.Handle, GWL_STYLE, WS_CHILD | WS_VISIBLE);

4) Объявляю пустое окно родительским для этой формы
var s2 = WinAPI.SetParent(frm.Handle, vsoWindow.WindowHandle32);

5) frm.Top = 0;
frm.Left = 0;
frm.Show();
Это уже от безысходности - пытаюсь показать окно. Но оно не показывается. В чем ошибка?


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Окна Ancor в Visio
СообщениеДобавлено: 15 сен 2020, 22:03 
Не в сети
Ветеран
Аватара пользователя

Зарегистрирован: 28 апр 2013, 14:03
Сообщений: 963
Откуда: Вена, Австрия
Использую Visio c: 1998
Очков репутации: 100614

Добавить очки репутацииУменьшить очки репутации
Не очень понятно, в чем беда - в проекте же окно галочкой добавляется? Зачем снова все делать руками? Вот попробовал записать видео:
https://youtu.be/X1gcBOeI84w

Если не поможет, можно подробности?

_________________
Полезные инструменты для создания диаграмм Visio:
https://unmanagedvisio.com/


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Окна Ancor в Visio
СообщениеДобавлено: 16 сен 2020, 14:19 
Не в сети
Бывалый

Зарегистрирован: 19 июн 2015, 22:18
Сообщений: 114
Использую Visio c: 2013
Очков репутации: 21

Добавить очки репутацииУменьшить очки репутации
Да, мой код на порядок примитивнее. Я просто хотел выполнить то, что описано в MSDN, но видно здесь много подводных камней.
Я изучил Ваш код.
Вижу была задумка сделать управление несколькими окнами (класс PanelManager), но потом (метод TogglePanel) все было свернуто до одного окна. Хотя возможно в этом есть смысл: один плагин - одно окно.
Но самая большая прелесть - это, конечно, класс PanelFrame : IVisEventProc.
Я вижу, что была проделана большая работа и, возможно, множество экспериментов. У меня есть несколько вопросов, буду очень благодарен, если Вы мне объясните некоторую магию этого кода.
1)
Код:
private const string AddonWindowMergeId = "29dc9325-911a-4ad1-8594-d775e374c180";

....
_visioWindow = visioParentWindow.Windows.Add(
                        _form.Text,
                        (int)VisWindowStates.visWSDockedRight | (int)VisWindowStates.visWSAnchorMerged | (int)VisWindowStates.visWSVisible,
                        VisWinTypes.visAnchorBarAddon,
                        0,
                        0,
                        300,
                        300,
                        AddonWindowMergeId,
                        string.Empty,
                        0);

Что за AddonWindowMergeId ? Для чего он нужен? В документации по Visio сказано, что это : Merge ID of the window.
То есть ID объединенного окна. Но когда мы добавляем окно в словарь ( _panelFrames.Add(window.ID, panelFrame ); ) я вижу в отладчике просто ID окна - простые цифры, не GUID.

2)
Код:
SetWindowLong(_form.Handle, GWL_EXSTYLE, WS_EX_COMPOSITED);

Этот стиль окна определяет, что окно будет перезаписываться снизу-вверх. То есть сначала родительское окно (нижнее), потом дочернее (верхнее). В MSDN об этом не было сказано. Без этого не работало?

3)
Код:
private static void JiggleWindow(
            IntPtr handle)
        {
            var lpRect = new RECT();
            GetWindowRect(handle, ref lpRect);

            var l = lpRect.left;
            var T = lpRect.top;
            var w = lpRect.right - lpRect.left;
            var h = lpRect.bottom - lpRect.top;

            const int flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER;
            SetWindowPos(handle, new IntPtr(0), l, T, w, h + 1, flags);
            SetWindowPos(handle, new IntPtr(0), l, T, w, h, flags);
        }

Для чего сначала считывается позиция окна, а потом устанавливается? Для того, чтобы прописать флаги?
SWP_NOCOPYBITS - не перерисовывать содержимое клиентской области.
Область родительского окна закрыта дочерним. Возможно это нужно для улучшения производительности?
SWP_NOMOVE | SWP_NOZORDER - определяют не изменять Z порядок и положения окна.
Получается, что мы передаем в окно только РАЗМЕР, то есть меняем размер окна?

4)
Код:
SetWindowPos(handle, new IntPtr(0), l, T, w, h + 1, flags);
SetWindowPos(handle, new IntPtr(0), l, T, w, h, flags);

Для чего нужно было менять размер окна? Оно не перерисовывалось?

5) Событие закрытие окна отлавливается 2-мя способами
1 - Привязкой к событию закрытия окна : _visioWindow.BeforeWindowClosed += OnBeforeWindowClosed;
2 - В отлавливании события закрытия окна в object IVisEventProc.VisEventProc

Для чего? BeforeWindowClosed не всегда отрабатывало?

6)
Код:
if (_visioWindow != null && _form != null)
                {
                    _form.Hide();

                    SetWindowLong(_form.Handle, GWL_STYLE, WS_OVERLAPPED);
                    SetParent(_form.Handle, (IntPtr)0);

                    _visioWindow.Close();
                    _visioWindow = null;
                }

                if (_form != null)
                {
                    _form.Close();
                    _form.Dispose();
                    _form = null;
                }

Я вижу, что сначала убирается стиль дочернего окна в форме (SetWindowLong(_form.Handle, GWL_STYLE, WS_OVERLAPPED);)
Потом убирается указатель на родительское окно ( SetParent(_form.Handle, (IntPtr)0); )
И только после этого закрывается родительское окно, а затем форма.
Получается - закрытие родительского окна не приводит к закрытию окна дочерней формы?


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Окна Ancor в Visio
СообщениеДобавлено: 16 сен 2020, 14:52 
Не в сети
Ветеран
Аватара пользователя

Зарегистрирован: 28 апр 2013, 14:03
Сообщений: 963
Откуда: Вена, Австрия
Использую Visio c: 1998
Очков репутации: 100614

Добавить очки репутацииУменьшить очки репутации
О, круто ты реально полез в код :D Да, а вообще-то оно заработало? Спасибо за вопросы кстати, они все классные :D

1. MergeID - для случая нескольких окон. Чтобы окно не мержилось с окнами Visio в один таб, а вставало в отдельный фрейм.
Еще например если создается два окна с одним и тем же MergeID, чтобы можно было их поставить в один таб.
По этому слову ("MergeID") на VisGuy гуглится объяснение, также на этом форуме должен быть топик. Но по сути это поведение для докинга (вставать в один таб с другими или нет)
Изображение

2. Это добавлено для того чтобы избавиться от мерцания при перерисовке. Объяснение тут:
https://stackoverflow.com/questions/261 ... ls/2613272

3, 4. Эта безумная фигня с изменением размера на 1 пиксель, а потом назад да, для форсирования перерисовки (закрывает баг в одной из версий Visio).
Ссылку на баг и обсуждение сходу не нашел, найду - добавлю. Скорее всего на visguy и на microsoft connect (лет 5 назад). Redraw или Invalidate не помогало, только такой вот ресайз на 1 пиксель сработал.
Надо бы поставить для какаой конкретно версии Visio проблема, кажется 2013 и 2016.

5. Окно можно закрыть нажатием маленький на крестик (на панели), нажатием на кнопку. Также можно закрыть документ целиком. Там есть 2 случая - закрывается панель, и закрывается вся диаграмма (файл).
В общем надо учитывать, что может быть открыто несколько файлов диаграмм одновременно. Каждый файл будет иметь свою "панель", и в результате их может быть много (поэтому PanelManger)
Панель не одна на Visio, а одна на каждый открытый документ ("одна на все приложение" - в Visio такого нет, в отличие от других программ офиса)
Нотификация важна, чтобы перерисовать "нажатость" кнопки на ленте например. Также состояние кнопки надо обновлять при переключении на другое окно (файл)

6. Здесь я уже и сам не вспомню почему так. Вроде бы Visio падал, если не закрыть сначала дочернее. Но точно не помню.

Да если все заработает - с тебя подписка и колокольчик отзыв на маркетплейсе :mrgreen:

_________________
Полезные инструменты для создания диаграмм Visio:
https://unmanagedvisio.com/


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Окна Ancor в Visio
СообщениеДобавлено: 17 сен 2020, 11:28 
Не в сети
Бывалый

Зарегистрирован: 19 июн 2015, 22:18
Сообщений: 114
Использую Visio c: 2013
Очков репутации: 21

Добавить очки репутацииУменьшить очки репутации
nbelyh
Спасибо ОГРОМНОЕ за Ваш код и пояснения к нему. Все заработало. Если меня что-то будет не устраивать, я по-крайней мере. вижу путь для развития.
Я когда-то на VBA и ShapeSheet сделал несколько фигур с множеством текстовых полей.
Поля можно включать\отключать через контекстное меню, а так же двигать с помощью управляющих ручек. При щелчке мышью открывается редактор текста указанного поля.
Это удобно, когда рисуешь схему, и нужен какой-нибудь коммутатор с несколькими портами. Но добавление такого поля работа очень кропотливая. Нужно создавать все новые фигуры, а так же добавлять поля к ранее созданным. Поэтому хочу решить этот вопрос с помощью плагина.


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]



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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8


Вы можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Вы можете создать форум бесплатно PHPBB3 на Getbb.Ru, Также возможно сделать готовый форум PHPBB2 на Mybb2.ru
Русская поддержка phpBB