












麻烦的线线框框
环境:
vs2005+ActiveReportsNet2
本节代码:https://files.cnblogs.com/batoosai/SimpleExample11.rar
在我使用AR的过程当中,碰到最大的困难,不是数据的组织(虽然也很麻烦),而是画面的布局,尤其是一些奇怪的线线框框,常常会为了一些特殊的线框要求,浪费很多时间调试。
本节我就把在项目的碰到的一些常见框线问题,简单的进行一下分析。
1,帐票式样,还是上节那张帐票。
该帐票的框线要求是:3个sub模版的四周要求粗线;Detail中的纪录,要求每5行为粗线。

2,对于一个textbox或label等控件,初始状态是没有边框的(就像图中的”成绩一览表”这个控件),为控件提供边框,一般有2种方法。
1)给控件设置border(right click控件,选border),这样可以很方便的给控件设置4条边框。
当然,也可以代码中控制:
'Set four borders.
Me.TextBox3.Border.Style = BorderLineStyle.Solid'Set the top border.
Me.TextBox3.Border.TopStyle = BorderLineStyle.Solid
style可以设置成虚线,实线等。粗细有普通,2倍,4倍像素(仅适用于实线)
2)给控件四周手动画4条line。
你可以直接在rpt画面上画上4条线,然后在界面或代码中控制他们的位置。
当然,你也可以在代码中直接动态生成4条line
方法1)的好处是方便,而且一样可以在代码中做控制(比如加粗top line,隐藏right line等);但同时也有一点局限性比如框线的粗细设定不够灵活(只能1,2,4倍),对于有严格规定的帐票,并不适用,而且当控件比较多的话,给每个控件设置border也是挺麻烦的。
方法2)的好处是很灵活,同时可以写个共通方法,对整个section内的控件一次性画线。缺点是稍微麻烦了点。
用哪种方法可以根据实际情况,图中,右上角的教师承认栏肯定是用方法1)简单,而下面数据区域一般用方法2),这样比较容易控制框线。
3先确定一些概念。
1)整个rpt上,不管是section、控件的位置,高宽,还是实际打印的printWidth都是用Inch(英寸)为单位;
而line的weight和控件border的粗细,确是以pixels为单位的
2)不管是画线,还是直接调整控件的border,框线的粗细都是以中点为基点,向2边扩张或缩小的,如图:

这样就会产生一个问题,如图:

用的是方法1),由于border向2边扩张,所以产生了字和框线重叠的问题。这在控件比较小,而框线特别粗的情况下会发生。
为了解决这个问题,我们有一种偏移控件的方法:
用方法2),把线画在控件的外面,比如要在控件top上画一条4单位宽的线,则就在控件上2单位高度的地方画线,这条线会向上和向下各扩张2单位,这样,线的下部正好和控件的顶部碰到,而又不会发生重叠的现象。当然,用这种方法的话,需要控制好控件之间的间距,否则2个控件之间的框线会互相重叠。
恩,我在这里仅仅提供一个思路,具体怎么做自己可以实践一下。我下面的示例没有用这种偏移控件的方法,只是简单的在控件上画线而已。
4,改造example10,改成方法2)画线(直接在控件上画线了,没有去设置控件的偏移)
先把sub1,sub2,sub3上面控件的border都去掉,然后再代码中动态生成line(示例代码为sub1.vb)
Private secGroupHeader1 As SectionLinesPrivate secGroupHeader2 As SectionLinesPrivate secDetail As SectionLinesPublic Structure SectionLinesPublic TopLine As LinePublic BottomLine As LinePublic LeftLine As LinePublic RightLine As LineEnd StructurePrivate Sub sub1_ReportStart(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ReportStart'
'
Me.secGroupHeader1 = Me.DrawLine(Me.GroupHeader1, New ARControl() {Me.lbl1})Me.secGroupHeader2 = Me.DrawLine(Me.GroupHeader1, New ARControl() {Me.lblID, Me.lblName})Me.DrawLine(Me.Detail, New ARControl() {Me.txtID, Me.txtName})'
'
End Sub''' <summary>
''' 對一排控件進行集体画綫,不在同一排上的控件,不能一起画
''' </summary>
''' <param name="section">The section.</param>
''' <param name="controls">The controls.</param>
''' <param name="outlineBorderWeight">外框的粗細.</param>
''' <param name="inlineBorderWeight">内框的粗細.</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function DrawLine(ByVal section As Section, ByVal outlineBorderWeight As Single, ByVal inlineBorderWeight As Single, ByVal controls As ARControl()) As SectionLinesIf controls Is Nothing OrElse controls.Length = 0 ThenReturn NothingEnd IfDim sec As New SectionLinesDim ln As LineDim controlsNum As Int32 = controls.Length'画第一个控件到倒数第2个控件的右綫
For iForControls As Int32 = 0 To controlsNum - 2'Right line
ln = New Line
ln.LineWeight
= inlineBorderWeightln.BringToFront()
section.Controls.Add(ln)
With ln.X1
= controls(iForControls).Left + controls(iForControls).Width.Y1
= controls(iForControls).Top.X2
= .X1.Y2
= controls(iForControls).Top + controls(iForControls).HeightEnd WithNext'画所有控件的top綫ln.LineWeight
= outlineBorderWeightln.BringToFront()
section.Controls.Add(ln)
With ln'x1和x2要増加偏移量.Y1
= controls(0).Top.X2
= controls(controlsNum - 1).Left + controls(controlsNum - 1).Width + 0.007F * outlineBorderWeight / 2.Y2
= .Y1End Withsec.TopLine
= ln'画所有控件的bottom綫ln.LineWeight
= outlineBorderWeightln.BringToFront()
section.Controls.Add(ln)
With ln'x1和x2要増加偏移量.Y1
= controls(0).Top + controls(0).Height.X2
= controls(controlsNum - 1).Left + controls(controlsNum - 1).Width + 0.007F * outlineBorderWeight / 2.Y2
= .Y1End Withsec.BottomLine
= ln'画最左面的left綫ln.LineWeight
= outlineBorderWeightln.BringToFront()
section.Controls.Add(ln)
With ln.X1
= controls(0).Left.Y1
= controls(0).Top - 0.007F * outlineBorderWeight / 2.X2
= .X1.Y2
= controls(0).Top + controls(0).Height + 0.007F * outlineBorderWeight / 2End Withsec.LeftLine
= ln'画最右面的right綫ln.LineWeight
= outlineBorderWeightln.BringToFront()
section.Controls.Add(ln)
With ln.X1
= controls(controlsNum - 1).Left + controls(controlsNum - 1).Width.Y1
= controls(controlsNum - 1).Top - 0.007F * outlineBorderWeight / 2.X2
= .X1.Y2
= controls(controlsNum - 1).Top + controls(controlsNum - 1).Height + 0.007F * outlineBorderWeight / 2End Withsec.RightLine
= lnReturn secEnd Function其中SectionLines 结构和DrawLine方法可以写成共通的,sub1,sub2,sub3都会用到.
这里定义一个SectionLines的用途是,可以对返回的四根线进行处理。

ok,效果是一样的
5,在DrawLine方法中,已经实现了最外面的框线用粗线,里面的框线用细线。
由于刚才定义了结构SectionLines,把画好的线返回给了它,所以要控制线条,就很方便了。
比如sub1的GroupHeader中,”科目”的bottom线和”番号””氏名”的top线是粗线,实际需要变成细线,这种效果都可以在代码中通过SectionLines控制,代码:
Me.secGroupHeader1.BottomLine.LineWeight = 1Me.secGroupHeader2.TopLine.LineWeight = 1
看看效果:

仔细看的话,会发现groupheader的bottom line 的确变粗了,但其他3根线比较奇怪,虽然向内也变粗了,但向外却没变粗。
这是由于我们主模版上sub1的容器设定的宽度,正好是子模版里“科目”控件的宽度,而我现在的画线方法是在控件的边上画线,线条有一半的粗细被遮掉了。
解决方法:子模版中,控件left,top,预留线粗的一半距离,然后把整个子模版的ReportWidth加上线粗的偏移量。1单位的线粗,转换到Inch是0.007。改动的代码如下:
Private Sub sub1_ReportStart(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ReportStart'
'
Me.lbl1.Left = 0.007Me.lbl1.Top = 0.007Me.PrintWidth = Me.lblName.Left + Me.lblName.Width +0.007FMe.Detail.Height = Me.txtID.Top + Me.txtID.Height + 0.007F'
'
End SubPublic ReadOnly Property ReportWidth() As SingleGetReturn Me.txtID.Width + Me.txtName.Width + 0.007FEnd GetEnd Property
效果:

由于bottom和right和其他区域控件的线重叠了,所以看上去比较粗,可以把其他线隐藏掉(比如把sub2的left 线隐藏掉)
然后,用相同的方法弄好sub1的detail,以及sub2,sub3。出来这样的效果:

6,整个帐票top,left,right的粗线画好了,现在有个需求是detail中每5行画一条粗线。
直接给detail中控件的bottom画粗线当然不可以,那会使得detail中每一行都变成粗线。
我们项目中的做法是:
1)在组织数据源时,为数据源增加一个字段,用来判断改行是印刷粗线还是细线。
比如sub1的数据源
|
番号 |
氏名 |
|
1 |
Tony |
|
2 |
Zhu |
|
3 |
Li |
|
4 |
Zhang |
|
5 |
Zha |
|
6 |
Sun |
增加一个字段,变成:
|
番号 |
氏名 |
LineFlag |
|
1 |
Tony |
0 |
|
2 |
Zhu |
0 |
|
3 |
Li |
0 |
|
4 |
Zhang |
0 |
|
5 |
Zha |
1 |
|
6 |
Sun |
1 |
5的这一行印刷粗线,6由于是最后一行了,也要印刷粗线。
2)数据源有了这个字段,然后在detail中放一个隐藏的textbox,邦定LineFlag

3)Detail_BeforePrint事件中根据lineflag的值,来判断是否要把该Detail下的控件的bottom线变粗
Private Sub Detail_BeforePrint(ByVal sender As Object, ByVal e As System.EventArgs) Handles Detail.BeforePrintIf Me.txtLineFlag.Text = "1" ThenMe.secDetail.BottomLine.LineWeight = 2End IfEnd Sub
4)最后的效果

7,这节就讲到这里。
AR里线框的处理的确很麻烦。
不过在我们项目中,像DrawLine这种方法,以及5行粗线的方法,都做好了共通方法。而且大部分功能都写在了基类里,对于开发帐票的同学来说,只管调用方法就可以了,具体这些个方法是怎么实现的,可以不用理睬。当然,为了更深的理解,有空也可以研究一下。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。