# Custom UI features

<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

> <strong>Important</strong>
>
> See [UI legal notices](/docs/meeting-sdk/ui-notices/) for Zoom legal notices and how to display them in your app.

## Initialize the SDK

The struct **InitParam** (declared in the `zoom_sdk_def.h` source file)
is used as the parameter when you call the Init SDK API. One member of
it is **obConfigOpts** which is also a struct. The value of the
`obConfigOpts.optionalFeatures` function should be set to **32** to tell
the server that you want to use the Customized UI service.

> Note
>
> Initializing the SDK means that you want to use the Customized UI
> service. It does not mean that you have the license to use the service.

```cpp
ZOOM_SDK_NAMESPACE::InitParam SDKinitParam;
SDKinitParam.strWebDomain = strWebDomain.c_str();
SDKinitParam.obConfigOpts.optionalFeatures = (1 << 5); //Using Customized UI

//Using a boolean variable to record the return value of the InitSDK API is the simplest
//way.  If you want to handle more details here you can declare a variable with the
//SDKError type, just like the following two lines.
//SDKError err(SDKERR_SUCCESS);
//err = ZOOM_SDK_NAMESPACE::InitSDK(SDKinitParam);

bool bInitSDK = ZOOM_SDK_NAMESPACE::InitSDK(SDKinitParam);
```

## Create Customized UI Service and SetEvent

The customized UI service is dependent on the meeting service. You must
create the meeting service first before the personalized UI service can
be created.

It is recommended to create the meeting service when you receive the
`onMeetingStatusChanged` notification with the parameter
**MeetingStatus** equalling
`ZOOM_SDK_NAMESPACE::MEETING_STATUS_CONNECTING`. This allows you to work
with the preview meeting function as well.

```cpp
ZOOM_SDK_NAMESPACE::CreateCustomizedUIMgr( & _ui_mgr);
if (_ui_mgr)
  _ui_mgr - > SetEvent(this);
```

## Create Video Container, Video Element(s) and SetEvent

![](/img/1536134396400.png)

![](/img/1536134408500.png)

The **video container** is used to pack one or more video elements into
one container. This allows you to create a highly customizable video
layout. You can create one or more video containers as needed to create
the UI you need.

After you create the Customized UI service successfully you should
create a video container and SetEvent.

```cpp
ui_mgr_->CreateVideoContainer(&_video_container, m_hOwnerHwnd, rc);
        if (NULL == _video_container)
            break;
        _video_container->SetEvent(this);
        _video_container->Show();

        //a function to map the container, so your app knows which container should be handle
        CustomizedUIMgrWrap::GetInst().MapUIVideoContainer2SDKObj(this,                _video_container);
```

> Note
>
> Make sure to always set the element type correctly when you create a
> video element for a container.

```cpp
ZOOM_SDK_NAMESPACE::IVideoRenderElement * elem_ = NULL;
_video_container - > CreateVideoElement( & elem_, ZOOM_SDK_NAMESPACE::VideoRenderElement_ACTIVE);
_active_elem =
  dynamic_cast < ZOOM_SDK_NAMESPACE::IActiveVideoRenderElement * > (elem_);
if (_active_elem) {
  _active_elem - > Start();
  _active_elem - > Show();
}
```

## Create Share Render and SetEvent

Share render is an operation used to implement annotation capabilities
as well as other shared views. You should call the SetEvent function for
the annotation controller.

```cpp
ZOOM_SDK_NAMESPACE::ICustomizedAnnotationControllerEvent * anno_ctrl_cb = NULL;
if (meeting_service_) {
  anno_ctrl_cb = this;
}
if (_meeting_service - > GetAnnotationController() &&
  _meeting_service - > GetAnnotationController() - > GetCustomizedAnnotationController())
  _meeting_service - > GetAnnotationController() - > GetCustomizedAnnotationController() - > SetEvent(anno_ctrl_cb);
```

