现在大家应该都知道caption="0,0,0,32",是指示标题栏区了吧,如果想要整个窗口都能拖动呢? 那直接把高度改成和窗口一样不就得了~O(∩_∩)O~

  嗯,这样是可以,比如窗口高度是600,那么我们指定caption="0,0,0,600",这样整个窗口就可以拖动了,但是如果窗口大小改变了呢?假如调整窗口的大小到800,这个时候最下面的200个像素的高度就不能拖动啦,因此这里进行一个改进,也是举手之劳,在WindowImplBase::OnNcHitTest里的

  RECT rcCaption = m_PaintManager.GetCaptionRect(); 下面添加

    if (- == rcCaption.bottom)
{
rcCaption.bottom = rcClient.bottom;
}

  这样只需要指定caption="0,0,0,-1",不管窗口大小如何变,都可以整个窗口拖动啦~

  不过问题又来了,当鼠标移到Slider、TreeView等控件上面时,可以发现这些控件都没有响应啦。这是因为下面只判断了ButtonUI、OptionUI、TextUI,所以我们需要排除掉其他控件,Slider好办,加上SliderUI的判断就OK了,TreeView控件就不能这么加啦,因为TreeView是由很多子控件组成的,很显然,这里需要遍历获取到父窗口,判断父窗口的类型。然而还有一个问题就是,改了SliderUI之后,可以发现还有ActiveX、Edit、List等一大波控件需要处理,就这样直接加上十几个判断当然可以解决问题,但是如果后面又加了几个控件呢? 这里不就得跟着改? 因此这里采用排除法,不管之后加一个还是十个控件,都不需要再改动这里。而TreeView控件的遍历也是一样,采用排除法,因此Alberl提供了一个函数IsInStaticControl用来判断是否在静态控件中,这里的静态控件和MFC一样,指的是Static、Text、Picture等文本控件。

  这时,我们只需将这段代码

    RECT rcCaption = m_PaintManager.GetCaptionRect();
if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {
CControlUI* pControl = static_cast<CControlUI*>(m_PaintManager.FindControl(pt));
if( pControl && _tcsicmp(pControl->GetClass(), _T("ButtonUI")) != &&
_tcsicmp(pControl->GetClass(), _T("OptionUI")) != &&
_tcsicmp(pControl->GetClass(), _T("TextUI")) != )
return HTCAPTION;
} return HTCLIENT;

  换成这段代码即可:

    // bottom为-1时,则整个窗口的高度都可以拖动
RECT rcCaption = m_PaintManager.GetCaptionRect();
if (- == rcCaption.bottom)
{
rcCaption.bottom = rcClient.bottom;
} if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right
&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom )
{
CControlUI* pControl = m_PaintManager.FindControl(pt);
if (IsInStaticControl(pControl))
{
return HTCAPTION;
}
} return HTCLIENT;

  

  

  IsInStaticControl函数的代码如下:

// 包含头文件#include <algorithm>
BOOL WindowImplBase::IsInStaticControl(CControlUI *pControl)
{
BOOL bRet = FALSE;
if (! pControl)
{
return bRet;
} CDuiString strClassName;
std::vector<CDuiString> vctStaticName; strClassName = pControl->GetClass();
strClassName.MakeLower();
vctStaticName.push_back(_T("controlui"));
vctStaticName.push_back(_T("textui"));
vctStaticName.push_back(_T("labelui"));
vctStaticName.push_back(_T("containerui"));
vctStaticName.push_back(_T("horizontallayoutui"));
vctStaticName.push_back(_T("verticallayoutui"));
vctStaticName.push_back(_T("tablayoutui"));
vctStaticName.push_back(_T("childlayoutui"));
vctStaticName.push_back(_T("dialoglayoutui")); std::vector<CDuiString>::iterator it = std::find(vctStaticName.begin(), vctStaticName.end(), strClassName);
if (vctStaticName.end() != it)
{
CControlUI* pParent = pControl->GetParent();
while (pParent)
{
strClassName = pParent->GetClass();
strClassName.MakeLower();
it = std::find(vctStaticName.begin(), vctStaticName.end(), strClassName);
if (vctStaticName.end() == it)
{
return bRet;
} pParent = pParent->GetParent();
} bRet = TRUE;
} return bRet;
}

  

  这样不管大小怎么变,窗口都可以全屏拖动啦~O(∩_∩)O~

