Visual C++程序开发范例宝典(软件工程师典藏版)
上QQ阅读APP看书,第一时间看更新

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;                                        //设置左上角纵坐标
            }
        }

举一反三

根据本实例,读者可以:

自由组合的磁性窗体。