duilib是什么_double blind

duilib是什么_double blind部分BUG一、WindowImplBase的bug在第8个教程【2013duilib入门简明教程–完整的自绘标题栏(8)】中,可以发现窗口最大化之后有两个问题,1、最大化按钮的样式还是没变,正确的样式应该是这样的2、再次点击最大化按钮,不能还原到正常大小。这个是WindowImplBase的bug,已经提交给官方有一段时间了,但是貌似没有被合并到SVN上去,所以这里说明一下,我们需要在WindowImplBase的OnSysComma…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

部分BUG

 一、WindowImplBase的bug

    在第8个教程【2013 duilib入门简明教程 — 完整的自绘标题栏(8)】中,可以发现窗口最大化之后有两个问题,

    1、最大化按钮的样式还是没变

duilib是什么_double blind

,正确的样式应该是这样的

    2、再次点击最大化按钮,不能还原到正常大小。

    这个是WindowImplBase的bug,已经提交给官方有一段时间了,但是貌似没有被合并到SVN上去,所以这里说明一下,

我们需要在WindowImplBase的OnSysCommand函数里,在if( ::IsZoomed(*this) != bZoomed )里面加上下面这段代码:

if( ::IsZoomed(*this) != bZoomed )
    {
        CControlUI* pbtnMax     = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("maxbtn")));       // 最大化按钮
        CControlUI* pbtnRestore = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("restorebtn")));   // 还原按钮
 
        // 切换最大化按钮和还原按钮的状态
        if (pbtnMax && pbtnRestore)
        {
            pbtnMax->SetVisible(TRUE == bZoomed);       // 此处用表达式是为了避免编译器BOOL转换的警告
            pbtnRestore->SetVisible(FALSE == bZoomed);
        }
    }

Jetbrains全家桶1年46,售后保障稳定

 二、CDuiString的bug (重温了一下 Effective C++,发现这就是条款24所指出的问题,看来读书百遍不如写代码一遍啊)

    在Notify处理消息时会有很多if语句,我通常喜欢把常量放在双等号前面,变量放在后面,比如:   

if( _T("click") ==  msg.sType )
{
}

    但是却发现并没有进到这个if里,调试发现,将常量调到前面时,并没有进入到CDuiString重载的 == 函数里面,所以这里必须将常量放到后面。   

if( msg.sType == _T("click") )
{
}

    这个bug的原因是因为将常量放在前面时,并没有调用CDuiString重载的 == 函数,而是调用了CDuiString重载的 ()函数,然后用系统自带的==函数做比较,而系统自己的==函数只是比较两个指针的首地址是否相等。_T(“click”) 的首地址指向的是一块临时变量,而msg.sType 是返回了CDuiString里面那个字符串的指针,很显然这两个指针地址是不相等的,所以我们只能把它放在前面,或者直接调用_tcscmp   

if( ! _tcscmp( _T("click"), msg.sType) )
{
}

    当然,如果要解决这个bug,就要重载多个==操作符,

    由于CDuiString是将==函数作为成员函数重载的,所以只有CDuiString对象在操作符左边时,才会调用这个重载函数,如果想要CDuiString对象在右边时也能调用重载的==函数,那么必须将重载操作符放到外部。这里我们可以看一下MFC的CString是怎么重载的:

duilib是什么_double blind

    CString 重载了5个==操作符,都是友元函数,定义在#include<cstringt.h>里面。

    再看下STL的std::string :

duilib是什么_double blind

    std::string重载了3个==操作符,都是全局函数,定义在#include<string>里面。

duilib是什么_double blind

  不过需要提醒的是,我稍微看了下CDuiString的代码,有很多漏洞,比如在清零字符串时,只是调用了 m_szBuffer[0] = ‘\0’; 并不是调用memset,那么就会有以下问题,我们随意现在用下面两种方式给CDuiString 附值,然后监视字符串数组的内容,可以发现虽然显示是正确的,但是在零值后面的值全部是乱码:

duilib是什么_double blind

duilib是什么_double blind

    这样的话,虽然_tcslen、_tcscmp等函数能用,但是还有很多函数都会出问题的。

    所以这个CDuiString能不用则不用,如果嫌MFC生成的exe体积大,可以用WTL的CString,如果WTL也不想用,那就只好用STL的string了。

    当然,为了保证代码的兼容性,一些简单的处理还是用CDuiString比较好,比如 msg.sType。

    而逻辑处理等复杂的场景,最好用久经考验的代码。  虽然微软的CString很强大,而用STL的string时可能不方便,但是我现在越来越喜欢STL的string啦,当然,我是定义了一个string_t,加上一个名字空间,以防和一些开源库冲突,

    一些著名的开源库喜欢如下定义:

