智慧服务,成就美好体验 项目咨询

主页 > 服务与支持 > 开发平台 > 客户端SDK参考 > Windows UI SDK > 快速入门 快速入门

入门使用

快速入门

更新时间:2019-11-20

开发环境准备

在开发的过程中请满足如下环境要求。

表1 环境要求

环境和工具名称

版本要求

说明

操作系统

Windows 10专业版

硬件要求:

  • CPU:i5-2400四核 3.1GHz及以上。
  • 内存:4GB及以上。

Microsoft Visual Studio

Visual Studio 2015

-

会议云服务的用户帐号

-

帐号可来源于华为公有云。开通方法请参见“开发前准备”。

SDK快速集成

  1. 解压SDK开发包内容到本地。

     

    1. 在本地创建名为“Hello_SDK”的目录。
    2. 将下载的SDK文件夹中的所有内容拷贝到“Hello_SDK”目录。
      图1 拷贝SDK内容到本地 

     

  2. 创建工程项目。

     

    1. 打开Visual Studio 2015,单击菜单栏的“文件> 新建> 项目”,打开“新建项目”窗口。
      图2 打开新建项目 
    2. 在“新建项目”左侧选择“模板> Visual C++ > MFC”,然后在右侧模板中选择“MFC 应用程序”,在“名称”输入工程名称“Hello_World”,在“位置”选择工程保存位置,此处选择“E:\”,完成后点击“确定”。
      图3 新建项目 
    3. 在“MFC应用程序向导”中单击“下一步”,然后选择“应用程序类型”为“基于对话框”,其余设置均保持默认值,点击完成。
      图4 MFC应用程序向导 

     

  3. 拷贝静态库文件与头文件到项目中。

     

    1. 在“Hello_World”工程目录下新建“SDK”目录,与.sln文件同级。
      图5 新建“SDK” 
    2. 将“Hello_SDK”目录下的“lib”和“include”目录拷贝到“SDK”目录下。
      图6 拷贝文件 

     

  4. 修改项目“配置属性”。

     

    说明: 

    以下操作基于项目默认配置Debug与默认平台Win32,更改配置和平台时需要重新添加附加包含目录和附加依赖库。

    1. 在“Hello_World”项目右键单击“属性”。
      图7 项目属性 
    2. 在属性页左侧选择“配置属性 > C/C++ > 常规”,将“附加包含目录”的值修改为“..\SDK\include”, 点击“应用”按钮。
      图8 配置“附加包含目录” 
    3. 在属性页左侧选择“配置属性 > 链接器> 常规”,将“附加库目录”的值修改为“..\SDK\lib\win32”, 点击“应用”按钮。
      图9 配置“附加库目录” 
    4. 在属性页左侧选择“配置属性> 链接器> 输入”,将“附加依赖项”的值修改为“CWSDK.lib”,点击“应用”。
      图10 添加“附加依赖项” 
    5. 在属性页左侧列表中选择“配置属性 > 常规”,“ 输出目录”值修改为“..\debug”,点击“确定”按钮。
      图11 配置“输出目录” 

     

  5. 添加界面资源控件。

     

    1. 在“资源视图 ”中,打开工程对应的Dialog页面。
      图12 工程Dialog页面 
    2. 选中页面上原有全部控件,按Delete键删除。
      图13 删除原有控件 
    3. 添加登录帐号控件和登录帐号注释控件。
      1. 添加登录帐号控件:打开“工具箱”页面,直接选中“Edit Control”控件拖至右边页面上,调整宽度。
        图14 添加登录帐号控件 
      2. 添加登录帐号注释控件:打开“工具箱”页面,直接选中“Static Text”控件,拖至右边页面上。
        图15 添加登录帐号注释控件 
      3. 修改登录帐号注释控件:选中登录帐号注释控件,右击选择“属性”。
        图16 打开登录帐号注释控件属性页 
      4. 在对应的属性页上,找到“Caption”项,将值修改为“Account”。
        图17 修改登录帐号注释 
    4. 添加登录密码控件和登录密码注释控件,修改注释为“Password”,其余操作同上一步。
      图18 添加密码控件 
    5. 添加登录按钮。
      1. 添加登录按钮控件:打开“工具箱”页面,选中“Button”控件,拖至右边页面上并调整宽度。
      图19 添加登录按钮 
      1. 修改登录按钮上面的注释:选中登录按钮,右击选择“属性。
        图20 打开登录按钮属性 
      2. 在对应的属性页上,找到“Caption”项,将值修改为“Login”。
        图21 修改登录按钮属性 

     

  6. 添加控件变量

     

    1. 为帐号控件添加变量。
      1. 选中帐号控件,右击选择 “添加变量”,打开“添加成员变量向导”页面。
        图22 打开添加变量 
      2. 在“添加成员变量向导”页面填写“变量名”为“m_loginAccountEdit”,其它默认设置保持不变,点击完成。
        图23 添加帐号控件变量 
    2. 添加密码控件变量“m_loginPwdEdit”,操作同上一步。
      图24 添加密码控件变量 
    3. 调整Dialog页面尺寸到合适位置,保存现有工程。
      图25 调整页面尺寸 

     

  7. 添加登录按钮点击事件处理。

     

    1. 双击“Login”控件,系统会自动在Hello_WorldDlg.cpp中添加登录按钮事件方法OnBnClickedButton1()。
      图26 创建登录按钮事件方法 

     

  8. 添加代码文件。

     

    1. 添加回调处理类。
      1. 选中项目右键“添加 > 类”。
        图27 添加类 
      2. 在添加类页面中选中“C++类”,点击“添加”。
        图28 添加“C++类” 
      3. 在“一般C++类向导”中填写类名“NotifyAndCallBackProc”,其他保持默认,点击“完成”,保持现有工程。

    2. 添加公共消息定义头文件。
      1. 选中“项目> 头文件”右键点击,选择“添加> 新建项”。

      2. 在“添加新项”页面左侧选中“Visual C++”,然后在右侧选中“头文件(.h)”。在“名称”中修改名称为“Message.h”,点击“添加”。

     

  9. 添加逻辑代码。

     

    1. 在Message.h文件中增加登录结果回调消息定义。
      #define DEMO_CUSTOM_BEGIN               WM_USER
      
      #define CUSTOM_WM_BEGIN                 (DEMO_CUSTOM_BEGIN + 300)
      //初始化接口结果回调通知
      #define WM_INIT_RESULT                  (CUSTOM_WM_BEGIN + 1)
      //登录接口结果回调通知
      #define WM_LOGIN_RESULT                 (CUSTOM_WM_BEGIN + 2)
      
       
    2. 在NotifyAndCallBackProc.cpp文件中包含相关头文件。
      #include "Hello_World.h"
      #include "Hello_WorldDlg.h"
      #include "Message.h"
      
       
    3. 在NotifyAndCallBackProc.cpp文件中定义通知消息回调接口、初始化结果回调接口和登录结果回调接口。
      /**
      * notify消息通知处理接口
      */
      void NotifyAndCallBackProc::getNotify(int notifyId, void* data)
      {
      	//当前没有消息通知需要处理
      }
      
      /**
      * 初始化结果回调
      */
      void NotifyAndCallBackProc::initCallBack(plugin_call_back_result* ret, void* data)
      {
      	CHello_WorldApp* app = (CHello_WorldApp*)AfxGetApp();
      	if (!app)
      	{
      		//窗口已经关闭
      		return;
      	}
      	CHello_WorldDlg* logindlg = (CHello_WorldDlg*)(app->m_pMainWnd);
      	::PostMessage(logindlg->GetSafeHwnd(), WM_INIT_RESULT, (WPARAM)ret->code, (LPARAM)data);
      }
      /**
      * 登录结果回调
      */
      void NotifyAndCallBackProc::loginCallBack(plugin_call_back_result* ret, void* data)
      {
      	CHello_WorldApp* app = (CHello_WorldApp*)AfxGetApp();
      	if (!app)
      	{
      		//窗口已经关闭直接返回
      		return;
      	}
      	//获取登录窗口
      	CHello_WorldDlg* logindlg = (CHello_WorldDlg*)(app->m_pMainWnd);
      	//传递窗口消息
      	::PostMessage(logindlg->GetSafeHwnd(), WM_LOGIN_RESULT, (WPARAM)ret->code, (LPARAM)data);
      }
      
       
    4. 在NotifyAndCallBackProc.h文件中包含相关头文件。
      #include "plugin_msg.h"
      
       
    5. 在NotifyAndCallBackProc.h文件中声明通知消息回调接口、初始化结果回调接口和登录结果回调接口。
      class NotifyAndCallBackProc
      {
      public:
      	NotifyAndCallBackProc();
      	~NotifyAndCallBackProc();
      public:
      	//通知消息回调
      	static void getNotify(int notifyId, void* data);
      	//初始化结果回调
      	static void initCallBack(plugin_call_back_result* ret, void* data);
      	//登录结果回调
      	static void loginCallBack(plugin_call_back_result* ret, void* data);
      };
      
       
      说明: 

      上文代码部分与工程代码重复,注意区分,不要重复添加。

    6. 在Hello_WorldDlg.h文件中定义将要使用的变量。
      public:
              CString m_loginAccount;//账号变量
      	CString m_loginPwd;    //密码变量
      
       
    7. 在Hello_WorldDlg.cpp文件中包含用到的头文件。
      #include "NotifyAndCallBackProc.h"
      #include "plugin_interface.h"
      #include "Message.h"
      
       
    8. 在Hello_WorldDlg.cpp文件中定义初始化接口。
      /**
      * 初始化接口
      */
      int CHello_WorldDlg::Init()
      {
      	//组装入参结构体
      	struct plugin_init_param initParam;
      	memset(&initParam, 0, sizeof(plugin_init_param));
      	//设置消息通知回调接口
              initParam.notifyFunc = NotifyAndCallBackProc::getNotify;
      	//设置回调接口
      	initParam.callbackFunc = NotifyAndCallBackProc::initCallBack;
              initParam.path = "E:\\Hello_World\\debug\\";
              initParam.appId = "demo";
      	//调用初始化接口
      	int ret = clm_init(&initParam);
      	return ret;
      }
      
       
    9. 在Hello_WorldDlg.cpp文件中定义初始化结果回调接口。
      /**
      * 初始化结果回调
      */
      afx_msg LRESULT CHello_WorldDlg::initCallBack(WPARAM wParam, LPARAM lParam)
      {
      	if (wParam != PLUGIN_STATUS_SUCCESS)
      	{
      		AfxMessageBox(_T("Init failed"));
      	}
      	else
      	{
      		//初始化成功后调用登录接口
      		int ret = Login();
      		if (PLUGIN_STATUS_SUCCESS != ret)
      		{
      			AfxMessageBox(_T("login error"));
      		}
      	}
      	return 0L;
      }
      
       
    10. 在Hello_WorldDlg.cpp文件中定义登录结果回调接口。
      /**
      * 登录成功回调接口
      */
      afx_msg LRESULT CHello_WorldDlg::loginCallBack(WPARAM wParam, LPARAM lParam)
      {
      	if (wParam != PLUGIN_STATUS_SUCCESS)
      	{
      		//提示登录失败
      		AfxMessageBox(_T("Login failed"));
      	}
      	else
      	{
      		//提示登录成功
      		AfxMessageBox(_T("Login success"));
      	}
      	return 0L;
      }
      
       
    11. 在Hello_WorldDlg.cpp文件中绑定初始化结果和登录结果回调消息。
      BEGIN_MESSAGE_MAP(CHello_WorldDlg, CDialogEx)
      	ON_WM_SYSCOMMAND()
      	ON_WM_PAINT()
      	ON_WM_QUERYDRAGICON()
      	ON_BN_CLICKED(IDC_BUTTON1, &CHello_WorldDlg::OnBnClickedButton1)
      	//绑定初始化结果回调消息
      	ON_MESSAGE(WM_INIT_RESULT, &CHello_WorldDlg::initCallBack)
              //绑定登录结果回调消息
      	ON_MESSAGE(WM_LOGIN_RESULT, &CHello_WorldDlg::loginCallBack)
      END_MESSAGE_MAP()
      
       
      说明: 

      上文代码部分与工程代码重复,注意区分,不要重复添加

    12. 在Hello_WorldDlg.cpp文件中定义字符串转换接口。
      /**
      * 将UNICODE字符串转成UTE-8格式
      */
      std::string CHello_WorldDlg::UNICODE2UTF(const CString& cstr)
      {
      	char* pElementText;
      	int iTextLen;
      	std::wstring wstr = (LPCWSTR)CStringW(cstr);;
      	//获取字符串长度
      	iTextLen = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
      	//长度为0返回空
      	if (0 >= (iTextLen + 1))
      	{
      		return "";
      	}
      	//申请字符串长度的内存空间
      	pElementText = new char[iTextLen + 1];
      	memset((void*)pElementText, 0, sizeof(char) * (iTextLen + 1));
      	::WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, pElementText, iTextLen, NULL, NULL);
              //将char数组转为string
      	std::string strText;
      	strText = pElementText;
      	//释放内存
      	delete[] pElementText;
      	pElementText = NULL;
      
      	return strText;
      }
      
       
    13. 在Hello_WorldDlg.cpp文件中定义登录处理接口。
      /**
      * 登录逻辑接口
      */
      int CHello_WorldDlg::Login()
      {
      	int ret;
      	//获取界面填入的信息
      	m_loginAccountEdit.GetWindowText(m_loginAccount);
      	m_loginPwdEdit.GetWindowText(m_loginPwd);
      
      	std::string account = UNICODE2UTF(m_loginAccount);
      	std::string password = UNICODE2UTF(m_loginPwd);
      
      	//组装入参结构体
      	struct plugin_login_param loginParam;
      	memset(&loginParam, 0, sizeof(plugin_login_param));
      
      	loginParam.account = (char*)account.c_str();
      	loginParam.password = (char*)password.c_str();
      
      	//设置回调接口
      	loginParam.callbackFunc = NotifyAndCallBackProc::loginCallBack;
      
      	ret = clm_login(&loginParam);
      	return ret;
      }
      
       
    14. 在Hello_WorldDlg.cpp文件中实现登录按钮点击事件处理。
      void CHello_WorldDlg::OnBnClickedButton1()
      {
      	// TODO: 在此添加控件通知处理程序代码
      	int ret = Init();
      	if (PLUGIN_STATUS_SUCCESS != ret)
      	{
      		AfxMessageBox(_T("Init error"));
      	}
      }
      
       
      说明: 

      上文代码部分与工程代码重复,注意区分,不要重复添加。

    15. 在Hello_WorldDlg.cpp定义退出接口
      /**
      * 退出接口
      */
      void CHello_WorldDlg::exit()
      {
      	int ret = clm_exit_sync();
      }
      
       
    16. 在Hello_WorldDlg.h文件中包含头文件
      #include <string>
      
       
    17. 在Hello_WorldDlg.h文件中添加上述所有新增接口声明。
      public:
      	//初始化接口
      	int Init();
      	//字符转换接口
      	std::string UNICODE2UTF(const CString& cstr);
      	//登录逻辑接口
      	int Login();
      	//初始化结果回调消息
      	afx_msg LRESULT initCallBack(WPARAM wParam, LPARAM lParam);
      	//登录结果回调消息
      	afx_msg LRESULT loginCallBack(WPARAM wParam, LPARAM lParam);
      	//退出接口
      	static void exit();
      
       
      说明: 

      exit接口必须声明为static接口。

    18. 在Hello_World.cpp文件中找到InitInstance接口,在窗口退出时调用exit接口。
      BOOL CHello_WorldApp::InitInstance()
      {
      	// 如果一个运行在 Windows XP 上的应用程序清单指定要
      	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
      	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
      	INITCOMMONCONTROLSEX InitCtrls;
      	InitCtrls.dwSize = sizeof(InitCtrls);
      	// 将它设置为包括所有要在应用程序中使用的
      	// 公共控件类。
      	InitCtrls.dwICC = ICC_WIN95_CLASSES;
      	InitCommonControlsEx(&InitCtrls);
      
      	CWinApp::InitInstance();
      
      
      	AfxEnableControlContainer();
      
      	// 创建 shell 管理器,以防对话框包含
      	// 任何 shell 树视图控件或 shell 列表视图控件。
      	CShellManager *pShellManager = new CShellManager;
      
      	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
      	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
      
      	// 标准初始化
      	// 如果未使用这些功能并希望减小
      	// 最终可执行文件的大小,则应移除下列
      	// 不需要的特定初始化例程
      	// 更改用于存储设置的注册表项
      	// TODO: 应适当修改该字符串,
      	// 例如修改为公司或组织名
      	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
      
      	CHello_WorldDlg dlg;
      	m_pMainWnd = &dlg;
      	INT_PTR nResponse = dlg.DoModal();
      	if (nResponse == IDOK)
      	{
      		// TODO: 在此放置处理何时用
      		//  “确定”来关闭对话框的代码
      		// 窗口关闭时调用sdk退出接口
      		CHello_WorldDlg::exit();
      	}
      	else if (nResponse == IDCANCEL)
      	{
      		// TODO: 在此放置处理何时用
      		//  “取消”来关闭对话框的代码
      		// 窗口关闭时调用sdk退出接口
      		CHello_WorldDlg::exit();
      	}
      	else if (nResponse == -1)
      	{
      		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
      		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
      	}
      
      	// 删除上面创建的 shell 管理器。
      	if (pShellManager != NULL)
      	{
      		delete pShellManager;
      	}
      
      #ifndef _AFXDLL
      	ControlBarCleanUp();
      #endif
      
      	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
      	//  而不是启动应用程序的消息泵。
      	return FALSE;
      }
      
       
      说明: 

      上文代码部分与工程代码重复,注意区分,不要重复添加。

     

  10. 编译及调试工程。

     

    1. 选中工程,右键选择“重新生成”,进行编译。
      图29 生成文件 
    2. 观察“Output”窗口,出现信息“全部重新生成: 成功 1 个,失败 0 个,跳过 0 个”,代表编译成功。
      图30 生成结果 
    3. 编译成功后,生成的可执行程序Hello_World.exe在输出目录下,当前输出目录路径为${path}\Hello_World\debug。
      图31 exe文件 
    4. 拷贝“Hello_SDK\dll”目录下对应平台的.dll文件到输出目录。
      图32 拷贝dll库 
      说明: 

      配置为Win32平台时,目录地址为Hello_SDK\dll\win32,配置为x64平台时,目录地址为Hello_SDK\dll\x64。

    5. 拷贝“Hello_SDK”目录下的“HuaweiMeeting”目录到输出目录。
      图33 拷贝HuaweiMeeting 
    6. 双击Hello_World.exe文件,启动登录界面。
      图34 登录页面 
    7. 输入登录信息,点击“Login”按钮登录,登录成功会有“Login success”提示。
      图35 登录成功提示