转载请注明原始出处。谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207

假设要使用透明异形窗口功能,首先要改进duilib库让他本身支持(能够下载duilib扩展群群主改进的库。或者下载我的库),然后要开启窗口的bktrans属性。

这时仅仅要使用透明的背景素材就能做出透明异形窗口。可是透明窗口并不好驾驭,会带来非常多麻烦。当中之中的一个就是原Edit控件无法使用。这时改用Richedit控件是不错的选择。

RichEdit有非常多优势,一是支持透明窗口、二十属性更丰富功能很多其它,他本身就能够是透明背景,同一时候还是容器,能够容纳其它控件。

只是我在使用他的过程中发现几点不足,所以做了简单的改进,记录到博客里。

改进例如以下:

1.richedit 控件的容器布局基类从Container改为HorizontalLayout。能够支持相对布局。让richedit能够内嵌更复杂灵活的布局

2.richedit 添加textpadding属性。方便控制布局。控制文字和光标的输出范围,而不须要用原来的inset属性来控制光标的位置

3.richedit添加四种状态的图片。normal、hot、focus、disable。来完毕一些细节效果的显示

改进1:

richedit本身是个容器。这点非常不错,可是他继承自CContainer容器,本身没有布局功能,这点非常不好。我这里做改进时没有让他继承CHorizontalLayout类,由于richedit已经重写了SetPos函数,直接用CHorizontalLayout的SetPos函数的逻辑代码替换掉richedit的SetPos函数的部分代码即可了。记住不要所有替换,由于richedit的SetPos函数的前段的代码是处理richedit光标的代码。改动后的完整代码例如以下:

void CRichEditUI::SetPos(RECT rc)
{
CControlUI::SetPos(rc);
rc = m_rcItem; rc.left += m_rcInset.left;
rc.top += m_rcInset.top;
rc.right -= m_rcInset.right;
rc.bottom -= m_rcInset.bottom;
bool bVScrollBarVisiable = false;
if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {
bVScrollBarVisiable = true;
rc.right -= m_pVerticalScrollBar->GetFixedWidth();
}
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {
rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
} if( m_pTwh ) {
RECT rcRich = rc;
rcRich.left += m_rcTextPadding.left;
rcRich.right -= m_rcTextPadding.right;
rcRich.top += m_rcTextPadding.top;
rcRich.bottom -= m_rcTextPadding.bottom;
m_pTwh->SetClientRect(&rcRich);
if( bVScrollBarVisiable && (!m_pVerticalScrollBar->IsVisible() || m_bVScrollBarFixing) ) {
LONG lWidth = rcRich.right - rcRich.left + m_pVerticalScrollBar->GetFixedWidth();
LONG lHeight = 0;
SIZEL szExtent = { -1, -1 };
m_pTwh->GetTextServices()->TxGetNaturalSize(
DVASPECT_CONTENT,
GetManager()->GetPaintDC(),
NULL,
NULL,
TXTNS_FITTOCONTENT,
&szExtent,
&lWidth,
&lHeight);
if( lHeight > rcRich.bottom - rcRich.top ) {
m_pVerticalScrollBar->SetVisible(true);
m_pVerticalScrollBar->SetScrollPos(0);
m_bVScrollBarFixing = true;
}
else {
if( m_bVScrollBarFixing ) {
m_pVerticalScrollBar->SetVisible(false);
m_bVScrollBarFixing = false;
}
}
}
} if( m_pVerticalScrollBar != NULL && m_pVerticalScrollBar->IsVisible() ) {
RECT rcScrollBarPos = { rc.right, rc.top, rc.right + m_pVerticalScrollBar->GetFixedWidth(), rc.bottom};
m_pVerticalScrollBar->SetPos(rcScrollBarPos);
}
if( m_pHorizontalScrollBar != NULL && m_pHorizontalScrollBar->IsVisible() ) {
RECT rcScrollBarPos = { rc.left, rc.bottom, rc.right, rc.bottom + m_pHorizontalScrollBar->GetFixedHeight()};
m_pHorizontalScrollBar->SetPos(rcScrollBarPos);
} SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() )
szAvailable.cx += m_pHorizontalScrollBar->GetScrollRange(); int nAdjustables = 0;
int cxFixed = 0;
int nEstimateNum = 0;
for( int it1 = 0; it1 < m_items.GetSize(); it1++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) continue;
SIZE sz = pControl->EstimateSize(szAvailable);
if( sz.cx == 0 ) {
nAdjustables++;
}
else {
if( sz.cx < pControl->GetMinWidth() ) sz.cx = pControl->GetMinWidth();
if( sz.cx > pControl->GetMaxWidth() ) sz.cx = pControl->GetMaxWidth();
}
cxFixed += sz.cx + pControl->GetPadding().left + pControl->GetPadding().right;
nEstimateNum++;
}
cxFixed += (nEstimateNum - 1) * m_iChildPadding; int cxExpand = 0;
int cxNeeded = 0;
if( nAdjustables > 0 ) cxExpand = MAX(0, (szAvailable.cx - cxFixed) / nAdjustables);
// Position the elements
SIZE szRemaining = szAvailable;
int iPosX = rc.left;
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {
iPosX -= m_pHorizontalScrollBar->GetScrollPos();
}
int iAdjustable = 0;
int cxFixedRemaining = cxFixed;
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();
szRemaining.cx -= rcPadding.left;
SIZE sz = pControl->EstimateSize(szRemaining);
if( sz.cx == 0 ) {
iAdjustable++;
sz.cx = cxExpand; 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 = { iPosX + rcPadding.left, rc.top + rcPadding.top, iPosX + sz.cx + rcPadding.left , rc.top + rcPadding.top + sz.cy};
pControl->SetPos(rcCtrl);
iPosX += sz.cx + m_iChildPadding + rcPadding.left + rcPadding.right;
cxNeeded += sz.cx + rcPadding.left + rcPadding.right;
szRemaining.cx -= sz.cx + m_iChildPadding + rcPadding.right;
}
cxNeeded += (nEstimateNum - 1) * m_iChildPadding;
//reddrain
if( m_pHorizontalScrollBar != NULL ) {
if( cxNeeded > rc.right - rc.left ) {
if( m_pHorizontalScrollBar->IsVisible() ) {
m_pHorizontalScrollBar->SetScrollRange(cxNeeded - (rc.right - rc.left));
}
else {
m_pHorizontalScrollBar->SetVisible(true);
m_pHorizontalScrollBar->SetScrollRange(cxNeeded - (rc.right - rc.left));
m_pHorizontalScrollBar->SetScrollPos(0);
rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
}
}
else {
if( m_pHorizontalScrollBar->IsVisible() ) {
m_pHorizontalScrollBar->SetVisible(false);
m_pHorizontalScrollBar->SetScrollRange(0);
m_pHorizontalScrollBar->SetScrollPos(0);
rc.bottom += m_pHorizontalScrollBar->GetFixedHeight();
}
}
}
//redrain }

