Custom Registration of Created Objects

DllRegisterDesigner and DllUnregisterDesigner are optional entry points through which a run-time designer can register and unregister custom information for authored objects. These APIs must be exported from the DLL that implements the run-time object. If a designer implements these routines, it must set the DESIGNERFEATURE_REGISTRATION and DESIGNERFEATURE_CANBEPUBLIC flags in the registry. These flags notify the host that the designer is publicly exposed and requires custom registration.

The run-time object must already be registered before the host can call DllRegisterDesigner. To determine which DLL contains the DllRegisterDesigner API, the host uses the Instance CLSID registered by the designer to look up the InprocServer32 subkey under the CLSID of the run-time object. The InprocServer32 subkey specifies the DLL file that implements the run-time object.

When the compiled project is registered, the host calls DllRegisterDesigner once for each authored object in the project. The DllRegisterDesigner routine registers information specific to the authored object. The parameter to DllRegisterDesigner is a pointer to a DESIGNERREGINFO structure, which contains the programmatic ID (ProgID), class ID (CLSID), type library ID, and version numbers of the object to be registered, along with an array of designer-specified data.

In the following example, the designer registers information for a single authored object in the class MyClass. It creates an instance of the component categories manager (as in the preceding section), then registers the object (denoted by pdri->clsid) as an implemented category of CATID_MyClass.

STDAPI DllRegisterDesigner(DESIGNERREGINFO *pdri)
{
   HRESULT hr = S_OK;
   ICatRegister* pICatRegister = NULL;
   CATID rgcatid[1];
   
   rgcatid[0] = CATID_MyClass;
   
   hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
      NULL, CLSCTX_SERVER, IID_ICatRegister,
      (void**) &pICatRegister);
   CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS);

   hr = pICatRegister->RegisterClassImplCategories(pdri->clsid, 
         1, rgcatid);
   CSF_CHECK(SUCCEEDED(hr), hr, CSF_TRACE_EXTERNAL_ERRORS);

CLEANUP:
   if(pICatRegister != NULL)
      pICatRegister->Release();

   return hr;
}

When unregistering the compiled project, the host calls DllUnregisterDesigner to delete custom information from the registry. The designer must again create an instance of the component categories manager and use its UnRegisterClassImplCategories method to remove the registration data, as follows:

STDAPI DllUnregisterDesigner(DESIGNERREGINFO *pdri)
{
   HRESULT hr = S_OK;
   ICatRegister* pICatRegister = NULL;
   CATID rgcatid[1];
   
   rgcatid[0] = CATID_MyClass;
   
   hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
            NULL, CLSCTX_SERVER, IID_ICatRegister,
            (void**) &pICatRegister);
   CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS);

   hr = pICatRegister->UnRegisterClassImplCategories(pdri->clsid, 
            1, rgcatid);
   CSF_CHECK(SUCCEEDED(hr), hr, CSF_TRACE_EXTERNAL_ERRORS);

CLEANUP:
   if(pICatRegister != NULL)
      pICatRegister->Release();

   return hr;
}

Designers also can implement the optional IDesignerRegistration interface to pass registry information from a design-time instance to the DllRegisterDesigner and DllUnregisterDesigner APIs. For example, a designer might allow a user to specify a specific component category with which to register the authored component. The designer could use this interface to pass the necessary information (the CATID data) to the DllRegisterDesigner API.

Through the GetRegistrationInfo method of this interface, a designer can pass a data structure to the host at design time. At run time, after the host registers the authored component, it calls DllRegisterDesigner, passing the same data structure.

At design time, the host calls IDesignerRegistration::GetRegistrationInfo to request the registration information. The designer returns an array of bytes specifying the data to pass to DllRegisterDesigner and DllUnregisterDesigner.

The format of the bytes is unspecified; you can write the information in any form you choose. However, you must be sure to read the data in the same form in the DLLRegisterDesigner routine.

Within their registration routines, designers call registry interfaces and APIs to add entries to and delete entries from the system-wide registry, as shown in the previous section. See the COM Programmer’s Reference in the Platform Software Development Kit (SDK) for information on the registry interfaces and APIs.