转载:http://www.cnblogs.com/XiHua/articles/3490490.html

转载:http://blog.csdn.net/lostspeed/article/details/19275249

知识回顾:

  当鼠标在窗口内移动,点击或者释放时都会产生WM_NCHITTEST消息,响应函数OnNcHitTest会返回一个枚举值,系统会根据这个枚举值进行相应的处理。 当返回值为HTCAPTION时,系统会认为此时鼠标位于标题栏上,因而当鼠标按下并移动时就会执行拖动操作。我们需要做的就是响应这个消息,然后根据自己的需要,返回HTCAPTION参数即可!

所以Duilib在客户区设置标题栏能让用户拖动窗口,其实就是当鼠标按下时在OnNcHitTest消息响应里面返回HTCAPTION,让系统默认为此时鼠标位于标题栏,原理就这么简单。

这种方法不修改Duilib库的源码,需要的话直接在你自己的窗口类中添加两个方法实现,不需要的话,还使用原来的方法。

方法一:

MyWnd

.h文件

 virtual LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);  

 BOOL IsInStaticControl(CControlUI * pControl); 

.cpp文件

加入头文件

 #include <algorithm>
 LRESULT MyWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt;
RECT rcClient;
RECT rcCaption;
CControlUI * pControl = NULL; rcCaption = m_PaintManager.GetCaptionRect();
GetClientRect(m_PaintManager.GetPaintWindow(), &rcClient);
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
::ScreenToClient(m_PaintManager.GetPaintWindow(), &pt); if (- == rcCaption.bottom) ///< xml中描述bottom为-1时,整个窗口区域都可以拖动
{
rcCaption.bottom = rcClient.bottom;
} if ((pt.x >= rcClient.left)
&& (pt.x < rcClient.right)
&& (pt.y >= rcCaption.top)
&& (pt.y < rcCaption.bottom))
{
pControl = m_PaintManager.FindControl(pt);
if (IsInStaticControl(pControl))
{
return HTCAPTION;
}
} return __super::OnNcHitTest(uMsg, wParam, lParam, bHandled);
} BOOL MyWnd::IsInStaticControl(CControlUI * pControl)
{
CDuiString strClassName;
std::vector<CDuiString> vctStaticName;
std::vector<CDuiString>::iterator it; if (NULL == pControl)
return FALSE; strClassName = pControl->GetClassName();
strClassName.MakeLower();
vctStaticName.push_back(L"controlui");
vctStaticName.push_back(L"textui");
vctStaticName.push_back(L"labelui");
vctStaticName.push_back(L"containerui");
vctStaticName.push_back(L"horizontallayoutui");
vctStaticName.push_back(L"verticallayoutui");
vctStaticName.push_back(L"tablayoutui");
vctStaticName.push_back(L"childlayoutui");
vctStaticName.push_back(L"dialoglayoutui");

//可以指定那些控件在响应 WM_NCHITTEST 消息 不返回 HTCAPTION
 it = std::find(vctStaticName.begin(), vctStaticName.end(), strClassName);  return (it != vctStaticName.end());  }

最后在窗口xml中指定caption="0,0,0,-1",不管窗口大小如何变,都可以整个窗口拖动啦~

效果图:

方法二:

这种方法是纯Win32的函数调用,首先我们要理清楚拖动窗口任意位置移动的原理:

其实在移动过程中会产生WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP这三个消息,其过程就是鼠标左键按下---->拖动窗口移动--->鼠标左键弹起   窗口移动完成。因此我们可以在自己的窗口处理函数中对这三个消息进行处理。

首先在.h文件中定义三个窗口的成员变量以及三个消息函数响应的声明:

private:

Crect m_startRect;     //窗口的初始位置所在的矩形 

bool m_isMouseDown;    //鼠标是否按下   初始化为false 

CPoint m_startPoint;   //鼠标按下的位置  

................

public:

LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

..............

.cpp中进行响应的处理

LRESULT CxxxWnd::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
isMouseDown = true;//记录鼠标按下 //鼠标按下时的坐标
m_startPoint.x = GET_X_LPARAM(lParam);
m_startPoint.y = GET_Y_LPARAM(lParam); //鼠标按下时窗口的位置
GetWindowRect(this->GetHWND(),&startRect); return ;
}
LRESULT CLoginWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(isMouseDown == true)
{ POINT point; //获取当前鼠标的位置 //第一种获取位置方法
//point.x = GET_X_LPARAM(lParam);
//point.y = GET_Y_LPARAM(lParam); //第二种获取位置方法
::GetCursorPos(&point); ::ScreenToClient(m_PaintManager.GetPaintWindow(), &point); int Dx = point.x - startPoint.x;
int Dy = point.y - startPoint.y;
startRect.left += Dx;
startRect.right += Dx;
startRect.top +=Dy;
startRect.bottom +=Dy; //获取新的位置
SetWindowPos(this->GetHWND(),NULL,startRect.left,startRect.top,,,SWP_NOSIZE); //将窗口移到新的位置
} return ;
}
LRESULT CLoginWnd::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
//左键弹起,改变鼠标状态
isMouseDown = false;
return ;
}

运行效果:

参考:http://blog.csdn.net/luanwujian/article/details/9059861