#ifdef _UNICODE
    typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > string_t;
#else
    typedef std::basic_string<char, std::char_traits<char>, std::allocator<char> > string_t;
#endif

不过我喜欢更简短的定义:

#ifdef _UNICODE
    typedef std::wstring string_t;
#else
    typedef std::string  string_t;
#endif

 下面是我常用的Unicode定义:

#include <string>
#include <sstream> 
 
namespace duilib
{
#ifdef _UNICODE
    typedef wchar_t              char_t;
    typedef std::wstring         string_t;
    typedef std::wstringstream   stringstream_t;
#else
    typedef char                 char_t;
    typedef std::string          string_t;
    typedef std::stringstream    stringstream_t;
#endif
}

简单控件介绍

 前面的教程应该让大家对duilib的整体有所映像了,下面就来介绍下duilib具体控件的使用。

    由于官方没有提供默认的控件样式,所以我就尽量使用win7或者XP自带的按钮样式了,虽然界面比较土鳖,但是想要换成百度杀毒那样的界面,只需要更换图片即可,如果有哪位小伙伴能够提供一些控件样式,那就再好不过啦~

    首先利用一下前面教程的框架,效果图如下:

duilib是什么_double blind

main.cpp的代码如下:

class CDuiFrameWnd : public WindowImplBase
{
public:
    virtual LPCTSTR    GetWindowClassName() const   {   return _T("DUIMainFrame");  }
    virtual CDuiString GetSkinFile()                {   return _T("duilib.xml");    }
    virtual CDuiString GetSkinFolder()              {   return _T("");  }
};
 
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    CPaintManagerUI::SetInstance(hInstance);
 
    CDuiFrameWnd duiFrame;
    duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    duiFrame.CenterWindow();
    duiFrame.ShowModal();
    return 0;
}

 XML代码如下(由于前面的教程里都一一介绍了各种属性,所以以后的XML就不一一注释了):

<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
  <VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
    <!-- 标题栏区 -->
    <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">   
      <VerticalLayout /> 
      <VerticalLayout width="77"> 
          <Button name="minbtn"   tooltip="最小化" float="true" pos="0,5,22,24"  width="23" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' " pushedimage=" file='SysBtn\MinFocus.bmp' "/>
          <Button name="maxbtn"   tooltip="最大化" float="true" pos="22,5,44,24" width="23" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' " pushedimage=" file='SysBtn\MaxFocus.bmp' " />
          <Button name="restorebtn" visible="false" tooltip="还原" float="true" pos="22,5,44,24" width="23" normalimage=" file='SysBtn\StoreNormal.bmp' " hotimage=" file='SysBtn\StoreFocus.bmp' " pushedimage=" file='SysBtn\StoreFocus.bmp' " />
          <Button name="closebtn" tooltip="关闭"   float="true" pos="44,5,74,24" width="28" normalimage=" file='SysBtn\CloseNormal.bmp' " hotimage=" file='SysBtn\CloseFocus.bmp' " pushedimage=" file='SysBtn\CloseFocus.bmp' "/>
        </VerticalLayout>      
    </HorizontalLayout>
  </VerticalLayout>
</Window>

前面教程的Hello World就是一个大大的按钮,大家对按钮应该很熟悉了,下面我们来几个按钮样式吧:

XP默认按钮        

duilib是什么_double blind

win7默认按钮     

duilib是什么_double blind

百度杀毒            

duilib是什么_double blind

        

百度卫士            

duilib是什么_double blind

        

  

      上述图片资源请点击这里下载,下载后解压到exe目录即可,此时Debug文件夹如下(别忘了前面教程的SysBtn文件夹哦):

duilib是什么_double blind

  我们先用DuiDesigner添加一些按钮,并且把他们排整齐,如图:

duilib是什么_double blind

  保存之后就可以看到这几个按钮的pos等属性了,再手动将这几个Button节点加到前面的XML中,并添加图片属性,如下:

