论文部分内容阅读
摘要:在大型专业软件的工程管理中,要求在打开一个工程的时候,能够恢复其保存时的所有信息,窗口恢复是其中的重点,而窗口Z坐标处理是窗口恢复的难点,也是实现窗口恢复的关键。文章以自动处理窗口信息来实现工程中各独立窗口所有信息的轻松保存与恢复为目标,提供一种基于MFC的视图Z坐标保存与恢复算法。
关键词:窗口;Z坐标;算法;消息
引言
在一个大型专业软件项目中,存在很多不同类型的窗口。而一个优秀的专业软件,在工程管理方面,应该能够在打开一个旧的工程时,自动恢复该工程关闭时的所有信息。然而,由于实现的难度大,许多专业软件都没有这一功能,用户在打开一个工程后,往往还要手动调整以恢复到需要的操作状态,这给用户带来极大不便。
面对不同类型的窗口对象,找到一个简单通用的工程视图信息保存与恢复算法,以支持窗口恢复,提高软件的友好性与操作便利性,显得十分必要。窗口Z坐标处理是窗口恢复的难点,也是实现窗口恢复的关键,只要解决了窗口Z坐标处理的问题,实现窗口恢复便不再困难。本文充分利用Windows系统的消息机制,以自动处理窗口信息、实现工程中各独立窗口所有信息轻松保存与恢复为目标,提供一种基于MFC的视图Z坐标保存与恢复算法。在实现的过程中,建立一个文档类和一个视图类,在这两个类中实现这一套算法,其它的不同类型的窗口只需从这两个类派生,就能一劳永逸地实现窗口Z坐标保存与恢复,进而实现窗口恢复。这是一个通用的算法,可以应用在任何使用MFC文档视图结构的应用程序中。
1、MFC文档管理解析
MFC(Microsoft Foundation Class Library)是一个编程框架,将其中的各种类结合起来就能构成一个应用程序框架。MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。文档视图结构(Document/ViewArchitecture)是MFC的精髓,也是Observer模式的具体实现框架之一,Document/View Architecture通过将数据和其表示分开,提供了很好的数据层次和表现层次的解耦。
文档用来保存数据,提供对数据进行处理的主要方法,并为视图显示提供数据。一个文档可以拥有多个视图。视图在Windows中就是一个窗口,也就是一个可视化的矩形区域,用来展示文档中的数据。每个视图必须依附于一个框架。框架实际也是一个Windows窗口,但是在框架上可以放置菜单、工具栏、状态栏等,而视图则放在框架的客户区。因此在MFC中我们看到的窗口实际上是Frame和View共同作用的结果。在某一具体时刻,程序中只有一个活动的文档、框架和视图,即当前的文档、框架、视图。文档视图结构如图1所示。
图2示出了MFC多文档管理方法。MFC文档视图结构的应用程序类CWinApp可以包含多个文档模板对象,MFC通过文档模板管理类CDocManager对这些文档模板对象进行管理。文档模板管理类中包含一个链表CPtrList m_templateList,用于保存程序中加入的文档模板类对象。
文档模板管理类CDocManager是一个隐藏的类,甚至在MSDN中都找不到其相关说明。在应用程序类中,可以直接通过函数AddDocTemplate把已定义的文档模板对象加入到文档模板管理类对象m_pDocManager中。函数AddDocTemplate的原型为:
void AddDocTemplate(CDocTemplate* pTemplate);
pTemplate是要添加的文档模板的指针。
文档模板类CDocTemplate统一了文档和视图,CDocTem-plate在定义时必须指明一个文档类、一个框架类和一个视图类。这三个类的不同,形成了各式各样的窗口。多文档模板类CMuliiDocTemplate派生于CDocTemplate,其中增加了一个保护型链表成员CPtrList m_docList用来保存相应文档类所打开的各个文档。这样,应用程序就和文档有机地结合起来。
MFC通过文档模板管理类,文档模板类,文档这三层关系紧密结合,有机地管理着程序中的文档。
基于以上MFC文档视图结构及其多文档管理方法,我们设计出以下一套窗口Z坐标的保存与恢复算法。本算法把窗口信息保存在与之相对应的文档中,将视图类与框架类结合,处理窗口操作信息。
2、窗口Z坐标的提取与保存
窗口Z坐标用以表示窗口前后位置,表明在多窗口的情况下,哪个窗口在前面,哪个在后面(被遮住)。窗口Z坐标的保存过程,即是提取窗口Z坐标并保存在适当地方的过程。本文为实现窗口z坐标处理,自定义两个消息,即:WM_GETWNDPOS,用于提取窗口Z坐标;WM_SETWNDPOS,用于窗口Z坐标的恢复处理。自定义消息由消息名称和消息处理函数两部分组成。其中,消息名称是消息的标识,为一个常数,常用宏的形式给出;消息处理函数即消息处理的方法,它带两个参数,通过这两个参数,实现窗口之间信息的传递,这两个参数在发送消息时,由消息发送函数带进来。
消息WM_GETWNDPOS的处理函数是OnGetWndPos,它接收一个有效参数wParam,用于计算窗口的坐标z。消息处理算法流程图如图3所示。
2.1算法解析
消息WM_GETWNDPOS传递参数wParam,通过在各个窗口之间传递,可逐一得到各窗口Z坐标。以下是结合图3对该算法的解析,其中的关键点如取顶层窗口的方法等在算法实现部分给出。
z坐标的提取算法从当前激活窗口也就是顶层窗口开始执行。算法启动,首先取上层窗口,如果不成功,则证明本窗口为最顶层窗口,置z=0。如果没有得到上层窗口,则wParam+l即为当前窗口z坐标。
为本窗口设置完z坐标后,取下层窗口,如果成功,则把wParam作为参数,向下层窗口发送本消息。如果没有下层窗口,证明所有窗口已全部计算完毕,提取Z坐标处理终止。
通过以上算法,得到窗口的Z坐标,然后将数据保存到文档,并进一步保存到文件中,为窗口恢复准备数据。
2.2算法实现
2.2.1取顶层窗口
顶层窗口就是当前处于激活状态的窗口,处于所有窗口的顶层。它代表着当前活动的文档、框架和视图,可以通过取主框架窗口类的活动框架,然后进一步取其活动视图来得到。在MFC中可以用标准方法GetActiveFrame和GetActiveView分别实现。
2.2.2取下一窗口的方法
视图类没有取下一窗口的方法,但框架类有。所以取下一窗口,首先要用GetParentFrame函数得到视图类的父框架,然后通 过框架窗口的GetNextWindow函数来得到下一窗口,如果成功,函数返回下一窗口的指针,否则返回NULL。GetNextWindow函数带一个参数nFlag,nFlag有两种取值:GW_HWNDNEXT、GW_HWNDPREV,分别用来取下层和上层窗口,这i-i5函数的具体用法,参见MSDN。
2.2.3发进消息
Windows通过消息实现窗口之间数据的传递。向窗口发送消息,用Windows API函数SendMessage,其原型如下:
LRESULT SendMessage(HWND hWnd,UINT Msg,
WPARAM wParam,LPARAM IParam);
hWnd为消息目标窗口句柄。Msg为要发送的消息。wParam,IParam为消息参数。
本消息传递的四个参数是:消息的目的地(下一个窗口);消息名称WM_GE7WNDPOS;消息参数wParam;还有一个参数不使用,填为0即可。
3、窗口Z坐标的恢复方法
窗口Z坐标的恢复,即是在所需窗口全部打开后,根据工程文件中保存的Z坐标数据,调整窗口的前后位置至工程保存前的状态。
自定义消息WM_SETWNDPOS,处理函数OnSetWndPos。用来设置Z坐标。它接收一个参数wParam,wParam用于控制本消息的正常路由方向。打开工程后,可根据工程参数创建相应的各类型窗口(创建窗口的方法可参见3.2.1)。自定义消息处理算法流程图如图4所示。
3.1算法解析
Z坐标恢复过程可以选择在任意一窗口启动,为方便起见,这里取顶层窗口。
算法开始,从文件中读取Z坐标z并赋予临时坐标zT,对zT进行处理,从而防止改变坐标z,然后移动窗口。进一步计算消息路由条件。如果消息应该继续路由,则向路由方向上的下一窗口路由消息;如果不再满足路由条件,则退出算法,也同时结束了Z坐标的恢复过程。
3.2算法实现
3.2.1创建所有窗口
Z坐标恢复的前提是所有窗口已经创建。而要创建一个窗口,只需有这个窗口的类型,也就是知道文档模板类对象,然后通过CDocTemplate:OpenDocumentFile函数来打开一个文档,并同时创建窗口。
3.2.2移动窗口
移动窗口,包括移动窗口的位置,控制窗口的大小以及改变窗口的z坐标。这里主要控制窗口的Z坐标。可使用CWnd类的SetWindowPos函数,原型为:
BOOL SetWindowPos(const CWnd*pWndlnsertAfter,int x,
int y,int cx,int cy,UINT nFlags);
参数说明:pWndlnsertAfter,指名移动窗口的位置,也就是把窗口移动到哪一个窗口的后面。可以有四个取值:wndBottom,wndTop,wndTopMost,wndNoTopMost。x,y,cx,cy,指定窗口大小。nFlags是大小和位置处理方式的指示。
本算法中移动窗口,还包括对临时坐标zT操作:首先定义COMNUM代表最大窗口个数,为一个足够大的值,可以取500。COMMAX为一个较COMNUM大的值,用作辅助标记,可取1000。观察ZT是否等于0,如果等于o,则移动窗口至最底层,并置zT=COMMAX,否则,让zT自减1。置zT=COMMAX,就是让zT成为一个很大的值,这将在计算路由条件时用到。
3.2.3路由条件
路由条件就是决定消息是否继续路由的条件,同时还包含消息路由所必需的消息,如消息路由方向,路由数据等。路由条件由消息参数wParam及zT共同决定。wParam控制初始路由方向,wParam=1时,消息向上层窗口传递,wParam=0时,消息向下层窗口传递。zT为临时z坐标,窗口的每一次操作都会改变zT。通过观察zT的变化与取值,结合路由方向,可计算出路由条件。
路由条件计算方法:通过zT
4、算法复杂度
窗口z坐标的提取算法:
提取算法比较简单,由于各窗口仅需遍历一遍,其复杂度为0(N)。
窗口z坐标的恢复算法:
每一个窗口的临时坐标zT根据z自减至0时算法即结束。其复杂度为:
1+2+3+…+n-1+n=(n+1)*n/2为O(n2)。
由上述算法复杂度分析可以得出本文所提供的窗口z坐标保存与恢复算法的复杂度是很低的。在实际应用中它能在毫无感觉的情况下保存和恢复众多窗口,满足复杂专业项目应用要求。
5、结束语
窗口Z坐标的提取、保存与恢复是实现大型专业软件项目工程保存与恢复的关键技术,处理了Z坐标,就可以进一步完成整个项目工程的保存与恢复了。本算法基于MFC,以较低的复杂度实现了窗口Z坐标的快速恢复,具有很好的实用价值。同时,本算法具有很强的通用性,可以轻松地应用到任何基于MFC的软件。
该算法已在3G移动通信路测软件项目中成功使用。
关键词:窗口;Z坐标;算法;消息
引言
在一个大型专业软件项目中,存在很多不同类型的窗口。而一个优秀的专业软件,在工程管理方面,应该能够在打开一个旧的工程时,自动恢复该工程关闭时的所有信息。然而,由于实现的难度大,许多专业软件都没有这一功能,用户在打开一个工程后,往往还要手动调整以恢复到需要的操作状态,这给用户带来极大不便。
面对不同类型的窗口对象,找到一个简单通用的工程视图信息保存与恢复算法,以支持窗口恢复,提高软件的友好性与操作便利性,显得十分必要。窗口Z坐标处理是窗口恢复的难点,也是实现窗口恢复的关键,只要解决了窗口Z坐标处理的问题,实现窗口恢复便不再困难。本文充分利用Windows系统的消息机制,以自动处理窗口信息、实现工程中各独立窗口所有信息轻松保存与恢复为目标,提供一种基于MFC的视图Z坐标保存与恢复算法。在实现的过程中,建立一个文档类和一个视图类,在这两个类中实现这一套算法,其它的不同类型的窗口只需从这两个类派生,就能一劳永逸地实现窗口Z坐标保存与恢复,进而实现窗口恢复。这是一个通用的算法,可以应用在任何使用MFC文档视图结构的应用程序中。
1、MFC文档管理解析
MFC(Microsoft Foundation Class Library)是一个编程框架,将其中的各种类结合起来就能构成一个应用程序框架。MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。文档视图结构(Document/ViewArchitecture)是MFC的精髓,也是Observer模式的具体实现框架之一,Document/View Architecture通过将数据和其表示分开,提供了很好的数据层次和表现层次的解耦。
文档用来保存数据,提供对数据进行处理的主要方法,并为视图显示提供数据。一个文档可以拥有多个视图。视图在Windows中就是一个窗口,也就是一个可视化的矩形区域,用来展示文档中的数据。每个视图必须依附于一个框架。框架实际也是一个Windows窗口,但是在框架上可以放置菜单、工具栏、状态栏等,而视图则放在框架的客户区。因此在MFC中我们看到的窗口实际上是Frame和View共同作用的结果。在某一具体时刻,程序中只有一个活动的文档、框架和视图,即当前的文档、框架、视图。文档视图结构如图1所示。
图2示出了MFC多文档管理方法。MFC文档视图结构的应用程序类CWinApp可以包含多个文档模板对象,MFC通过文档模板管理类CDocManager对这些文档模板对象进行管理。文档模板管理类中包含一个链表CPtrList m_templateList,用于保存程序中加入的文档模板类对象。
文档模板管理类CDocManager是一个隐藏的类,甚至在MSDN中都找不到其相关说明。在应用程序类中,可以直接通过函数AddDocTemplate把已定义的文档模板对象加入到文档模板管理类对象m_pDocManager中。函数AddDocTemplate的原型为:
void AddDocTemplate(CDocTemplate* pTemplate);
pTemplate是要添加的文档模板的指针。
文档模板类CDocTemplate统一了文档和视图,CDocTem-plate在定义时必须指明一个文档类、一个框架类和一个视图类。这三个类的不同,形成了各式各样的窗口。多文档模板类CMuliiDocTemplate派生于CDocTemplate,其中增加了一个保护型链表成员CPtrList m_docList用来保存相应文档类所打开的各个文档。这样,应用程序就和文档有机地结合起来。
MFC通过文档模板管理类,文档模板类,文档这三层关系紧密结合,有机地管理着程序中的文档。
基于以上MFC文档视图结构及其多文档管理方法,我们设计出以下一套窗口Z坐标的保存与恢复算法。本算法把窗口信息保存在与之相对应的文档中,将视图类与框架类结合,处理窗口操作信息。
2、窗口Z坐标的提取与保存
窗口Z坐标用以表示窗口前后位置,表明在多窗口的情况下,哪个窗口在前面,哪个在后面(被遮住)。窗口Z坐标的保存过程,即是提取窗口Z坐标并保存在适当地方的过程。本文为实现窗口z坐标处理,自定义两个消息,即:WM_GETWNDPOS,用于提取窗口Z坐标;WM_SETWNDPOS,用于窗口Z坐标的恢复处理。自定义消息由消息名称和消息处理函数两部分组成。其中,消息名称是消息的标识,为一个常数,常用宏的形式给出;消息处理函数即消息处理的方法,它带两个参数,通过这两个参数,实现窗口之间信息的传递,这两个参数在发送消息时,由消息发送函数带进来。
消息WM_GETWNDPOS的处理函数是OnGetWndPos,它接收一个有效参数wParam,用于计算窗口的坐标z。消息处理算法流程图如图3所示。
2.1算法解析
消息WM_GETWNDPOS传递参数wParam,通过在各个窗口之间传递,可逐一得到各窗口Z坐标。以下是结合图3对该算法的解析,其中的关键点如取顶层窗口的方法等在算法实现部分给出。
z坐标的提取算法从当前激活窗口也就是顶层窗口开始执行。算法启动,首先取上层窗口,如果不成功,则证明本窗口为最顶层窗口,置z=0。如果没有得到上层窗口,则wParam+l即为当前窗口z坐标。
为本窗口设置完z坐标后,取下层窗口,如果成功,则把wParam作为参数,向下层窗口发送本消息。如果没有下层窗口,证明所有窗口已全部计算完毕,提取Z坐标处理终止。
通过以上算法,得到窗口的Z坐标,然后将数据保存到文档,并进一步保存到文件中,为窗口恢复准备数据。
2.2算法实现
2.2.1取顶层窗口
顶层窗口就是当前处于激活状态的窗口,处于所有窗口的顶层。它代表着当前活动的文档、框架和视图,可以通过取主框架窗口类的活动框架,然后进一步取其活动视图来得到。在MFC中可以用标准方法GetActiveFrame和GetActiveView分别实现。
2.2.2取下一窗口的方法
视图类没有取下一窗口的方法,但框架类有。所以取下一窗口,首先要用GetParentFrame函数得到视图类的父框架,然后通 过框架窗口的GetNextWindow函数来得到下一窗口,如果成功,函数返回下一窗口的指针,否则返回NULL。GetNextWindow函数带一个参数nFlag,nFlag有两种取值:GW_HWNDNEXT、GW_HWNDPREV,分别用来取下层和上层窗口,这i-i5函数的具体用法,参见MSDN。
2.2.3发进消息
Windows通过消息实现窗口之间数据的传递。向窗口发送消息,用Windows API函数SendMessage,其原型如下:
LRESULT SendMessage(HWND hWnd,UINT Msg,
WPARAM wParam,LPARAM IParam);
hWnd为消息目标窗口句柄。Msg为要发送的消息。wParam,IParam为消息参数。
本消息传递的四个参数是:消息的目的地(下一个窗口);消息名称WM_GE7WNDPOS;消息参数wParam;还有一个参数不使用,填为0即可。
3、窗口Z坐标的恢复方法
窗口Z坐标的恢复,即是在所需窗口全部打开后,根据工程文件中保存的Z坐标数据,调整窗口的前后位置至工程保存前的状态。
自定义消息WM_SETWNDPOS,处理函数OnSetWndPos。用来设置Z坐标。它接收一个参数wParam,wParam用于控制本消息的正常路由方向。打开工程后,可根据工程参数创建相应的各类型窗口(创建窗口的方法可参见3.2.1)。自定义消息处理算法流程图如图4所示。
3.1算法解析
Z坐标恢复过程可以选择在任意一窗口启动,为方便起见,这里取顶层窗口。
算法开始,从文件中读取Z坐标z并赋予临时坐标zT,对zT进行处理,从而防止改变坐标z,然后移动窗口。进一步计算消息路由条件。如果消息应该继续路由,则向路由方向上的下一窗口路由消息;如果不再满足路由条件,则退出算法,也同时结束了Z坐标的恢复过程。
3.2算法实现
3.2.1创建所有窗口
Z坐标恢复的前提是所有窗口已经创建。而要创建一个窗口,只需有这个窗口的类型,也就是知道文档模板类对象,然后通过CDocTemplate:OpenDocumentFile函数来打开一个文档,并同时创建窗口。
3.2.2移动窗口
移动窗口,包括移动窗口的位置,控制窗口的大小以及改变窗口的z坐标。这里主要控制窗口的Z坐标。可使用CWnd类的SetWindowPos函数,原型为:
BOOL SetWindowPos(const CWnd*pWndlnsertAfter,int x,
int y,int cx,int cy,UINT nFlags);
参数说明:pWndlnsertAfter,指名移动窗口的位置,也就是把窗口移动到哪一个窗口的后面。可以有四个取值:wndBottom,wndTop,wndTopMost,wndNoTopMost。x,y,cx,cy,指定窗口大小。nFlags是大小和位置处理方式的指示。
本算法中移动窗口,还包括对临时坐标zT操作:首先定义COMNUM代表最大窗口个数,为一个足够大的值,可以取500。COMMAX为一个较COMNUM大的值,用作辅助标记,可取1000。观察ZT是否等于0,如果等于o,则移动窗口至最底层,并置zT=COMMAX,否则,让zT自减1。置zT=COMMAX,就是让zT成为一个很大的值,这将在计算路由条件时用到。
3.2.3路由条件
路由条件就是决定消息是否继续路由的条件,同时还包含消息路由所必需的消息,如消息路由方向,路由数据等。路由条件由消息参数wParam及zT共同决定。wParam控制初始路由方向,wParam=1时,消息向上层窗口传递,wParam=0时,消息向下层窗口传递。zT为临时z坐标,窗口的每一次操作都会改变zT。通过观察zT的变化与取值,结合路由方向,可计算出路由条件。
路由条件计算方法:通过zT
4、算法复杂度
窗口z坐标的提取算法:
提取算法比较简单,由于各窗口仅需遍历一遍,其复杂度为0(N)。
窗口z坐标的恢复算法:
每一个窗口的临时坐标zT根据z自减至0时算法即结束。其复杂度为:
1+2+3+…+n-1+n=(n+1)*n/2为O(n2)。
由上述算法复杂度分析可以得出本文所提供的窗口z坐标保存与恢复算法的复杂度是很低的。在实际应用中它能在毫无感觉的情况下保存和恢复众多窗口,满足复杂专业项目应用要求。
5、结束语
窗口Z坐标的提取、保存与恢复是实现大型专业软件项目工程保存与恢复的关键技术,处理了Z坐标,就可以进一步完成整个项目工程的保存与恢复了。本算法基于MFC,以较低的复杂度实现了窗口Z坐标的快速恢复,具有很好的实用价值。同时,本算法具有很强的通用性,可以轻松地应用到任何基于MFC的软件。
该算法已在3G移动通信路测软件项目中成功使用。