RespoitionBars的用法和参数的意义(引用别人的)

2024-06-09 04:08

本文主要是介绍RespoitionBars的用法和参数的意义(引用别人的),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MFC窗口位置管理详细分析及实例 在一般用MFC编写的程序的窗口客户区中,可能有好几个子窗口(具有WM_CHILD风格的窗口)。上边是工具栏,中间是视图窗口,下边是状态栏。三个窗口在框架的客户区里和平共处,互不重叠。主框架窗口的尺寸改变了,别的子窗口都能及时调整自己的尺寸以便保持相互位置关系不变,例如状态条窗口总能保持在主框架客户区底部,并且其宽度总能和主框架客户区宽度一致。工具栏窗口总能停靠在主框架的某一边不变,其宽度或高度总能和主框架客户区的宽度或高度一致,视图窗口总能填满主框架客户区的剩余空间。

假如我们自己从CWnd类派生一个窗口类并生成一个窗口,在它的客户区里要生成若干个子窗口,我们想使这些子窗口排列得规规矩矩,互不重叠,当父窗口的尺寸变了时各个子窗口能适时调整自己的尺寸和位置,使各个子窗口之间的位置大小比例关系不变。当移动其中一个或几个子窗口时,别的子窗口能及时为这个移动了的子窗口让位。当然我们可以利用api函数里管理窗口的函数来编写自己的管理子窗口的方法。可是如果在父窗口的客户区里有了工具栏,状态条等等子窗口时,你自己加进来的子窗口还能和这些mfc提供的子窗口融洽相处吗?你如何保证你的子窗口不会覆盖了能够四处停靠的工具栏?当工具栏和状态条消失后你的子窗口如何才能知道,以便及时调整自己的大小从而覆盖工具栏和状态条腾出的空间?基于文档视图构架的窗口的客户区内还有个视图,你自己硬加上的子窗口能不和视图窗口争地盘吗?

所以必须了解mfc的窗口管理它的客户区的方法。其实,mfc的窗口管理它的客户区的方法是非常简单的:父窗口调用一个函数,子窗口响应一个消息,就这么多。

CWnd::RepositionBars函数和WM_SIZEPARENT消息

先简述一下mfc的窗口为子窗口分配客户区空间的过程:这一过程是父窗口与子窗口共同协调完成的。父窗口先提供它的客户区内的一块区域,叫做起始可用区域。然后调用一个函数,在这个函数里,父窗口把这片区域通过一个消息提交给它的第一个子窗口,该子窗口决定自己要占用多大一块,然后在可用区域里把它将占据的部分划出去,这样可用区域就被切去了一块。父窗口再把这块剩下的可用区域通过同样的消息提交给第二个子窗口,第二个子窗口再根据自己的需要切掉一块。如此这般,每个子窗口都切去自己所需的一块。最后剩下的可用区域就给最后的子窗口使用。可以看出,除了最后一个子窗口外,其它子窗口都得在消息响应函数里有自己的算法来决定自己将在可用区域里占据多大一块,最后一个子窗口由于别无选择,所以不需要这样的算法。

当然,初始的可用区域是一个矩形,每次被切割后剩下的可用区域还是一个矩形,不可能是别的形状的。

举例说来,在一个典型单文档程序中,父窗口就是从CFrameWnd派生的主框架窗口,最后一个子窗口就是视图窗口,如果用了CSplitterWnd生成分隔条的话,最后一个子窗口就是拥有分隔条的那个窗口。其它子窗口就是工具栏窗口和状态条窗口,以及可能有的别的控件窗口。

在典型多文档界面程序中,父窗口就是主框架窗口,最后一个子窗口就是覆盖在主窗口客户区,背景为黑灰色,拥有包含文档的子框架窗口的那个窗口,这是个预定义了窗口类的窗口,它的窗口类名是“MDIClient”。如果用了CSplitterWnd生成分隔条的话,最后一个子窗口就是拥有分隔条的那个窗口。其它窗口就是工具栏窗口,状态条窗口以及可能有的别的控件窗口。

这个函数和消息是:函数CWnd::RepositionBars()以及消息WM_SIZEPARENT。这个消息是mfc自定义的,不是windows自有的。

先简单说明一下这个函数和消息。

1。函数CWnd::RepositionBars()