这样子改进后,就能够非常easy的做出仿酷狗的搜索栏的效果,也就是richedit内嵌一个button。而不须要用到绝对布局来控制button,也不须要为button的位置自适应文字操心。

相应的布局代码例如以下:

<RichEdit name="Edt_Title_Search" rich="false" multiline="false" font="0" text="张学友 童真年代" height="27" textpadding="9,3,35,5" textcolor="#646464" bkcolor="#00FFFFFF" bkimage="UI\title\edit.png" >
<Control height="1"/>
<Button name="Btn_Title_Search" width="33" height="27" normalimage="UI\title\search_normal.png" hotimage="UI\title\search_hover.png" pushedimage="UI\title\search_down.png" />
</RichEdit>

这个改进我已经用到仿酷狗里面了,大家能够下载我的源代码去看。布局中设置了一个高度为1的Control,起到了占位作用。让button能够自适应位置。

改进2:



在duilib的CRichEditUI控件中,richedit的功能,实际上是调用了系统的richedit的接口来完毕的。在CRichEditUI中把这个richedit当作了容器中的一个控件,所以这个richedit的位置,是在SetPos函数中去指定的。在原本CRichEditUI中。要想控制文本的输入区域和光标的位置,须要用到inset属性来控制,这显然和Label以及Edit控件的用法不一样。Label和Edit都是用textpadding属性来控制的,所以改动了CRichEdit的代码。让他改用textpadding属性来控制。

首先要在UIRichEdit.h文件里添加两个成员函数和一个成员变量。而且在构造函数里初始化,具体的相信也不须要多说:

	RECT GetTextPadding() const;
void SetTextPadding(RECT rc);
	RECT m_rcTextPadding;

然后改动SetAttribute函数,添加例如以下代码:

	else if( _tcscmp(pstrName, _T("textpadding")) == 0 ) {
RECT rcTextPadding = { 0 };
LPTSTR pstr = NULL;
rcTextPadding.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
SetTextPadding(rcTextPadding);
}

最后改动SetPos函数。在函数里依据m_rcTextPadding的值去布局richedit组件的位置就能够了。SetPos函数已经在前面给出了。

改进3:



在Edit控件中,支持四种状态的图片:normal、hot、focus、disable。这样能够做到一些细微的效果,比方鼠标移动到edit上面后让控件边框变亮,这点能够看QQ登录器的帐号和password输入框。可是richedit控件却没有,所以我给他添加了这几个状态图。

1、 首先还是成员函数和成员变量:

	LPCTSTR GetNormalImage();
