3

CheckedListBox があります。テキストをクリックするとアイテムを選択できるようにしたいのですが、左側のチェックボックス領域をクリックするとチェック/チェックを外します。CheckOnClick を設定すると、テキスト上であっても、クリックするたびにアイテムがチェックされたりチェックされなくなったりするので、それは良くありません。しかし、CheckOnClick をクリアすると、2 回クリックしてチェックを入れたり外したりしなければなりません。

私が最初に考えたのは、MouseClick または MouseDown イベントを処理し、IndexFromPoint を呼び出して、どの行がクリックされたかを調べることです。次に、チェックボックスが x=position から 0 まで、たとえば ItemRectangle.Height の左側にあると推測します。左からの距離に応じて、選択またはチェック/チェック解除できます。

問題は、マウスがチェックボックス上にあるかテキスト上にあるかを判断するより良い方法があるかどうかです。スタイルが異なればチェックボックスのサイズも異なり、左、右などに配置することもできます...

4

2 に答える 2

2

私はこれを書きました、そしてそれはSLaksのおかげでうまくいくようです。これを使用するには、CheckOnClickがtrueであり、CheckInCheckboxもtrueである必要があります。CheckedListboxから継承します。

チェックボックスがどこにあるかを把握し、クリックがチェックボックスの外側にある場合は、チェック状態を反対に設定するという考え方です。後で、基本クラスであるCheckedListboxがマウスクリックを受信すると、チェックボックスの状態が元の状態に戻ります。

状態を前後に変更する少しハッキーですが、CheckedListboxがSelectedIndexを使用してチェック/チェック解除する方法を回避する他の方法を見つけることができませんでした。これも一種のハックです。

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
于 2009-12-10T13:34:28.903 に答える
1

DrawItemイベントでチェックボックスを描画する実際のコード(.Net参照ソースから)は次のとおりです。

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;
   }

}

于 2009-12-10T00:12:27.073 に答える