代码仓库:https://github.com/yangpan4485/duilib/tree/develop/MyDemo
一、复杂控件介绍
1、ActiveX 浏览器控件
xml
<?xml version="1.0" encoding="UTF-8"?>
<Window size="960,540" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<Font id="0" shared="true" name="宋体" size="18" bold="false" underline="false" italic="false" />
<Font id="1" shared="true" name="宋体" size="20" bold="false" underline="false" italic="false" />
<Font id="2" shared="true" name="宋体" size="16" bold="false" underline="false" italic="false" />
<VerticalLayout bkcolor="#FFDFFDF0" width="300" height="318"> <!-- 整个窗口使用 VerticalLayout 布局 -->
<ActiveX name="ActiveXDemo1" float="true" pos="60,40,0,0" width="800" height="400" />
</VerticalLayout>
</Window>
complex_control.h
#pragma once
#include "UIlib.h"
class ComplexControl : public DuiLib::CWindowWnd, public DuiLib::INotifyUI
{
public:
ComplexControl();
~ComplexControl();
void Init();
bool CreateDUIWindow();
void ShowWindow();
LPCTSTR GetWindowClassName() const override;
void Notify(DuiLib::TNotifyUI& msg) override;
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnClick(DuiLib::TNotifyUI& msg);
private:
void InitWindow();
private:
HINSTANCE _hInstance;
DuiLib::CPaintManagerUI _paintManager{};
HWND _ownerWnd{};
};
complex_control.cpp
ActiveX 控件和其它控件不一样的点就是要在创建的时候进行初始化操作,不然就会崩溃,所以在 OnCreate() 函数结束的时候要自己实现 InitWindow() 函数
#include "complex_control.h"
#include <iostream>
#include <string>
ComplexControl::ComplexControl()
{
}
ComplexControl::~ComplexControl()
{
}
void ComplexControl::Init()
{
SetProcessDPIAware();
_hInstance = GetModuleHandle(0);
DuiLib::CPaintManagerUI::SetInstance(_hInstance);
DuiLib::CPaintManagerUI::SetResourcePath(DuiLib::CPaintManagerUI::GetInstancePath() + +_T("resources"));
}
bool ComplexControl::CreateDUIWindow()
{
_ownerWnd = Create(NULL, _T("Complex"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
if (!_ownerWnd)
{
std::cout << "create dui window failed" << std::endl;
return false;
}
return true;
}
void ComplexControl::ShowWindow()
{
ShowModal();
}
LPCTSTR ComplexControl::GetWindowClassName() const
{
return _T("DUICOMPLEXFrame");
}
void ComplexControl::Notify(DuiLib::TNotifyUI& msg)
{
if (msg.sType == _T("click"))
{
OnClick(msg);
}
}
LRESULT ComplexControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = 0;
switch (uMsg) {
case WM_CREATE:
lRes = OnCreate(uMsg, wParam, lParam);
break;
case WM_CLOSE:
lRes = OnClose(uMsg, wParam, lParam);
break;
default:
break;
}
if (_paintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{
return lRes;
}
return __super::HandleMessage(uMsg, wParam, lParam);
}
LRESULT ComplexControl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
_paintManager.Init(m_hWnd);
DuiLib::CDialogBuilder builder;
DuiLib::CControlUI* pRoot = builder.Create(_T("complexControl.xml"), (UINT)0, NULL, &_paintManager);
_paintManager.AttachDialog(pRoot);
_paintManager.AddNotifier(this);
InitWindow();
return 0;
}
LRESULT ComplexControl::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}
void ComplexControl::OnClick(DuiLib::TNotifyUI& msg)
{
}
void ComplexControl::InitWindow()
{
DuiLib::CActiveXUI* pActiveXUI = static_cast<DuiLib::CActiveXUI*>(_paintManager.FindControl(_T("ActiveXDemo1")));
if (pActiveXUI)
{
IWebBrowser2* pWebBrowser = NULL;
pActiveXUI->SetDelayCreate(false); // 相当于界面设计器里的DelayCreate属性改为FALSE,在duilib自带的FlashDemo里可以看到此属性为TRUE
pActiveXUI->CreateControl(CLSID_WebBrowser); // 相当于界面设计器里的Clsid属性里填入{8856F961-340A-11D0-A96B-00C04FD705A2},建议用CLSID_WebBrowser,如果想看相应的值,请见<ExDisp.h>
pActiveXUI->GetControl(IID_IWebBrowser2, (void**)&pWebBrowser);
if (pWebBrowser != NULL)
{
pWebBrowser->Navigate(L"https://www.baidu.com/", NULL, NULL, NULL, NULL);
pWebBrowser->Release();
}
}
}
运行效果,打开的十 IE 浏览器,但是在我这会提示有脚本错误
2、Progress 进度条控件
xml 里面添加一个进度条控件,value=“0” 表示默认值设置为 0,添加一个 Button,当点击 Button 的时候进度条从 0 - 100,textpadding="0,6,0,0" 表示 value 的位置离 top 的距离为6,差不多在中间了,corner 可以参考这一篇文章:https://blog.csdn.net/CAir2/article/details/45936215,align=“center” 表示居中对齐,只是左右会居中对齐,hor 颜色的渐变方向,hor是水平方向,ver是垂直方向
<Progress name="progressControl" text="0" textpadding="0,6,0,0" float="true" pos="30,28,0,0" width="139" height="30" bkimage="file='common/progress_back.png' corner='5,4,4,5'" foreimage="common/progress_fore.png" min="0" max="100" value="0" hor="true" align="center" font="2" />
<Button name="startBtn" text="开始" pos="28,90,100,120" float="true" />
在 cpp 中对 OnClick 消息做出响应
if (msg.pSender->GetName() == _T("startBtn"))
{
DuiLib::CProgressUI* pProgress = static_cast<DuiLib::CProgressUI*>(_paintManager.FindControl(_T("progressControl")));
std::thread work = std::thread([pProgress, this]() {
for (int i = 1; i <= 100; ++i) {
pProgress->SetValue(i);
std::string text = std::to_string(i) + "%";
pProgress->SetText(text.c_str());
Sleep(50);
}
});
work.detach();
}
运行就可以看见进度条在动了
3、Slider 滑块控件
xml
<Slider name="sliderControl" float="true" pos="28,150,0,0" width="139" height="18" thumbsize="12,20" value="0" bkimage="file='common/SliderBar_BK.bmp' mask='0xffff00ff'" thumbimage="file='common/SliderBar_Thumb.png' mask='0xffffffff'"/>
在 cpp 中对可以接收 OnValueChange 消息,然后做出处理
if (msg.pSender->GetName() == _T("sliderControl"))
{
DuiLib::CSliderUI* slider = static_cast<DuiLib::CSliderUI*>(_paintManager.FindControl(_T("sliderControl")));
// 获取 slider 的进度
std::cout << "slider:" << slider->GetValue() << std::endl;
}
4、List 列表控件
xml,在 xml 里面设置列表的头部,然后具体元素的添加在 cpp 中完成
<Default shared="true" name="List" value="headerbkimage="res='common/list_header_bg.png'" itemalign="center" itemlinecolor="#FF888888" itemshowrowline="true" itemshowcolumnline="true"" />
<Default name="VScrollBar" shared="true" value="width="8" showbutton1="false" showbutton2="false" thumbnormalimage="file='common/vscrollbar.png' source='0,60,8,100' corner='0,4,0,4'" thumbhotimage="file='common/vscrollbar.png' source='8,60,16,100' corner='0,4,0,4'" thumbpushedimage="file='common/vscrollbar.png' source='16,60,24,100' corner='0,4,0,4'" railnormalimage="" railhotimage="" railpushedimage="" raildisabledimage="" bknormalimage="file='common/vscrollbar.png' source='0,0,8,60' corner='0,4,0,4'" bkhotimage="" bkpushedimage="" bkdisabledimage="" "/>
<Default name="HScrollBar" shared="true" value="height="8" showbutton1="false" showbutton2="false" thumbnormalimage="file='common/hscrollbar.png' source='0,0,32,8' corner='4,0,4,0'" thumbhotimage="file='common/hscrollbar.png' source='0,8,32,16' corner='4,0,4,0'" thumbpushedimage="file='common/hscrollbar.png' source='0,16,32,24' corner='4,0,4,0'" railnormalimage="" railhotimage="" railpushedimage="" raildisabledimage="" bknormalimage="file='common/hscrollbar.png' source='0,0,32,8' corner='4,0,4,0'" bkhotimage="" bkpushedimage="" bkdisabledimage="" "/>
<List name="listControl" float="true" pos="30,200,0,0" width="400" height="218" vscrollbar="true" hscrollbar="true" bkcolor="#FFFFFFFF" itemtextcolor="#FF000000" itembkcolor="#FFE2AADF" itemselectedtextcolor="#FF000000" itemselectedbkcolor="#FFC1E3FF" itemhottextcolor="#FF000000" itemhotbkcolor="#FFE9F5FF" itemdisabledtextcolor="#FFCCCCCC" itemdisabledbkcolor="#FFFFFFFF" >
<ListHeader name="domain" bkimage="common/list_header_bg.png">
<ListHeaderItem text="姓名" width="80" height="30" minwidth="25" sepwidth="1" align="center" hotimage="common/list_header_hot.png" pushedimage="common/list_header_pushed.png" sepimage="common/list_header_sep.png" bkcolor="0xffaa00ff"/>
<ListHeaderItem text="学号" width="160" height="30" minwidth="25" sepwidth="1" align="center" hotimage="common/list_header_hot.png" pushedimage="common/list_header_pushed.png" sepimage="common/list_header_sep.png" bkcolor="0xffaa00ff"/>
<ListHeaderItem text="成绩" width="160" height="30" minwidth="25" sepwidth="1" align="center" hotimage="common/list_header_hot.png" pushedimage="common/list_header_pushed.png" sepimage="common/list_header_sep.png" bkcolor="0xffaa00ff"/>
</ListHeader>
</List>
cpp 添加元素
void ComplexControl::InitWindow()
{
CListUI* pList = static_cast<CListUI*>(_paintManager.FindControl(_T("listControl")));
for (int i = 0; i < 20; i++)
{
CListTextElementUI* pItem = new CListTextElementUI();
pItem->SetTag(i);
pItem->SetFixedHeight(30);
pList->Add(pItem);
std::string number;
if (i < 10)
{
number = "100" + std::to_string(i);
}
else {
number = "10" + std::to_string(i);
}
std::string score = std::to_string(i + 60);
pItem->SetText(0, _T("张三"));
pItem->SetText(1, _T(number.c_str()));
pItem->SetText(2, _T(score.c_str()));
}
}
5、RichEdit 控件
<RichEdit name="wordedit" pos="450,200,0,0" float="true" width="350" height="178" bkcolor="#FFFFFFFF" textcolor="#FFAAA001" font="0" password="false" tipvalue="请输入文字" mutiline="true" autovscroll="true" rich="false" vscrollbar="true" hscrollbar="false" autohscroll="false"/>
<Button name="okBtn" text="确定" pos="450,388,522,418" float="true" />
6、TreeView 控件
<TreeView pos="850,20,1115,418" float="true" bkcolor="#FF111111" name="treePlaylist" childpadding="4" multipleitem="true" inset="4,0,3,0" bordersize="1" bordercolor="#FF2B2B2B" itemtextcolor="#FFC8C6CB" itemhottextcolor="#FFC8C6CB" selitemtextcolor="#FFC8C6CB" itemhotbkcolor="#FF1B1B1B" itemselectedbkcolor="#FF151C2C" vscrollbar="true" hscrollbar="true" >
<TreeNode name="nodePlaylist" text="播放列表" height="33" bkimage="common/treeview_header.png" itemattr="valign="vcenter" font="1" textpadding="12,0,0,0"" folderattr="width="0" float="true"">
<TreeNode text="迅雷下载" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="下载1" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="下载2" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
</TreeNode>
<TreeNode name="onlineMedialist" text="在线媒体" height="33" bkimage="common/treeview_header.png" itemattr="valign="vcenter" font="1" textpadding="12,0,0,0"" folderattr="width="0" float="true"">
<TreeNode text="今日热播" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="八公" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="HACHI" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
<TreeNode text="热点新闻" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="八公" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="HACHI" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
</TreeNode>
<TreeNode name="gameCenterlist" text="娱乐中心" height="33" bkimage="common/treeview_header.png" itemattr="valign="vcenter" font="1" textpadding="12,0,0,0"" folderattr="width="0" float="true"">
<TreeNode text="短视频广场" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="热门视频" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="美女视频" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
<TreeNode text="直播频道" height="22" inset="8,0,0,0" itemattr="valign="vcenter" font="0"" folderattr="width="0" float="true""/>
</TreeNode>
</TreeView>
折叠 TreeView
void ComplexControl::OnItemClick(DuiLib::TNotifyUI& msg)
{
auto name = msg.pSender->GetName();
DuiLib::CTreeNodeUI* treeNode = nullptr;
if (name == "nodePlaylist")
{
treeNode = static_cast<DuiLib::CTreeNodeUI*>(_paintManager.FindControl(_T("nodePlaylist")));
}
else if (name == "onlineMedialist")
{
treeNode = static_cast<DuiLib::CTreeNodeUI*>(_paintManager.FindControl(_T("onlineMedialist")));
}
else if (name == "gameCenterlist")
{
treeNode = static_cast<DuiLib::CTreeNodeUI*>(_paintManager.FindControl(_T("gameCenterlist")));
}
if (treeNode && treeNode->IsHasChild()) {
CTreeViewUI * pTreeView = treeNode->GetTreeView();
if (NULL != pTreeView) {
CCheckBoxUI* pFolder = treeNode->GetFolderButton();
pFolder->Selected(!pFolder->IsSelected());
treeNode->SetVisibleTag(!pFolder->GetCheck());
pTreeView->SetItemExpand(!pFolder->GetCheck(), treeNode);
}
}
}
7、DateTime 日期时间控件
xml
<DateTime name="dataTime" pos="450,30,650,70" float="true" bordersize="1" bordercolor="#FF888888" textpadding="3" bkcolor="#FFE2E5EA" font="2"/>
8、Container 容器控件,可以使用 Container 显示两张图片,也可以在 container 控件里面添加其它的控件,方便管理
xml
<Container pos="450,90,550,200" float="true" bkimage="file='common/test.jpg' dest='0,5,98,105'" />
<Container pos="550,90,650,200" float="true" bkimage="file='common/test.jpg' dest='2,5,100,105'" />
9、Control 控件,利用 Control 控件显示横线和竖线
<Control pos="450,80,650,85" float="true" bkcolor="#FF000000"/>
<Control pos="250,20,255,160" float="true" bkcolor="#FF000000"/>
10、全部代码
xml
<?xml version="1.0" encoding="UTF-8"?>
<Window size="1200,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<Font id="0" shared="true" name="宋体" size="18" bold="false" underline="false" italic="false" />
<Font id="1" shared="true" name="宋体" size="20" bold="false" underline="false" italic="false" />
<Font id="2" shared="true" name="宋体" size="16" bold="false" underline="false" italic="false" />
<Font id="3" shared="true" name="宋体" size="16" bold="false" underline="false" italic="false" />
<Font id="4" shared="true" name="宋体" size="16" bold="false" underline="false" italic="false" />
<Default shared="true" name="Button" value=" height="30" width="100" normalimage="file='common/button_normal.bmp'" hotimage="file='common/button_over.bmp'" pushedimage="file='common/button_down.bmp'" font="0"" />
<Default shared="true" name="List" value="headerbkimage="res='common/list_header_bg.png'" itemalign="center" itemlinecolor="#FF888888" itemshowrowline="true" itemshowcolumnline="true"" />
<Default name="VScrollBar" shared="true" value="width="8" showbutton1="false" showbutton2="false" thumbnormalimage="file='common/vscrollbar.png' source='0,60,8,100' corner='0,4,0,4'" thumbhotimage="file='common/vscrollbar.png' source='8,60,16,100' corner='0,4,0,4'" thumbpushedimage="file='common/vscrollbar.png' source='16,60,24,100' corner='0,4,0,4'" railnormalimage="" railhotimage="" railpushedimage="" raildisabledimage="" bknormalimage="file='common/vscrollbar.png' source='0,0,8,60' corner='0,4,0,4'" bkhotimage="" bkpushedimage="" bkdisabledimage="" "/>
<Default name="HScrollBar" shared="true" value="height="8" showbutton1="false" showbutton2="false" thumbnormalimage="file='common/hscrollbar.png' source='0,0,32,8' corner='4,0,4,0'" thumbhotimage="file='common/hscrollbar.png' source='0,8,32,16' corner='4,0,4,0'" thumbpushedimage="file='common/hscrollbar.png' source='0,16,32,24' corner='4,0,4,0'" railnormalimage="" railhotimage="" railpushedimage="" raildisabledimage="" bknormalimage="file='common/hscrollbar.png' source='0,0,32,8' corner='4,0,4,0'" bkhotimage="" bkpushedimage="" bkdisabledimage="" "/>
<VerticalLayout bkcolor="#FFDFFDF0"> <!-- 整个窗口使用 VerticalLayout 布局 -->
<Progress name="progressControl" text="0" textpadding="0,6,0,0" float="true" pos="30,28,0,0" width="139" height="30" bkimage="file='common/progress_back.png' corner='5,4,4,5'" foreimage="common/progress_fore.png" min="0" max="100" value="0" hor="true" align="center" font="2" />
<Button name="startBtn" text="开始" pos="28,90,100,120" float="true" />
<Slider name="sliderControl" float="true" pos="28,150,0,0" width="139" height="18" thumbsize="12,20" value="0" bkimage="file='common/SliderBar_BK.bmp' mask='0xffff00ff'" thumbimage="file='common/SliderBar_Thumb.png' mask='0xffffffff'"/>
<List name="listControl" float="true" pos="30,200,0,0" width="400" height="218" vscrollbar="true" hscrollbar="true" bkcolor="#FFFFFFFF" itemtextcolor="#FF000000" itembkcolor="#FFE2AADF" itemselectedtextcolor="#FF000000" itemselectedbkcolor="#FFC1E3FF" itemhottextcolor="#FF000000" itemhotbkcolor="#FFE9F5FF" itemdisabledtextcolor="#FFCCCCCC" itemdisabledbkcolor="#FFFFFFFF" >
<ListHeader name="domain" bkimage="common/list_header_bg.png">
<ListHeaderItem text="姓名" width="80" height="30" minwidth="25" sepwidth="1" align="center" hotimage="common/list_header_hot.png" pushedimage="common/list_header_pushed.png" sepimage="common/list_header_sep.png" bkcolor="0xffaa00ff"/>
<ListHeaderItem text="学号" width="160" height="30" minwidth="25" sepwidth="1" align="center" hotimage="common/list_header_hot.png" pushedimage="common/list_header_pushed.png" sepimage="common/list_header_sep.png" bkcolor="0xffaa00ff"/>
<ListHeaderItem text="成绩" width="160" height="30" minwidth="25" sepwidth="1" align="center" hotimage="common/list_header_hot.png" pushedimage="common/list_header_pushed.png" sepimage="common/list_header_sep.png" bkcolor="0xffaa00ff"/>
</ListHeader>
</List>
<RichEdit name="wordedit" pos="450,200,0,0" float="true" width="350" height="178" bkcolor="#FFFFFFFF" textcolor="#FFAAA001" font="0" password="false" tipvalue="请输入文字" mutiline="true" autovscroll="true" rich="false" vscrollbar="true" hscrollbar="false" autohscroll="false"/>
<Button name="okBtn" text="确定" pos="450,388,522,418" float="true" />
<DateTime name="dataTime" pos="450,30,650,70" float="true" bordersize="1" bordercolor="#FF888888" textpadding="3" bkcolor="#FFE2E5EA" font="2"/>
<Control pos="450,80,650,85" float="true" bkcolor="#FF000000"/>
<Control pos="250,20,255,160" float="true" bkcolor="#FF000000"/>
<Container pos="450,90,550,200" float="true" bkimage="file='common/test.jpg' dest='0,5,98,105'" />
<Container pos="550,90,650,200" float="true" bkimage="file='common/test.jpg' dest='2,5,100,105'" />
<TreeView pos="850,20,1115,418" float="true" bkcolor="#FF111111" name="treePlaylist" childpadding="4" multipleitem="true" inset="4,0,3,0" bordersize="1" bordercolor="#FF2B2B2B" itemtextcolor="#FFC8C6CB" itemhottextcolor="#FFC8C6CB" selitemtextcolor="#FFC8C6CB" itemhotbkcolor="#FF1B1B1B" itemselectedbkcolor="#FF151C2C" vscrollbar="true" hscrollbar="true" >
<TreeNode name="nodePlaylist" text="播放列表" height="33" bkimage="common/treeview_header.png" itemattr="valign="vcenter" font="1" textpadding="12,0,0,0"" folderattr="width="0" float="true"">
<TreeNode text="迅雷下载" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="下载1" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="下载2" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
</TreeNode>
<TreeNode name="onlineMedialist" text="在线媒体" height="33" bkimage="common/treeview_header.png" itemattr="valign="vcenter" font="1" textpadding="12,0,0,0"" folderattr="width="0" float="true"">
<TreeNode text="今日热播" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="八公" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="HACHI" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
<TreeNode text="热点新闻" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="八公" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="HACHI" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
</TreeNode>
<TreeNode name="gameCenterlist" text="娱乐中心" height="33" bkimage="common/treeview_header.png" itemattr="valign="vcenter" font="1" textpadding="12,0,0,0"" folderattr="width="0" float="true"">
<TreeNode text="短视频广场" inset="-8,0,0,0" height="22" itemattr="valign="vcenter" font="0" textpadding="4,0,0,0"" folderattr="padding="0,5,0,0" width="12" height="12" selectedimage="file='common/treeview_expand.png' source='0,0,12,12' " normalimage="file='common/treeview_expand.png' source='13,0,25,12' "">
<TreeNode text="热门视频" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
<TreeNode text="美女视频" height="22" inset="7,0,0,0" itemattr="valign="vcenter" font="4"" folderattr="width="0" float="true""/>
</TreeNode>
<TreeNode text="直播频道" height="22" inset="8,0,0,0" itemattr="valign="vcenter" font="0"" folderattr="width="0" float="true""/>
</TreeNode>
</TreeView>
</VerticalLayout>
</Window>
.h
#pragma once
#include "UIlib.h"
class ComplexControl : public DuiLib::CWindowWnd, public DuiLib::INotifyUI
{
public:
ComplexControl();
~ComplexControl();
void Init();
bool CreateDUIWindow();
void ShowWindow();
LPCTSTR GetWindowClassName() const override;
void Notify(DuiLib::TNotifyUI& msg) override;
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnClick(DuiLib::TNotifyUI& msg);
void OnValueChange(DuiLib::TNotifyUI& msg);
void OnItemClick(DuiLib::TNotifyUI& msg);
private:
void InitWindow();
private:
HINSTANCE _hInstance;
DuiLib::CPaintManagerUI _paintManager{};
HWND _ownerWnd{};
};
.cpp
#include "complex_control.h"
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
using namespace DuiLib;
ComplexControl::ComplexControl()
{
}
ComplexControl::~ComplexControl()
{
}
void ComplexControl::Init()
{
SetProcessDPIAware();
_hInstance = GetModuleHandle(0);
DuiLib::CPaintManagerUI::SetInstance(_hInstance);
DuiLib::CPaintManagerUI::SetResourcePath(DuiLib::CPaintManagerUI::GetInstancePath() + +_T("..\\..\\..\\resources"));
}
bool ComplexControl::CreateDUIWindow()
{
_ownerWnd = Create(NULL, _T("Complex"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
if (!_ownerWnd)
{
std::cout << "create dui window failed" << std::endl;
return false;
}
return true;
}
void ComplexControl::ShowWindow()
{
ShowModal();
}
LPCTSTR ComplexControl::GetWindowClassName() const
{
return _T("DUICOMPLEXFrame");
}
void ComplexControl::Notify(DuiLib::TNotifyUI& msg)
{
if (msg.sType == _T("click"))
{
OnClick(msg);
}
else if (msg.sType == _T("valuechanged"))
{
OnValueChange(msg);
}
else if (msg.sType == _T("itemclick"))
{
OnItemClick(msg);
}
}
LRESULT ComplexControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = 0;
switch (uMsg) {
case WM_CREATE:
lRes = OnCreate(uMsg, wParam, lParam);
break;
case WM_CLOSE:
lRes = OnClose(uMsg, wParam, lParam);
break;
default:
break;
}
if (_paintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{
return lRes;
}
return __super::HandleMessage(uMsg, wParam, lParam);
}
LRESULT ComplexControl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
_paintManager.Init(m_hWnd);
DuiLib::CDialogBuilder builder;
DuiLib::CControlUI* pRoot = builder.Create(_T("complexControl.xml"), (UINT)0, NULL, &_paintManager);
_paintManager.AttachDialog(pRoot);
_paintManager.AddNotifier(this);
InitWindow();
return 0;
}
LRESULT ComplexControl::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}
void ComplexControl::OnClick(DuiLib::TNotifyUI& msg)
{
if (msg.pSender->GetName() == _T("startBtn"))
{
DuiLib::CProgressUI* pProgress = static_cast<DuiLib::CProgressUI*>(_paintManager.FindControl(_T("progressControl")));
std::thread work = std::thread([pProgress, this]() {
for (int i = 1; i <= 100; ++i) {
pProgress->SetValue(i);
std::string text = std::to_string(i) + "%";
pProgress->SetText(text.c_str());
Sleep(50);
}
});
work.detach();
}
if (msg.pSender->GetName() == _T("okBtn"))
{
// 如果有手动输入的换行,字符会被覆盖掉
DuiLib::CRichEditUI* pRichEdit = static_cast<DuiLib::CRichEditUI*>(_paintManager.FindControl(_T("wordedit")));
std::cout << pRichEdit->GetText() << std::endl;
}
}
void ComplexControl::OnValueChange(DuiLib::TNotifyUI& msg)
{
if (msg.pSender->GetName() == _T("sliderControl"))
{
DuiLib::CSliderUI* slider = static_cast<DuiLib::CSliderUI*>(_paintManager.FindControl(_T("sliderControl")));
// 获取 slider 的进度
std::cout << "slider:" << slider->GetValue() << std::endl;
}
}
void ComplexControl::OnItemClick(DuiLib::TNotifyUI& msg)
{
auto name = msg.pSender->GetName();
DuiLib::CTreeNodeUI* treeNode = nullptr;
if (name == "nodePlaylist")
{
treeNode = static_cast<DuiLib::CTreeNodeUI*>(_paintManager.FindControl(_T("nodePlaylist")));
}
else if (name == "onlineMedialist")
{
treeNode = static_cast<DuiLib::CTreeNodeUI*>(_paintManager.FindControl(_T("onlineMedialist")));
}
else if (name == "gameCenterlist")
{
treeNode = static_cast<DuiLib::CTreeNodeUI*>(_paintManager.FindControl(_T("gameCenterlist")));
}
if (treeNode && treeNode->IsHasChild()) {
CTreeViewUI * pTreeView = treeNode->GetTreeView();
if (NULL != pTreeView) {
CCheckBoxUI* pFolder = treeNode->GetFolderButton();
pFolder->Selected(!pFolder->IsSelected());
treeNode->SetVisibleTag(!pFolder->GetCheck());
pTreeView->SetItemExpand(!pFolder->GetCheck(), treeNode);
}
}
}
void ComplexControl::InitWindow()
{
CListUI* pList = static_cast<CListUI*>(_paintManager.FindControl(_T("listControl")));
for (int i = 0; i < 20; i++)
{
CListTextElementUI* pItem = new CListTextElementUI();
pItem->SetTag(i);
pItem->SetFixedHeight(30);
pList->Add(pItem);
std::string number;
if (i < 10)
{
number = "100" + std::to_string(i);
}
else {
number = "10" + std::to_string(i);
}
std::string score = std::to_string(i + 60);
pItem->SetText(0, _T("张三"));
pItem->SetText(1, _T(number.c_str()));
pItem->SetText(2, _T(score.c_str()));
}
#if 0
DuiLib::CActiveXUI* pActiveXUI = static_cast<DuiLib::CActiveXUI*>(_paintManager.FindControl(_T("ActiveXDemo1")));
if (pActiveXUI)
{
IWebBrowser2* pWebBrowser = NULL;
pActiveXUI->SetDelayCreate(false); // 相当于界面设计器里的DelayCreate属性改为FALSE,在duilib自带的FlashDemo里可以看到此属性为TRUE
pActiveXUI->CreateControl(CLSID_WebBrowser); // 相当于界面设计器里的Clsid属性里填入{8856F961-340A-11D0-A96B-00C04FD705A2},建议用CLSID_WebBrowser,如果想看相应的值,请见<ExDisp.h>
pActiveXUI->GetControl(IID_IWebBrowser2, (void**)&pWebBrowser);
if (pWebBrowser != NULL)
{
pWebBrowser->Navigate(L"https://www.baidu.com/", NULL, NULL, NULL, NULL);
pWebBrowser->Release();
}
}
#endif
}
运行结果
二、参考资料
1、duilib 复杂控件介绍:https://blog.csdn.net/rundll64/article/details/24749287?utm_medium=distribute.pc_relevant.none-task-blog-title-12&spm=1001.2101.3001.4242
2、duilib 中基于 wke 的浏览器控件:https://blog.csdn.net/lionzl/article/details/52449413
3、改进 RichEdit 的部分功能:https://blog.csdn.net/zhuhongshu/article/details/41208207
4、RichEdit 源码分析:https://blog.csdn.net/jcx517266098/article/details/79374671
5、TreeView 控件:https://www.cnblogs.com/Alberl/p/3402328.html
6、TreeView 折叠:https://blog.csdn.net/eGirlAsm/article/details/51010862