如何进行排版


前面我们分析过对于WM_SIZE消息的处理过程,CBkDialogViewImpl窗口类在处理WM_SIZE消息时,调用了自身的_RepositionItems方法,在这个方法内对窗口上的虚拟控件进行处理,现在我们来详细看一下控件体系内是如何进行排版操作的。

在_RepositionItems方法中定义了4个CRect变量,就是rcClient, rcHeader, rcFooter和rcBody,其中rcHeader,rcFooter和rcBody分别对应m_bkHeader,m_bkFooter和m_bkBody的位置,rcClient是rcHeader,m_bkFooter和m_bkBody之和。

 

在控件中哪些变量表示控件的位置信息呢:

在CBkWindow中,用m_rcWindow这个CRect类型的变量来表示每个控件的基本位置信息(控件的长宽以及左上角相对于实窗口的pos),用m_dlgpos这个BKDLG_POSITION类型的变量来表示从Xml获取的控件位置信息(相对于父控件的距离)。

CBkWindow类中的BKDLG_POSITION类型包含了控件上下左右的边界位置,而且可以表示控件边界相对于父控件边界是左对齐,右对齐还是居中对齐,以及具体的偏移量。

而在CBkWindow类中也设置了一系列的枚举值:

 

enum {
       // Specify by "width" attribute
       SizeX_Mask          = 0x0007UL,
       SizeX_Specify       = 0x0001UL, //width > 0
       SizeX_FitContent    = 0x0002UL, //width <= 0
       SizeX_FitParent     = 0x0004UL, //width = "full" default
       // Specify by "height" attribute
       SizeY_Mask          = 0x0070UL,
       SizeY_Specify       = 0x0010UL, //height > 0
       SizeY_FitContent    = 0x0020UL, //height <= 0 default
       SizeY_FitParent     = 0x0040UL, //height = "full" default
       // Specify by "float" attribute
       Position_Mask       = 0x0300UL,
       Position_Relative   = 0x0100UL, //float = 0 default
       Position_Float      = 0x0200UL, //float = 1
       // Specify by "valign" and"align" attribute, only using at float = 1 or panel control(Vert-Align)
       Align_Mask          = 0xF000UL,
       VAlign_Top          = 0x0000UL, //valign = top
       VAlign_Middle       = 0x1000UL, //valign = middle
       VAlign_Bottom       = 0x2000UL, //valign = bottom
       Align_Left          = 0x0000UL, //align = left
       Align_Center        = 0x4000UL, //align = center
       Align_Right         = 0x8000UL, //align = right
};



用来表示控件是按照内容填充,按照父控件填充,还是按照固定的值进行填充,也可以定义对齐的方式,这些描述可以比上面的BKDLG_POSITION类型更加丰富,对于在xml中描述控件位置也更加灵活。

 

控件中用于处理位置信息的方法有哪些呢:

CBkWindow:
OnWindowPosChanged:处理WM_WINDOWPOSCHANGED消息,发送WM_NCCALCSIZE消息获取自身长宽,通过传入的Pos和前面取得的长宽设置m_rcWindow变量

OnNcCalcSize:处理WM_NCCALCSIZE消息,根据父控件的长宽信息以Xml文件中自身位置信息的描述来计算自身对于父控件的位置信息。

CBkPanel:

OnWindowPosChanged:处理WM_WINDOWPOSCHANGED消息,调用CBkWindow类的OnWindowPosChanged方法,调用_ComposingPanel方法。

CBkDialog:

OnWindowPosChanged:处理WM_WINDOWPOSCHANGED消息,调用CBkWindow类的OnWindowPosChanged方法,调用_RepositionChilds方法(依次调用每个子节点的RepositionChild方法)。

所以对控件发送WM_WINDOWPOSCHANGED消息时需要传入WINDOWPOS结构体,其中x和y为控件的位置,而cx和cy为父窗口的长宽,控件根据cx和cy以及xml中的描述来计算自身的长宽。

 

现在我们来看一下控件位置调整的过程:

java集成金山文档_java集成金山文档

CBkWindow类负责自身的计算工作,所有控件的自身计算工作都是由调用父类CBkWindow的OnWindowPosChanged方法来进行的,在这个方法中通过xml描述和传入的父控件长宽计算自身大小,同时根据传入的pos设置控件的m_rcWindow。CBkDialog类计算自身,并计算其子节点的大小,设置子节点的pos并向其发送WM_WM_WINDOWPOSCHANGED消息,令其计算自身。