<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
    <VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
        <!-- 标题栏区 -->
        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">   
            <VerticalLayout /> 
            <VerticalLayout width="77"> 
                <Button name="minbtn"   tooltip="最小化" float="true" pos="0,5,22,24"  width="23" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' " pushedimage=" file='SysBtn\MinFocus.bmp' "/>
                <Button name="maxbtn"   tooltip="最大化" float="true" pos="22,5,44,24" width="23" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' " pushedimage=" file='SysBtn\MaxFocus.bmp' " />
                <Button name="restorebtn" visible="false" tooltip="还原" float="true" pos="22,5,44,24" width="23" normalimage=" file='SysBtn\StoreNormal.bmp' " hotimage=" file='SysBtn\StoreFocus.bmp' " pushedimage=" file='SysBtn\StoreFocus.bmp' " />
                <Button name="closebtn" tooltip="关闭"   float="true" pos="44,5,74,24" width="28" normalimage=" file='SysBtn\CloseNormal.bmp' " hotimage=" file='SysBtn\CloseFocus.bmp' " pushedimage=" file='SysBtn\CloseFocus.bmp' "/>
            </VerticalLayout>      
        </HorizontalLayout>
 
        <!-- 客户区 -->
        <HorizontalLayout>
            <Button text="XP"       float="true" pos="20,14,0,0" width="60" height="25" normalimage=" file='BtnStyle\XP\button_nor.png' " hotimage=" file='BtnStyle\XP\button_over.png' " pushedimage=" file='BtnStyle\XP\button_down.png' " focusedimage=" file='BtnStyle\XP\button_focus.png' " />
            <Button text="win7"     float="true" pos="20,50,0,0" width="60" height="25" normalimage=" file='BtnStyle\win7\button_nor.png' " hotimage=" file='BtnStyle\win7\button_over.png' " pushedimage=" file='BtnStyle\win7\button_down.png' " focusedimage=" file='BtnStyle\win7\button_focus.png' " />
            <Button text="百度杀毒" float="true" pos="20,86,0,0" width="102" height="35" normalimage=" file='BtnStyle\BDKV\button_nor.png' " hotimage=" file='BtnStyle\BDKV\button_over.png' " pushedimage=" file='BtnStyle\BDKV\button_down.png' " />
            <Button                 float="true" pos="20,132,0,0" width="171" height="46" normalimage=" file='BtnStyle\BDKV2\button_nor.png' " hotimage=" file='BtnStyle\BDKV2\button_over.png' " pushedimage=" file='BtnStyle\BDKV2\button_down.png' " />
        </HorizontalLayout>
    </VerticalLayout>
</Window>

  效果如下:

duilib是什么_double blind

    用鼠标移上去,或者点击一下,看看是不是和系统按钮一样呢^_^

    下面我们介绍一下duilib的另一种特性,那就是可以定制默认样式,这样做有什么好处呢?

    假如我们有10个按钮,按钮样式都一样,如果用之前介绍的方式,则需要在每个Button节点都指定图片背景、宽度、高度等信息,一旦需要改动任何一个属性,则需要在10个按钮里面都改一次,所以为了方便修改,我们可以指定一个默认样式,就算有100个按钮,我们也只需要改一次属性。方法如下:

    给<Window>节点添加一个Default节点即可,其中name属性填写控件的名字,value属性添加控件的属性的值,不过需要将双引号【”】换成【&quot;】,单引号【’】换成【&apos;】,单引号也可以不转换。

XML如下(由于标题栏基本不再变化,所以后面的教程将省略<!– 标题栏区 –>那一段XML):

<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
    <Default name="Button" value="  height="25" width="60" normalimage="file=&apos;BtnStyle\XP\button_nor.png&apos;" hotimage="file=&apos;BtnStyle\XP\button_over.png&apos;" pushedimage="file=&apos;BtnStyle\XP\button_down.png&apos;" focusedimage="file=&apos;BtnStyle\XP\button_focus.png&apos;" " />
    <VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
        <!-- 客户区 -->
        <HorizontalLayout>
            <Button text="XP"       float="true" pos="20,14,0,0"  height="25" />
            <Button text="win7"     float="true" pos="20,50,0,0"  height="25" />
            <Button text="百度杀毒" float="true" pos="20,86,0,0"  height="25" />
            <Button                 float="true" pos="20,132,0,0" height="25" />
        </HorizontalLayout>
    </VerticalLayout>
</Window>

duilib是什么_double blind

XML是不是清爽多了呢^_^  注意,这里面要指定height属性,不然会看不到按钮,估计是因为放在了HorizontalLayout水平布局里。(如果是VerticalLayout ,应该是指定width属性,这个只是猜测,暂未验证~\(^o^)/~)

    不过你会发现,启动的时候,最小化按钮图片不对了,那是因为最小化按钮没有指定focusedimage属性,所以就用了默认的focusedimage属性,只需要指定一下就行了。

duilib是什么_double blind

    按钮的用法就介绍完啦,大家可以看到UI设计器里面还有下面这些控件,

duilib是什么_double blind

    其中:

    Control是所有控件的基类,一般放图片啥的就用它了。

    Label和Text是用于放文字的,其中Label的对齐功能比Text要好一些,所以我一般用Label,这个对应于MFC的Static控件。

    Edit显然就是编辑框啦,Button就不用多说了吧~

    上面提到的控件都是简单控件,拖到设计器上就能直观的看到效果,绝大部分属性都和Button一样,就不赘述了,所有控件的所有属性都在【duilib控件 XML属性列表】里有详细说明(不过有一点点遗漏,需要去看源码),下一节将介绍复杂控件。