可惜这样修改后有一个bug,当你拖动窗口一直到任务栏,然后松开鼠标左键,这时窗口自动跟着鼠标移动,暂时没找到这个bug,所以暂时采用响应WM_NCHITTEST消息方式,

在消息响应函数里面直接返回 HTCAPTION

 LRESULT CLoginWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return HTCAPTION;
}

Duilib改进窗口拖动,使整个窗口都能拖动两种方法(转载)的更多相关文章

  1. Response.Redirect 打开新窗口的两种方法

    一般情况下,Response.Redirect 方法是在服务器端进行转向,因此,除非使用 Response.Write("<script>window.location='htt ...

  2. C#代码像QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法

    你QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法: 要么重写需要弹出的窗体的事件: protected override CreateParams ...

  3. Qt 之 设置窗口边框的圆角(使用QSS和PaintEvent两种方法)

    Qt在设置窗口边框圆角时有两种方式,一种是设置样式,另一种是在paintEvent事件中绘制窗口.下面分别叙述用这两种方式来实现窗口边框圆角的效果. 一.使用setStyleSheet方法 this- ...

  4. 在Delphi中使用C++对象(两种方法,但都要改造C++提供的DLL)

    Delphi是市场上最好的RAD工具,但是现在C++占据着主导地位,有时针对一个问题很难找到Delphi或Pascal的解决方案.可是却可能找到了一个相关的C++类.本文描述几种在Delphi代码中使 ...

  5. 在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法。

    在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法.    方法一: 1.首先确认你在Windows   ...

  6. hive权威安装出现的不解错误!(完美解决)两种方法都可以

    以下两种方法都可以,推荐用方法一! 方法一: 步骤一: yum -y install mysql-server 步骤二:service mysqld start 步骤三:mysql -u root - ...

  7. 两种方法使vue实现jQuery调用

    引言 如果说vue是前端工程化使用较多的骨架,那么JavaScript就是我们的前端的细胞.MVVM模式让我们体验到前端开发的便携,无需再过多的考虑DOM的操作.而vue的渐进式开发(逐步引用组件,按 ...

  8. 两种方法操作其它mac应用的窗口

    (图文基本无关) 如果单纯说简单方便,其使用AppleScript更好,特别是现在有了JS的加入,比如: (* This Apple script will resize any program wi ...

  9. DUI-分层窗口两种模式(SetLayeredWindowAttributes和UpdateLayeredWindow两种方法各有利弊)

    LayeredWindow提供两种模式: 1.使用SetLayeredWindowAttributes去设置透明度, 完成窗口的统一透明,此时窗口仍然收到PAINT消息, 其他应用跟普通窗口一样. 2 ...

随机推荐

  1. idea使用心得(4)-踩过的坑

    1.非法的表达式开始 / 需要';' / 未结束的字符串文字  表现形式:    原因/解决:       这个一定是文件编码问题:依次检查setting中的file Encodings 中的IDE ...

  2. Sublime WiFi真机同步和WiFi真机预览使用说明

    概述WiFi真机同步: 通过在Sublime中建立调试服务,接收真机设备主动连接调试的方式,配合apploader及自定义loader,为开发者提供在局域网内通过WiFi实现应用快速真机同步和实时预览 ...

  3. MQTT——服务器搭建(一)

    MQTT介绍 MQTT,是IBM推出的一种针对移动终端设备的基于TCP/IP的发布/预订协议,可以连接大量的远程传感器和控制设备: 轻量级的消息订阅和发布(publish/subscribe)协议 建 ...

  4. MsChart在MVC下的问题

    项目为webform和mvc混用,新建了Areas,在Areas目录下的aspx页面的图表无法显示. 解决方案 第一种方法: 将控件的ImageStorageMode设置为UseImageLocati ...

  5. 跟着思维导图学习javascript

    1.javascript 变量 2.javascript 运算符 3.javascript 数组 4.javascript 流程语句 5.javascript字符串函数 6.javascript 函数 ...

  6. iOS APP开发的小知识(分享)

          亿合科技小编发现从2007年第一款智能手机横空出世,由此开启了人们的移动智能时代.我们从一开始对APP的陌生,到现在的爱不释手,可见APP开发的出现对我们的生活改变有多巨大.而iOS AP ...

  7. The connection to adb is down, and a severe error has occured.(转)

    启动android模拟器时.有时会报The connection to adb is down, and a severe error has occured.的错误.在网友说在任务管理器上把所有ad ...

  8. 百度地图坐标纠偏和转换工具和DLL

    百度一直以来都是个即想装出一副拥抱互联网开放的样子,又为了短期商业利益封闭自己的公司,模仿谷歌地图,开放了自己的百度地图 API,为了防止别人盗用其数据和用户自由迁移,地图相比于火星坐标,又更加封闭, ...

  9. ibatis输入多个参数

    ibatis输入多个参数     在ibatis中,会发现其输入参数只能有一个,于是当出现需要进行多个输入参数的时候,就要想点办法了,我看到的有以下两种比较好的方法能够解决这个问题1) 用String ...

  10. Infinite V1 Release Note

      游戏地址 PLAY 玩法说明 WASD 控制角色移动 更新内容 - 初步完成了角色移动(攻击状态) 开发心得 独立做游戏 其实最耽误时间的就是在自己的短板上, 对于我来说 就是3D建模和动作制作. ...