2010-01-04 5 views
1

Простая ситуация (VS2005, .NET2): I have a textBox1 on a panel1. I need to track all the emitted events from this textBox1.Track (все) события из Control

На самом деле, когда мне нужно отслеживать одно событие (TextChanged, путем, например) от этого textBox1 добавить обработчик (событие TextChanged), я установил затем неблокирующую ошибку , которая записывает на выходную консоль сообщение, содержащее имя функции (eventhandler). Итак, для одного события я могу написать этот обработчик и установить брекерскую точку, но могу ли я сделать что-то подобное для всех возможных событий текстового поля (или другого элемента управления)?

alt text http://lh5.ggpht.com/_1TPOP7DzY1E/S0H5NHjXSjI/AAAAAAAAC24/tV0IiUsxwAU/s800/eventsTrack.png

Более глубоко, мне нужно знать, какое событие имеет место в определенный момент времени на упомянутом управления (TextBox).

Спасибо.

ответ

3

пост Aviad является хорошим началом. Вы можете использовать его для событий типа EventHandler. Для других типов делегатов вы можете использовать один и тот же метод, создающий обработчик для каждого типа вручную.

Если вы хотите быть более гибким, вы должны создать обработчик событий во время выполнения, используя System.Reflection.Emit. Вот подробное объяснение: http://msdn.microsoft.com/en-us/library/ms228976.aspx. Прокрутите вниз до «Чтобы создать обработчик события во время выполнения с использованием динамического метода».

// EDIT

Я создал простой класс, который способен обрабатывать все события конкретного объекта и передать их универсального обработчика событий. Код основан на примерах от Microsoft и XTreme.NET Talk.

Основная идея

  • создать метод во время выполнения, который имеет те же аргументы, что события
  • набор это mehod в качестве обработчика события для каждого события в Type.GetEvents()
  • из этого вызова метода универсальный обработчик события

Использование

Объект для прикрепления к передается в конструкторе. Следующий анонимный метод типа UniversalEventHandler используется для обработки всех событий. Этот метод получает имя события как eventName и аргументы события в args. Вы можете установить точку останова на этом методе и просмотреть аргументы в Visual Studio или распечатать их самостоятельно.В этом примере используется только имя события, которое можно найти в окне «Вывод» (меню «Вид»> «Вывод» в Visual Studio). В этом примере рассматривается стандартная кнопка button1.

private void Form1_Load(object sender, EventArgs e) 
{    
    UniversalEventHandler handler = (UniversalEventHandler) delegate(string eventName, object[] args) 
    { 
     System.Diagnostics.Trace.WriteLine(eventName); 
    }; 

    EventInspector inspector = new EventInspector(button1, handler); 

} 

Код

public delegate void UniversalEventHandler(string eventName, object[] args); 

public class EventInspector 
{ 
    private UniversalEventHandler eventHandler; 
    private object srcObject; 

    public EventInspector(object srcObject, UniversalEventHandler eventHandler) 
    { 
     this.eventHandler = eventHandler; 
     this.srcObject = srcObject; 
     Attach(); 
    } 

    public void EventReceived(string eventName, object[] args) 
    { 
     if (eventHandler != null) 
      eventHandler(eventName, args); 
    } 

