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();
}