【转】MFC 无边框窗口的拖动
void CXXXXDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
}
UINT CEllipseWndDlg::OnNcHitTest(CPoint point)
{
// 取得鼠标所在的窗口区域
UINT nHitTest = CDialog::OnNcHitTest(point);
// 如果鼠标在窗口客户区,则返回标题条代号给Windows
// 使Windows按鼠标在标题条上类进行处理,即可单击移动窗口
return (nHitTest==HTCLIENT) ? HTCAPTION : nHitTest;
}
方法二:
当用户在窗口客户区按下鼠标左键时,使Windows认为鼠标是在标题条上,即在处理WM_LBUTTONDOWN消息的处理函数OnLButtonDown中发送一个wParam参数为HTCAPTION,lParam为当前坐标的WM_NCLBUTTONDOWN消息。
void CEllipseWndDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// 调用父类处理函数完成基本操作
CDialog::OnLButtonDown(nFlags, point);
// 发送WM_NCLBUTTONDOWN消息
// 使Windows认为鼠标在标题条上
PostMessage(WM_NCLBUTTONDOWN,HTCAPTION, MAKELPARAM(point.x, point.y));
//或SendMessage(WM_SYSCOMMAND,0xF012,0); //0xF012 = SC_MOVE | HTCAPTION
}
首先,看看在正常情况下系统是怎样来移动程序窗口的。当使用者在程序窗口标题栏区域(非工作区)内,按下鼠标左键时将会发生下列事情:
caseWM_NCLBUTTONDOWN return ;
然后,同样是在窗口标题栏内按住鼠标左键并移动鼠标,但此时窗口却并不随同鼠标一起移动了,这是怎么回事?这是因为上述语句中设有“return 0”语句的缘故。该语句使得WM_NCLBUTTONDOWN消息未能传递到DefWindowProc()函数,就在窗口过程函数中提前返回了,当然移动窗口的操作就无从进行了。这也从反面印证了一个事实,那就是,最后完成移动窗口的操作将是由DefWindowProc()函数来完成的。
case WM_LBUTTONDOWN:
SendMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,);
break;
消息发送时,通过HTCAPTION参数给DefWindowProc()函数带去一个信息,告诉它鼠标左键是在窗口非工作区内的标题栏处按下的。当然这是一个假情报,但DefWindowProc()函数会信以为真并根据这个信息来执行相应的操作。
case WM_LBUTTONDOWN:
SendMessage(hWnd,WM_SYSCOMMAND,SC_DRAGMOVE,);
break;
能使用WM_SYSCOMMAND消息来移动窗口,得益于一个新近扩展的SC_DRAGMOVE风格标志,该标志从字面上就能看出是"拖曳移动"的意思。该标志在低版本的编译器(VC 6.0中就没有)中是找不到的,所以在引用该标志时应预先声明:
#define SC_DRAGMOVE 0xF012
也可以直接使用其常量值:
SendMessage(hWnd,WM_SYSCOMMAND,0xF012,);
上述无标题栏窗口移动窗体的机理与窗口有标题栏时是相似的,相同处最后都是由DefWindowProc()函数来完成实际的操作;不同处是发送消息的方式不同,一个是由系统隐含发送;另一个则是由程序公开发送。
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,true,NULL,);
即:
case WM_LBUTTONDOWN:
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,true,NULL,);
SendMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,);
break;
这样在移动窗口时,虚线指示框将不会出现。注意,上述语句的位置顺序不能错,否则,在移动时虚线框还会出现。
case WM_MOUSEMOVE:
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,false ,NULL,);
break;
3、自编代码
static POINT pt, pe; static RECT rt, re; case WM_RBUTTONDOWN: SetCapture(hWnd); // 设置鼠标捕获(防止光标跑出窗口失去鼠标热点) GetCursorPos(&pt); // 获取鼠标光标指针当前位置 GetWindowRect(hWnd,&rt); // 获取窗口位置与大小 re.right=rt.right-rt.left; // 保存窗口宽度 re.bottom=rt.bottom-rt.top; // 保存窗口高度 break; case WM_RBUTTONUP: ReleaseCapture(); // 释放鼠标捕获,恢复正常状态 break; case WM_MOUSEMOVE: GetCursorPos(&pe); // 获取光标指针的新位置 if(wParam==MK_RBUTTON) // 当鼠标右键按下
{ re.left=rt.left+(pe.x - pt.x); // 窗口新的水平位置 re.top =rt.top+(pe.y - pt.y); // 窗口新的垂直位置 MoveWindow(hWnd,re.left,re.top,re.right,re.bottom,true);// 移动窗口 } break; 或: OnLButtonDown() 中: SetCapture(); CRect rW; GetWindowRect(rW); CPoint ptW = point; ClientToScreen(&ptW); m_ptCursorOffset.x = ptW.x - rW.left; OnMouseMove()中: if ((nFlags & MK_LBUTTON) && this == GetCapture()) { CPoint ptW = point; ClientToScreen(&ptW); ptW.x -= m_ptCursorOffset.x; ptW.y -= m_ptCursorOffset.y; ::SetWindowPos(m_hWnd, ,ptW.x,ptW.y,,,SWP_NOSIZE); } m_ptCursorOffset.y = ptW.y - rW.top; OnLButtonUp()中: ReleaseCapture();
BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int x, int y,int cx, int cy, UINT nFlags); //MoveWindow也可以实现窗体移动
函数功能
参数
最新文章
- ubuntu下Eclipse安装
- Hibernate单向多对一对象关系模型映射
- Oracle 索引<;七>;
- hdu 1059 多重背包
- python 核心编程第二版 课后习题 第11章
- solr 相似查询-MoreLikeThis
- Arrays.sort(new String[]{";aaa";}); 排序方法
- iOS8 Core Image In Swift:自动改善图像以及内置滤镜的使用
- c++学籍管理系统v1.10
- code forces 148D Bag of mice (概率DP)
- Linux Set Command
- work 2013-07-19
- nifi1.6.0汉化
- npm方法
- 我的Java自学之路
- C、C++打包成.dll .so .a 给Unity使用
- Java Web之路(二)Servlet之HttpServletResponse和HttpServletRequest
- 搭建hadoop_之 创建3个虚拟机配置好网络
- 保存全局Crash报告
- 安卓开发之Toolbar