zoukankan      html  css  js  c++  java
  • 【积累】利用WM_NCHITTEST消息实现无标题窗口的拖动

      利用WM_NCHITTEST消息实现无标题窗口的拖动

    Windows首先确定鼠标点中了哪个窗口,然后向那个窗口发送一个WM_NCHITTEST消息找出此窗口的哪个"非客户区"(如边界、最大化/最小化按钮、菜单、标题等等)拥有鼠标光标。接着默认的窗口过程响应消息并返回一个特定的代码。如果鼠标指针落在标题栏中,那么这个特定代码就是HTCAPTION,此时Windows便进入拖拽模式,以便用户能够对窗口进行移动操作。所以要想在客户区里用鼠标拖动对话框,那么只要在客户区里模仿标题栏里的鼠标拖动行为即可。

        如果应用不是一个纯粹的对话框程序,而是是包含CFormView或其它非对话框视图,处理方法几乎是一样的,只需在视图代码中做一点小小的改动即可,因为Windows在发送WM_NCHITTEST消息时,是将它发送到鼠标光标下的框架/视图最顶层非透明窗口,由于视图首先获得WM_NCHITTEST消息。所以只要在视图的WM_NCHITTEST消息处理例程中返回HTTRANSPARENT,让视图对鼠标点击"透明"即可。这样做以后,Windows将忽略视图并继续搜索能接收WM_NCHITTEST的窗口。如果顺利的话,将找到父窗口,这时用与对话框相同的WM_NCHITTEST处理代码即可,即在客户区中的点击返回HTCAPTION。你甚至可以通过鼠标坐标的象素计算,在规定的局部范围内实现视图透明。
          下面以一个实例说明,窗口单文本的视图客户区,按上面所说在主框架Frame类和View类中都要添加WM_NCHITTEST消息响应函数,如果在classWizard中没找到此消息,则要在classWizard最右边的页选项Class info中的Message filter中选则Windows,就可以添加此消息了。此实例要实现鼠标移动客户区某一范围则显示图片,鼠标在这范围之外则在该区域显示另一图片并该区域外能实现窗口拖动。

    首先在View类的WM_NCHITTEST消息响应函数OnNcHitTest中添加如下代码:

                 

    UINT CUIdemoView::OnNcHitTest(CPoint point) 
    {      
    	CDC dcComp;
    	BITMAP bminfo;
    	CDC *pDC=GetDC();
    	if(dcComp.CreateCompatibleDC(pDC)==FALSE)
    		 AfxMessageBox("Can't create DC");
    	// TODO: Add your message handler code here and/or call default
    	    CPoint pt=point;
            ScreenToClient(&pt);//point是屏幕坐标点,在这转换成客户区坐标点,方便后面区域判定。
    		if (pt.x>70 && pt.x<213 && pt.y>178 && pt.y<318)
    		{
    			return CView::OnNcHitTest(point);//在范围里则不实现视图透明,由View类中的鼠标消息响应函数响应鼠标消息
    		}
    		else
    		{
    			dcComp.SelectObject(&bitmap_scan);
    		    bitmap_scan.GetObject(sizeof(bminfo),&bminfo);
    		    pDC->BitBlt(70,178,143,bminfo.bmHeight,&dcComp,0,0,SRCCOPY);
                
    		   return HTTRANSPARENT;// 在一个被其它窗口覆盖的窗口中,在实现视图透明区域按此返回则鼠标消息被送到父窗口,
    		   //View类中不能在响应此鼠标消息,所以在返回之前,要在这实现视图透明区域的鼠标消息响应。
    		}
    }
    

    再在Frame类的WM_NCHITTEST消息响应函数OnNcHitTest中添加如下代码:

       

    UINT CMainFrame::OnNcHitTest(CPoint point) 
    {
    	// TODO: Add your message handler code here and/or call default
    	
            CPoint pt=point;
            ScreenToClient(&pt);//point中存的是屏幕坐标,在这要转换成客户区坐标
    		if (pt.x>70 && pt.x<213 && pt.y>178 && pt.y<318)
    		{
    			return CMainFrame::OnNcHitTest(point);
    		}
    		else 
    	       return HTCAPTION;//在规定范围之外,返回HTCAPTION把客户区当做标题栏
    
     }
    
  • 相关阅读:
    Vue+element UI实现“回到顶部”按钮组件
    JS判断字符串长度的5个方法(区分中文和英文)
    从vue源码看Vue.set()和this.$set()
    mac下git安装与使用
    JS数组reduce()方法详解及高级技巧
    vue中router.go、router.push和router.replace的区别
    上传及更新代码到github(以及如何在vscode上提交自己的代码)
    VSCode打开多个项目文件夹的解决方法
    get请求和post请求的区别
    android 进程的优先级
  • 原文地址:https://www.cnblogs.com/ljhero/p/1964714.html
Copyright © 2011-2022 走看看