在UserControl上放一个CheckBox,名称为chk.一个Label,名称为lbl,index为0.一个TextBox,名称为txt,index为0.
控件的功能是想实现一个CheckTextBox,有多个Label和多个TextBox.其中有一个属性为Rows.设计时正常。把Rows属性设为3
运行时,设置端点后,发现先运行UserControl_Initialize,接下来是UserControl_WriteProperties,
在UserControl_WriteProperties事件的End Sub代码上设置端点,监测m_Rows的值为3,按F8,代码跳到
UserControl_Resize事件,这时候监测m_Rows的值突然变为0了。导致程序出错。代码如下
Option Explicit
'自定义常量
Const TOP_MERGIN = 0
Const BOTTOM_MERGIN = 24
Const HEIGHT_GAP = 0
Const WIDTH_GAP = 24
'缺省值属性常量
Const m_def_Caption = "CheckTextBox"
Const m_def_DataFormat = "XXXX"
Const m_def_ControlCode = "00"
Const m_def_FlagCode = "0000"
Const m_def_ReadOnly = False
Const m_def_TextBoxWidth = 1000
Const m_def_LabelForeColor = vbBlack
Const m_def_TextBoxBackColor = vbWhite
Const m_def_TextBoxForeColor = vbBlack
Const m_def_BackColorStart = &HC0C0FF
Const m_def_BackColorEnd = &HC0C0FF
Const m_def_Rows = 1
Const m_def_MaxRow = 255
'属性变量
Dim m_Caption As String
Dim m_DataFormat As String
Dim m_ControlCode As String
Dim m_FlagCode As String
Dim m_ReadOnly As Boolean
Dim m_TextBoxWidth As Long
Dim m_LabelForeColor As OLE_COLOR
Dim m_LabelFont As Font
Dim m_TextBoxBackColor As OLE_COLOR
Dim m_TextBoxForeColor As OLE_COLOR
Dim m_Font As Font
Dim m_BackColorStart As OLE_COLOR
Dim m_BackColorEnd As OLE_COLOR
Dim m_Rows As Long
Dim m_MaxRow As Long

