代码之家  ›  专栏  ›  技术社区  ›  si618

如何在CheckedListbox中选中复选框,但仅在选中复选框时才选中?

  •  2
  • si618  · 技术社区  · 15 年前

    我的第一个想法是处理MouseClick或MouseDown事件,并调用IndexFromPoint来确定单击了哪一行。然后我猜复选框在左边,从x=position从0到ItemRectangle.Height。根据与左侧的距离,我可以选择或选中/取消选中。

    问题是是否有更好的方法来确定鼠标是在复选框上还是在文本上。不同的样式可能有不同大小的复选框,并可能将它们放在左侧、右侧等处。。。

    2 回复  |  直到 15 年前
        1
  •  2
  •   si618    15 年前

    这是我写的,多亏了SLaks,它似乎起了作用。要使用它,CheckOnClick必须为true,CheckInCheckbox也必须为true。从CheckedListbox继承。

    这样做的目的是找出复选框的位置,如果单击在复选框之外,则将checkstate设置为相反的状态。稍后,当基类CheckedListbox收到mouseclick时,它将再次将复选框状态更改回原来的状态。

    Private MyCheckInCheckbox As Boolean = False
    
    ''' <summary>
    ''' Only change the checkbox value when clicking on the box
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property CheckInCheckbox() As Boolean
        Get
            Return MyCheckInCheckbox
        End Get
        Set(ByVal value As Boolean)
            MyCheckInCheckbox = value
        End Set
    End Property
    
    Private Sub MyCheckedListBox_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
        If CheckInCheckbox Then
            Dim border As Integer = 1
            Dim index As Integer = IndexFromPoint(e.Location)
            If index <> ListBox.NoMatches Then
                Dim bounds As Rectangle = Me.GetItemRectangle(index)
                Dim idealCheckSize As Integer
                If Application.RenderWithVisualStyles Then
                    Dim cbState As VisualStyles.CheckBoxState
                    Select Case Me.GetItemCheckState(index)
                        Case CheckState.Checked
                            cbState = VisualStyles.CheckBoxState.CheckedNormal
                        Case CheckState.Indeterminate
                            cbState = VisualStyles.CheckBoxState.MixedNormal
                        Case CheckState.Unchecked
                            cbState = VisualStyles.CheckBoxState.UncheckedNormal
                    End Select
                    Dim g As Graphics = Me.CreateGraphics
                    idealCheckSize = CheckBoxRenderer.GetGlyphSize(g, cbState).Width
                    g.Dispose()
                End If
                Dim centeringFactor As Integer = Math.Max((bounds.Height - idealCheckSize) \ 2, 0)
                If centeringFactor + idealCheckSize > bounds.Height Then
                    centeringFactor = bounds.Height - idealCheckSize
                End If
                Dim box As Rectangle = New Rectangle(bounds.X + border, bounds.Y + centeringFactor, idealCheckSize, idealCheckSize)
                If RightToLeft = Windows.Forms.RightToLeft.Yes Then
                    box.X = bounds.X + bounds.Width - idealCheckSize - border
                End If
                If Not box.Contains(e.Location) Then
                    Me.SelectedIndex = index
                    SetItemChecked(index, Not GetItemChecked(index))
                End If
            End If
        End If
    End Sub
    
        2
  •  1
  •   SLaks    15 年前

    下面是绘制复选框的实际代码(来自.Net参考源代码),位于 DrawItem 活动:

    Rectangle bounds = e.Bounds;
    int border = 1; 
    int height = Font.Height + 2 * border;
    
    // set up the appearance of the checkbox 
    // [Snip]
    
    // If we are drawing themed CheckBox .. get the size from renderer.. 
    // the Renderer might return a different size in different DPI modes.. 
    if (Application.RenderWithVisualStyles) {
       VisualStyles.CheckBoxState cbState = CheckBoxRenderer.ConvertFromButtonState(state, false, ((e.State & DrawItemState.HotLight) == DrawItemState.HotLight)); 
       idealCheckSize = (int)(CheckBoxRenderer.GetGlyphSize(e.Graphics, cbState)).Width;
    }
    
    // Determine bounds for the checkbox 
    //
    int centeringFactor = Math.Max((height - idealCheckSize) / 2, 0); 
    
    // Keep the checkbox within the item's upper and lower bounds
    if (centeringFactor + idealCheckSize > bounds.Height) { 
        centeringFactor = bounds.Height - idealCheckSize;
    }
    
    Rectangle box = new Rectangle(bounds.X + border, 
                                  bounds.Y + centeringFactor,
                                  idealCheckSize, 
                                  idealCheckSize); 
    
    if (RightToLeft == RightToLeft.Yes) { 
        // For a RightToLeft checked list box, we want the checkbox
        // to be drawn at the right.
        // So we override the X position.
        box.X = bounds.X + bounds.Width - idealCheckSize - border; 
    }
    
    // Draw the checkbox. 
    //
    if (Application.RenderWithVisualStyles) {
        VisualStyles.CheckBoxState cbState = CheckBoxRenderer.ConvertFromButtonState(state, false, ((e.State & DrawItemState.HotLight) == DrawItemState.HotLight));
        CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(box.X, box.Y), cbState); 
    }
    else { 
        ControlPaint.DrawCheckBox(e.Graphics, box, state); 
    }
    

    编辑 CheckBoxRenderer.ConvertFromButtonState :

    internal static CheckBoxState ConvertFromButtonState(ButtonState state, bool isMixed, bool isHot) { 
       if (isMixed) {
           if ((state & ButtonState.Pushed) == ButtonState.Pushed) {
               return CheckBoxState.MixedPressed;
           } 
           else if ((state & ButtonState.Inactive) == ButtonState.Inactive) {
               return CheckBoxState.MixedDisabled; 
           } 
           else if (isHot) {
               return CheckBoxState.MixedHot; 
           }
    
           return CheckBoxState.MixedNormal;
       } 
       else if ((state & ButtonState.Checked) == ButtonState.Checked) {
           if ((state & ButtonState.Pushed) == ButtonState.Pushed) { 
               return CheckBoxState.CheckedPressed; 
           }
           else if ((state & ButtonState.Inactive) == ButtonState.Inactive) { 
               return CheckBoxState.CheckedDisabled;
           }
           else if (isHot) {
               return CheckBoxState.CheckedHot; 
           }
    
           return CheckBoxState.CheckedNormal; 
       }
       else { //unchecked 
           if ((state & ButtonState.Pushed) == ButtonState.Pushed) {
               return CheckBoxState.UncheckedPressed;
           }
           else if ((state & ButtonState.Inactive) == ButtonState.Inactive) { 
               return CheckBoxState.UncheckedDisabled;
           } 
           else if (isHot) { 
               return CheckBoxState.UncheckedHot;
           } 
    
           return CheckBoxState.UncheckedNormal;
       }
    

    }