Tony Gong的技术Blog  
技术旅途中蹒跚的行者

麻烦的线线框框

 

环境:

vs2005+ActiveReportsNet2

本节代码:https://files.cnblogs.com/batoosai/SimpleExample11.rar

 

在我使用AR的过程当中,碰到最大的困难,不是数据的组织(虽然也很麻烦),而是画面的布局,尤其是一些奇怪的线线框框,常常会为了一些特殊的线框要求,浪费很多时间调试。

本节我就把在项目的碰到的一些常见框线问题,简单的进行一下分析。

 

1,帐票式样,还是上节那张帐票。

该帐票的框线要求是:3sub模版的四周要求粗线;Detail中的纪录,要求每5行为粗线。

2,对于一个textboxlabel等控件,初始状态是没有边框的(就像图中的成绩一览表这个控件),为控件提供边框,一般有2种方法。

    1)给控件设置borderright 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)给控件四周手动画4line

       你可以直接在rpt画面上画上4条线,然后在界面或代码中控制他们的位置。

              当然,你也可以在代码中直接动态生成4line

 

       方法1)的好处是方便,而且一样可以在代码中做控制(比如加粗top line,隐藏right line等);但同时也有一点局限性比如框线的粗细设定不够灵活(只能124倍),对于有严格规定的帐票,并不适用,而且当控件比较多的话,给每个控件设置border也是挺麻烦的。

       方法2)的好处是很灵活,同时可以写个共通方法,对整个section内的控件一次性画线。缺点是稍微麻烦了点。

用哪种方法可以根据实际情况,图中,右上角的教师承认栏肯定是用方法1)简单,而下面数据区域一般用方法2),这样比较容易控制框线。

 

3先确定一些概念。

       1)整个rpt上,不管是section、控件的位置,高宽,还是实际打印的printWidth都是用Inch(英寸)为单位;

       lineweight和控件border的粗细,确是以pixels为单位的

       2)不管是画线,还是直接调整控件的border,框线的粗细都是以中点为基点,向2边扩张或缩小的,如图:


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


用的是方法1),由于border2边扩张,所以产生了字和框线重叠的问题。这在控件比较小,而框线特别粗的情况下会发生。

为了解决这个问题,我们有一种偏移控件的方法:

用方法2),把线画在控件的外面,比如要在控件top上画一条4单位宽的线,则就在控件上2单位高度的地方画线,这条线会向上和向下各扩张2单位,这样,线的下部正好和控件的顶部碰到,而又不会发生重叠的现象。当然,用这种方法的话,需要控制好控件之间的间距,否则2个控件之间的框线会互相重叠。

 

恩,我在这里仅仅提供一个思路,具体怎么做自己可以实践一下。我下面的示例没有用这种偏移控件的方法,只是简单的在控件上画线而已。

4,改造example10,改成方法2)画线(直接在控件上画线了,没有去设置控件的偏移)

先把sub1,sub2,sub3上面控件的border都去掉,然后再代码中动态生成line(示例代码为sub1.vb

    Private secGroupHeader1 As SectionLines

    
Private secGroupHeader2 As SectionLines

    
Private secDetail As SectionLines

 

    
Public Structure SectionLines

        
Public TopLine As Line

        
Public BottomLine As Line

        
Public LeftLine As Line

        
Public RightLine As Line

    
End Structure

 

    
Private Sub sub1_ReportStart(ByVal sender As ObjectByVal 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 SingleByVal inlineBorderWeight As SingleByVal controls As ARControl()) As SectionLines

        
If controls Is Nothing OrElse controls.Length = 0 Then

            
Return Nothing

        
End If

 

        
Dim sec As New SectionLines

        
Dim ln As Line

 

        
Dim controlsNum As Int32 = controls.Length

        
'画第一个控件到倒数第2个控件的右綫

        
For iForControls As Int32 = 0 To controlsNum - 2

            
'Right line

            ln 
= New Line

            ln.LineWeight 
= inlineBorderWeight

            ln.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).Height

            
End With

        
Next

 

        
'画所有控件的top綫

        
'Top line

        ln 
= New Line

        ln.LineWeight 
= outlineBorderWeight

        ln.BringToFront()

        section.Controls.Add(ln)

        
With ln

            
'x1和x2要増加偏移量

            .X1 
= controls(0).Left - 0.007F * outlineBorderWeight / 2

            .Y1 
