The premise condition

  • Microsoft Visual Studio 2017 or above

  • Supports Windows 7 or later devices

  • Valid Agora account (free registration)

Note: If your network environment has a firewall deployed, please open the relevant port according to the “Application Enterprise Firewall Restrictions” in the Audio Network Documentation Center.

Setting up the Development Environment

Start by creating the project and integrating the Agora SDK into your project.

Creating a Windows project

Follow these steps to create a Windows project. If you already have a Windows project, view the integrated SDK directly.

Creating a Windows project

  1. Open Microsoft Visual Studio and click New Project.

  2. Go to the New project window, select the project type as MFC application, enter the project name, select the project storage path, and click OK.

  3. Enter the MFC Application window, select the application type as based dialog box, and click Finish.

To integrate the SDK

Follow these steps to integrate the Agora SDK into your project.

1. Configure the project file

Obtain the latest SDK from the official website, decompress it, and open it based on the application scenario.

Copy the SDK folder from the download package into your project folder.

2. Configure project attributes

In the Solution Explorer window, right-click the project name and click Properties to do the following configuration, and when complete, click OK.

  • Go to the C/C++ > General > Attach Include directory menu, click Edit and type $(SolutionDir)include in the pop-up window.

  • Go to the Linker > General > Attached libraries directory menu, click Edit and type $(SolutionDir) in the pop-up window.

  • Go to the Linker > Input > Attach Dependencies menu, click Edit, and enter agora_rtc_sdK.lib in the window that pops up.

Audio and video calls are made

Then implement audio and video calls. The sequence of API calls for video calls is shown below:

1. Create a user interface

Create a user interface for audio and video calls for your project, depending on the scenario. If you already have a user interface, you can directly initialize IRtcEngine.

If you want to implement a video call, we recommend adding the following UI elements:

  • Local video window

  • Remote video window

  • End call button

When you use the UI design in the sample project, you will see the following interface:

2. Initialize IRtcEngine

Before invoking the other Agora apis, you need to create and initialize the IRtcEngine object.

You need to enter the project’s App ID in this step. Please refer to the following steps to create the Agora project on the console (console.agora.io) and obtain the App ID:

  1. Log in to the console and click the project management icon in the left navigation bar.

  2. Click Create, set the project name as prompted, select an authentication mechanism, and click Submit.

  3. On the project management page, you can get the App ID of the project.

To initialize IRtcEngine, call the createAgoraRtcEngine and Initialize methods, passing in the obtained App ID.

You can also register the callback events you want to listen for during initialization, such as local users joining a channel or decoding the first frame of a remote user’s video, depending on the situation.


CAgoraObject *CAgoraObject::GetAgoraObject(LPCTSTR lpAppId)
{
    if (m_lpAgoraObject == NULL)
        m_lpAgoraObject = new CAgoraObject();
    ifM_lpAgoraEngine == NULL m_lpAgoraEngine = (IRtcEngine *)createAgoraRtcEngine();if (lpAppId == NULL)
        returnm_lpAgoraObject; RtcEngineContext ctx; // Add the registration callback and event. ctx.eventHandler = &m_EngineEventHandler;#ifdef UNICODEchar szAppId[128]; ::WideCharToMultiByte(CP_ACP, 0, lpAppId, -1, szAppId, 128, NULL, NULL); // Enter your App ID. ctx.appId = szAppId;#else
    ctx.appId = lpAppId;
#endif// Initialize IRtcEngine. m_lpAgoraEngine->initialize(ctx);return m_lpAgoraObject;
}
Copy the code
// Inherits the callback and event from IRtcEngineEventHandler class. class CAGEngineEventHandler : public IRtcEngineEventHandler { public: CAGEngineEventHandler(void); ~CAGEngineEventHandler(void); void SetMsgReceiver(HWND hWnd = NULL); HWNDGetMsgReceiver() {returnm_hMainWnd; }; // Register the onJoinChannelSuccess callback. // This callback is triggered when a local user successfully joins a channel. virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed); // Register the onLeaveChannel callback. // This callback is triggered when the local user successfully leaves the channel. virtual void onLeaveChannel(const RtcStats&stat); / / registered onFirstRemoteVideoDecoded callback. // This callback is triggered when the SDK receives the first frame of remote video and decodes it successfully. The setupRemoteVideo method can be called in this callback to setup the remote view. virtual void onFirstRemoteVideoDecoded(uid_t uid, int width, int height, int elapsed); // Register the onUserOffline callback. // This callback is triggered when the remote user leaves the channel or goes offline. virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason); private: HWND m_hMainWnd; };Copy the code

3. Set the local view

If you want to make a voice call, you can skip this step and go to the next step, “Join channels.”