    public void Attach() 
    { 
     Type type = srcObject.GetType(); 
     EventInfo[] srcEvents = type.GetEvents(); 

     for (int i = 0; i < srcEvents.Length; i++) 
     { 
      EventInfo srcEvent = srcEvents[i]; 

      Type[] parameterTypes = GetDelegateParams(srcEvent.EventHandlerType); 
      DynamicMethod handler = new DynamicMethod("", typeof(void), parameterTypes, typeof(EventInspector)); 
      string name = srcEvent.Name; 
      ILGenerator il = handler.GetILGenerator(); 
      il.DeclareLocal(typeof(object[])); 
      il.DeclareLocal(typeof(string)); 

      il.Emit(OpCodes.Ldstr, srcEvent.Name); 
      il.Emit(OpCodes.Stloc_1); 
      il.Emit(OpCodes.Ldc_I4, parameterTypes.Length - 1); 
      il.Emit(OpCodes.Newarr, typeof(object)); 
      il.Emit(OpCodes.Stloc_0); 

      for (int j = 0; j < parameterTypes.Length - 1; j++) 
      { 
       Type parameter = parameterTypes[j]; 
       il.Emit(OpCodes.Ldloc_0); 
       il.Emit(OpCodes.Ldc_I4, j); 
       il.Emit(OpCodes.Ldarg, j + 1); 
       il.Emit(OpCodes.Stelem_Ref); 
      } 

      il.Emit(OpCodes.Ldarg_0); 
      il.Emit(OpCodes.Ldloc_1); 
      il.Emit(OpCodes.Ldloc_0); 

      MethodInfo eventReceivedMethod = this.GetType().GetMethod("EventReceived", BindingFlags.Public | BindingFlags.Instance); 
      il.EmitCall(OpCodes.Callvirt, eventReceivedMethod, null); 
      il.Emit(System.Reflection.Emit.OpCodes.Ret);         

      srcEvent.AddEventHandler(srcObject, handler.CreateDelegate(srcEvent.EventHandlerType, this)); 
     } 
    } 

    private Type[] GetDelegateParams(Type d) 
    { 
     MethodInfo delegateMethod = d.GetMethod("Invoke"); 
     ParameterInfo[] delegateParams = delegateMethod.GetParameters(); 

     Type[] result = new Type[delegateParams.Length + 1]; 
     result[0] = this.GetType(); 

     for (int i = 0; i < delegateParams.Length; i++) 
     { 
      result[i + 1] = delegateParams[i].ParameterType; 
     } 

     return result; 
    } 
} 
+0

@Petr: Прежде всего, метод Aviad, к сожалению, не работает для меня (.NET 2), так как он не может преобразовать «System.EventHandler» в «System.Windows.Forms.MouseEventHandler». Вторичный, мне не нужно * генерировать * событие, но * перехватывать * его ... – serhio

+1

Удивительный класс !! Разумеется, полезно в миллионах сценариев. – Dested

+0

Serhio: Используя код в моем отредактированном ответе, вы можете перехватить все события и его аргументы. метод Aviad работает для меня под .NET 2.0, пожалуйста, попробуйте этот код: this.GetType() GetEvent ("KeyDown") AddEventHandler (это, (EventHandler) делегат (объект ЦСИ EventArgs эв) { ... .. }); Он ничего не сделает, потому что KeyDown не является EventHandler, но он будет компилироваться без ошибок. Если вы измените «KeyDown» на обработчик «Click», будет запущен. Надеюсь, это поможет. –

0

Вы не можете сделать это автоматически.

Однако, если вы просто пытаетесь выяснить, какие события срабатывают, попробуйте Spy ++.

+0

это перехват всех типов событий, или только системы из них? – serhio

+0

Он отображает сообщения Windows; почти все стандартные события отображаются непосредственно в сообщениях Windows. – SLaks

1

Вы можете использовать отражение, чтобы получить все события объекта и подключить их все к вашему отладочному методу.

void HookAllEvents(object obj) 
{ 
    foreach (var evInfo in obj.GetType().GetEvents()) 
    { 
     evInfo.AddEventHandler(obj, new EventHandler(DebugEventHandler)); 
    } 
} 

void DebugEventHandler(object sender, EventArgs e) 
{ 
} 

Не забудьте отцепить в конце :)

+0

Это не будет работать для таких событий, как 'KeyPress', которые не являются' EventHandler'. – SLaks

+0

Мне кажется, что это обычный обработчик событий. http://msdn.microsoft.com/en-us/library/system.windows.forms.keypresseventhandler.aspx –

+0

KeyPress - это «KeyPressEventHandler», а не «EventHandler». – SLaks

Смежные вопросы