duilib list控件扩展

对于简单的list控件已经有前辈分析了自带demo的ListRes全过程,duilib DirectUI库里面的一个简单的例子ListDemo

他分析了listdemo的来龙去脉,这里我只是将个人理解的list分析一下。

由于自带的listdemo不能满足要求,所以必须个人扩展list,通过尝试 发现

1. 列表头禁止拖动情况

这种情况很简单, 配置xml的时候将 表头宽度 和 元素宽度设置相同就行了,listheader布局如下:

		<List name="domainlist" bkcolor="#FFFFFFFF" inset="0,0,0,0" itemshowhtml="true" vscrollbar="true" hscrollbar="true" headerbkimage="file='list_header_bg.png'" itemalign="center" itembkcolor="#FFE2DDDF" itemaltbk="true" hscrollbar="false" menu="true">
			<ListHeader height="24" menu="true">
				<ListHeaderItem text="No" font="1" width="130" hotimage="file='list_header_hot.png'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sep.png'" sepwidth="1"/>
				<ListHeaderItem text="Domain" font="1" width="160" hotimage="file='list_header_hot.png'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sep.png'" sepwidth="1"/>
				<ListHeaderItem text="Description" font="1" width="140" hotimage="file='list_header_hot.png'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sep.png'" sepwidth="1"/>
			</ListHeader>
		</List>

上面是listdemo自带的xml,只是将listheaderitem宽度修改了

下面是listelement布局:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window>
    <HorizontalLayout width="266" height="60" bkcolor="#FFD2D2D2" >
        <HorizontalLayout width="130" height="60" bordersize="1" bordercolor="#FF00FF00">
			<HorizontalLayout />
			<VerticalLayout width="32">
				<HorizontalLayout />
				<Label name="listmem1" text="111" align="center" float="false" bkcolor="#FFFFFFFF" pos="22,0,0,0" width="32" height="18" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />
				<HorizontalLayout />
			</VerticalLayout>
			<HorizontalLayout />
        </HorizontalLayout>
        <VerticalLayout width="160" height="60" bordersize="1" bordercolor="#FF00FF00">
            <Label name="listmem2" text="222" align="center" float="true" bkcolor="#FFFFFFFF" pos="17,7,0,0" width="51" height="15" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />
        </VerticalLayout>
        <VerticalLayout width="140" height="60" bordersize="1" bordercolor="#FF00FF00">
            <Edit name="listmem3" text="333" float="true" pos="10,7,0,0" width="61" height="15" bkcolor="#FFFFFFFF" textpadding="4,3,4,3" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />
            <Button float="true" pos="18,29,0,0" width="72" height="24" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file='offline_down.png' source='0,0,72,24'" hotimage="file='offline_down.png' source='0,24,72,48'" pushedimage="file='offline_down.png' source='0,48,76,72'" />
        </VerticalLayout>
    </HorizontalLayout>
</Window>

使用的时候添加代码如下:

我是直接修改listdemo的,

屏蔽原有的OnSearch函数,添加下面代码即可:

		CDialogBuilder builder;
		CVerticalLayoutUI *plist_element = static_cast<CVerticalLayoutUI*>( builder.Create( _T("listmem1.xml") , 0 , NULL , &m_pm , NULL ) );
		CListUI *plist = static_cast< CListUI* >( m_pm.FindControl("domainlist") );
		if ( !plist )
		{
			return ;
		}
		plist->Add(plist_element);

最后启动程序,得到下面的界面

2.列表头可拖动情况

如果直接使用CListContainerElementUI就会出现下面排版了。

可以看到位置完全打乱了,通过源码可以查到位置布局使用的函数是

void SetPos(RECT rc);

CListContainerElementUI里面并没有这个函数,那就是调用了CContainerUI的SetPos函数

CContainerUI的SetPos函数

	void CContainerUI::SetPos(RECT rc)
	{
		CControlUI::SetPos(rc);
		if( m_items.IsEmpty() ) return;
		rc.left += m_rcInset.left;
		rc.top += m_rcInset.top;
		rc.right -= m_rcInset.right;
		rc.bottom -= m_rcInset.bottom;

		for( int it = 0; it < m_items.GetSize(); it++ ) {
			CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
			if( !pControl->IsVisible() ) continue;
			if( pControl->IsFloat() ) {
				SetFloatPos(it);
			}
			else {
				pControl->SetPos(rc); // 所有非float子控件放大到整个客户区
			}
		}
	}

