【积累】利用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把客户区当做标题栏

 }
posted @ 2010-07-28 13:33 ljhero 阅读(...) 评论(...) 编辑 收藏