void SetNormalImage(LPCTSTR pStrImage);
LPCTSTR GetHotImage();
void SetHotImage(LPCTSTR pStrImage);
LPCTSTR GetFocusedImage();
void SetFocusedImage(LPCTSTR pStrImage);
LPCTSTR GetDisabledImage();
void SetDisabledImage(LPCTSTR pStrImage);
void PaintStatusImage(HDC hDC);
	CDuiString m_sNormalImage;
CDuiString m_sHotImage;
CDuiString m_sFocusedImage;
CDuiString m_sDisabledImage;

然后相应的函数定义为:

LPCTSTR CRichEditUI::GetNormalImage()
{
return m_sNormalImage;
} void CRichEditUI::SetNormalImage(LPCTSTR pStrImage)
{
m_sNormalImage = pStrImage;
Invalidate();
} LPCTSTR CRichEditUI::GetHotImage()
{
return m_sHotImage;
} void CRichEditUI::SetHotImage(LPCTSTR pStrImage)
{
m_sHotImage = pStrImage;
Invalidate();
} LPCTSTR CRichEditUI::GetFocusedImage()
{
return m_sFocusedImage;
} void CRichEditUI::SetFocusedImage(LPCTSTR pStrImage)
{
m_sFocusedImage = pStrImage;
Invalidate();
} LPCTSTR CRichEditUI::GetDisabledImage()
{
return m_sDisabledImage;
} void CRichEditUI::SetDisabledImage(LPCTSTR pStrImage)
{
m_sDisabledImage = pStrImage;
Invalidate();
} RECT CRichEditUI::GetTextPadding() const
{
return m_rcTextPadding;
} void CRichEditUI::SetTextPadding(RECT rc)
{
m_rcTextPadding = rc;
Invalidate();
} void CRichEditUI::PaintStatusImage(HDC hDC)
{
if( IsFocused() ) m_uButtonState |= UISTATE_FOCUSED;
else m_uButtonState &= ~ UISTATE_FOCUSED;
if( !IsEnabled() ) m_uButtonState |= UISTATE_DISABLED;
else m_uButtonState &= ~ UISTATE_DISABLED; if( (m_uButtonState & UISTATE_DISABLED) != 0 ) {
if( !m_sDisabledImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sDisabledImage) ) m_sDisabledImage.Empty();
else return;
}
}
else if( (m_uButtonState & UISTATE_FOCUSED) != 0 ) {
if( !m_sFocusedImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sFocusedImage) ) m_sFocusedImage.Empty();
else return;
}
}
else if( (m_uButtonState & UISTATE_HOT ) != 0 ) {
if( !m_sHotImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sHotImage) ) m_sHotImage.Empty();
else return;
}
} if( !m_sNormalImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sNormalImage) ) m_sNormalImage.Empty();
else return;
}
}

2、相同也须要在SetAttribute中添加例如以下代码:

	else if( _tcscmp(pstrName, _T("normalimage")) == 0 ) SetNormalImage(pstrValue);
else if( _tcscmp(pstrName, _T("hotimage")) == 0 ) SetHotImage(pstrValue);
else if( _tcscmp(pstrName, _T("focusedimage")) == 0 ) SetFocusedImage(pstrValue);
else if( _tcscmp(pstrName, _T("disabledimage")) == 0 ) SetDisabledImage(pstrValue);

3、另外还须要添加一个成员变量来记录控件是否处在hot状态下

        UINT m_uButtonState;

然后在DoEvent函数中增加例如以下代码来改变成员变量

	else if( event.Type == UIEVENT_MOUSEMOVE ) 
    <span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if( IsEnabled() ) {
<span style="white-space:pre"> </span>m_uButtonState |= UISTATE_HOT;
<span style="white-space:pre"> </span>Invalidate();
<span style="white-space:pre"> </span>}
    <span style="white-space:pre"> </span>return;
    <span style="white-space:pre"> </span>}
    <span style="white-space:pre"> </span>else if( event.Type == UIEVENT_BUTTONUP ) 
    <span style="white-space:pre"> </span>{       <span style="white-space:pre"> </span>return;
    }