这个函数不是虚函数,所以就无法在派生类里通过覆盖来编制自己的版本了,只能搞懂它的功能,以便能灵活使用。

简单而言,这个函数的功能是将可用的客户区区域信息放到消息WM_SIZEPARENT的消息参数里,然后枚举本窗口的所有子窗口,给每个子窗口 (除掉一个特定的子窗口,相当于上文提到的最后一个子窗口)都发送这个消息,每个响应这个消息的子窗口都会把可用客户区切去一块。最后把那个特定的子窗口的尺寸和位置调整到刚好放在最后剩下的可用区域里。

2。消息WM_SIZEPARENT

每个欲参与分配客户区的子窗口都要响应这个消息,除非这个子窗口是那个特定的子窗口。

响应这个消息的子窗口至少要做两件事:1,将可用的父窗口客户区切去自己所占据的一块。2,根据消息参数的指示,将自己的大小和位置调整到刚好容纳到自己所占据的区域里或不做调整。

下面详细介绍一下函数CWnd::RepositionBars()和消息WM_SIZEPARENT。

1。函数CWnd::RepositionBars() void RepositionBars( UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver, UINT nFlag = CWnd::reposDefault, LPRECT lpRectParam = NULL, LPCRECT lpRectClient = NULL, BOOL bStretch = TRUE );

参数比较多,但还是比较好懂的。

(1)nIDFirst和nIDLast

参与分配父窗口客户区的子窗口的id范围。

每个WM_CHILD风格的窗口都有个id,这是在窗口创建过程中指定的。函数CWnd::Create()的第六个参数就是这个id。api函数CreateWindow和 CreateWindowEx里的那个HMENU类型的参数,当窗口的风格里有WM_CHILD时,它不是指的菜单句柄,而是该窗口的id。

nIDFirst和nIDLast参数指明了:如果一个子窗口的id值大于等于nIDFirst并且小于等于nIDLast,在这个函数中才会给这个子窗口发送 WM_SIZEPARENT消息,这个子窗口才能参与父窗口客户区的分配。

(2)nIDLeftOver

前面说过,有一个特定的子窗口,它不响应WM_SIZEPARENT消息。只有当其它的子窗口都分配完了,它才来捡取父窗口客户区里剩下的那块。 nIDLeftOver正是这个子窗口的id。它也必须大于等于nIDFirst并且小于等于nIDLast。

(3)lpRectClient

这是一个指向RECT结构数据的指针。这个RECT结构里存放的正是父窗口客户区的初始可用区域。随着在该函数里依次给各个子窗口发送 WM_SIZEPARENT消息,每个响应这个消息的子窗口都会切去自己所占据的部分。最后剩下的部分,就是id为nIDLeftOver的子窗口将要占据的区域了。这个参数可以为NULL,这时初始的可用区域就是整个父窗口客户区。

(4)nFlag和lpRectParam

这两个参数放在一起讲比较好。nFlag是该函数的功能标志,它可以有三个值:reposDefault,reposQuery 和reposExtra。

当nFlag等于reposDefault时,RepositionBars函数的功能是这样的:依次给id介于nIDFirst和nIDLast之间并且不等于nIDLeftOver的子窗口发送WM_SIZEPARENT消息,每个响应这个消息的子窗口从lpRectClient所指的结构里切去自己所占据的部分,并且将自己的大小和位置调整到自己所占据的区域的大小,最后RepositionBars函数还将id为nIDLeftOver的子窗口的大小和位置调整到被其他子窗口切剩的可用区域内,使这个子窗口正好完全覆盖最后的可用区域。这种情况下lpRectParam不用,可以为NULL。

当nFlag等于reposQuery 时,RepositionBars函数的功能是这样的:依次给id介于nIDFirst和nIDLast之间并且不等于nIDLeftOver的子窗口发送WM_SIZEPARENT消息,每个响应这个消息的子窗口从lpRectClient所指的结构里切去自己所占据的部分,但是他们并不调整自己的大小和位置,最后RepositionBars函数并不调整将id为nIDLeftOver的子窗口的大小和位置,而是根据bStretch的值来做动作:如果bStretch为TRUE,那么 RepositionBars函数把最后剩下的可用区域拷贝到lpRectParam指向的RECT结构里;如果bStretch为FALSE,那么RepositionBars函数把所有其他子窗口占用掉的可用区域的高和宽(要所有的子窗口都紧排在一起,形成一个大的矩形,这个值才有意义)拷贝到lpRectParam指向的RECT结构的bottom 和right成员里,其top和left成员被置零。使用这个nFlag值来调用RepositionBars的目的不是要重排子窗口,而是要看看,假如重排子窗口的话,这些子窗口将占去多大一块,最后剩下的可用区域在什么位置等等信息。

