# Use in-meeting chat

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

> 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<SegmentDetails>* 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.

---
