简体   繁体   中英

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

Since you can't use PerformClick , you won't be able to rely on the control's Click event handler firing automatically in this case. Instead, just make a method that takes a control and figure out from that control which action to take. Example:

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)))
            {
                handleClick (cntrl);
            }
        }
    }
}

private void handleClick(Control c)
{
    if (c == button1)
    {
        // handle button1 click, e.g. by calling its `Click` handler
    }
    else if (c == picureBox1)
    {
        // handle pictureBox1 click
    }
    // et cetera
}

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

put all the stuff from your button click handler to a separate function, and call that function instead of triggering a button click.

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)))
            {
                PerformActionsOnClick();
            }
        }
    }
}
private void MyButton_Click(object sender, EventArgs e)
{
    PerformActionsOnClick();
}
void PerformActionsOnClick()
{
    //do your stuff here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM