2013. 9. 23. 16:35

Implement event sink by ATL

Implement dispinterface and dual interface event sink by ATL

http://msdn.microsoft.com/en-us/library/windows/desktop/dd695280(v=vs.85).aspx

2012. 8. 1. 15:57

ATL with IE(HTML)


  1. Implement IObjectSafety
    1. 미 구현 시 script 구간에서 경고 창이 뜬다.
    2. 구현 방법
    3. public IObjectSafetyImpl<Ctest, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>,

      COM_INTERFACE_ENTRY(IObjectSafety)

  2. Implement IObjectWithSite
    1. javascript 에서 new ActiveXObject 로 구현 가능하도록 하려면 
    2. 구현 방법
      1. wizard 창에서 선택 가능
  3. Implement IProvideClassInfo2
    1. web page 에서 Event catch 를 위해서 (IConnectionPoint 도 구현해야 된다. wizard 에서 선택 가능)
    2. 구현 방법
      1. public IProvideClassInfo2Impl<&CLSID_<object_name>, NULL,
                                         &LIBID_<project_name>Lib>

         COM_INTERFACE_ENTRY(IProvideClassInfo)
           COM_INTERFACE_ENTRY(IProvideClassInfo2)

    3. url : http://support.microsoft.com/?id=200839>

       



2011. 8. 9. 15:23

InPlaceActivate on ATL control not called until mouse event

IE8 에서 ActiveX 가 mouse가 이동하지 전에는 화면에 안 보이는 현상이 있었다.

http://stackoverflow.com/questions/1891194/inplaceactivate-on-atl-control-not-called-until-mouse-event 

http://minolta.egloos.com/464903   => ActiveX 에 대한 전반적인 글 

IOleObject::GetMiscStatus 라는 함수를 통하여 Container 와 Control 이 세부 설정에 대한 교환작업을 한다.

ATL 에서는 DECLARE_OLEMISC_STATUS macro를 통하여 해당 설정을 setting 할 수 있다.

이런 경우 ATL control class의 OnCreate 가 호출이 안되는 경우이며 아래 링크 의 resolution 코드를 이용하면 Oncreate 가 강제적(?)으로 호출이 된다.

http://support.microsoft.com/kb/195188/en-us 





 
2010. 3. 11. 17:48

Problem AtlGetObjectSourceInterface with Delphi ActiveX

AtlGetObjectSourceInterface는 IProvideClassInfo2 와 IPersist interface를 이용하여 source interface를 얻어온다. 하지만 Delphi로 만든 ActiveX 중에는 이 2가지 interface를 지원하지 않는 경우가 있으며 이 경우 위 함수가 실패하여 event에 대한 정보를 얻는데 문제가 발생한다.

아래코드가 대안이 될 수 있다.




Try out the following code :

int main()
{
   ITypeLib* pITypeLib = NULL;
   HRESULT   hrRet = S_OK;

   hrRet = LoadTypeLibEx
   ( 
      (LPCOLESTR)(L"C:\\WINDOWS\\system32\\FM20.DLL"), 
      (ITypeLib**)&pITypeLib
   );

   if (pITypeLib)
   {
      ITypeInfo *pITypeInfo_Coclass = NULL;
      CLSID      clsid;

      CLSIDFromString
      (
         L"{8BD21D40-EC42-11CE-9E0D-00AA006002F3}",
         &clsid
      );
      
      pITypeLib -> GetTypeInfoOfGuid(clsid, &pITypeInfo_Coclass);

      if (pITypeInfo_Coclass)
      {
         TYPEATTR*     pTYPEATTR = NULL ;

         pITypeInfo_Coclass -> GetTypeAttr (&pTYPEATTR);

         // For each implemented interface in this coclass, get its name and determine if it is the default interface.
         int i ;
         for (i = 0 ; i < (pTYPEATTR->cImplTypes); i ++) 
         {
            HREFTYPE hRefType = NULL;
     
            pITypeInfo_Coclass->GetRefTypeOfImplType (i, &hRefType);

            if (hRefType)
            {
        ITypeInfo*     pRefTypeInfo = NULL;
        BSTR          bstrName = NULL;

               pITypeInfo_Coclass->GetRefTypeInfo (hRefType, &pRefTypeInfo);

               if (pRefTypeInfo)
        {
                  pRefTypeInfo->GetDocumentation(MEMBERID_NIL, &bstrName, NULL, NULL, NULL);

           int iImplTypeFlags = 0;

                  pITypeInfo_Coclass->GetImplTypeFlags
           (
              i,
              &iImplTypeFlags
           );

                  if (iImplTypeFlags & IMPLTYPEFLAG_FDEFAULT)
           {
                     if (iImplTypeFlags & IMPLTYPEFLAG_FSOURCE)
              {
          printf ("[default, source] interface is [%s].\r\n", (LPCTSTR)_bstr_t(bstrName));
              }
              else
              {
          printf ("[default] interface is [%s].\r\n", (LPCTSTR)_bstr_t(bstrName));
              }
           }

           pRefTypeInfo->Release();
           pRefTypeInfo = NULL;
               }

               if (bstrName)
        {
           ::SysFreeString(bstrName);
           bstrName = NULL;
        }
            }
         }

         pITypeInfo_Coclass->ReleaseTypeAttr(pTYPEATTR);
         pTYPEATTR = NULL;

         pITypeInfo_Coclass->Release();
         pITypeInfo_Coclass = NULL;
      }

      pITypeLib->Release();
      pITypeLib = NULL;
   }

   return 0;
}


