# Custom UI features > Important > > 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.