概述
Duilib 是 Windows 系统下的开源的 DirectUI 界面库(遵循 BSD 协议),完全免费,可用于商业软件开发。
Duilib 可以简单方便地实现大多数界面需求,包括换肤、换色、透明等功能,支持多种图片格式,使用 XML 可以方便地定制窗口,能较好地做到 UI 和逻辑相分离,尽量减少在代码里创建 UI 控件。目前,Duilib 已经在国内有较为广泛的使用。
网易 Duilib 使用 C++11 重写,在其原有基础上做了较大重构,搭配谷歌的基础组件 Base 库、基于 Chromium 的 WebView 框架 CEF 以及常用的 UI 组件,形成了一套功能强大、简单易用的完整桌面 UI 开发框架。
整体框架

框架中提供了多线程模型、高精度定时器、基本的 xml 解析、zip 解压等功能;封装了一层渲染接口和全局样式资源的统一管理;并且对 DPI 适配、多语言、虚拟键盘、手写板等功能增加了支持;在上层提供了丰富的控件。
工程结构
├─base 基础类库
├─bin 各个示例程序输出目录,包含预设的皮肤和语言文件以及 CEF 依赖
├─docs duilib 接口的说明文档
├─duilib duilib 核心代码,依赖 base 但不依赖 shared
├─libs 静态库编译后的输出目录,包含预设的一些 CEF 组件静态库
├─examples 各类示例程序源代码
├─third_party 第三方库,目前仅有 cef_control 有依赖
├─ui_components 基于 duilib 封装的常用组件库如 msgbox、toast、cef_control 等
Demo
新建一个空的Windows项目
添加2个引用

添加一个头文件stdafx.h
#pragma once
// C runtime header
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// base header
#include "base/base.h"
// duilib
#include "duilib/UIlib.h"
新建一个窗口类
CMyDuiWin.h
#pragma once
class CMyDuiWin : public ui::WindowImplBase
{
public:
CMyDuiWin();
~CMyDuiWin();
/** 纯虚函数
* @brief 创建窗口时被调用,由子类实现用以获取窗口皮肤目录
* @return 子类需实现并返回窗口皮肤目录
*/
virtual std::wstring GetSkinFolder();
/** 纯虚函数
* @brief 创建窗口时被调用,由子类实现用以获取窗口皮肤 XML 描述文件
* @return 子类需实现并返回窗口皮肤 XML 描述文件
*/
virtual std::wstring GetSkinFile();
/** 纯虚函数
* @brief 创建窗口时被调用,由子类实现用以获取窗口唯一的类名称
* @return 子类需实现并返回窗口唯一的类名称
*/
virtual std::wstring GetWindowClassName(void) const;
/**
* @brief 窗口消息的派发函数
* @param[in] uMsg 消息内容
* @param[in] wParam 消息附加参数
* @param[in] lParam 消息附加参数
* @param[out] bHandled 返回 true 则继续派发该消息,否则不再派发该消息
* @return 返回消息处理结果
*/
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
/**
* 收到 WM_CLOSE 消息时该函数会被调用
*/
virtual LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
/**
* @brief 窗口功能按钮被点击时调用
* @param[in] param 携带的参数
* @return 始终返回 true
*/
bool OnButtonClick(ui::EventArgs* param);
};
CMyDuiWin.cpp
#include "stdafx.h"
#include "CMyDuiWin.h"
CMyDuiWin::CMyDuiWin()
{
}
CMyDuiWin::~CMyDuiWin()
{
}
std::wstring CMyDuiWin::GetSkinFolder()
{
return std::wstring(); //我没有使用xml加载界面布局
}
std::wstring CMyDuiWin::GetSkinFile()
{
return std::wstring();
}
std::wstring CMyDuiWin::GetWindowClassName(void) const
{
return _T("MyDuiWin");
}
LRESULT CMyDuiWin::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
//全局样式管理器,这里手动加了一些样式
//默认 在调用 GlobalManager::Startup 方法后,会根据设定的皮肤资源路径下查找 global.xml 作为全局的样式资源
ui::GlobalManager::Startup(std::wstring(), ui::CreateControlCallback(), false);
ui::GlobalManager::AddTextColor(_T("light_green"), _T("#ff21c7a6"));
ui::GlobalManager::AddTextColor(_T("textdefaultcolor"), _T("#ff333333"));
ui::GlobalManager::AddTextColor(_T("textdefaultdisablecolor"), _T("#ffa1aebc"));
ui::GlobalManager::AddTextColor(_T("bk_wnd_darkcolor"), _T("#fff0f2f5"));
ui::GlobalManager::AddFont(_T("system_18"), _T("system"), 18, false, false, false, true);
//窗口的容器
ui::Box* pBox = new ui::Box;
pBox->SetBkColor(_T("bk_wnd_darkcolor"));
//在容器中添加一个按钮
ui::Button* pButton = new ui::Button;
pButton->SetText(_T("我是一个小按钮"));
pButton->SetBkColor(_T("light_green"));
pButton->SetVerAlignType(ui::kVerAlignCenter);
pButton->SetHorAlignType(ui::kHorAlignCenter);
//attachClick消息
pButton->AttachClick(nbase::Bind(&CMyDuiWin::OnButtonClick, this, std::placeholders::_1));
pBox->Add(pButton);
//把布局容器 attach到窗口上
AttachDialog(pBox);
//初始化窗口
Init(m_hWnd);
//设置窗口大小
ui::UiRect rect(100, 100, 600, 500);
this->SetPos(rect, false, SWP_NOMOVE);
return 0; //这里直接返回,如果不返回会去调用基类的Create消息,会从xml加载布局
}
break;
case WM_DESTROY:
{
//释放全局样式
ui::GlobalManager::Shutdown();
}
break;
default:
break;
}
return ui::WindowImplBase::HandleMessage(uMsg, wParam, lParam);
}
LRESULT CMyDuiWin::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
{
PostQuitMessage(0L);
return __super::OnClose(uMsg, wParam, lParam, bHandled);
}
bool CMyDuiWin::OnButtonClick(ui::EventArgs * param)
{
MessageBox(this->m_hWnd, _T("按钮单击了"), _T("提示"), MB_OK);
return false;
}
main函数
#include "stdafx.h"
#include "CMyDuiWin.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
//new窗口对象,duilib会管理ui对象
CMyDuiWin* pMyWin = new CMyDuiWin;
pMyWin->Create(NULL, _T("HelloDuilib"), WS_OVERLAPPEDWINDOW, 0);
pMyWin->CenterWindow();
pMyWin->ShowWindow();
MSG nMsg = { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
857

被折叠的 条评论
为什么被折叠?



