无标题栏对话框的拖动

2016-01-29 11:51 47 1 收藏

无标题栏对话框的拖动,无标题栏对话框的拖动

【 tulaoshi.com - C语言心得技巧 】

标题栏对话框的拖动


编译/NorthTibet

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

下载源代码


    很多基于对话框的应用程序都是不带框架的,也就是说对话框没有标题栏。众所周知,窗口的移动都是通过鼠标点住标题栏拖动窗口实现的,那么现在没有了标题栏,如何移动对话框呢?本文拟针对这个问题提出解决的办法。
    解决这个问题有两种方案。一种很业余,另外一种比较专业。前者使用一种常规思路处理鼠标拖拽事件。当窗口获得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

来源:https://www.tulaoshi.com/n/20160129/1483649.html

延伸阅读
在c++Builder控件板上的Dialogs页上的VCL控件包括了Windows常用的对话框。换句话说,VCL并没有提供对话框,那些对话框都是Windows的一部分。VCL只是使得使用这些对话框变得轻易些。在一些应用中,你可能想改变打开对话框中打开按钮的标题,例如,变成表示你的程序答应用户添加文件到文档中,这中情况下,你可能想打开按钮上的标题自己的标题而不...
在c++Builder控件板上的Dialogs页上的VCL控件包括了Windows常用的对话框。换句话说,VCL并没有提供对话框,那些对话框都是Windows的一部分。VCL只是使得使用这些对话框变得容易些。在一些应用中,你可能想改变打开对话框中打开按钮的标题,例如,变成表示你的程序允许用户添加文件到文档中,这中情况下,你可能想打开按钮上的标题自己的标...
标签: 办公软件
    Excel 2000 新增的在对话框中输入区域引用可以折叠的按钮,这样用户在工作表上选定所需的区域时,对话框就不会阻挡视线。对这类对话框的操作是,在折叠按钮上单击可以将其折叠,再次单击则返回到对话框,图2-9和图2-10分别显示了折叠前后的效果。
问:程序是基于对话框的,我显示两个对话框,一个在另一个后面,下面是我的做法: CMyApp::InitInstance () { ... CMyDialog1 dlg1; m_hMainWnd = &dlg1; int result = dlg1.DoModal (); CMyDialog2 dlg2; result = dlg2.DoModal (); ... } 在上面的代码中,首先一个对话框得到了适当地调用...
获取静态控件文本的方法:GetDlgItem函数获得对话框中控件的指针,然后调用GetWindowText获得文本。注意:静态控件的属性必须将Notify选为可能。同理:SetWindowText可以指定文本。 获取编辑框内容:GetDlgItem(ID)-GetWindowText(); 字符内容转换为数值:atoi()把字符串转换为数值;同理:数字到字符串itoa(); GetDlgItemText(ID)可以完成...

经验教程

277

收藏

57
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部