Search code examples
c#.netcompact-framework

Trigger button click in .NET Compact Framework


Say I have a Panel with many Button and PictureBox controls. Each control has an associated Click event. This is a touchscreen application, so the user may be a little imprecise with their click (or the touchscreen calibration might not be perfect). So, I'd like to handle the click event on the panel and then programmatically call the Button's or PictureBox's Click event if the click is close to a button/picture.

A number of other answers suggest using the "PerformClick" event, but this is not supported in the Compact Framework. Any alternatives? My code:

private void pnlButtons_Click(object sender, EventArgs e)
{
    Point ptClick = Control.MousePosition;
    foreach (Control cntrl in pnlButtons.Controls)
    {
        // Make sure the control is visible!
        if (cntrl.Visible)
        {
            // Click close to control?
            if ((ptClick.X > (cntrl.Left - 5)) &&
                (ptClick.X < (cntrl.Right + 5)) &&
                (ptClick.Y > (cntrl.Top - 5)) &&
                (ptClick.Y < (cntrl.Bottom + 5)))
            {
                // Click Button or PictureBox without cntrl.PerformClick?
            }
        }
    }
}

Solution

  • First off, try subclassing button and calling the click event from your own PerformClick. Else, You can write a method which takes a button and performs a click. First get the handle of the control, then p/invoke the windows API functions to send a mousedown then mouseup event to it. I believe it is the SendMessage function. All you have to do then is write the logic to find the closest button and pass it to the function. Or, write it as an extension method to Button

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx

    EDIT: Here's the full code to simulate a click by sending a mousedown and mouseup message to the control:

    // Windows constants for mouse messages
    private const int WM_LBUTTONDOWN        = 0x0201;
    private const int WM_LBUTTONUP          = 0x0202;
    
    // P/Invoke for SendMessage
    [DllImport("coredll.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, int nMsg, IntPtr wParam, IntPtr lParam);
    
    // Method to click a control
    public void ClickControl(IntPtr hWnd)
    {
        // Send a MOUSE_DOWN and MOUSE_UP message to the control to simulate a click
        SendMessage(hWnd, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
        SendMessage(hWnd, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
    }
    
    // Method to handle click event on parent Panel control
    private void pnlButtons_Click(object sender, EventArgs e)
    {
        // See if the click point is close to a (visible) button and if so, click the button.
        // The user was probably a little imprecise or the screen might need re-calibration.
        Point pt = pnlButtons.PointToClient(Cursor.Position);
    
        // Now look for any Button / PictureBox controls nearby
        foreach (Control cntrl in pnlButtons.Controls)
        {
            Rectangle inflated = cntrl.Bounds;
            inflated.Inflate(4, 5);
            if (cntrl.Visible && inflated.Contains(pt))
            {
                // Simulate a click on the control
                ClickControl(cntrl.Handle);
                break;
            }
        }
    }