当nFlag等于reposExtra时,该函数的功能和nFlag等于reposDefault时差不多,有点小小的区别。此时需要用到lpRectParam。前面说过,当 nFlag等于reposDefault时,RepositionBars函数将在最后把id为nIDLeftOver的子窗口的大小和位置调整到被其他子窗口切剩的可用区域内,使这个子窗口正好完全覆盖最后的可用区域。而当nFlag等于reposExtra时,RepositionBars在调整id为nIDLeftOver的子窗口的大小和位置前,还要用 lpRectParam来对最后剩下的可用区域做修正。假设lpRect指向的是最后的可用区域,那么这个修正是这样进行的:


lpRect->top+=lpRectParam->top;
lprect->left+=lpRectParam->left;
lpRect->right-=lpRectParam->right;
lpRect->bottom-=lpRectParam->bottom;

通过这样的修正,可以使最后剩下的可用区域不被id为nIDLeftOver的子窗口占满,而是空出一些地方来留作他用。
(5)bStretch

这个参数上面已经提到一点它的作用。它主要是提供给各个响应WM_SIZEPARENT消息的子窗口用的,子窗口例如工具栏,状态条等在决定自己将从父窗口客户区的可用空间里划走多少时,这个参数也是个判断的依据。详细可以参阅工具栏和状态条响应WM_SIZEPARENT的函数OnSizeParent()。  

这篇关于RespoitionBars的用法和参数的意义(引用别人的)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1044186

相关文章

Java资源管理和引用体系的使用详解

《Java资源管理和引用体系的使用详解》:本文主要介绍Java资源管理和引用体系的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Java的引用体系1、强引用 (Strong Reference)2、软引用 (Soft Reference)3、弱引用 (W

Java中 instanceof 的用法详细介绍

《Java中instanceof的用法详细介绍》在Java中,instanceof是一个二元运算符(类型比较操作符),用于检查一个对象是否是某个特定类、接口的实例,或者是否是其子类的实例,这篇文章... 目录引言基本语法基本作用1. 检查对象是否是指定类的实例2. 检查对象是否是子类的实例3. 检查对象是否

Java中的内部类和常用类用法解读

《Java中的内部类和常用类用法解读》:本文主要介绍Java中的内部类和常用类用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录内部类和常用类内部类成员内部类静态内部类局部内部类匿名内部类常用类Object类包装类String类StringBuffer和Stri

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Python 异步编程 asyncio简介及基本用法

《Python异步编程asyncio简介及基本用法》asyncio是Python的一个库,用于编写并发代码,使用协程、任务和Futures来处理I/O密集型和高延迟操作,本文给大家介绍Python... 目录1、asyncio是什么IO密集型任务特征2、怎么用1、基本用法2、关键字 async1、async

史上最全nginx详细参数配置

《史上最全nginx详细参数配置》Nginx是一个轻量级高性能的HTTP和反向代理服务器,同时也是一个通用代理服务器(TCP/UDP/IMAP/POP3/SMTP),最初由俄罗斯人IgorSyso... 目录基本命令默认配置搭建站点根据文件类型设置过期时间禁止文件缓存防盗链静态文件压缩指定定错误页面跨域问题

SpringBoot3.4配置校验新特性的用法详解

《SpringBoot3.4配置校验新特性的用法详解》SpringBoot3.4对配置校验支持进行了全面升级,这篇文章为大家详细介绍了一下它们的具体使用,文中的示例代码讲解详细,感兴趣的小伙伴可以参考... 目录基本用法示例定义配置类配置 application.yml注入使用嵌套对象与集合元素深度校验开发

SpringBoot UserAgentUtils获取用户浏览器的用法

《SpringBootUserAgentUtils获取用户浏览器的用法》UserAgentUtils是于处理用户代理(User-Agent)字符串的工具类,一般用于解析和处理浏览器、操作系统以及设备... 目录介绍效果图依赖封装客户端工具封装IP工具实体类获取设备信息入库介绍UserAgentUtils

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置