现在大家应该都知道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. Oracle SQL优化一(常见方法)

    1.表访问方式优化: a)普通表优先“Index Lookup 索引扫描”,避免全表扫描 大多数场景下,通过“Index Lookup 索引扫描”要比“Full Table Scan (FTS) 全表 ...

  2. SQL Server AlwaysOn架构及原理

    SQL Server AlwaysOn架构及原理 SQL Server2012所支持的AlwaysOn技术集中了故障转移群集.数据库镜像和日志传送三者的优点,但又不相同.故障转移群集的单位是SQL实例 ...

  3. ORACLE服务端详细安装步骤(配图解)

    ORACLE服务端的安装及配置 l 将下载的安装包解压缩,双击[setup.exe]文件,系统检查监听参数,耐心等待,完成后出现如下界面,电子邮件可不填,"我希望..."建议不勾选 ...

  4. Train Problem I hdu 1022(栈)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=1022 题意:给出火车的进站与出站顺序,判断是否可以按照给出的出站顺序出站. #include < ...

  5. LVS三种工作方式八种算法

    一.集群简介 什么是集群 计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一台计算机.集群系统中的单个计算 ...

  6. Android编译环境搭建(0818-0819)

    1 在虚拟机VMware上安装64位Ubuntu14.04LTS 首先需要安装虚拟机并激活.然后新建虚拟机,选择使用下载好的Ubuntu镜像.注意需要将光驱改为自己下载的,而不是autoinst.is ...

  7. 安装window服务

    1 使用管理员权限启动命令提示符 2 输入 cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 3 输入installUtil.exe  服务文件所在目录 ...

  8. XE3随笔9:使用不同的数据类型标记数组

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...

  9. 有些网站为什么要使用CDN,CDN又是什么呢

    如果你有一个小站,经过细心经营,流量慢慢变大,或者你想搞个活动,请求量会比平时多很多.你租的虚拟主机网络可能会被打爆,导致整个网站打开变慢.想扩大带宽却发现独享带宽很贵,这个时候你可以使用CDN. 如 ...

  10. C# HttpHelper 采集

    httphelper http://www.sufeinet.com/thread-6-1-1.html