duilib进阶教程 -- 改进窗口拖动 (12)的更多相关文章

  1. duilib进阶教程 -- 改进List控件 (16)

    一.控件隐藏后,允许用代码操作所有行为. 在做播放器的时候,最常用的功能莫过于顺序播放.随机播放了,而当我们切换歌曲的时候,显然应该选中该歌曲,List的选中函数是SelectItem,但是调用此函数 ...

  2. duilib进阶教程 -- 总结 (17)

    整个教程的代码下载:http://download.csdn.net/detail/qq316293804/6502207 (由于duilib进阶教程主要介绍界面,所以这个教程只给出界面相关的代码,完 ...

  3. duilib进阶教程 -- Container控件的bug (14)

    在<duilib进阶教程 -- TreeView控件的bug (9)>里,Alberl发现了两个bug,并解决了其中一个,现在教程已经接近尾声啦,所以Alberl就解决了另外一个bug. ...

  4. Duilib改进窗口拖动,使整个窗口都能拖动两种方法(转载)

    转载:http://www.cnblogs.com/XiHua/articles/3490490.html 转载:http://blog.csdn.net/lostspeed/article/deta ...

  5. duilib进阶教程 -- 设置资源路径 (15)

    在前面的教程里,虽然图片都放到了skin文件夹里,但是XML却都在外面,当XML比较多时,就不太好看啦,如下图: 所以需要整理一下,将XML也放入skin文件夹,这样exe的目录就简洁多了: 将XML ...

  6. duilib进阶教程 -- 在MFC中使用duilib (1)

    由于入门教程的反响还不错,因此Alberl就以直播的形式来写<进阶教程>啦,本教程的前提: 1.请先阅读<仿迅雷播放器教程> 2.要有一定的duilib基础,如果还没,请先阅读 ...

  7. duilib进阶教程 -- TreeView控件(6)

    代码下载:http://download.csdn.net/detail/qq316293804/6483905 上一个教程中,界面已经和迅雷一模一样啦,大小和位置一个像素都不差哟,亏得Alberl调 ...

  8. duilib进阶教程 -- Container控件 (3)

    前面两个教程的目的是教大家与MFC结合,那么从这篇起,将不再使用MFC,而使用纯win32项目,本文的所有知识已经在<duilib入门教程>里面讲过了,因此基础知识不再赘述. 代码下载:h ...

  9. duilib进阶教程 -- 响应windows原生消息和自定义消息(13)

    一.windows原生消息 同样,入门教程只是给出了响应windows原生消息的方法,并没给出例子,这里以自适应屏幕分辨率为例.迅雷播放器虽然可以在启动的时候自动调整窗口大小,但是当屏幕分辨率实时改变 ...

随机推荐

  1. Blob(二进制)、byte[]、long、date之间的类型转换

    String转成byte[]类型存入数据库,数据库字段对应byte[]的类型为Blob类型 String value = this.getParamNotNnll("bgvalue" ...

  2. 使用Aspose插件将程序中的表格,导出生成excel表格

    http://www.cnblogs.com/lanyue52011/p/3372452.html这个是原文地址 /// <summary> /// 点击按钮,将内存表导出excel表格! ...

  3. echo 换行不换行

    echo换行输出需要转义符 -e 看以下例子: echo -e "It is the first line." >> a; echo -e "It is th ...

  4. Til the Cows Come Home

    Description Bessie is out in the field and wants to get back to the barn to get as much sleep as pos ...

  5. 奇葩问题之ToolBar返回键失效

    今天遇到一个奇葩问题,先说现象:接口调用成功,但是在后台业务上报错时(比如:手机号已经被注册过时,接口调用成功,但是后台返回了错误信息:手机号已被注册),toolBar的返回键失效了. 后来仔细看了一 ...

  6. HDU 1754 I Hate It (线段树)

    题意:略. 析:裸的线段树. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include < ...

  7. 编程之美2014挑战赛 复赛 Codehunt平台试题答案

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  8. (转) Active Record

    ActiveRecord是什么:1. 每一个数据库表对应创建一个类.类的每一个对象实例对应于数据库中表的一行记录; 通常表的每个字段在类中都有相应的Field;2. ActiveRecord同时负责把 ...

  9. Dynamic Time Warping 动态时间规整算法

    转自:http://www.cnblogs.com/luxiaoxun/archive/2013/05/09/3069036.html Dynamic Time Warping(DTW)是一种衡量两个 ...

  10. DateSort选择法、冒泡法排序

    public class DateSort {public static void main(String args[]) {Date d[] = new Date[11];d[0] = new Da ...