直接将得到的rc设置给子控件了,也就是说,ListContainerElement每一列的宽度都是一样的,第二列 被 第三列 覆盖了 ,第一列一直居中。

这里说明一下,duilib 控件位置布局是由父控件设置的,父控件只管自己的子控件。如下图所示

Root只管理下一层的Root1和Root2,其余的和他不相干。

Root1管理Root3和Root4,Root2管理Root5和Root6.

这里的父节点都是IContainerUI控件或者继承于IContainerUI控件的类,叶子节点一般都是CControlUI类或者继承于CControlUI的类。

所以我们需要在ListContainerElement添加SetPos函数

void CListContainerElementUI::SetPos(RECT rc)
{
	CControlUI::SetPos(rc);
	rc = m_rcItem;

	// Adjust for inset
	rc.left += m_rcInset.left;
	rc.top += m_rcInset.top;
	rc.right -= m_rcInset.right;
	rc.bottom -= m_rcInset.bottom;

	TListInfoUI *plistinfo = GetOwner()->GetListInfo();

	// Determine the width of elements that are sizeable
	SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };

	for( int it2 = 0; it2 < m_items.GetSize(); it2++ )
	{
		CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);
		if( !pControl->IsVisible() )
			continue;
		if( pControl->IsFloat() )
		{
			SetFloatPos(it2);
			continue;
		}
		RECT rcPadding = pControl->GetPadding();
		SIZE sz = pControl->EstimateSize(szAvailable);
		if( sz.cx == 0 )
		{
			if( sz.cx < pControl->GetMinWidth() )
				sz.cx = pControl->GetMinWidth();
			if( sz.cx > pControl->GetMaxWidth() )
				sz.cx = pControl->GetMaxWidth();
		}
		else
		{
			if( sz.cx < pControl->GetMinWidth() )
				sz.cx = pControl->GetMinWidth();
			if( sz.cx > pControl->GetMaxWidth() )
				sz.cx = pControl->GetMaxWidth();
		}

		sz.cy = pControl->GetFixedHeight();
		if( sz.cy == 0 )
			sz.cy = rc.bottom - rc.top - rcPadding.top - rcPadding.bottom;
		if( sz.cy < 0 )
			sz.cy = 0;
		if( sz.cy < pControl->GetMinHeight() )
			sz.cy = pControl->GetMinHeight();
		if( sz.cy > pControl->GetMaxHeight() )
			sz.cy = pControl->GetMaxHeight();

		RECT rcCtrl = { plistinfo->rcColumn[it2].left + rcPadding.left,
			rc.top + rcPadding.top,
			plistinfo->rcColumn[it2].right + rcPadding.left,
			rc.top + sz.cy + rcPadding.top + rcPadding.bottom };
		pControl->SetPos(rcCtrl);
	}
}

这里面代码主要来自于CHorizontalLayoutUI,删除了个人认为不需要的代码,当然本人接触这东西才一个月,也有可能多删除了一些东西。

重新写OnSearch函数

		CDialogBuilder builder;
		CListContainerElementUI *plist_element = static_cast<CListContainerElementUI*>( builder.Create( _T("listmem.xml") , 0 , NULL , &m_pm , NULL ) );
		if ( !plist_element )
		{
			return ;
		}

		if ( !plist )
		{
			return ;
		}
		plist->Add(plist_element);

现在可以看到拖动效果了

直接上图吧,原始图

拖动图

时间: 2024-10-11 08:11:18

duilib list控件扩展的相关文章

Duilib初级控件扩展一例: 具有鼠标滚动消息的OptionUI

当初之所以有这个想法, 是因为我想在Option上滚动鼠标的时候自动切换到前一个(或后一个)Option上面去. 所有的OptionUI在水平布局HorizontalLayout上面. 例子虽然能达到我要的前后的效果, 但是后来证明我错了, 试想想看, 为什么是让OptionUI来处理鼠标滚动消息, 让一个OptionUI处理鼠标滚动消息有啥意义? 明明该交给Option所在的水平布局来处理, 不是最好的选择吗? 的确是这样, 我当时就应该多想法再写的, 也可能是熟能生巧的原因吧, 以后注意了.

