当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 无标题栏对话框的拖动

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 无标题栏对话框的拖动


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 123 ::
收藏到网摘: n/a

标题栏对话框的拖动


编译/NorthTibet

下载源代码


    很多基于对话框的应用程序都是不带框架的,也就是说对话框没有标题栏。众所周知,窗口的移动都是通过鼠标点住标题栏拖动窗口实现的,那么现在没有了标题栏,如何移动对话框呢?本文拟针对这个问题提出解决的办法。
    解决这个问题有两种方案。一种很业余,另外一种比较专业。前者使用一种常规思路处理鼠标拖拽事件。当窗口获得WM_LBUTTONDOWN(OnLButtonDown)时,通过设置标志并调用SetCapture控制鼠标使应用程序进入移动模式。进入移动模式之后,只要有WM_MOUSEMOVE消息过来,就可以据此移动框架窗口。最后,当用户释放鼠标按钮,则WM_LBUTTONUP消息处理例程清除标志并调用ReleaseCapture函数将鼠标控制返还给Windows。之所以说这种方法业余,主要是因为比较繁琐,首先要决定窗口移到哪?然后要想好如何重绘窗口等等,而且根据屏幕显示属性对话框“效果”页中“视觉效果”项的“拖动实显示窗口内容”复选框是不是选中,拖动效果是不同的。那么你怎么知道的设置呢?(方法是调用SystemParametersInfo(SPI_GETDRAGFULLWINDOWS)。Windows要程序员来事务巨细地处理这些繁琐的事情真是太遭了。由于Windows本身知道通过鼠标点住标题栏可以移动窗口,那么能不能将鼠标在窗口客户区任何地方的点击拖动行为都模仿成好像是在标题栏中一样呢?


图五 显示器的属性对话框-“效果”标签

    答案是肯定的。有心的读者可能已经猜测到下一步该怎么做了答。实际上,用鼠标点住对话框背景进行拖动操作并不难,但是你必须了解在标题栏里拖动窗口的原理。Windows首先确定鼠标点中了那个窗口,然后向那个窗口发送一个WM_NCHITTEST消息找出此窗口的哪个“非客户区”(如边界、最大化/最小化按钮、菜单、标题等等)拥有鼠标光标。接着默认的窗口过程响应消息并返回一个特定的代码。如果鼠标指针落在标题栏中,那么这个神奇的特定代码就是HTCAPTIONA。如果WM_NCHITTEST返回HTCAPTION,那么Windows便进入拖拽模式,以便对窗口进行移动操作。所以要想在客户区里用鼠标拖动对话框,那么只要在客户区里模仿标题栏里的鼠标拖动行为即可。这个我们下面要介绍的比较专业的方法,其主要思路是处理WM_NCHITTEST消息:

UINT CMyDialog::OnNcHitTest(CPoint pt){ CRect rc; GetClientRect(&rc); ClientToScreen(&rc); return rc.PtInRect(pt) ? HTCAPTION : CDialog::OnNcHitTest(pt);} 
    上面这个代码很容易理解,当鼠标落在客户区内,函数返回HTCAPTION。对于一个简单的对话框来说,仅仅用这个代码就完全可以实现在对话框背景内的拖动操作。因为Windows使用z-order坐标来确定鼠标下是哪个窗口,所以对话框中其它的所有对象照常工作。如果用户单击某个控制,只要这个控制不是静态位图图像或者文本,那么Windows都将鼠标事件发送到该控制上,而不是对话框。由于静态位图图像或者文本对于对话框是透明的,所以鼠标在上面的拖动同样实现移动,而对于对话框中的编辑框、按钮、组合框等其它非静态控制则按通常的行为方式运行。
如图二是本文例子程序运行画面:


如图二

    用鼠标在背景上可以拖动对话框。如果应用不是一个纯粹的对话框程序,而是CFormView或其它非对话框视图,处理方法几乎是一样的,只需在视图代码中做一点小小的改动即可,因为Windows在发送WM_NCHITTEST消息时,是将它发送到鼠标光标下的框架/视图最顶层非透明窗口,由于视图首先获得WM_NCHITTEST消息。所以只要在视图的WM_NCHITTEST消息处理例程中返回HTTRANSPARENT,让视图对鼠标点击透明即可。注意是在在视图中,而不是框架中加上下面代码:
UINT CMyView::OnNcHitTest(CPoint pt){ return HTTRANSPARENT;} 
    这样做以后,Windows将忽略视图并继续搜索能接收WM_NCHITTEST的窗口。如果顺利的话,将找到父窗口,这时用与对话框相同的WM_NCHITTEST处理代码即可,即在客户区中的点击返回HTCAPTION。你甚至可以通过鼠标坐标的象素计算,在规定的局部范围内实现视图透明。
UINT CMyView::OnNcHitTest(CPoint pt){ return PointLiesWithinDraggableRegion(pt) ? HTTRANSPARENT : CView::OnNcHitTest(pt);} 
&nbs