<span style="white-space:pre"> </span>else if( event.Type == UIEVENT_MOUSEENTER )
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if( IsEnabled() ) {
<span style="white-space:pre"> </span>m_uButtonState |= UISTATE_HOT;
<span style="white-space:pre"> </span>Invalidate();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>else if( event.Type == UIEVENT_MOUSELEAVE )
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if( IsEnabled() ) {
<span style="white-space:pre"> </span>m_uButtonState &= ~UISTATE_HOT;
<span style="white-space:pre"> </span>Invalidate();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>}

总结:

上面的全部代码的改进。我都已经在我自己的库里面改好了,我自己的库下载地址为:点击打开链接

假设有错误或者不妥,请联系我。

Redrain 2014.11.17



QQ:491646717

版权声明:本文博客原创文章,博客,未经同意,不得转载。

提高duilib的richedit控制的一些特征的更多相关文章

  1. 改进duilib的richedit控件的部分功能

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207 如果要使用透明异形窗体功能,首先要改进duilib库让他本 ...

  2. 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

    P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...

  3. 【noip 2012】提高组Day2T3.疫情控制

    Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 ...

  4. 【NOIP】提高组2012 疫情控制

    [题意]n个点的树,1为根,要求删除一些点使得截断根节点和所有叶子结点的路径(不能删根,可以删叶子).有m支军队在m个点上,每时刻所有军队可以走一步,最终走到的地方就是删除的点,求最短时间. [算法] ...

  5. 机器学习中的特征缩放(feature scaling)

    参考:https://blog.csdn.net/iterate7/article/details/78881562 在运用一些机器学习算法的时候不可避免地要对数据进行特征缩放(feature sca ...

  6. Java利用Mybatis进行数据权限控制

    权限控制主要分为两块,认证(Authentication)与授权(Authorization).认证之后确认了身份正确,业务系统就会进行授权,现在业界比较流行的模型就是RBAC(Role-Based ...

  7. 特征价格(Hedonic price)

    特征价格法,又称 Hedonic 模型法和效用估价法,认为房地产由众多不同的特征组成,而房地产价格是由所有特征带给人们的效用决定的.由于各特征的数量及组合方式不同,使得房地产的价格产生差异.因此,如能 ...

  8. IT兄弟连 Java语法教程 流程控制语句 控制循环结构1

    Java语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性.为了弥补这种不足,Java提供了continue和break来控制循环结构.除此之外 ...

  9. matlab学习笔记9 高级绘图命令_1 图形对象_根对象,轴对象,用户控制对象,用户菜单对象

    一起来学matlab-matlab学习笔记9 高级绘图命令_1 图形对象_根对象,轴对象,用户控制对象,用户菜单对象 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matl ...

随机推荐

  1. 主席树(可持久化线段树) 静态第k大

    可持久化数据结构介绍 可持久化数据结构是保存数据结构修改的每一个历史版本,新版本与旧版本相比,修改了某个区域,但是大多数的区域是没有改变的, 所以可以将新版本相对于旧版本未修改的区域指向旧版本的该区域 ...

  2. Vb.net/VB 声明API功能父窗口功能

    回想第一次敲房费,他说自己是api函数实现父窗口及其子窗口最小化的功能.现在再次遇到,自己就在思考,能不能继续使用API函数呢?答案当然是Of Course! 事实上细致看两者并没有多大的差别,先看看 ...

  3. 给节点设置tag【从零開始cocos3.0final 】

    在cocos中通过tag来管理节点是非经常常使用的:以下介绍一个关于在cocos中使用tag的实例: typedef enum{ tag1 }Tag; 这里能够使用枚举类型,来为多个节点设置tag: ...

  4. (七)unity4.6Ugui中国教程文档-------摘要-UGUI Auto Layout

    大家好,我是太阳广东. 转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:http://www.unityman ...

  5. iOS设备定位

    一.iOS谈到定位 1.SignInSignOutViewController.h @interface SignInSignOutViewController : UIViewController& ...

  6. 基于lua的网页脚本开发语言cgilua(转)

    这里为大家介绍基于lua脚本实现的网页开发语言,cgilua 介绍 cgilua使用Lua是一个用于创建动态网页的服务器端脚本语言.纯LUA脚本和LUA页(LP)的支持,cgilua.Lua脚本是一个 ...

  7. 每天努力一点之SQL

    今天工作当中遇到一个问题:统计信息并导出EXcel 报表. 刚开始只做了统计信息: 如下图 请看最后一列的数据. 我当时想都从数据库里取出来,但是由于我能力有限没有做出来.先贴下后来写的SQL 语句. ...

  8. leetcode第一刷_Merge Sorted Array

    水题,只是思想还是实用的. 当然能够新建出一个数组.比較着拷贝过去.可是没有必要啊亲.想想为什么用源数组会麻烦,由于确定了前面的数.为了后面的数字不被覆盖,要依次往后移,转念一想,先确定后面的数字.就 ...

  9. ZOJ 3826 Hierarchical Notation 模拟

    模拟: 语法的分析 hash一切Key建设规划,对于记录在几个地点的每个节点原始的字符串开始输出. . .. 对每一个询问沿图走就能够了. .. . Hierarchical Notation Tim ...

  10. MonkenRunner通过HierarchyViewer定位控制的方法和建议(Appium/UIAutomator/Robotium侣)

    1. 背景 正在使用MonkeyRunner当我们经常使用Chimchat下面HierarchyViewer模块获得目标控制的一些信息,以协助我们测试.但在MonkeyRunner官方的说法是没有看到 ...