Как получить IDrawingObject

Автор midreyk, 06.02.10, 20:00:21

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

midreyk

Люди подскажите как получить интерфейс IDrawingObject в API7 для слоя или вида.
В справке написано что через  IUnknown QueryInterface, но вот как я не въехал  :%:

udachnik

Для IVIEW в справке написано, что можно получить интерфейсы: IViewDesignation,  IDrawingContainer,  IBuildingContainer, ISymbols2DContainer.Для ILayer вообще ничего не написано, по поводу возможности получения от него дополнительных интерфейсов.
IDrawingContainer например от IVIew можно получить так(C#):
  public static IDrawingContainer GetIDrawingContainer(IView CurrentView)
        {       
         IntPtr pUnk = IntPtr.Zero;
         IntPtr ppv = IntPtr.Zero;
         IDrawingContainer NewDrawingContainer;
         try
         {         
            pUnk = Marshal.GetIDispatchForObject(CurrentView);
            Attribute INewInterfaceAttribute =
                 Attribute.GetCustomAttribute(typeof(IDrawingContainer), typeof(GuidAttribute));           
            Guid iid = new Guid(((GuidAttribute)INewInterfaceAttribute).Value);
            if ( Marshal.QueryInterface(pUnk, ref iid, out ppv) != 0)
            {
                throw new Exception();
            }
            NewDrawingContainer =
               Marshal.GetObjectForIUnknown(ppv) as IDrawingContainer;               
          }
          finally
          {
            if (pUnk != IntPtr.Zero)
                 Marshal.Release(pUnk);         
            if (ppv != IntPtr.Zero)
                 Marshal.Release(ppv);       
          }
          return NewDrawingContainer;
         }   
Только зачем тебе это нужно?Я думаю есть пути попроще, чем так изгалятся.

midreyk

Мудрено. Но спасибо за сочувствие.
Нужно оно для того чтобы изменить свойство вида.
Вот из справки.
Цитировать
Свойство вступает в силу после вызова метода IDrawingObject::Update.
.

Я вроде сам додумался, вот на делфи
----------
var
  myView: IView;
  DrwObj: IDrawingObject;
begin
  ......
  DrwObj := myView as IDrawingObject;
  DrwObj.Update;
  ........
end
--------------
Работает.


udachnik

Отмечу, что в моём примере речь шла о IDrawingContainer.
Я не понял ваш вопрос с самомго начала.
По иерархии IView реализует IDrawingObject, поидее и так должно работать:

var
  myView: IView;
  begin
  ......
  myView.Update;
    ........
end

midreyk

14.02.10, 18:08:48 #4 Последнее редактирование: 14.02.10, 18:42:11 от midreyk
Да так работает. Спасибо.

А справка к API корявая. Нельзя было сразу написать что у IViews есть метод Update.

Misha

                 Подскажите, пожалуйста где у меня ошибка. Пытаюсь получить интерфейс  IModelContainer, так, как было описано выше, но не получается:(
.....
                    IKompasDocument3D document3D = (IKompasDocument3D)KompDoc.Application.ActiveDocument;

                    IPart7 part7 = document3D.TopPart;
.....

      IntPtr pUnk = IntPtr.Zero;
                            IntPtr ppv = IntPtr.Zero;
                            IModelContainer NewModelContainer;

                            try
                            {
                                pUnk = Marshal.GetIDispatchForObject(part7);

                                Attribute INewInterfaceAttribute = Attribute.GetCustomAttribute(
                                    typeof (IModelContainer), typeof (GuidAttribute));
                                Guid iid = new Guid(((GuidAttribute) INewInterfaceAttribute).Value);
                                if (Marshal.QueryInterface(pUnk, ref iid, out ppv) != 0)
                                {
                                    throw new Exception();      // ВЫЗЫВАЕТ ОШИБКУ !!!!
                                }
                                NewModelContainer = Marshal.GetObjectForIUnknown(ppv) as IModelContainer;
                            }
                            finally
                            {
                                if (pUnk != IntPtr.Zero)
                                    Marshal.Release(pUnk);
                                if (ppv != IntPtr.Zero)
                                    Marshal.Release(ppv);
                            }

udachnik

Скопировал ниже приведённый код - всё работает.
Цитата: Misha от 12.08.10, 17:41:25
           IntPtr pUnk = IntPtr.Zero;
                            IntPtr ppv = IntPtr.Zero;
                            IModelContainer NewModelContainer;

                            try
                            {
                                pUnk = Marshal.GetIDispatchForObject(part7);

                                Attribute INewInterfaceAttribute = Attribute.GetCustomAttribute(
                                    typeof (IModelContainer), typeof (GuidAttribute));
                                Guid iid = new Guid(((GuidAttribute) INewInterfaceAttribute).Value);
                                if (Marshal.QueryInterface(pUnk, ref iid, out ppv) != 0)
                                {
                                    throw new Exception();      // ВЫЗЫВАЕТ ОШИБКУ !!!!
                                }
                                NewModelContainer = Marshal.GetObjectForIUnknown(ppv) as IModelContainer;
                            }
                            finally
                            {
                                if (pUnk != IntPtr.Zero)
                                    Marshal.Release(pUnk);
                                if (ppv != IntPtr.Zero)
                                    Marshal.Release(ppv);
                            }

Если у вас генерится исключение в этом
Цитата: Misha от 12.08.10, 17:41:25
                                if (Marshal.QueryInterface(pUnk, ref iid, out ppv) != 0)
                                {
                                    throw new Exception();      // ВЫЗЫВАЕТ ОШИБКУ !!!!
                                }                     
месте, значит не удалось получить указаетль на интересующий вас интерфейс.
Псомотрите, что возвращает метод QueryInterface. Там и будет видно куда дальше копать. 
В случае успеха  QueryInterface взвращает 0(ноль).            

KrissKross

К чему такие сложности

цитата из справки
ЦитироватьПримечание.

Интерфейс контейнера является дополнительным к интерфейсу IPart7. Данный интерфейс можно получить от IPart7 посредством вызова метода IUnknown::QueryInterface (const GUID far& iid, void** pif);

С помощью приведения типов от вашего IPart7 part7;
как
IModelContainer NewModelContainer = part7 as IModelContainer;
или
IModelContainer NewModelContainer = (IModelContainer)part7;

udachnik

Да, можно и так.
Цитата: из MSDN
...QueryInterface для COM-объекта аналогично выполнению операции приведения в управляемом коде....
Во втором посте я приводил лишь один из методов получения интерфейсов.
Пусть он и не самый простой, но демонстрирующий суть происходящего  :)