1

Is it possible to use an image as the checkbox "checked" indicator square?

I know I can use a background image, but that goes behind the label aswell and also it is not possible (as far as I know) to align it.

How can I use an image instead of the square and leave the label and all other customization as they are?

Thanks in advance!

Tony Bogdanov
  • 7,436
  • 10
  • 49
  • 80
  • The ideal solution would be to subclass the `CheckBox` control and do your own rendering by overriding the `OnPaint` method. An easier, although probably messier solution, would be to place a `PictureBox` over the check box and control the image in the `PictureBox` through the `CheckBox`'s `CheckedChange` event. – xfx Jan 14 '13 at 13:24
  • Just as I thought.. it is for a course work though, so no :) I'll just go and use a background image as switch and no label. Post your comment as reply so I can accept it. – Tony Bogdanov Jan 14 '13 at 13:31
  • You can draw checkbox yourself with any logic which you need. For example take a look at this [toggle switch](http://stackoverflow.com/a/38432140/3110834) example which is in fact a check box but with a different appearance. – Reza Aghaei Oct 18 '16 at 21:41

4 Answers4

4

You look like this?

Dim frm As New Form
frm.Size = New Size(320, 200)

Dim iList As New ImageList
iList.Images.Add(Image.FromFile("check.png"), Color.White)
iList.Images.Add(Image.FromFile("uncheck.png"), Color.White)

Dim chk As New CheckBox
chk.Text = "Check Box With Image"
chk.AutoSize = False
chk.Size = New Size(350, 20)
chk.ImageList = iList
chk.ImageIndex = 1
chk.CheckAlign = ContentAlignment.MiddleRight
chk.ImageAlign = ContentAlignment.MiddleLeft
chk.TextImageRelation = TextImageRelation.ImageBeforeText
chk.Location = New Point(32, 32)

frm.Controls.Add(chk)

AddHandler chk.CheckStateChanged,
    Sub(sender1 As Object, e1 As EventArgs)
        chk.ImageIndex = IIf(chk.Checked, 0, 1)
    End Sub

frm.ShowDialog()
iBener
  • 469
  • 6
  • 18
1

UPDATE #1: Actually, @brahm solution's below is much better than mine!

UPDATE #2: Actually, it's not. Now I see how he did it: he's moving the checkbox out of sight by placing it way off the visible Form's area. Not a great solution...


The ideal solution would be to subclass the CheckBox control and do your own rendering by overriding the OnPaint method.

An easier, although probably messier solution, would be to place a PictureBox over the check box and control the image in the PictureBox through the CheckBox's CheckedChange event.

Another option: You could still use the CheckBox in button mode (Appearance = Button), as you suggested, but then add a label right next to it. Then, handle the Click event on the Label to toggle the Checked state of the CheckBox. Then end result should provide you exactly what you are looking for.

xfx
  • 1,329
  • 8
  • 18
0
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Windows.Forms.VisualStyles

Public Class ImageCheckBox

  Public State As CheckBoxState = CheckBoxState.UncheckedNormal
  Public Hot As Boolean = False
  Public Pressed As Boolean = False
  Public ImageDictionary As Dictionary(Of CheckBoxState, Image) = New Dictionary(Of CheckBoxState, Image)
  Private Const PaddingModifier As Integer = 2

  Sub New()
    Me.New(New Dictionary(Of CheckBoxState, Image) From {
      {CheckBoxState.CheckedDisabled, My.Resources.form_checkbox_checked},
      {CheckBoxState.CheckedHot, My.Resources.form_checkbox_checked},
      {CheckBoxState.CheckedNormal, My.Resources.form_checkbox_checked},
      {CheckBoxState.CheckedPressed, My.Resources.form_checkbox_checked},
      {CheckBoxState.UncheckedDisabled, My.Resources.form_checkbox_unchecked},
      {CheckBoxState.UncheckedHot, My.Resources.form_checkbox_unchecked},
      {CheckBoxState.UncheckedNormal, My.Resources.form_checkbox_unchecked},
      {CheckBoxState.UncheckedPressed, My.Resources.form_checkbox_unchecked}})
  End Sub

  Sub New(imageDictionary As Dictionary(Of CheckBoxState, Image))

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.


    Me.ImageDictionary = imageDictionary
  End Sub

  Sub CheckBox_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    'Return if the specific Image is not found
    If Not ImageDictionary.ContainsKey(State) Then Return

    'Get the Size of the CheckBox
    Dim glyphSize As Size = CheckBoxRenderer.GetGlyphSize(e.Graphics, State)

    'Get the Location of the CheckBox in relation to the Alignment of it
    Dim glyphLocation As Point
    Select Case Me.CheckAlign
      Case Drawing.ContentAlignment.TopLeft
        glyphLocation = New Point(Me.Padding.Left, Me.Padding.Top)
        Exit Select
      Case Drawing.ContentAlignment.TopCenter
        glyphLocation = New Point(Me.Padding.Left + (Me.Width - glyphSize.Width) / 2, Me.Padding.Top)
        Exit Select
      Case Drawing.ContentAlignment.TopRight
        glyphLocation = New Point(Me.Padding.Left + Me.Width - glyphSize.Width, Me.Padding.Top)
        Exit Select
      Case Drawing.ContentAlignment.MiddleLeft
        glyphLocation = New Point(Me.Padding.Left, Me.Padding.Top + (Me.Height - glyphSize.Height) / 2)
        Exit Select
      Case Drawing.ContentAlignment.MiddleCenter
        glyphLocation = New Point(Me.Padding.Left + (Me.Width - glyphSize.Width) / 2, Me.Padding.Top + (Me.Height - glyphSize.Height) / 2)
        Exit Select
      Case Drawing.ContentAlignment.MiddleRight
        glyphLocation = New Point(Me.Padding.Left + Me.Width - glyphSize.Width, Me.Padding.Top + (Me.Height - glyphSize.Height) / 2)
        Exit Select
      Case Drawing.ContentAlignment.BottomLeft
        glyphLocation = New Point(Me.Padding.Left, Me.Padding.Top + Me.Height - glyphSize.Height)
        Exit Select
      Case Drawing.ContentAlignment.BottomCenter
        glyphLocation = New Point(Me.Padding.Left + (Me.Width - glyphSize.Width) / 2, Me.Padding.Top + Me.Height - glyphSize.Height)
        Exit Select
      Case Drawing.ContentAlignment.BottomRight
        glyphLocation = New Point(Me.Padding.Left + Me.Width - glyphSize.Width, Me.Padding.Top + Me.Height - glyphSize.Height)
        Exit Select
    End Select

    'Set the drawing Area
    Dim glyphRectangle As Rectangle = New Rectangle(glyphLocation, glyphSize)

    'Enlarge the Rectangle to completely hide default symbol
    Dim clearRectangle As Rectangle = New Rectangle(glyphLocation.X - PaddingModifier,
                                                    glyphLocation.Y - PaddingModifier,
                                                    glyphSize.Width + 2 * PaddingModifier,
                                                    glyphSize.Height + 2 * PaddingModifier)

    'Draw the Parent Background over the default CheckBox to clear it
    CheckBoxRenderer.DrawParentBackground(e.Graphics, clearRectangle, Me)

    Debug.WriteLine(State)
    'Finally draw the custom CheckBox image on the position of the default one
    e.Graphics.DrawImage(ImageDictionary(State), glyphRectangle)
  End Sub

  Sub CheckBox_MouseClick(sender As Object, e As EventArgs) Handles Me.MouseClick
    Me.Checked = Not Me.Checked
  End Sub
  Sub CheckBox_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    Me.Pressed = True
  End Sub
  Sub CheckBox_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    Me.Pressed = False
  End Sub
  Sub CheckBox_MouseEnter(sender As Object, e As EventArgs) Handles Me.MouseEnter
    Me.Hot = True
  End Sub
  Sub CheckBox_MouseLeave(sender As Object, e As EventArgs) Handles Me.MouseLeave
    Me.Hot = False
  End Sub

  Public Sub updateState() Handles Me.MouseClick, Me.MouseDown, Me.MouseUp, Me.MouseEnter, Me.MouseLeave, Me.EnabledChanged
    Debug.WriteLine(Me.Checked & " " & Me.Enabled & " " & Me.Hot & " " & Me.Pressed)
    Me.State = CurrentState()
    Me.Refresh()
    Debug.WriteLine(State)
  End Sub

  Public Function CurrentState() As CheckBoxState
    If (Me.Checked) Then
      If (Not Me.Enabled) Then Return CheckBoxState.CheckedDisabled
      If (Me.Pressed) Then Return CheckBoxState.CheckedPressed
      If (Me.Hot) Then Return CheckBoxState.CheckedHot
      Return CheckBoxState.CheckedNormal
    Else
      If (Not Me.Enabled) Then Return CheckBoxState.UncheckedDisabled
      If (Me.Pressed) Then Return CheckBoxState.UncheckedPressed
      If (Me.Hot) Then Return CheckBoxState.UncheckedHot
      Return CheckBoxState.UncheckedNormal
    End If
  End Function

End Class
Error404
  • 719
  • 9
  • 30
0

I also had this problem with a mute/unmute audiotrack i first went for the CheckBox but deceided to just use the PictureBox click event and used .location to get the New Point overlay the other PictureBox and enable the visibility of the one or the other box, works fine for a complete newb that i am :-) Picture of the PictureBox in the Designer

Private Sub PictureBoxMute_Click(sender As Object, e As EventArgs) Handles PictureBoxMute.Click

        PictureBoxMute.Visible = False
        PictureBoxUnmute.Location = New Point(590, 433)
        PictureBoxUnmute.Visible = True
        Volume = 0
        myplayer.Volume = Volume

    End Sub

    Private Sub PictureBoxUnmute_Click(sender As Object, e As EventArgs) Handles PictureBoxUnmute.Click

        PictureBoxUnmute.Visible = False
        PictureBoxMute.Visible = True
        Volume = 1
        myplayer.Volume = Volume

    End Sub
MrPapaya
  • 1
  • 1