DuilibAndCef
学习Duilib和Cef联合开发
编译duilib和Cef
下载duilib我这里选择网易云修改版,看起来界面好像比原版好看点
而且cef库也给封装好了
git clone https://github.com/netease-im/NIM_Duilib_Framework
新建工程
新建一个 Windows 桌面程序后,将生成的代码清理一下只保留 wWinMain 函数。
然后把我们之前下载的几个项目给拷贝到我们项目的根目录
然后配置项目属性所有平台的属性设置输出目录和中间文件就好
将 Debug 模式的运行库修改为 /MTd
,将 Release 模式的运行库修改为 /MT
项目右键->添加->引用,将 base、shared、duilib 作为引用项目,这样就不需要手动引入静态库文件了。
在 stdafx.h 中引入所需的头文件,这里目前只用到最基础的,所有添加这两个即可
// base header
#include "base/base.h"
// duilib
#include "duilib/UIlib.h"
但是用到一些ui或者cef控件的话还要添加
// base header
#include "base/base.h"
// duilib
#include "duilib/UIlib.h"
// ui components
#include "ui_components/ui_components.h"
#include "ui_components/ui_cef_control.h"
到这里框架基本结束了
编写代码
在创建的项目中 wWinMain 所属的头文件中,增加自定义的主线程对象。
/** @class MainThread
* @brief 主线程(UI线程)类,继承 nbase::FrameworkThread
* @copyright (c) 2015, NetEase Inc. All rights reserved
* @author towik
* @date 2015/1/1
*/
class MainThread : public nbase::FrameworkThread
{
public:
MainThread() : nbase::FrameworkThread("MainThread") {}
virtual ~MainThread() {}
private:
/**
* 虚函数,初始化主线程
* @return void 无返回值
*/
virtual void Init() override;
/**
* 虚函数,主线程退出时,做一些清理工作
* @return void 无返回值
*/
virtual void Cleanup() override;
};
在WinMain函数同文件内先实现上面两个函数
void MainThread::Init()
{
nbase::ThreadManager::RegisterThread(kThreadUI);
// 获取资源路径,初始化全局参数
std::wstring theme_dir = nbase::win32::GetCurrentModuleDirectory();
// Debug 模式下使用本地文件夹作为资源
// 默认皮肤使用 resources\\themes\\default
// 默认语言使用 resources\\lang\\zh_CN
// 如需修改请指定 Startup 最后两个参数
ui::GlobalManager::Startup(theme_dir + L"resources\\", ui::CreateControlCallback(), false);
}
void MainThread::Cleanup()
{
ui::GlobalManager::Shutdown();
SetThreadWasQuitProperly(true);
nbase::ThreadManager::UnregisterThread();
}
创建一个窗口类,继承 ui::WindowImplBase
类,并覆写 GetSkinFolder
GetSkinFile
GetWindowClassName
三个方法。
class MainWndFrame :
public ui::WindowImplBase
{
public:
MainWndFrame();
~MainWndFrame();
/**
* 一下三个接口是必须要覆写的接口,父类会调用这三个接口来构建窗口
* GetSkinFolder 接口设置你要绘制的窗口皮肤资源路径
* GetSkinFile 接口设置你要绘制的窗口的 xml 描述文件
* GetWindowClassName 接口设置窗口唯一的类名称
*/
virtual std::wstring GetSkinFolder() override;
virtual std::wstring GetSkinFile() override;
virtual std::wstring GetWindowClassName() const override;
/**
* 收到 WM_CREATE 消息时该函数会被调用,通常做一些控件初始化的操作
*/
virtual void InitWindow() override;
/**
* 收到 WM_CLOSE 消息时该函数会被调用
*/
virtual LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
static const std::wstring kClassName;
};
const std::wstring MainWndFrame::kClassName = L"MyStudyDuilib";
MainWndFrame::MainWndFrame()
{
}
MainWndFrame::~MainWndFrame()
{
}
std::wstring MainWndFrame::GetSkinFolder()
{
return L"basic";
}
std::wstring MainWndFrame::GetSkinFile()
{
return L"basic.xml";
}
std::wstring MainWndFrame::GetWindowClassName() const
{
return kClassName;
}
void MainWndFrame::InitWindow()
{
// 做一些初始化工作
}
LRESULT MainWndFrame::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
PostQuitMessage(0L);
return __super::OnClose(uMsg, wParam, lParam, bHandled);
}
编写XML文件,因为上面设置xml名字和路径的原因,所以要在生成exe的目录下resources\themes\default\basic\basic.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" caption="0,0,0,35">
<VBox bkcolor="bk_wnd_darkcolor">
<HBox width="stretch" height="35" bkcolor="bk_wnd_lightcolor">
<Control />
<Button class="btn_wnd_min" name="minbtn" margin="4,6,0,0"/>
<Box width="21" margin="4,6,0,0">
<Button class="btn_wnd_max" name="maxbtn"/>
<Button class="btn_wnd_restore" name="restorebtn" visible="false"/>
</Box>
<Button class="btn_wnd_close" name="closebtn" margin="4,6,8,0"/>
</HBox>
<Box>
<VBox margin="0,0,0,0" valign="center" halign="center" width="auto" height="auto">
<Label name="tooltip" text="This is a baisc window form created by nim duilib."/>
</VBox>
</Box>
</VBox>
</Window>
显示窗口
在主线程的 Init 方法中,创建窗口并居中显示,创建窗口前先引入窗口的头文件,修改后的代码如下:
void MainThread::Init()
{
nbase::ThreadManager::RegisterThread(kThreadUI);
// 获取资源路径,初始化全局参数
std::wstring theme_dir = nbase::win32::GetCurrentModuleDirectory();
// Debug 模式下使用本地文件夹作为资源
// 默认皮肤使用 resources\\themes\\default
// 默认语言使用 resources\\lang\\zh_CN
// 如需修改请指定 Startup 最后两个参数
ui::GlobalManager::Startup(theme_dir + L"resources\\", ui::CreateControlCallback(), false);
// 创建一个默认带有阴影的居中窗口
MainWndFrame* window = new MainWndFrame();
window->Create(NULL, MainWndFrame::kClassName.c_str(), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, 0);
window->CenterWindow();
window->ShowWindow();
}