在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
以下文章载自:【巴蛮子的破新茅屋】http://blog.csdn.net/bamanzi/archive/2006/02/11/596962.aspx Windows编程的习惯是直接指定控件的座标和大小,而UNIX下面的习惯是在容器里面堆放,用不同的layout manager来控制布局(java,wx等也是这种思想)。这也是为什么Windows程序的对话框一般都不让改变大小(因为这意味着要自己写很多代码逐步调整子控件的位置),而UNIX下一般都可以。Delphi程序原来有Align属性来控制控件对那边靠拢。但如果想要一个控件固定离左边、右边有多远,得用D6开始提供Anchors属性。 所以DELPHI提供3种布局属性:Align, Anchor,和 Constraint。基本能满足布局设计的需要。 这样还是不够的,比如有七八个按钮顺排或者表格式布局,这在D2006里面可以用新增的TFlowPanel和TGridPanel来实现。
TFlowPanel和TGridPanel的使用方法: http://edn.embarcadero.com/article/33421 呵呵,没找到中文说明的,只能看看E文了。里面的DEMO无法DOWN。 其中有一个事情要注意:任何一个控件被放到这两个布局上后,无法调整位置,DELPHI提供了一种方法,就是选择要调整的控件,在属性窗体的最下面会出现和布局有关的属性,进行调整就可以了。TFlowPanel有ControlIndex。TGridPanel有column,row,columnspan,rowspan。
评价 DELPHI提供的GridPanel貌似很好,但是使用起来实在不方便。我自己用GridPanel准备画一个人口信息的输入界面,结果画了一会就觉得烦了,根本没办法用。考虑再三,还是自己写一个。 至少提供如下功能: 1.能够在设计状态用鼠标调整行的行的宽度和列的高度。 2.panel的宽度和高度应该随着里面行和列的高度和宽度的变化而变化。而不应该是像GridPanel,宽度和高度不边,而让行和列的值来适应GridPanel。 3.能方便的增加和删除行和列。 4.放入pane中的控件的宽度要随着所在格子的宽度变化而变化。 开发思路: 1.从TCustomGridPanel继承。 2.在设计状态当鼠标移动到网格线上的时候,Cursor变成可crHSplit和crVSplit,(可以通过继承WMSetCursor来实现) 3.设计状态,当在网按住鼠标并移动的时候,修改对应的格子的大小(可以通过继承WMLButtonDown,WMLButtonUp,和WMMouseMove来实现) 4.当Panel上放入一个控件的时候,自动设置到对应格子的宽度(可以通过继承AlignControls来实现)。 5.增加RowCount和ColumnCount属性,可以通过设置这两个属性来设置行和列的总数。 效果:
可惜,这个GIF无法显示鼠标移动到网格中的时候改变鼠标形状的情况。 DELPHI问题 在写这个panel的时候发现一个问题,可能是DELPHI的BUG 在 ExtCtrls单元第3500行,procedure TCustomGridPanel.AlignControls(AControl: TControl; var Rect: TRect);方法中,代码如下: AnchorSubset := AControl.Anchors * [akLeft, akRight]; if AnchorSubset = [akLeft] then NewBounds.Left := CellRect.Left else if AnchorSubset = [akRight] then NewBounds.Left := Max(CellRect.Left, CellRect.Right - AControl.Margins.ExplicitWidth) else NewBounds.Left := Max(CellRect.Left, CellRect.Left + ((CellRect.Right - CellRect.Left) - AControl.Margins.ControlWidth) div 2); 这个应该是一个明显的BUG,如果Control的Anchors同时设置了akLeft和akRight,则系统就不再处理,也就是前面提到的如果用GridPanel,放到PANEL上的控件无法根据格子的宽度自动调整宽度。 修复方法:增加一个判断就可以: AnchorSubset := AControl.Anchors * [akLeft, akRight]; //hl add 20090415原来控件没有提供对 Anchors = akLeft, akRight的处理 if AnchorSubset = [akLeft, akRight] then begin NewBounds.Left := CellRect.Left; NewBounds.Right := CellRect.Right; end else begin if AnchorSubset = [akLeft] then NewBounds.Left := CellRect.Left else if AnchorSubset = [akRight] then NewBounds.Left := Max(CellRect.Left, CellRect.Right - AControl.Margins.ExplicitWidth) else NewBounds.Left := Max(CellRect.Left, CellRect.Left + ((CellRect.Right - CellRect.Left) - AControl.Margins.ControlWidth) div 2); NewBounds.Right := NewBounds.Left + Min(CellRect.Right - CellRect.Left, AControl.Margins.ExplicitWidth); end; |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论