= controls(0).Top

            .X2 
= controls(controlsNum - 1).Left + controls(controlsNum - 1).Width + 0.007F * outlineBorderWeight / 2

            .Y2 
= .Y1

        
End With

        sec.TopLine 
= ln

 

        
'画所有控件的bottom綫

        ln 
= New Line

        ln.LineWeight 
= outlineBorderWeight

        ln.BringToFront()

        section.Controls.Add(ln)

        
With ln

            
'x1和x2要増加偏移量

            .X1 
= controls(0).Left - 0.007F * outlineBorderWeight / 2

            .Y1 
= controls(0).Top + controls(0).Height

            .X2 
= controls(controlsNum - 1).Left + controls(controlsNum - 1).Width + 0.007F * outlineBorderWeight / 2

            .Y2 
= .Y1

        
End With

        sec.BottomLine 
= ln

 

        
'画最左面的left綫

        
'Left line

        ln 
= New Line

        ln.LineWeight 
= outlineBorderWeight

        ln.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 / 2

        
End With

        sec.LeftLine 
= ln

 

        
'画最右面的right綫

        
'Right line

        ln 
= New Line

        ln.LineWeight 
= outlineBorderWeight

        ln.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 / 2

        
End With

        sec.RightLine 
= ln

 

        
Return sec

End Function

其中SectionLines 结构和DrawLine方法可以写成共通的,sub1,sub2,sub3都会用到.

这里定义一个SectionLines的用途是,可以对返回的四根线进行处理。


ok,效果是一样的

 

5,在DrawLine方法中,已经实现了最外面的框线用粗线,里面的框线用细线。

由于刚才定义了结构SectionLines,把画好的线返回给了它,所以要控制线条,就很方便了。

比如sub1GroupHeader中,科目bottom线和番号””氏名top线是粗线,实际需要变成细线,这种效果都可以在代码中通过SectionLines控制,代码:

        Me.secGroupHeader1.BottomLine.LineWeight = 1

        
Me.secGroupHeader2.TopLine.LineWeight = 1

看看效果:


仔细看的话,会发现groupheaderbottom line 的确变粗了,但其他3根线比较奇怪,虽然向内也变粗了,但向外却没变粗。

这是由于我们主模版上sub1的容器设定的宽度,正好是子模版里“科目”控件的宽度,而我现在的画线方法是在控件的边上画线,线条有一半的粗细被遮掉了。

解决方法:子模版中,控件left,top,预留线粗的一半距离,然后把整个子模版的ReportWidth加上线粗的偏移量。1单位的线粗,转换到Inch0.007。改动的代码如下:

    Private Sub sub1_ReportStart(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.ReportStart

 

       
'

       
'

 

        
Me.lbl1.Left = 0.007

        
Me.lbl1.Top = 0.007

Me.PrintWidth = Me.lblName.Left + Me.lblName.Width +0.007F

 

        
Me.Detail.Height = Me.txtID.Top + Me.txtID.Height + 0.007F

       
'

       
'

     
End Sub

 

    
Public ReadOnly Property ReportWidth() As Single

        
Get

            
Return Me.txtID.Width + Me.txtName.Width + 0.007F

        
End Get

End Property

效果:


由于bottomright和其他区域控件的线重叠了,所以看上去比较粗,可以把其他线隐藏掉(比如把sub2left 线隐藏掉)

 

然后,用相同的方法弄好sub1detail,以及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


       3Detail_BeforePrint事件中根据lineflag的值,来判断是否要把该Detail下的控件的bottom线变粗

    Private Sub Detail_BeforePrint(ByVal sender As ObjectByVal e As System.EventArgs) Handles Detail.BeforePrint

        
If Me.txtLineFlag.Text = "1" Then

            
Me.secDetail.BottomLine.LineWeight = 2

        
End If

    
End Sub

 

 

4)最后的效果

 

 

7,这节就讲到这里。

AR里线框的处理的确很麻烦。

不过在我们项目中,像DrawLine这种方法,以及5行粗线的方法,都做好了共通方法。而且大部分功能都写在了基类里,对于开发帐票的同学来说,只管调用方法就可以了,具体这些个方法是怎么实现的,可以不用理睬。当然,为了更深的理解,有空也可以研究一下。

posted on 2007-03-07 11:57  Tony.Gong  阅读(5660)  评论(23编辑  收藏  举报