本文主要是介绍duilib:设计一个高可用,支持uri下载的duilib控件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
先喵两句,本文只是提供一个具体思路,直接copy肯定编译不过,需要自己实现以下接口:
1. uri下载接口
2. 主线程调用接口(如果可能的话)
3. 线程池
duilib默认没有支持uri图片的控件,很多业务逻辑都需要自己实现,因此就有了以下的大胆想法,由于图片下载/显示的逻辑都很雷同,没必要一个个继承,然后重复写一套逻辑,显得代码很冗余,于是就有了以下想法,直接用模板类来实现这些接口。
代码上面也会有相应的注释,将就着看吧:
.h文件:
using namespace std::tr2;//这里你可以根据需要实例化各种控件,比如edit,combo等
template<typename Control>
class CUriControlUI : Control {
public:static DuiLib::CControlUI* CreateControl();public:CUriControlUI() {//m_tp.init(1);}~CUriControlUI() {m_tp.destroy();}void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue){if (_tcsicmp(pstrName, _T("url")) == 0) {m_url = pstrValue;//在初始化的时候,这个管理器有可能没有创建出来if (!m_pManager) {//OnInit是基类实现的一套观察者模式的机制,有点像C#里面event//在空间初始化完成后,再调用下载接口,设置图片就万无一失了OnInit += MakeDelegate(this, &CUriControlUI<Control>::OnControlReady);}else {m_tp.add_task(std::bind(&CUriControlUI<Control>::LoadUriImg, this));}}Control::SetAttribute(pstrName, pstrValue);}
private:bool OnControlReady(void*) {//线程池,需要自己实现,当然随便开个线程来做也行m_tp.add_task(std::bind(&CUriControlUI<Control>::LoadUriImg, this));return true;}int LoadUriImg() {if (-1 == m_url.Find(L"http:") && -1 == m_url.Find(L"https:")){return -1;}else {std::string filename = CStringUtil::url_encode(XW2A(m_url.GetData()));std::string local = CGlobalDataManage::GetInstance().GetUserDirectory() + "\\" + filename;sys::path file(local);if (!sys::exists(file)){//需要自己实现图片下载接口if (0 != HTTPDOWDLOAD_SYNC(XW2A(m_url.GetData()),local,HTTP_HEADER)){return -1;}}else{}if (m_pManager) {//这里是主线程调用接口,UI的东西肯定UI线程操作嘛POST_MAIN_THREAD_SYNC_TASK(m_pManager->GetPaintWindow(), [&] (){SetBkImage(XA2W(local).c_str());});}return 0;}}DuiLib::CDuiString m_url;//uriCThreadPool m_tp;//线程池
};//这里仅仅展示label跟button的例子
using CUriLabelUI = CUriControlUI<DuiLib::CLabelUI>;
using CUriButtonUI = CUriControlUI<DuiLib::CButtonUI>;
.cpp
//就是定义CreateControl接口而已
IMPLEMENT_DUICONTROL(CUriLabelUI)
IMPLEMENT_DUICONTROL(CUriButtonUI)
注册控件
需要的地方往duilib的factory注册以上的控件即可
这篇关于duilib:设计一个高可用,支持uri下载的duilib控件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!