复杂控件介绍

首先将本节要介绍的控件全部拖到界面上,并调整好位置,如图:  

duilib是什么_double blind

     然后将Name属性改成其他名字,    

duilib是什么_double blind

    不能是【控件名+UI+数字】这种,因为这是DuiDesigner默认的名字,它不会实际写入到XML,所以如果控件的名字被取成ActiveXUI1、ActiveXUI2、ButtonUI1这种格式的话,Name属性会被忽略,可以看到XML是没有Name属性的:

duilib是什么_double blind

    所以我们必须给它们指定其他的名字,这里格式统一为【控件名+Demo+数字】,如图:   

duilib是什么_double blind

    XML如下(删除了暂时没用到的属性,删除了标题栏区域,要关闭窗口请按Esc或者在任务栏右键关闭):

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="800,600" sizebox="4,4,4,4" caption="0,0,0,32" mininfo="600,400">
    <VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
        <HorizontalLayout>
            <Progress name="ProgressDemo1" text="Progress" float="true" pos="30,28,0,0" width="139" height="30" />
            <Slider name="SliderDemo1" text="Slider" float="true" pos="30,77,0,0" width="139" height="30" />
            <Combo name="ComboDemo1" float="true" pos="30,264,0,0" width="139" height="30" />
            <List name="ListDemo1" float="true" pos="30,314,0,0" width="139" height="218" >
                <ListHeader />
            </List>
            <ActiveX name="ActiveXDemo1" float="true" pos="202,265,0,0" width="568" height="266" />
            <Option name="OptionDemo1" text="Option1" float="true" pos="207,28,0,0" width="60" height="30" />
            <Option name="OptionDemo2" text="Option2" float="true" pos="284,28,0,0" width="60" height="30" />
            <Option name="OptionDemo3" text="Option3" float="true" pos="361,28,0,0" width="60" height="30" />
        </HorizontalLayout>
    </VerticalLayout>
</Window>

    各种控件的图片资源请点击这里下载(这是整个工程的地址,资源都在Release目录下),也是解压到exe目录即可。

    由于复杂控件都需要初始化,所以这里介绍一个初始化函数InitWindow,相当于MFC的OnInitDialog,所有的初始化操作都在这里进行。

一、ActiveX控件

    由于ActiveX控件必须要初始化,否则启动时会崩溃,所以第一个介绍它。

    因为ActiveX控件用到了COM,所以需要初始化COM,此时main.cpp的代码如下:

class CDuiFrameWnd : public WindowImplBase
{
public:
    virtual LPCTSTR    GetWindowClassName() const   {   return _T("DUIMainFrame");  }
    virtual CDuiString GetSkinFile()                {   return _T("duilib.xml");    }
    virtual CDuiString GetSkinFolder()              {   return _T("");  }
 
    virtual void       InitWindow()
    {
        CActiveXUI* pActiveXUI = static_cast<CActiveXUI*>(m_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://code.google.com/p/duilib/",NULL,NULL,NULL,NULL);  
                pWebBrowser->Navigate(L"http://www.baidu.com/",NULL,NULL,NULL,NULL);  // 由于谷歌时不时被墙,所以换成反应快的网站
                pWebBrowser->Release();
            }
        }
    }
};
 
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    CPaintManagerUI::SetInstance(hInstance);
    HRESULT Hr = ::CoInitialize(NULL);
    if( FAILED(Hr) ) return 0;
 
    CDuiFrameWnd duiFrame;
    duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    duiFrame.CenterWindow();
    duiFrame.ShowModal();
 
    ::CoUninitialize();
    return 0;
}
duilib是什么_double blind

    此Demo用的是浏览器控件,其他的ActiveX控件也是一样的原理,就不赘述了,duilib自带了一个FlashDemo,里面用的是Flash控件,请自行参阅。不过关闭窗口后,会发现产生了崩溃,这是CActiveXUI的一个Bug,详情请点击这里~   暂时给出一个临时的快速解决方案,就是将主框架用new的方式生成,而不是直接用变量生成,所以_tWinMain改为下面这样:

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    CPaintManagerUI::SetInstance(hInstance);
    HRESULT Hr = ::CoInitialize(NULL);
    if( FAILED(Hr) ) return 0;
 
    CDuiFrameWnd *pFrame = new CDuiFrameWnd;
    pFrame->Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    pFrame->CenterWindow();
    pFrame->ShowModal();
 
    delete pFrame;
    ::CoUninitialize();
    return 0;
}