解决方案 »

  1.   

    '防止在调整布局时重复发生Control_Resize事件
    Private isProcessCurResizeEnd As Boolean
    '是否选择
    Public Property Get Value() As CheckBoxConstants
        Value = chk.Value
    End Property
    Public Property Let Value(ByVal New_Value As CheckBoxConstants)
        chk.Value() = New_Value
        PropertyChanged "Value"
    End Property
    '标题组
    Public Property Get Caption() As String
        Caption = m_Caption
    End Property
    Public Property Let Caption(ByVal New_Caption As String)
        m_Caption = New_Caption
        PropertyChanged "Caption"
    End Property
    '格式组
    Public Property Get DataFormat() As String
        DataFormat = m_DataFormat
    End Property
    Public Property Let DataFormat(ByVal New_DataFormat As String)
        m_DataFormat = New_DataFormat
        PropertyChanged "DataFormat"
    End Property
    '控制码
    Public Property Get ControlCode() As String
        ControlCode = m_ControlCode
    End Property
    Public Property Let ControlCode(ByVal New_ControlCode As String)
        m_ControlCode = New_ControlCode
        PropertyChanged "ControlCode"
    End Property
    '标识码
    Public Property Get FlagCode() As String
        FlagCode = m_FlagCode
    End Property
    Public Property Let FlagCode(ByVal New_FlagCode As String)
        m_FlagCode = New_FlagCode
        PropertyChanged "FlagCode"
    End Property
    '是否只读
    Public Property Get ReadOnly() As Boolean
        ReadOnly = m_ReadOnly
    End Property
    Public Property Let ReadOnly(ByVal New_ReadOnly As Boolean)
        m_ReadOnly = New_ReadOnly
        PropertyChanged "ReadOnly"
    End Property
    '文本框部分宽度
    Public Property Get TextBoxWidth() As Long
        TextBoxWidth = m_TextBoxWidth
    End Property
    Public Property Let TextBoxWidth(ByVal New_TextBoxWidth As Long)
        m_TextBoxWidth = New_TextBoxWidth
        PropertyChanged "TextBoxWidth"
    End Property
    '标题部分前景色
    Public Property Get LabelForeColor() As OLE_COLOR
        LabelForeColor = m_LabelForeColor
    End Property
    Public Property Let LabelForeColor(ByVal New_LabelForeColor As OLE_COLOR)
        m_LabelForeColor = New_LabelForeColor
        PropertyChanged "LabelForeColor"
    End Property
    '文本框部分背景色
    Public Property Get TextBoxBackColor() As OLE_COLOR
        TextBoxBackColor = m_TextBoxBackColor
    End Property
    Public Property Let TextBoxBackColor(ByVal New_TextBoxBackColor As OLE_COLOR)
        m_TextBoxBackColor = New_TextBoxBackColor
        PropertyChanged "TextBoxBackColor"
    End Property
    '文本框部分前景色
    Public Property Get TextBoxForeColor() As OLE_COLOR
        TextBoxForeColor = m_TextBoxForeColor
    End Property
    Public Property Let TextBoxForeColor(ByVal New_TextBoxForeColor As OLE_COLOR)
        m_TextBoxForeColor = New_TextBoxForeColor
        PropertyChanged "TextBoxForeColor"
    End Property
    '字体(需要重新调整布局)
    Public Property Get Font() As Font
        Set Font = m_Font
    End Property
    Public Property Set Font(ByVal New_Font As Font)
        Set m_Font = New_Font
        PropertyChanged "Font"
    End Property
    '控件背景开始颜色
    Public Property Get BackColorStart() As OLE_COLOR
        BackColorStart = m_BackColorStart
    End Property
    Public Property Let BackColorStart(ByVal New_BackColorStart As OLE_COLOR)
        m_BackColorStart = New_BackColorStart
        PropertyChanged "BackColorStart"
    End Property
    '控件背景开始颜色
    Public Property Get BackColorEnd() As OLE_COLOR
        BackColorEnd = m_BackColorEnd
    End Property
    Public Property Let BackColorEnd(ByVal New_BackColorEnd As OLE_COLOR)
        m_BackColorEnd = New_BackColorEnd
        PropertyChanged "BackColorEnd"
    End Property
    '当前行数(需要重新调整布局)
    Public Property Get Rows() As Long
        Rows = m_Rows
    End Property
    Public Property Let Rows(ByVal New_Rows As Long)
        '检查合法性
        If (New_Rows > m_MaxRow) Or (New_Rows < 1) Then
            Exit Property
        End If
        
        Call SetLayout(New_Rows)
        
        m_Rows = New_Rows
        PropertyChanged "Rows"
    End Property
    '最大行数
    Public Property Get MaxRow() As Long
        MaxRow = m_MaxRow
    End Property
    Public Property Let MaxRow(ByVal New_MaxRow As Long)
        If New_MaxRow > m_def_MaxRow Then
            Exit Property
        End If
        m_MaxRow = New_MaxRow
        PropertyChanged "MaxRow"
    End Property
      

  2.   

    Private Sub UserControl_Initialize()
        '可以触发resize事件
        isProcessCurResizeEnd = True
    End Sub'控件初始化
    Private Sub UserControl_InitProperties()
        m_Caption = m_def_Caption
        m_DataFormat = m_def_DataFormat
        m_ControlCode = m_def_ControlCode
        m_FlagCode = m_def_FlagCode
        m_ReadOnly = m_def_ReadOnly
        m_TextBoxWidth = m_def_TextBoxWidth
        m_LabelForeColor = m_def_LabelForeColor
        Set m_Font = Ambient.Font
        m_TextBoxBackColor = m_def_TextBoxBackColor
        m_TextBoxForeColor = m_def_TextBoxForeColor
        m_BackColorStart = m_def_BackColorStart
        m_BackColorEnd = m_def_BackColorEnd
        m_Rows = m_def_Rows
        m_MaxRow = m_def_MaxRow
        
    End Sub
    '从存储器加载属性值
    Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
        chk.Value = PropBag.ReadProperty("Value", 0)
        m_Caption = PropBag.ReadProperty("Caption", m_def_Caption)
        m_DataFormat = PropBag.ReadProperty("DataFormat", m_def_DataFormat)
        m_ControlCode = PropBag.ReadProperty("ControlCode", m_def_ControlCode)
        m_FlagCode = PropBag.ReadProperty("FlagCode", m_def_FlagCode)
        m_ReadOnly = PropBag.ReadProperty("ReadOnly", m_def_ReadOnly)
        m_TextBoxWidth = PropBag.ReadProperty("TextBoxWidth", m_def_TextBoxWidth)
        m_LabelForeColor = PropBag.ReadProperty("LabelForeColor", m_def_LabelForeColor)
        Set m_Font = PropBag.ReadProperty("Font", Ambient.Font)
        m_TextBoxBackColor = PropBag.ReadProperty("TextBoxBackColor", m_def_TextBoxBackColor)
        m_TextBoxForeColor = PropBag.ReadProperty("TextBoxForeColor", m_def_TextBoxForeColor)
        m_BackColorStart = PropBag.ReadProperty("BackColorStart", m_def_BackColorStart)
        m_BackColorEnd = PropBag.ReadProperty("BackColorEnd", m_def_BackColorEnd)
        m_Rows = PropBag.ReadProperty("Rows", m_def_Rows)
        m_MaxRow = PropBag.ReadProperty("MaxRow", m_def_MaxRow)
    End Sub
    '保存属性值到存储器中
    Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
        Call PropBag.WriteProperty("Value", chk.Value, 0)
        Call PropBag.WriteProperty("Caption", m_Caption, m_def_Caption)
        Call PropBag.WriteProperty("DataFormat", m_DataFormat, m_def_DataFormat)
        Call PropBag.WriteProperty("ControlCode", m_ControlCode, m_def_ControlCode)
        Call PropBag.WriteProperty("FlagCode", m_FlagCode, m_def_FlagCode)
        Call PropBag.WriteProperty("ReadOnly", m_ReadOnly, m_def_ReadOnly)
        Call PropBag.WriteProperty("TextBoxWidth", m_TextBoxWidth, m_def_TextBoxWidth)
        Call PropBag.WriteProperty("LabelForeColor", m_LabelForeColor, m_def_LabelForeColor)
        Call PropBag.WriteProperty("Font", m_Font, Ambient.Font)
        Call PropBag.WriteProperty("TextBoxBackColor", m_TextBoxBackColor, m_def_TextBoxBackColor)
        Call PropBag.WriteProperty("TextBoxForeColor", m_TextBoxForeColor, m_def_TextBoxForeColor)
        Call PropBag.WriteProperty("BackColorStart", m_BackColorStart, m_def_BackColorStart)
        Call PropBag.WriteProperty("BackColorEnd", m_BackColorEnd, m_def_BackColorEnd)
        Call PropBag.WriteProperty("Rows", m_Rows, m_def_Rows)
        Call PropBag.WriteProperty("MaxRow", m_MaxRow, m_def_MaxRow)
    End Sub
    '控件大小发生变化
    Private Sub UserControl_Resize()
        If Not isProcessCurResizeEnd Then Exit Sub
        Call SetLayout(m_Rows)
    End Sub
    '加载控件数组,如果Rows变小了,则要卸载控件数组
    Private Sub SetLayout(CurRows As Long)
        Dim i As Long
        '加载控件
        If CurRows > txt.Count Then
            For i = txt.Count To CurRows - 1
                Load lbl(i): lbl(i).Visible = True
                Load txt(i): txt(i).Visible = True
            Next i
        '卸载控件
        ElseIf CurRows < txt.Count Then
            For i = txt.Count - 1 To CurRows Step -1
                Unload lbl(i)
                Unload txt(i)
            Next i
        End If
        '调整位置,由于SetPostion中代码会触发UserControl_Resize事件,因此设置标志
        isProcessCurResizeEnd = False
        Call SetPostion(CurRows)
        isProcessCurResizeEnd = True
    End Sub
    ''调整位置
    Private Sub SetPostion(CurRows As Long)
        Dim i As Long
        Dim maxLblWidth As Long
        Dim MinCtlWidth As Long
        
        For i = 0 To CurRows - 1
            If maxLblWidth < lbl(i).Width Then
                maxLblWidth = lbl(i).Width
            End If
        Next i
        MinCtlWidth = chk.Width + maxLblWidth + txt(0).Width + WIDTH_GAP * 3
        
        '设置usercontrol高度,宽度最后根据标题长度再设置
        UserControl.Height = txt(0).Height * txt.Count + (txt.Count - 1) * HEIGHT_GAP + TOP_MERGIN + BOTTOM_MERGIN
        If UserControl.Width < MinCtlWidth Then UserControl.Width = MinCtlWidth
        '设置文本框位置
        For i = 0 To txt.Count - 1
            txt(i).Left = UserControl.Width - WIDTH_GAP - txt(0).Width
            txt(i).Top = TOP_MERGIN + (txt(0).Height + HEIGHT_GAP) * i
        Next i
        '设置label的位置
        For i = 0 To lbl.Count - 1
            lbl(i).Left = txt(i).Left - WIDTH_GAP - lbl(i).Width
            lbl(i).Top = txt(i).Top + 45
        Next i
    End Sub