Note that there could be two default interfaces : one being the default incoming interface (i.e. [default]) and the other a default source interface (i.e. [default, source]. 

The important method to use is ITypeInfo::GetImplTypeFlags(). Call it on the ITypeInfo interface of the coclass that you are interested in e.g. :

pITypeInfo_Coclass->GetImplTypeFlags
(
   i,
   &iImplTypeFlags
);

This method will return a IMPLTYPEFLAGS. The code to obtain the default interface should be self-explanatory.

The calls to GetRefTypeOfImplType() and GetRefTypeInfo() are so that we can get the ITypeInfo interface on each of the interfaces of the coclass.
2009. 5. 29. 16:30

Supporting IDispEventImpl

ATL Library Reference 
Supporting IDispEventImpl 

The template class IDispEventImpl can be used to provide support for connection point sinks in your ATL class. A connection point sink allows your class to handle events fired from external COM objects. These connection point sinks are mapped with an event sink map, provided by your class.

To properly implement a connection point sink for your class, the following steps must be completed:

  • Import the type libraries for each external object

  • Declare the IDispEventImpl interfaces

  • Declare an event sink map

  • Advise and unadvise the connection points

The steps involved in implementing a connection point sink are all accomplished by modifying only the header file (.h) of your class.

Importing the Type Libraries

For each external object whose events you want to handle, you must import the type library. This step defines the events that can be handled and provides information that is used when declaring the event sink map. The #importdirective can be used to accomplish this. Add the necessary #import directive lines for each dispatch interface you will support to the header file (.h) of your class.

The following example imports the type library of an external COM server (MyServer):

#import "D:\MyServer.dll" raw_interfaces_only, no_namespace, named_guids
NoteNote

You must have a separate #import statement for each external type library you will support.

Declaring the IDispEventImpl Interfaces

Now that you have imported the type libraries of each dispatch interface, you need to declare separateIDispEventImpl interfaces for each external dispatch interface. Modify the declaration of your class by adding anIDispEventImpl interface declaration for each external object. For more information on the parameters, seeIDispEventImpl.

The following code declares two connection point sinks, for the custom IExtEvents1 and IExtEvents2 interfaces, for the COM object implemented by class CMyObj:

public IDispEventImpl<0, CMyObj, &DIID__IExtEvents1,
    &LIBID_EXTEVENTS1Lib, 1, 0>,
public IDispEventImpl<1, CMyObj, &DIID__IExtEvents2,
    &LIBID_EXTEVENTS2Lib, 1, 0>

Declaring an Event Sink Map

In order for the event notifications to be handled by the proper function, your class must route each event to its correct handler. This is achieved by declaring an event sink map.

ATL provides several macros, BEGIN_SINK_MAPEND_SINK_MAP, and SINK_ENTRY, that make this mapping easier. The standard format is as follows:

BEGIN_SINK_MAP(comClass)
   SINK_ENTRY(id, dispid, func)
   . . . //additional external event entries
END_SINK_MAP()

The following example declares an event sink map with two event handlers:

BEGIN_SINK_MAP(CMyObj)
   SINK_ENTRY(0, Events1, OnClick1)
   SINK_ENTRY(0, Events2, OnClick2)
END_SINK_MAP()

The implementation is nearly complete. The last step concerns the advising and unadvising of the external interfaces.

Advising and Unadvising the IDispEventImpl Interfaces

The final step is to implement a method that will advise (or unadvise) all connection points at the proper times. This advising must be done before communication between the external clients and your object can take place. Before your object becomes visible, each external dispatch interface supported by your object is queried for outgoing interfaces. A connection is established and a reference to the outgoing interface is used to handle events from the object. This procedure is referred to as "advising."

After your object is finished with the external interfaces, the outgoing interfaces should be notified that they are no longer used by your class. This process is referred to as "unadvising."

Because of the unique nature of COM objects, this procedure varies, in detail and execution, between implementations. These details are beyond the scope of this topic and are not addressed.