Вызвать нажатием кнопки компактная основа in.NET


Скажем, у меня есть панель со множеством кнопок и элементов управления PictureBox. С каждым элементом управления связано событие Click. Это сенсорное приложение, поэтому пользователь может быть немного неточным с их щелчком (или калибровка сенсорного экрана может быть не идеальной). Итак, я хотел бы обработать событие click на панели, а затем программно вызвать событие click кнопки или PictureBox, если щелчок находится рядом с кнопкой / изображением.

Ряд других ответов предлагают использовать " PerformClick" событие, но это не поддерживается в компактной структуре. Есть альтернативы? Мой код:

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

3 ответа:

Во-первых, попробуйте создать подкласс button и вызвать событие click из вашего собственного PerformClick. Кроме того, вы можете написать метод, который берет кнопку и выполняет щелчок. Сначала получите дескриптор элемента управления, затем p / вызовите функции API windows, чтобы отправить ему событие mousedown, а затем mouseup. Я считаю, что это функция SendMessage. Все, что вам нужно сделать, это написать логику, чтобы найти ближайшую кнопку и передать ее функции. Или запишите его как метод расширения для Кнопка

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

Править: Вот полный код для имитации щелчка, посылая сообщение mousedown и mouseup элементу управления:

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

Поскольку вы не можете использовать PerformClick, Вы не сможете полагаться на обработчик событий 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)))
            {
                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
}

Поместите все материалы из вашего обработчика нажатия кнопки в отдельную функцию и вызовите эту функцию вместо запуска нажатия кнопки.

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
}