After successfully initializing the IRtcEngine object, you need to set up the local view before joining the channel to see the local image during the call. Refer to the following steps to set the local view:

  • Call the enableVideo method to enable the video module.

  • Call the setupLocalVideo method to setup the local view.

// Enable the video module. m_lpAgoraObject->GetEngine()->enableVideo(); // Set the local view. VideoCanvas vc; vc.uid = 0; vc.view = m_wndLocal.GetSafeHwnd(); vc.renderMode = RENDER_MODE_FIT; m_lpAgoraObject->GetEngine()->setupLocalVideo(vc);Copy the code

4. Join the channel

After initializing and setting up the local view (video call scenario), you can call the joinChannel method to join the channel. You need to pass the following arguments to this method:

  • ChannelName: indicates the ID of a channel. Users with the same channel ID enter the same channel.

  • Token: The token that identifies user roles and permissions is passed in. Can be set to one of the following values:

    • NULL

    • Temporary Token. The temporary Token service is valid for 24 hours. You can generate a temporary Token in the console. For details, search “Obtain temporary Token” in the documentation center.

    • Tokens generated on your server side. In high security scenarios, we recommend that you use tokens generated in this way.

  • Uid: indicates the ID of a local user. The value is an integer and the UID of each user in the channel must be unique. If the UID is set to 0, the SDK will automatically assign a UID and report it in the onJoinChannelSuccess callback.

For more parameters, see the parameter description of joinChannel in the Audio Network Documentation Center.

// Join the channel. BOOL CAgoraObject::JoinChannel(LPCTSTR lpChannelName, UINT nUID,LPCTSTR lpToken) { int nRet = 0;#ifdef UNICODE
    CHAR szChannelName[128];
    ::WideCharToMultiByte(CP_UTF8, 0, lpChannelName, -1, szChannelName, 128, NULL, NULL);
    char szToken[128];
    ::WideCharToMultiByte(CP_UTF8, 0, lpToken, -1, szToken, 128, NULL, NULL);
    if(0 == _tcslen(lpToken))
        nRet = m_lpAgoraEngine->joinChannel(NULL, szChannelName, NULL, nUID);
    else
        nRet = m_lpAgoraEngine->joinChannel(szToken, szChannelName, NULL, nUID);
#else
    if(0 == _tcslen(lpToken))
        nRet = m_lpAgoraEngine->joinChannel(NULL, lpChannelName, NULL, nUID);
    else
        nRet = m_lpAgoraEngine->joinChannel(lpToken, lpChannelName, NULL, nUID);
#endif
    if (nRet == 0)
        m_strChannelName = lpChannelName;
    return nRet == 0 ? TRUE : FALSE;
}
Copy the code

5. Set the remote view

In video calls, you usually need to see other users as well. After joining the channel, you can set the view of the remote user by calling the setupRemoteVideo method.

Remote user after successful join channel, the SDK will trigger onFirstRemoteVideoDecoded callback, the callback will contain the remote user’s uid information. The setupRemoteVideo method is called in this callback, passing in the uid obtained and setting the view for the remote user.

// This callback is triggered when the SDK receives the first frame of remote video and decodes it successfully. Call the setupRemoteVideo method in this callback to set the remote view. LRESULT CAgoraTutorialDlg::OnFirstRemoteVideoDecoded(WPARAM wParam, LPARAM lParam) { LPAGE_FIRST_REMOTE_VIDEO_DECODED lpData = (LPAGE_FIRST_REMOTE_VIDEO_DECODED)wParam; VideoCanvas vc; vc.renderMode = RENDER_MODE_FIT; vc.uid = lpData->uid; vc.view = m_wndRemote.GetSafeHwnd(); // Set the remote view. m_lpAgoraObject->GetEngine()->setupRemoteVideo(vc); delete lpData;return 0;
}
Copy the code

6. Get off the channel

Call leaveChannel to leave the current call channel when the App is switched to the background, for example, to end the call, close the App, or switch to the background.

BOOL CAgoraObject::LeaveChannel() { m_lpAgoraEngine->stopPreview(); // Leave the channel. int nRet = m_lpAgoraEngine->leaveChannel();return nRet == 0 ? TRUE : FALSE;
}

 void CAgoraObject::CloseAgoraObject()
{
    if(m_lpAgoraEngine ! = NULL) // Release IRtcEngine object. m_lpAgoraEngine->release();if(m_lpAgoraObject ! = NULL) delete m_lpAgoraObject; m_lpAgoraEngine = NULL; m_lpAgoraObject = NULL; }Copy the code

The sample code

You can view the complete source code and code logic in the agora-Windows-tutorial-1to1 sample project’s agoratutorialdlg.cpp file.

Making: github.com/AgoraIO/Bas…

If you encounter problems during the development process, you can visit the “RTC Developer community” to post questions, and sound network engineers will help answer them online.