Link to home
Start Free TrialLog in
Avatar of Éric Moreau
Éric MoreauFlag for Canada

asked on

Detect which part of a CheckBox control was clicked

For a CheckBox control in .Net (WinForms) , is there a way to detect if the user really clicked within the boundaries of the square of the checkbox?

Currently, the Checked state gets changed even if the text label is clicked.

FYI, I cannot remove the Text and the use Autosize to limit the clickable surface.
Avatar of Zvonko
Zvonko
Flag of North Macedonia image

In the first parameter passed from event to event handler for CheckBox checked event you get the object reference.
Do you get same object reference when clicking on label and on box?
Not really as the text is part of the checkbox control. Why would you want to limit the User Experience?
Avatar of Éric Moreau

ASKER

Hi David, we had user double-clicking on the drop-down part of a datetime picker. The first click had the datetime picker to close and the second click change the state of the checkbox that was "under". the result was catastrophic! We tried to train that user but nothing to do with that stubborn guy!

Zvonko, not sure to understand, the object is the checkbox (which is built from a checkbox and label but we don't have access to that unless I missed something)
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi saige

I was almost ready to accept your solution but did a last test.

When the checkbox control has the focus, and you press the space bar to toggle the checked state, the Mouse Position is checked to be in the boundaries. Anyway to bypass the check when the space bar is pressed?
Ultimately, it depends on whether or not your end users will have different display settings, especially any with DPI or accessibility adjustments. For example, recent versions of Windows allows someone with a small laptop screen to make everything bigger, so a checkbox might take 20 pixels instead of 10.

Personally, I think it's always just a matter of time until that situation comes up, and then you're having to figure out how to fix it all over again.

That in mind, your best scenario is to...

1. Fire the person.
Just kidding.

2. Try to adjust saige's comment to utilize the Bounds property to determine length and then check the cursor based on a percentage rather than a pixel. That should help account for DPI/accessibility adjustments.

3. Use a separate text / label control for the label of the checkbox and clear the checkbox text.

4.If you can't modify the checkbox's label, place another label control over top of it (same text and format, but if they click on it, they'll be clicking on the top label).

5.(ugh) Use a timer to disable clicks on the checkboxes for 200 milliseconds after they select a date.

EDIT:
Just noticed your previous comment about the spacebar - just detect the key down and key up events. If the key is down then skip the mouse check. 
My testing cannot replicate that issue.  If the mouse is not directly over the boundaries of the checkbox, it shows that the boundaries were missed.

Are you saying that you want the space bar keypress to toggle the checkbox?

-saige-
change the state of the checkbox that was "under". the result was catastrophic
how about moving that box slightly down?
The control is part of a form that is created dynamically from the fields in a database. all controls are displayed in a scrolling panel. So I cannot move the controls around to prevent that situation.

>>Are you saying that you want the space bar keypress to toggle the checkbox?

It is the normal behavior of the checkbox that when it has focus, pressing the space bar toggles the checked state
I have something that I will continue to test tomorrow!

I am now handling the KeyPress event in addition to the boundary check.

Yes it is for the Infragistics UltraCheckEditor (which does not have an Autocheck property) but have been able to figure it out. Works mostly the same with a regular checkbox.
    Private Sub UltraCheckEditor2_BeforeCheckStateChanged(sender As Object, e As CancelEventArgs) Handles UltraCheckEditor2.BeforeCheckStateChanged
        Dim chk = TryCast(sender, UltraCheckEditor)

        If chk.Tag = "SKIP BOUNDARY CHECK" Then
            chk.Tag = String.Empty
            Return
        End If

        Dim point = New Point(MousePosition.X, MousePosition.Y)
        Dim position = PointToScreen(chk.Location)
        Dim boundaries = New Func(Of Boolean)() {Function() point.X >= position.X, Function() point.X <= position.X + 15, Function() point.Y >= position.Y, Function() point.Y <= position.Y + 15}

        If boundaries.All(Function(x) x.Invoke()) Then
            TextBox1.Text = $"Checkbox Boundaries clicked at {point} - {position}"
            'chk.Checked = Not chk.Checked
        Else
            TextBox1.Text = $"MISSED Checkbox Boundaries at {point} - {position}"
            e.Cancel = True
        End If
    End Sub

    Private Sub UltraCheckEditor2_KeyPress(sender As Object, e As KeyPressEventArgs) Handles UltraCheckEditor2.KeyPress
        If e.KeyChar = Convert.ToChar(Keys.Space) Then
            UltraCheckEditor2.Tag = "SKIP BOUNDARY CHECK"
        End If
    End Sub

Open in new window