二、进度条控件

    给Progress 加上背景图片(foreimage属性)和位置信息(value属性)即可生成如下效果:

duilib是什么_double blind

    XML代码如下:

<Progress name="ProgressDemo1" text="Progress" float="true" pos="30,28,0,0" width="139" height="30" foreimage="Progress/progress_fore.png" min="0" max="100" value="50" hor="true" align="center" />

    如果要改变进度条的位置,则调用以下代码即可:     

CProgressUI* pProgress = static_cast<CProgressUI*>m_PaintManager.FindControl(_T("ProgressDemo1")));    
pProgress->SetValue(100);
duilib是什么_double blind

三、滑块控件

    给Slider 加上背景图片(bkimage属性)和滑块图片(thumbimage属性)即可生成如下效果:

duilib是什么_double blind

    XML代码如下:

<Slider name="SliderDemo1" float="true" pos="30,77,0,0" width="139" height="18" thumbsize="12,20" bkimage="file='Slider/slider_fore.bmp' mask='0xffff00ff'" thumbimage="file='Slider/SliderBar.png' mask='0xffffffff'"/>

其他的操作和进度条类似~

四、组合框控件

    XML如下:

<Combo name="ComboDemo1" float="true" pos="30,264,0,0" width="139" height="30" normalimage="file='ComboBox/Combo_nor.bmp'" hotimage="file='ComboBox/Combo_over.bmp' " pushedimage="file='ComboBox/Combo_over.bmp' " >
                <ListLabelElement text="张三" selected="true" />
                <ListLabelElement text="李四" />
            </Combo>  
duilib是什么_double blind

由于此教程是入门教程,所以只加上了最基本的属性,如果想要将文字对齐等等,请参阅duilib自带的GameDemo的登录窗口。

五、列表控件

    由于ListBox只是ListCtrl的一个子集,并且比较简单,所以先介绍ListBox控件。XML如下:

<List name="ListDemo1" float="true" pos="30,314,0,0" width="139" height="218" header="hidden" bkcolor="#FFFFFFFF" itemtextcolor="#FF000000" itembkcolor="#FFE2DDDF" itemselectedtextcolor="#FF000000" itemselectedbkcolor="#FFC1E3FF" itemhottextcolor="#FF000000" itemhotbkcolor="#FFE9F5FF" itemdisabledtextcolor="#FFCCCCCC" itemdisabledbkcolor="#FFFFFFFF" >
    <ListLabelElement text="张三" selected="true" />
    <ListLabelElement text="李四" />
</List>
duilib是什么_double blind

    亲们可以发现ListBox和上面的ComboBox基本没啥区别,这是因为duilib的各个控件并没有严格的界限,很多控件都是通过一些基本控件组合起来的~

需要说明的就是:这里需要加上header=”hidden” 隐藏ListCtrl的表头。

    接下来介绍ListCtrl,只有一列的ListCtrl和ListBox并无明显区别,只需要将header=”hidden”去掉,并且设置好ListHeader属性即可,这里直接介绍多列的ListCtrl。

    先加上表头,XML如下:

<List name="ListDemo1" float="true" pos="30,314,0,0" width="139" height="218" bkcolor="#FFFFFFFF" itemtextcolor="#FF000000" itembkcolor="#FFE2DDDF" itemselectedtextcolor="#FF000000" itemselectedbkcolor="#FFC1E3FF" itemhottextcolor="#FF000000" itemhotbkcolor="#FFE9F5FF" itemdisabledtextcolor="#FFCCCCCC" itemdisabledbkcolor="#FFFFFFFF" >
    <ListHeader name="domain" bkimage="List/list_header_bg.png">
        <ListHeaderItem text="序号" width="40" height="23" minwidth="16"  sepwidth="1" align="center" hotimage="List/list_header_hot.png" pushedimage="List/list_header_pushed.png" sepimage="List/list_header_sep.png" />
        <ListHeaderItem text="文件名称" width="84" height="23" minwidth="16"  sepwidth="1" align="center" hotimage="List/list_header_hot.png" pushedimage="List/list_header_pushed.png" sepimage="List/list_header_sep.png" />
    </ListHeader>
    <ListLabelElement text="张三" selected="true" />
    <ListLabelElement text="李四" />
</List>
duilib是什么_double blind

    可以发现虽然表头有两列了,但是内容还只是一列,由于在XML里直接添加多列并不方便,所以这里采取和MFC类似的方式,即内容动态添加。那么XML代码需改为如下:

<List name="ListDemo1" float="true" pos="30,314,0,0" width="139" height="218" vscrollbar="true" hscrollbar="true" bkcolor="#FFFFFFFF" itemtextcolor="#FF000000" itembkcolor="#FFE2DDDF" itemselectedtextcolor="#FF000000" itemselectedbkcolor="#FFC1E3FF" itemhottextcolor="#FF000000" itemhotbkcolor="#FFE9F5FF" itemdisabledtextcolor="#FFCCCCCC" itemdisabledbkcolor="#FFFFFFFF" >
                <ListHeader name="domain" bkimage="List/list_header_bg.png">
                    <ListHeaderItem text="序号" width="40" height="23" minwidth="16"  sepwidth="1" align="center" hotimage="List/list_header_hot.png" pushedimage="List/list_header_pushed.png" sepimage="List/list_header_sep.png" />
                    <ListHeaderItem text="文件名称" width="84" height="23" minwidth="16"  sepwidth="1" align="center" hotimage="List/list_header_hot.png" pushedimage="List/list_header_pushed.png" sepimage="List/list_header_sep.png" />
                </ListHeader>
            </List>

     然后在main.cpp的InitWindow里添加如下代码:

CDuiString str;
CListUI* pList = static_cast<CListUI*>(m_PaintManager.FindControl(_T("ListDemo1")));
 
// 添加List列表内容,必须先Add(pListElement),再SetText
for (int i = 0; i < 100; i++)
{
    CListTextElementUI* pListElement = new CListTextElementUI;
    pListElement->SetTag(i);
    pList->Add(pListElement);
 
    str.Format(_T("%d"), i);
    pListElement->SetText(0, str);
    pListElement->SetText(1, _T("haha"));
}

即可生成如下效果:

duilib是什么_double blind

    是不是比duilib自带的Demo简洁明了得多呢~O(∩_∩)O~

    不过还没完工,因为滚动条好像不太美观~~~

    还记得前面介绍的Default属性吗?它不仅仅让我们少敲更多代码,而且还减少了错误的几率,提高了代码的可读性,真是一个强大的属性,那么我们的滚动条继续沿用此属性~

滚动条的XML代码如下:

    

    XML好乱,复制到XML编辑器上慢慢看吧~(*^__^*)

    稍微说明下:

source=&apos;0,0,16,16&apos; 相当于source=’0,0,16,16’,意思就是只显示图片中’0,0,16,16’矩形包含的那一部分,其中’0,0,16,16’分别是矩形的左上右下四个点

    至此,列表控件就大功告成啦~

duilib是什么_double blind
<Default name="VScrollBar" value="button1normalimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,0,16,16&apos;&quot; button1hotimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,0,16,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button1pushedimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,16,16,32&apos; mask=&apos;#FFFF00FF&apos;&quot; button1disabledimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,0,16,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button2normalimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,32,16,48&apos; mask=&apos;#FFFF00FF&apos;&quot; button2hotimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,32,16,48&apos; mask=&apos;#FFFF00FF&apos;&quot; button2pushedimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,48,16,64&apos; mask=&apos;#FFFF00FF&apos;&quot; button2disabledimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,32,16,48&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbnormalimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,64,16,80&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbhotimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,64,16,80&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbpushedimage=&quot;ffile=&apos;ScrollBar/scroll.png&apos; source=&apos;0,64,16,80&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbdisabledimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,64,16,80&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; railnormalimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,80,16,96&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; railhotimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,80,16,96&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; railpushedimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,96,16,112&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; raildisabledimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,80,16,96&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bknormalimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,128,16,146&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bkhotimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,128,16,146&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bkpushedimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,128,16,146&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bkdisabledimage=&quot;file=&apos;ScrollBar/scroll.png&apos; source=&apos;0,128,16,146&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; " />
    <Default name="HScrollBar" value="button1normalimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;0,0,16,16&apos;&quot; button1hotimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;0,0,16,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button1pushedimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;16,0,32,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button1disabledimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;0,0,16,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button2normalimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;32,0,48,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button2hotimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;32,0,48,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button2pushedimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;48,0,64,16&apos; mask=&apos;#FFFF00FF&apos;&quot; button2disabledimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;32,0,48,16&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbnormalimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;64,0,80,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbhotimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;64,0,80,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbpushedimage=&quot;ffile=&apos;ScrollBar/scrollH.png&apos; source=&apos;64,0,80,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; thumbdisabledimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;64,0,80,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; railnormalimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;80,0,96,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; railhotimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;80,0,96,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; railpushedimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;96,0,112,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; raildisabledimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;80,0,96,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bknormalimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;128,0,146,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bkhotimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;128,0,146,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bkpushedimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;128,0,146,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; bkdisabledimage=&quot;file=&apos;ScrollBar/scrollH.png&apos; source=&apos;128,0,146,16&apos; corner=&apos;2,2,2,2&apos; mask=&apos;#FFFF00FF&apos;&quot; " />