Create the share render. It's recommended to create the share render and
the video container together.

```cpp
ui_mgr_->CreateShareRender(&_share_render, m_hOwnerHwnd, rc);
        if (NULL == _share_render)
            break;
        _share_render->SetEvent(this);
        CustomizedUIMgrWrap::GetInst().MapUIShareRender2SDKObj(this,                   _share_render);
```

Remember to handle all of the event notifications. Since you are using a
custom UI, the SDK cannot handle drawing or building your UI.

## Preview Meeting

![](/img/1536134486600.png)

When joining a scheduled meeting that requires the host to start, you
can show a preview of the user's video before the meeting is started.

```cpp
ZOOM_SDK_NAMESPACE::IVideoRenderElement * elem_ = NULL;
_video_container - > CreateVideoElement( & elem_, ZOOM_SDK_NAMESPACE::VideoRenderElement_PRVIEW);
_active_elem =
  dynamic_cast < ZOOM_SDK_NAMESPACE::IActiveVideoRenderElement * > (elem_);
if (_active_elem) {
  _active_elem - > Start();
  _active_elem - > Show();
}
```

## Destroy Service

You should destroy all of the video elements video containers,
annotation controllers, and share renders when you no longer need them.

```cpp
if (_video_container)
  _video_container - > DestroyVideoElement(_preview_elem);

ZOOM_SDK_NAMESPACE::ICustomizedAnnotationController *
  anno_ctrl_ = _meeting_service - > GetAnnotationController() - > GetCustomizedAnnotationController();
if (anno_ctrl_) {
  if (_anno_obj) {
    _anno_obj - > SetEvent(NULL);
    anno_ctrl_ - > DestroyAnnoObj(_anno_obj);
    _anno_obj = NULL;
  }
  if (_sending_sharing_anno_obj) {
    _sending_sharing_anno_obj - > SetEvent(NULL);
    anno_ctrl_ - > DestroyAnnoObj(_sending_sharing_anno_obj);
    _sending_sharing_anno_obj = NULL;
  }
}
CustomizedUIMgrWrap::GetInst().GetSDKObj() - > DestroyAllVideoContainer();
CustomizedUIMgrWrap::GetInst().GetSDKObj() - > DestroyAllShareRender();

//Remember to destroy the service before the Meeting Service is destroied.
ZOOM_SDK_NAMESPACE::DestroyCustomizedUIMgr(_ui_mgr);
```

## Helper Interfaces

The Windows SDK provides some helper interfaces. Below is a description
on how to use the helper interfaces to build your custom UI.

## InetworkConnectionHelper Class Reference

Two interfaces are used to detect **Proxy Settings** and **SSL
Verification**. You should use these 2 interfaces to create a
network-connection-helper before you call the SDK Auth. The SDK will use
the helper to determine how to communicate with the Zoom meeting server.

## Create Connection Helper

```cpp
static CNetwrokHelperSink s_networksink;
s_networksink.m_pDemo = this;
ZOOM_SDK_NAMESPACE::CreateNetworkConnectionHelper( & m_pNetworkConnectionHelper);
if (m_pNetworkConnectionHelper) {
  m_pNetworkConnectionHelper - > RegisterNetworkConnectionHandler( & s_networksink);
  ShowWaiting(true);
}
```

## Destroy Connection Helper

```cpp
if (m_pNetworkConnectionHelper) {
  ZOOM_SDK_NAMESPACE::DestroyNetworkConnectionHelper(m_pNetworkConnectionHelper);
  m_pNetworkConnectionHelper = NULL;
}
```

## SDK Version

Input the `ZOOM_SDK_NAMESPACE::GetVersion()` instance and the API will
return information on the SDK version.

## Tips

-   There is sample code in the **SDK demo** folder.
-   You can find API Docs in the **Doc folder** (Zoom SDK.chm).
-   All of the SDK APIs only work in the main UI thread.
-   We recommend you to check the return value for each API call.
