# Use in-meeting chat > The code on this page works with either the **default UI** or the **custom UI**. The Meeting SDK lets you [use in-meeting chat](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0064400) to communicate with other participants in the same meeting. Handle chat functionality through the `IMeetingChatController` interface. ```cpp IMeetingChatController* meetingChatController = meetingService ? meetingService->GetMeetingChatController() : nullptr; if (meetingChatController) { // Use the chat controller. } ``` ## Control chat settings Before you use in-meeting chat, check if the current meeting or webinar supports chat, then look at which participants or attendees can use chat. ### Chat settings in a meeting In a meeting, use `IMeetingChatController`. ```cpp IMeetingChatController* meetingChatController = meetingService ? meetingService->GetMeetingChatController() : nullptr; if (meetingChatController) { const ChatStatus* chatStatus = meetingChatController->GetChatStatus(); if (chatStatus && !chatStatus->is_chat_off && !chatStatus->is_webinar_meeting) { const NormalMeetingChatStatus& normalMeetingPrivilege = chatStatus->ut.normal_meeting_status; normalMeetingPrivilege.can_chat; normalMeetingPrivilege.can_chat_to_all; normalMeetingPrivilege.can_chat_to_individual; normalMeetingPrivilege.is_only_can_chat_to_host; } } ``` The `NormalMeetingChatStatus` has these values. - `can_chat` - The user may use chat to send both private and public messages. - `can_chat_to_all` - The user may use chat, but private messages are not allowed. - `can_chat_to_individual` - The user may chat only to individual users. - `is_only_can_chat_to_host` - The user may use chat only with the host. If the current user is the meeting's host, they can control chat settings by specifying a `SDKChatPrivilege`. ```cpp meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_ALL); meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_HOST); meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_DISABLE_ATTENDEE_CHAT); meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_HOST_PUBLIC); ``` ### Chat settings in a webinar In a webinar, use `IMeetingChatController` or `IMeetingWebinarController`. ```cpp IMeetingChatController* meetingChatController = meetingService ? meetingService->GetMeetingChatController() : nullptr; IMeetingWebinarController* webinarController = meetingService ? meetingService->GetMeetingWebinarController() : nullptr; if (webinarController) { SDKPanelistChatPrivilege panelistChatPrivilege = SDKPanelistChatPrivilege_PanelistOnly; if (webinarController->GetPanelistChatPrivilege(panelistChatPrivilege) == SDKERR_SUCCESS) { switch (panelistChatPrivilege) { case SDKPanelistChatPrivilege_PanelistOnly: // Allow panelists only to chat with each other. break; case SDKPanelistChatPrivilege_All: // Allow panelists to chat with everyone. break; default: break; } } } if (meetingChatController) { const ChatStatus* chatStatus = meetingChatController->GetChatStatus(); if (chatStatus && !chatStatus->is_chat_off && chatStatus->is_webinar_meeting) { if (chatStatus->is_webinar_attendee) { const WebinarAttendeeChatStatus& attendeePrivilege = chatStatus->ut.webinar_attendee_status; attendeePrivilege.can_chat; attendeePrivilege.can_chat_to_all_panellist; attendeePrivilege.can_chat_to_all_panellist_and_attendee; } else { const WebinarOtherUserRoleChatStatus& panelistPrivilege = chatStatus->ut.webinar_other_status; panelistPrivilege.can_chat_to_individual; panelistPrivilege.can_chat_to_all_panellist; panelistPrivilege.can_chat_to_all_panellist_and_attendee; } } } ``` The `WebinarAttendeeChatStatus` uses one of these values. - `can_chat` - Can send chat messages. - `can_chat_to_all_panellist` - Can send messages to all panelists. - `can_chat_to_all_panellist_and_attendee` - Can send messages to all panelists and attendees. The `WebinarOtherUserRoleChatStatus` uses one of these values. - `can_chat_to_individual` - Can send messages to an individual attendee. - `can_chat_to_all_panellist` - Can send messages to all panelists. - `can_chat_to_all_panellist_and_attendee` - Can send messages to all panelists and attendees. Update a webinar's chat settings by setting a `SDKChatPrivilege`. ```cpp meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_ALL); meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_ALL_PANELIST); meetingChatController->SetParticipantsChatPrivilege(SDK_CHAT_PRIVILEGE_DISABLE_ATTENDEE_CHAT); ``` ## Send messages To send a public message in either a meeting or a webinar, instantiate a `IChatMsgInfoBuilder` and set the content and message type. ```cpp if (meetingChatController) { IChatMsgInfoBuilder* chatMsgInfoBuilder = meetingChatController->GetChatMessageBuilder(); if (chatMsgInfoBuilder) { /* MessageType (SDKChatMessageType) SDKChatMessageType_To_All - Meeting: everyone. Webinar: all panelists and attendees. SDKChatMessageType_To_All_Panelist - Webinar: all panelists. SDKChatMessageType_To_Individual_Panelist - Webinar: an individual attendee with panelists copied. SDKChatMessageType_To_Individual - An individual user. */ IChatMsgInfo* chatInfo = chatMsgInfoBuilder ->SetContent(L"Hello World!") ->SetReceiver(0) ->SetMessageType(SDKChatMessageType_To_All) ->Build(); if (chatInfo) { SDKError err = meetingChatController->SendChatMsgTo(chatInfo); } } } ``` To reply to an existing message in a thread, first get a `threadId` for the message being responded to. For more information on how to get the `threadId`, see [Receive messages](#receive-messages). Once you've retrieved the thread ID, pass it in and set the type based on whether the parent message is public or private. ```cpp if (meetingChatController) { // 1. Identify the message you want to reply to. IChatMsgInfo* parentMessage = nullptr; if (!parentMessage) { return; } const zchar_t* threadId = parentMessage->GetThreadID(); // 2. Build the reply. IChatMsgInfoBuilder* chatMsgInfoBuilder = meetingChatController->GetChatMessageBuilder(); if (!chatMsgInfoBuilder) { return; } IChatMsgInfo* threadReplyMessage = chatMsgInfoBuilder ->SetThreadId(threadId) ->SetContent(L"Reply to Hello World!") ->SetMessageType(SDKChatMessageType_To_All) ->Build(); // 3. Send the reply. if (threadReplyMessage) { SDKError err = meetingChatController->SendChatMsgTo(threadReplyMessage); } } ``` Messages sent from the SDK can also include quoted text. The quote position specifies the start and end characters in the quoted text string. ```cpp if (meetingChatController) { IChatMsgInfoBuilder* chatMsgInfoBuilder = meetingChatController->GetChatMessageBuilder(); if (chatMsgInfoBuilder) { IChatMsgInfo* quoteMessage = chatMsgInfoBuilder ->SetQuotePosition(0, 42) ->SetContent(L"This is a sample message stylized as a quote") ->SetMessageType(SDKChatMessageType_To_All) ->Build(); if (quoteMessage) { SDKError err = meetingChatController->SendChatMsgTo(quoteMessage); } } } ``` ## Receive messages To display content from chat messages, the SDK provides a callback to get notified of when a new message is sent to the meeting. You can also use this callback to confirm that a message sent by the current user has successfully been posted to the meeting chat. Conform to the `IMeetingChatCtrlEvent` and register it with `IMeetingChatController::SetEvent()` first, then use the `IChatMsgInfo` parameter within `onChatMsgNotification` to get information about the chat message. Some data, like [`receiverID`](https://marketplacefront.zoom.us/sdk/meeting/windows/class_i_chat_msg_info.html#a632a77554d90850f37743d2fc56d7e4f), will only be available for specific types of messages. ```cpp class MeetingChatEventHandler : public IMeetingChatCtrlEvent { public: void onChatMsgNotification(IChatMsgInfo* chatMsg, const zchar_t* content = nullptr) override { if (!chatMsg) { return; } chatMsg->GetMessageID(); // A unique identifier assigned to this message. chatMsg->GetContent(); // The content visible to users in the meeting. chatMsg->GetTimeStamp(); // The time at which the message was sent. chatMsg->GetSenderUserId(); // The Zoom user ID of the sender. chatMsg->GetSenderDisplayName(); // The display name of the sender. chatMsg->GetReceiverUserId(); // The receiver user ID for private messages. chatMsg->GetReceiverDisplayName(); // The receiver display name for private messages. chatMsg->IsChatToWaitingroom(); // Whether the message was sent to the waiting room. chatMsg->GetChatMessageType(); // The message type. See SDKChatMessageType. chatMsg->IsComment(); // Whether the message is a reply in a thread. chatMsg->IsThread(); // Whether the message can be replied to as a thread. chatMsg->GetThreadID(); // The unique identifier associated with a thread. chatMsg->GetSegmentDetails(); // Detailed rich-text segment attributes. } void onChatStatusChangedNotification(ChatStatus* status_) override {} void onChatMsgDeleteNotification(const zchar_t* msgID, SDKChatMessageDeleteType deleteBy) override {} void onChatMessageEditNotification(IChatMsgInfo* chatMsg) override {} void onShareMeetingChatStatusChanged(bool isStart) override {} void onFileSendStart(ISDKFileSender* sender) override {} void onFileReceived(ISDKFileReceiver* receiver) override {} void onFileTransferProgress(SDKFileTransferInfo* info) override {} }; MeetingChatEventHandler chatEventHandler; if (meetingChatController) { meetingChatController->SetEvent(&chatEventHandler); } ``` ## Delete messages To delete a message sent by the current user, call the `DeleteChatMessage` method under `IMeetingChatController` with the `msgId`. This will trigger the `onChatMsgDeleteNotification` callback under `IMeetingChatCtrlEvent` ```cpp if (meetingChatController) { const zchar_t* msgID = L""; if (meetingChatController->IsChatMessageCanBeDeleted(msgID)) { meetingChatController->DeleteChatMessage(msgID); } } ``` ## Parse text format The SDK supports receiving various styles of chat messages such as bold, italic, quote, font color and size, and many more. The styles are included as a list of `SegmentDetails` objects under each of the `IChatMsgInfo` object. ```cpp IList* chatInfoSegmentDetails = chatMsg->GetSegmentDetails(); if (chatInfoSegmentDetails) { for (int i = 0; i < chatInfoSegmentDetails->GetCount(); ++i) { SegmentDetails segment = chatInfoSegmentDetails->GetItem(i); segment.strContent; segment.boldAttrs.bBold; segment.italicAttrs.bItalic; segment.underlineAttrs.bUnderline; segment.quoteAttrs.bQuote; segment.fontColorAttrs; segment.fontSizeAttrs; } } ``` ## Understanding all the chat callbacks For chat related callbacks, there is 1 delegate to subscribe to, `IMeetingChatCtrlEvent`. - `onChatMsgNotification` - Invoked when a chat message is received. - `onChatStatusChangedNotification` - Invoked when chat privileges change. - `onChatMsgDeleteNotification` - Invoked when a chat message is deleted. - `onChatMessageEditNotification` - Invoked when a chat message is edited. ---