#c# #winforms
Вопрос:
У меня есть форма c# (назовем ее основной формой) с рядом пользовательских элементов управления на ней. Я бы хотел иметь основную форму.Метод OnClick() срабатывает в любое время, когда кто-то нажимает на форму, независимо от того, произошел ли щелчок в форме или был ли щелчок на одном из пользовательских элементов управления. Я ищу поведение, аналогичное функции KeyPreview в формах, за исключением щелчков мыши, а не нажатий клавиш.
Ответ №1:
Я рекомендую создать базовую форму для наследования других форм в вашем приложении. Добавьте этот код в свою базовую форму, чтобы создать новое событие под названием GlobalMouseClickEventHandler:
namespace Temp
{
public delegate void GlobalMouseClickEventHander(object sender, MouseEventArgs e);
public partial class TestForm : Form
{
[Category("Action")]
[Description("Fires when any control on the form is clicked.")]
public event GlobalMouseClickEventHander GlobalMouseClick;
public TestForm()
{
InitializeComponent();
BindControlMouseClicks(this);
}
private void BindControlMouseClicks(Control con)
{
con.MouseClick = delegate(object sender, MouseEventArgs e)
{
TriggerMouseClicked(sender, e);
};
// bind to controls already added
foreach (Control i in con.Controls)
{
BindControlMouseClicks(i);
}
// bind to controls added in the future
con.ControlAdded = delegate(object sender, ControlEventArgs e)
{
BindControlMouseClicks(e.Control);
};
}
private void TriggerMouseClicked(object sender, MouseEventArgs e)
{
if (GlobalMouseClick != null)
{
GlobalMouseClick(sender, e);
}
}
}
}
Это решение будет работать не только для элементов управления верхнего уровня, но и для вложенных элементов управления, таких как элементы управления, размещенные внутри панелей.
Комментарии:
1. Огромное спасибо! Простое и элегантное решение. Интересно, почему нет чего-то эквивалентного
KeyPreview
щелчкам мыши
Ответ №2:
В событии ControlAdded формы добавьте обработчик щелчка мыши в элемент управления с адресом события щелчка формы. Я еще не проверял это, но это может сработать.
Private Sub Example_ControlAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles Me.ControlAdded
AddHandler e.Control.MouseClick, AddressOf Example_MouseClick
End Sub
Private Sub Example_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
MessageBox.Show("Click")
End Sub
Комментарии:
1. Это все еще кажется немного странным, но, похоже, это лучший вариант, который у меня есть.
Ответ №3:
Единственный способ, которым мне когда-либо удавалось это сделать, — это обработать событие [c]Click[/c] каждого элемента управления. Я не верю, что событие возникает до того, как управление обработает его.
В WPF есть события предварительного просмотра «туннелирования», которые предоставляют эту функциональность, но это на самом деле не помогает вам в WinForms.
Комментарии:
1. Ну, сейчас уже слишком поздно переходить на WPF, но, думаю, мне придется серьезно подумать об его использовании в будущем.
Ответ №4:
Вы можете подключить все события элемента управления, если хотите, а затем отслеживать их таким образом. Я предполагаю, что существует какой-то необычный способ Win32 api для их всех, но в данный момент это выше моего понимания.
public Form1()
{
InitializeComponent();
HookEvents();
}
private void HookEvents() {
foreach (Control ctl in this.Controls) {
ctl.MouseClick = new MouseEventHandler(Form1_MouseClick);
}
}
void Form1_MouseClick(object sender, MouseEventArgs e)
{
LogEvent(sender, "MouseClick");
}
// and then this just logs to a multiline textbox you have somwhere on the form
private void LogEvent(object sender, string msg) {
this.textBox1.Text = string.Format("{0} {1} ({2}) n {3}",
DateTime.Now.TimeOfDay.ToString(),
msg,
sender.GetType().Name,
textBox1.Text
);
}
Результат выглядит примерно так: показаны все события и кто их «отправил» :
14:51:42.3381985 MouseClick (Form1)
14:51:40.6194485 MouseClick (RichTextBox)
14:51:40.0100735 MouseClick (TextBox)
14:51:39.6194485 MouseClick (Form1)
14:51:39.2131985 MouseClick (RichTextBox)
14:51:38.8694485 MouseClick (Button)
ХТ.
Ответ №5:
Поймать щелчок на открытом месте в форме легко, но чтобы получить щелчок, который на самом деле находится на элементе управления, вам потребуется сотрудничество этого элемента управления, чтобы отправить его в форму.
Одна из возможностей состоит в том, чтобы разместить прозрачный контроль над всей формой и принимать клики на нее, обрабатывать их, а затем передавать их в соответствующий элемент управления внизу.
Комментарии:
1. Я чувствую, что должно быть более элегантное решение, чем это.
Ответ №6:
Это распространенный паттерн в развитии, называемый паттерном наблюдателя. Существует множество примеров шаблонов наблюдателей, и c# вот 1 пример http://msdn.microsoft.com/en-us/library/ms954621.aspx но хорошенько погуглите вокруг.