给easyui datebox时间框控件扩展一个清空的实例

给easyui datebox扩展一个清空的实例 步骤一:拓展插件 /** * 给时间框控件扩展一个清除的按钮 */ $.fn.datebox.defaults.cleanText = '清空'; (function ($) { var buttons = $.extend([], $.fn.datebox.defaults.buttons); buttons.splice(1, 0, { text: function (target) { return $(target).datebox("o

Silverlight中DataPager控件扩展

大家一定遇到这样的情况,想改变一下SL的DataPager的显示信息,比如希望分页控件上显示数据的总数.那么就需要扩展一下DataPager控件即可. 其实扩展DataPager很简单,只要获取到DataPager控件上的元素,然后再改变元素上数据.比如DataPager控件上显示“总页数”的元素是一个TextBlock,那么可以通过方法GetTemplateChild获取到,参数是元素的名称.然后通过重写方法OnApplyTemplate即可,下面请看代码 代码 Code highlighti

ASP.NET MVC显示UserControl控件(扩展篇)

昨晚Insus.NET有怀旧一下<念念不忘,ASP.NET MVC显示WebForm网页或UserControl控件>http://www.cnblogs.com/insus/p/3641610.html 那仅是小小尝试,还有很多不明的地方. 那一篇其中有Render用户控件ascx的.如今Insus.NET想重构它一下,让步其能在Action或是Razor语法中使用. 创建一个AscxUtility.cs,这们我们可以在应用程序中多个地方使用. 这样我们就可以重构一下昨晚那个public A

WPF为控件扩展的附加属性不起作用需要注意的地方

我给WPF控件扩展了一个名为CornerRadius的附加属性,以便于所有控件在重写ControlTemplate的时候,在ControlTemplate中先加上一个Border,然后利用附加的CornerRadius,设置圆角属性,看起来是这样的: <ControlTemplate TargetType="{x:Type TextBox}"> <Border x:Name="TextBorder" CornerRadius="{Bind

修复duilib CEditUI控件和CWebBrowserUI控件中按Tab键无法切换焦点的bug

转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41556615 在duilib中,按tab键会让焦点在Button一类的控件中切换,但是切换焦点一直存在bug,具体的描述如下: 1.在主窗体里弹出新的窗体,当新窗体中存在CEditUI控件并且焦点在此CEditUI控件上,那么按tab键将无法切换焦点而一直处于CEditUI中.(只在新窗体中有此bug,主创体中没有,原因会在后面分析) 2.CWebBrowserUI控件

DevExpress控件扩展之表达式编辑器

业务需求: 业务工作中经常需要对表格中的数据进行处理,包括过滤.复合计算等.过滤需要有过滤条件,复合计算需要计算公式.这两种场景都需要一个表达式编辑器.GridControl自带过滤条件的表达式编辑器,我们要做的就是把这个编辑器拿出来,独立于GridControl,进而可以绑定到其它控件上. 实现原理: 找到表达式编辑器内部类UnboundColumnExpressionEditorForm,这是一个窗口类.我们将其边框设置为None,Dock属性设置为Fill,拖放到控件上,使其看上去像个控件

duilib 时间控件的认识

CDateTimeUI 1.该控件继承了CLabelUI控件,该空间并无重写SetAttribute的函数.全部属性跟CLabelUI控件一样. 2.该控件又有CDateTimeWnd类的一个指针用来显示具体让你选择的时间,该类就是创建的是SysDateTimePick32的控件. 也许会疑惑,为什么Init函数里面的Create没有关于DateTimePick32的相关说明,但是却能创建出这样一个控件.主要要看CWindowWnd::Create函数,该函数的第一个判断语句在GetSuperC

2、duilib 基本控件学习

1.关于创建问题: 在创建窗口的时候 CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()); MainWnd* main_wnd = new MainWnd(); main_wnd->Create(NULL, L"Demo2", UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE); main_wnd->CenterWindow(); main_wnd->ShowM