MFC技术系列(一)--窗口的风格

来源:互联网 发布:java微信刷卡支付开发 编辑:程序博客网 时间:2024/05/02 01:54

窗口风格是各种窗口开发的重要基础之一。它可以分为普通风格(WS_系列)和扩展风格(WS_EX_系列)。从其特点上,主要分成两大类:

1.         一类表明窗口和其它窗口的关系,包括:WS_CHILDWS_POPUPWS_OVERLAPPEDWS_CLIPCHILDRENWS_CLIPSIBLINGSWS_GROUP

WS_EX_TOPMOSTWS_EX_MDICHILD等。(这里的关系并不是指Foreground/Background windowZ-Order的概念)

2.         一类表明窗口自身的外观特征,包括:WS_BORDERWS_CAPTIONWS_MINIMIZEWS­­_MINIMIZEBOXWS_DLGFRAME

WS_EX_DLGMODALFRAME WS_EX_WINDOWEDGE等。

例如:

一个标准的Dialog窗口,除了Dialog自身的风格(DS_系列)外,其窗口风格如下:

普通风格:WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU

扩展风格:WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW

一个标准的Frame窗口,其风格如下:

普通风格:WS_CAPTION | WS_OVERLAPPED | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_MAXIMIZE | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX

扩展风格WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_WINDOWEDGE

大部分的窗口风格都比较容易理解。下面重点讲解一下第一类风格中主要几个风格的差异:

¨  WS_POPUPWS_OVERLAPPED的窗口均为top-level窗口,即:如果采用SetWindowPos改变其位置需要使用Screen坐标,而不是Client坐标。不同的是,WS_POPUP窗口有父窗口,使用GetParent方法可以获得;而WS_OVERLAPPED窗口却没有,GetParent方法为NULL。也就是说,对于一个界面应用程序而言,一定存在至少一个WS_OVERLAPPED窗口(作为应用程序的主窗口)。

此外,WS_OVERLAPPED窗口总是有title barborder,即使你显示删除WS_CAPTIONWS_BORDER风格,而WS_POPUP却没有该特点。

¨  WS_CLIPCHILDREN:绘图时,将该窗口中的子窗口所占的区域排除在外。当你创建父窗口时,可以使用该风格。如果使用Invalidate方法,这部分区域不会计算在更新区域内。因此,有可能产生这些子窗口没有刷新的问题。

¨  WS_CLIPSIBLINGS:绘图时,将该子窗口和其同级其它子窗口(具有相同的父窗口)重叠的区域排除在外。如果使用Invalidate方法,这部分区域不会计算在更新区域内。这样此时绘画,就不会画到其它窗口上。

¨  WS_EX_APPWINDOW:强迫一个top-level窗口在可见时,出现在TaskBar上。但这并不意味着一个窗口出现在TaskBar上就一定需要该风格,其实,如果是主线程的第一个窗口(m_pMainWnd),即使没有该风格,也会出现在TaskBar上。

¨  WS_EX_LAYERED:建立Layered窗口,即:具有复杂视觉特征的窗口,比如:透明窗口。该风格不能用于子窗口。主要有SetLayeredWindowAttributesUpdateLayeredWindow两个方法,其中,后者更加灵活。前者通常用来实现透明窗口等简单任务。

 

上面提到了top-level窗口,因此有必要解释下面几个方法的差异:

GetParent方法:如果是子窗口(具有WS_CHILD风格),那么总能得到一个有效的临时窗口对象(Immediate Window);如果是top-level窗口,又分为两种情况:如果该窗口为非拥有(unowned),那么返回NULL,否则,返回拥有者窗口对象。因此,GetParent并非总是返回父窗口。

GetOwner方法:获得拥有者窗口,默认为父窗口。父子窗口中的子窗口只能出现在父窗口的客户区域,而具有拥有者窗口的窗口可以出现在桌面的任何位置。这里的Owner窗口,不同于API方法GetWindow获得的Owner窗口,它是MFC特定的概念。

GetAncestor方法:获得祖先窗口。有三个选择,GA_PARENT, GA_ROOT, GA_ROOTOWNER

 

MFC中的Immediate窗口:在MSDN中关于MFC的描述中,经常能看到ImmediatePermanent Window字样。其中,Immediate窗口是MFC中临时产生的窗口对象,MFC会定期清理这些对象,因此通常不可以保存作为类成员变量。

对于窗口句柄的封装:MFC将窗口句柄封装后,提供了CWnd基类。关于句柄和窗口对象间的映射关系,将在《句柄和MFC对象》详细说明。MFC中还存在许多类似的封装方法,比如:对HDC的封装CDC

 

附录:

MSDN(2003)中关于窗口特点的描述链接(从API角度,与MFC无关):

ms-help://MS.MSDNQTR.2003FEB.2052/winui/winui/windowsuserinterface/windowing/windows/windowfeatures.htm (见后续的翻译文章《Windows下窗口的特征》)

 
原创粉丝点击