1.9 窗体位置应用实例
在许多的软件中,都会对窗体的位置和移动进行限定,同时如何以动画方式显示窗体、如何设置窗体始终在最上面等都是在设计窗体时需要解决的问题。本节将介绍与窗体位置有关的技术。
实例028 不可移动的窗体
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\01\028
实例说明
有些时候,开发人员在设计程序时不想让用户在使用中移动窗体。运行本实例,可以发现窗体不允许被拖动,结果如图1.38所示。
技术要点
要实现不允许拖动窗体的功能,只需要通过主窗体的虚函数PreTranslateMessage截获鼠标按下时的消息,将单击标题栏的消息修改成单击非标题栏区域的消息即可。
图1.38 不可移动的窗体
实现过程
(1)新建一个基于对话框的应用程序,将窗体标题改为“不可移动的窗体”。
(2)主要程序代码如下:
BOOL CBKydctDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message==WM_NCLBUTTONDOWN) //截获鼠标左键在标题栏按下消息 { pMsg->message=WM_LBUTTONDOWN; //修改为鼠标左键在非标题栏按下的消息 } return CDialog::PreTranslateMessage(pMsg); }
举一反三
根据本实例,读者可以:
利用鼠标在非标题栏区域拖动窗体。
实例029 始终在最上面的窗体
本实例是一个提高效率、人性化的程序
实例位置:光盘\mingrisoft\01\029
实例说明
在使用软件的过程中,有时会因为打开其他软件而将正在操作的软件置于其后,为操作带来了不便。
在程序运行后,无论用户打开多少个窗体,本程序的窗体始终在最上面,结果如图1.39所示。
图1.39 始终在最上面的窗体
技术要点
要实现将自己的程序永远置前,可以使用API函数SetWindowPos,该函数可以为窗口指定一个新位置和状态。SetWindowPos函数的原型如下:
BOOL SetWindowPos(HWN hWnd,HWND hWndlnsertAfter,int X,int Y,int cx,int cy,UNITFlags);
参数说明:
● hWnd:窗口句柄。
● hWndlnsertAfter:在z轴顺序中的标识窗口的句柄,该句柄将确定窗口出现在z轴中的顺序。
● X:以客户坐标指定窗口新位置的左边界。
● Y:以客户坐标指定窗口新位置的顶边界。
● cx::以像素指定窗口的新宽度。
● cy:以像素指定窗口的新高度。
● Flags:窗口尺寸和定位的标志。
如果将窗口置前,可以将该函数中的hWndlnsertAfter参数值设置为HWND_TOPMOST。
实现过程
(1)新建一个基于对话框的应用程序,将窗体标题改为“始终在最上面的窗体”。
(2)主要程序代码如下:
::SetWindowPos(AfxGetMainWnd()->m_hWnd,HWND_TOPMOST,10,10,450,300,SWP_NOMOVE);
举一反三
根据本实例,读者可以:
设置窗口置后。
实例030 磁性窗体
本实例是一个人性化的程序
实例位置:光盘\mingrisoft\01\030
实例说明
用户在使用一些播放器的软件时,会发现很多的播放器都是由几个窗体组合而成的,这些窗体可以连在一起移动,也可以分开单独移动,增加了软件应用的灵活性。运行程序,调整窗体位置,如图1.40所示。
图1.40 磁性窗体
技术要点
实现磁性窗体功能时主要用到了MapWindowPoints函数和MoveWindow函数设置并移动窗体位置,下面对本实例中用到的关键技术进行详细讲解。
MapWindowPoints函数:将某个窗口的区域坐标转换为另一个窗口的区域坐标,语法如下:
void MapWindowPoints( CWnd* pwndTo, LPRECT lpRect ) const;
参数说明:
● pwndTo:表示转换后的区域坐标窗口。
● lpRect:表示待转换的区域对象。
实现过程
(1)新建一个基于对话框的应用程序。
(2)向工程中插入两个BMP位图资源,向对话框中添加一个图片控件,设置其Type属性为Bitmap,设置其Image属性为IDB_BITMAP1。
(3)创建一个新的对话框资源,修改其ID为IDD_CHILD_DIALOG,将其窗体标题改为“均衡器”,并设置对话框显示的字体信息。
(4)通过类向导为新建的对话框资源关联一个对话框类CChildDlg。
(5)向新建的对话框中添加一个图片控件,设置其Type属性为Bitmap,设置其Image属性为IDB_BITMAP2。
(6)主要程序代码如下:
void CMagnetismDlg::OnMove(int x, int y) { CDialog::OnMove(x, y); if(m_IsCreate==TRUE) //已创建 { CRect pRect,cRect; //声明区域对象 GetWindowRect(pRect); //获得主窗体区域 MapWindowPoints(this,pRect); //转换窗体区域坐标 m_Dlg->GetWindowRect(cRect); //获得均衡器窗体区域 //如果移动播放器窗体距离均衡器窗体不到20像素则移动播放器窗体,使两个窗体相连 if(pRect.left-cRect.right<20 && pRect.left-cRect.right>0 && ( pRect.top>cRect.top-m_Height && pRect.bottom<cRect.bottom+m_Height)) pRect.left=cRect.right; //设置播放器左边与均衡器右边相连 else if(cRect.left-pRect.right<20 && cRect.left-pRect.right>0 && ( pRect.top>cRect.top-m_Height && pRect.bottom<cRect.bottom+m_Height)) pRect.left=cRect.left-m_Width; //设置播放器右边与均衡器左边相连 else if(cRect.top-pRect.bottom<20 && cRect.top-pRect.bottom>0 && ( pRect.left>cRect.left-m_Width && pRect.right<cRect.right+m_Width)) pRect.top=cRect.top-m_Height; //设置播放器下边与均衡器上边相连 else if(pRect.top-cRect.bottom<20 && pRect.top-cRect.bottom>0 && ( pRect.left>cRect.left-m_Width && pRect.right<cRect.right+m_Width)) pRect.top=cRect.bottom; //设置播放器上边与均衡器下边相连 MoveWindow(pRect.left,pRect.top,m_Width,m_Height); //移动播放器窗体 if(m_Berth) //如果两个窗体相连 { m_Dlg->MoveWindow(cRect.left+(pRect.left-m_Point.x), cRect.top+(pRect.top-m_Point.y),cRect.Width(),cRect.Height()); //移动均衡器窗体 } m_Point.x=pRect.left; //设置左上角横坐标 m_Point.y=pRect.top; //设置左上角纵坐标 } }
举一反三
根据本实例,读者可以:
自由组合的磁性窗体。