六、Tab控件

    MFC的Tab控件在duilib被称为Option控件,我们先给Tab上个色,XML如下:    

<Option name="OptionDemo1" text="Option1" float="true" pos="207,28,0,0" width="60" height="30" bkcolor="#FFC5D4F2" selectedtextcolor="#FF0000FF" selectedbkcolor="#FFC5D4F2" group="tabDemo" selected="true" />
<Option name="OptionDemo2" text="Option2" float="true" pos="284,28,0,0" width="60" height="30" bkcolor="#FFFFDC78" group="tabDemo" />
<Option name="OptionDemo3" text="Option3" float="true" pos="361,28,0,0" width="60" height="30" bkcolor="#FFBECEA1" group="tabDemo" />
duilib是什么_double blind

    接下来给每个Tab的点击做出响应,这里介绍一个新的布局,名为TabLayout,专门用于给Tab布局。

    由于我们添加了3个Option,所以要给TabLayout也加上三个控件,分别对应3个Option,在Option 节点下面添加如下XML代码:

<TabLayout name="tabTest" bkcolor="#FF757676">
    <Label text="Option1" bkcolor="#FFC5D4F2" align="center" />
    <Text  text="Option2" bkcolor="#FFFFDC78" align="centerwrap" />
    <Text  text="Option3" bkcolor="#FFBECEA1" align="center" />
</TabLayout>
duilib是什么_double blind

    咦~ 怎么整个背景都变色了?其他控件呢?

    这是因为前面忘记指定TabLayout的位置和大小了,下面我们继续使用界面设计器来调整它的位置和大小吧,

    由于我们已经在XML里面添加了TabLayout节点,所以无需再从DuiDesigner里面添加此控件,直接调节大小和位置即可,记得将float设置为true哦~  

duilib是什么_double blind
duilib是什么_double blind

    XML如下:

<TabLayout name="tabTest" float="true" pos="202,75,0,0" width="568" height="169" bkcolor="#FF757676">
    <Label text="Option1" bkcolor="#FFC5D4F2" align="center" />
    <Text  text="Option2" bkcolor="#FFFFDC78" align="centerwrap" />
    <Text  text="Option3" bkcolor="#FFBECEA1" align="center" />
</TabLayout>
duilib是什么_double blind

    但是点击后还是没有反应,因为Tab控件还需要手动添加代码来切换,代码如下:

virtual void Notify( TNotifyUI& msg )
{
        if(msg.sType == _T("selectchanged"))
        {
            CDuiString    strName     = msg.pSender->GetName();
            CTabLayoutUI* pControl = static_cast<CTabLayoutUI*>(m_PaintManager.FindControl(_T("tabTest")));
 
            if(strName == _T("OptionDemo1"))
                pControl->SelectItem(0);
            else if(strName == _T("OptionDemo2"))
                pControl->SelectItem(1);
            else if(strName == _T("OptionDemo3"))
                pControl->SelectItem(2);
        }
 
        __super::Notify(msg);
}

    注释:Notify函数是消息通知函数,所有的控件消息(比如点击、切换)都会经过这里。

    而Tab控件的切换会触发selectchanged消息,所以我们可以在这里处理它,此处的处理是切换到相应的Tab页(不过我觉得duilib应该做成自动切换的,无需写代码,只需写前面的XML即可自动切换)

    此时tab控件可以切换了,不过可以看到Option1并没有占据全部的Tab界面,这是因为没有布局的情况下,Label 和Text只会自动调整宽度(TabLayout的父节点是HorizontalLayout)、或高度(TabLayout的父节点是VerticalLayout)之一,而Control则会同时调整宽度和高度来沾满屏幕。

所以此时我们可以给TabLayout的子节点添加布局,或者手动调整高度,这些已经在前面的教程里介绍过啦,下面就直接上代码了,

<TabLayout name="tabTest" float="true" pos="202,75,0,0" width="568" height="169" bkcolor="#FF757676">
                <HorizontalLayout>
                    <Label text="Option1" bkcolor="#FFC5D4F2" align="center" />
                </HorizontalLayout>
                <Text   text="Option2" bkcolor="#FFFFDC78" align="centerwrap" height="160"/>
                <Button text="Option3" bkcolor="#FFBECEA1" align="centerwrap" width="300"/>
            </TabLayout>

    到现在为止,DuiDesigner上面除了Container、TileLayout这两个控件,其他控件都介绍完毕啦,由于Alberl学习duilib的时间非常有限,还没看到这两个控件,并且现在已能实现绝大部分界面,所以这两个控件将排到Alberl的下一轮学习中,如果有大神愿意贡献一下教程就太感谢啦~O(∩_∩)O~

    全家福:

duilib是什么_double blind

部分BUG

上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃

duilib是什么_double blind

    如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口都用new生成,_tWinMain改为下面这样:

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    CPaintManagerUI::SetInstance(hInstance);
    HRESULT Hr = ::CoInitialize(NULL);
    if( FAILED(Hr) ) return 0;
 
    CDuiFrameWnd *pFrame = new CDuiFrameWnd;    // 这里必须用new,否则有ActiveX控件时,关闭窗口会产生崩溃
    pFrame->Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    pFrame->CenterWindow();
    pFrame->ShowModal();
 
    delete pFrame;
    ::CoUninitialize();
    return 0;
}

 

其根本原因是ActiveX控件使用了类似COM的方式,而却没有控制好作用域,所以导致析构时,CActiveXCtrl的成员变量m_pViewObject所指向的内存已经无效,因此产生了崩溃。之所以用new的方式不会崩溃,是因为new出来的内存,即使对象析构后,其内存还是有效的。

    由于其使用了类似COM的行为,有几处delete this,而Alberl并不了解微软自己的COM和ActiveX内部是怎么处理的,所以也就无法评价duilib的COM和ActiveX,当然啦,Alberl还是调试了一下,发现 ActiveXUI.cpp里面的那几个类都是模拟了COM的方式,采用了引用计数,但是那几个类的Release顺序貌似有点乱,而且那几个类互相包含,所以才造成析构时的那些问题,由于Alberl目前的重心是写入门教程,加之水平有限,所以不能短时间从根本上解决这个问题,就坐等大神啦~~~

    在【2013 duilib入门简明教程 — 结合win32和MFC (16)】里发现如果在MFC中这样使用,则不会有问题,请大神不吝赐教~\(^o^)/~

参考:2013 duilib入门简明教程 — 部分bug 2 (14) – Alberl – 博客园

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/234979.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 简单搭建一个直播服务器

    简单搭建一个直播服务器一、动手搭建流媒体服务器1、下载srsv2.0_r8,下载地址是:https://codeload.github.com/ossrs/srs/zip/v2.0-r8建议用迅雷下载,个人感觉比较快2、下载下来后解压该文件(我是在我window电脑解压的)并上传====>使用上传工具将该文件夹上传到我的linux虚拟机中,并改名为srs3、开始安装进入到tru…

  • chip seq实验原理及步骤_思科真机实验环境搭建

    chip seq实验原理及步骤_思科真机实验环境搭建实验内容通过实验环境学习了解SR-PCE。xrv_7作为PCE,计算PE1到PE2的路径。网络中IP设置,metric值与之前的实验一致。拓扑图配置流程:配置SRGB在IGP(is-is)中使能segmentrouting和NodeID修改IGP和TE的链路metric配置PCE我们这次主要关注配置PCE的过程。前面的配置可以参考:SR-TEPolicy(思科)—-explicitpath实验SR-TEPolicy(思科)—-dynamicpath实验P

  • 一个对话让你明白架构师是做什么的?[通俗易懂]

    一个对话让你明白架构师是做什么的?[通俗易懂]阅读本文大概需要6分钟。很多人都想知道架构师是做什么?我们看看下面的一段对话。菜鸟——刚入门的程序员老鸟——资深架构师老鸟:菜鸟,你的目标是什么?菜鸟:我要成为一个软件架构师。老鸟:对一个年轻的工程师来说,这是一个很好的目标。那你为什么要成为架构师呢?菜鸟:我要领导一个团队,还要做所有关于数据库、框架和Web服务器的重要决定。老鸟…

    2022年10月27日
  • Idea激活码永久有效Idea2019.3.1激活码教程-持续更新,一步到位[通俗易懂]

    Idea激活码永久有效Idea2019.3.1激活码教程-持续更新,一步到位[通俗易懂]Idea激活码永久有效2019.3.1激活码教程-Windows版永久激活-持续更新,Idea激活码2019.3.1成功激活

  • redisclient命令_redisconnection

    redisclient命令_redisconnectionRedisClientRedis服务器是典型的一对多服务器程序一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复。通过使用由I/O多路复用技术实现的文件事件处理器,Redis服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信。核心实现概述对于每个与服务器进行连接的客户端,服务器都为这些客户端建立了相应的redis.h/redisClient结构(客户端状态),这个结构保存了

    2022年10月12日
  • 项目的生命周期_项目生命周期的阶段

    项目的生命周期_项目生命周期的阶段项目管理的基本内容:计划、组织和监控。项目生命周期划分为3个基本的阶段:计划、实时监控和总结。根据PMBOK,项目生命周期分为5个阶段:(1)启动。>项目正式被立项,并成立项目组,宣

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号