2009-07-20 28 views
6

Tôi có một điều khiển người dùng với một số điều khiển con. Tôi cần giao diện người dùng để phản ứng với các lần nhấn phím, vì vậy tôi quyết định đặt mã xử lý trong một sự kiện MainControl_KeyDown. Tuy nhiên, khi tôi nhấn một phím trong ứng dụng của tôi, sự kiện này không kích hoạt.Chụp các sự kiện KeyDown trong UserControl

Tôi đã tìm thấy giải pháp thông qua một công cụ tìm kiếm dựa trên việc sử dụng API Windows, mà tôi muốn tránh, vì nó có vẻ quá mức cần thiết cho chức năng được khung .NET hỗ trợ.

+2

tôi thấy [câu trả lời này] [1] là hữu ích nhất - bạn ghi đè ProcessCmdKey(). [1]: http://stackoverflow.com/a/1616965/327458 – bsegraves

+0

Liên kết này phải là câu trả lời. – OfficeAddinDev

Trả lời

7

Bạn có thể thêm một xử lý sự kiện KeyDown cho mỗi điều khiển con trong điều khiển người dùng của bạn và bắn các sự kiện KeyDown của điều khiển người dùng của bạn trong mỗi, như vậy:

private void textBox1_KeyDown(object sender, KeyEventArgs e) 
{ 
    this.OnKeyDown(e); 
} 
1

có lẽ bạn nên xử lý tất cả các sự kiện cục bộ và sau đó kích hoạt các sự kiện giả để giao tiếp với điều khiển chính?

hoặc có thể đây có thể là vấn đề trọng tâm; nếu có nhiều điều khiển con và chỉ một trong số chúng được tập trung, những người khác sẽ không phản ứng lại hành động chính.

có thể bạn có thể đăng một số đoạn mã ở đây để chắc chắn.

1

Dưới đây là một ví dụ vòng lặp mà ném từng điều khiển trong biểu mẫu để đính kèm sự kiện KeyDown. Nó giống như câu trả lời previouly trong bài viết này, nhưng xử lý nhiều trường hợp:

using Microsoft.VisualBasic; 
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Data; 
using System.Diagnostics; 

public class UserControlKeyboardProcessor 
{ 
    private void Control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) 
    { 
     base.OnKeyDown(e); 
    } 

    private void UserControlKeyboardProcessor_Disposed(object sender, System.EventArgs e) 
    { 
     foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) { 
      control.KeyDown -= Control_KeyDown; 
     } 
    } 

    private void UserControlKeyboardProcessor_Load(object sender, System.EventArgs e) 
    { 
     foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) { 
      control.KeyDown += Control_KeyDown; 
     } 
    } 

    public Generic.List<System.Windows.Forms.Control> GetAllControls(System.Windows.Forms.Control control) 
    { 
     Generic.List<System.Windows.Forms.Control> controls = new Generic.List<System.Windows.Forms.Control>(); 

     foreach (System.Windows.Forms.Control subControl in control.Controls) { 
      controls.Add(subControl); 
      controls.AddRange(this.GetAllControls(subControl)); 
     } 

     return controls; 
    } 
    public UserControlKeyboardProcessor() 
    { 
     Load += UserControlKeyboardProcessor_Load; 
     Disposed += UserControlKeyboardProcessor_Disposed; 
    } 
} 
9

Tôi biết chủ đề này là một chút cũ, nhưng tôi đã có một vấn đề tương tự và xử lý nó theo một cách khác:
Trong chính-cửa sổ Tôi đã thay đổi thuộc tính KeyPreview thành true. Tôi đã đăng ký trình xử lý sự kiện KeyDown của cửa sổ chính trong điều khiển người dùng của mình.

this.Parent.KeyDown += new KeyEventHandler(MyControl_KeyDown); 

Điều này ngăn tôi định tuyến sự kiện KeyDown của mọi kiểm soát con người dùng của tôi.
Tất nhiên, điều quan trọng là phải xóa trình xử lý sự kiện khi bạn bỏ điều khiển người dùng của mình.

Tôi hy vọng điều này sẽ giúp những người gặp phải sự cố tương tự ngay bây giờ.

+0

Điều này làm việc tuyệt vời khi một điều khiển được sử dụng trong nhiều biểu mẫu và chụp 'Enter' gọi một phương thức trong biểu mẫu – Wayne

0

Tôi có một số mẹo.

UcBase kế thừa từ UesrControl

UcSub1 và UcSub2 kế thừa từ UcBase. UcSuperClass kế thừa từ UcBase.

Sử dụng UcSub1, UcSub2 trong UcSuperClass.

Tôi điên UcSub1 và UcSub2 gọi ProcessCmdKey ok.

mã của tôi là

public class UcBase : UserControl 
{ 
    public delegate bool ProcessCmdKeyHandler(Keys keyData); 

    public ProcessCmdKeyHandler KeyHandler; 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 

     KeyHandler += ProcessKey; 

     if (Parent != null) 
     { 
      var parent = GetParentControl<UcBase>(Parent); 

      if (parent != null) 
      { 
       parent.KeyHandler += ProcessKey; 
      } 
     } 
    } 

    protected virtual bool ProcessKey(Keys keyData) 
    { 
     return false; 
    } 

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     const int WM_KEYDOWN = 0x100; 
     const int WM_SYSKEYDOWN = 0x104; 

     if (KeyHandler != null 
      && (msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) 
     { 
      if (KeyHandler(keyData) == true) 
      { 
       return true; 
      } 
     } 

     return base.ProcessCmdKey(ref msg, keyData); 
    } 

    private T GetParentControl<T>(Control control) 
     where T : Control 
    { 
     T parentControl = default(T); 
     var queue = new Queue<Control>(); 
     var targetControlType = typeof(T); 

     queue.Enqueue(control.Parent); 

     while (queue.Count > 0) 
     { 
      var parent = queue.Dequeue(); 

      if (parent != null) 
      { 
       if (parent.GetType().BaseType == targetControlType) 
       { 
        parentControl = (T)parent; 

        break; 
       } 
       else 
       { 
        queue.Enqueue(parent.Parent); 
       } 
      } 
      else 
      { 
       break; 
      } 
     } 

     return parentControl; 
    } 
} 

public class UcSub1 : UcBase 
{ 
    protected override bool ProcessKey(Keys keyData) 
    { 
     // if you process do something, and return true then UcBase.ProcessCmdKey pass by. 
     return false; 
    } 
} 

public class UcSub2 : UcBase 
{ 
    protected override bool ProcessKey(Keys keyData) 
    { 
     // if you process do something, and return true then UcBase.ProcessCmdKey pass by. 
     return false; 
    } 
} 

public class UcSuperClass : UcBase 
{ 
    private UcSub1 _ucSub1; 
    private UcSub2 _ucSub2; 

    public UcSuperClass() 
    { 
     _ucSub1 = new UcSub1(); 
     _ucSub2 = new UcSub2(); 
    } 

    protected override bool ProcessKey(Keys keyData) 
    { 
     // if you process do something, and return true then UcBase.ProcessCmdKey pass by. 
     return false; 
    } 
} 
5

Bạn có thể thêm following method để usercontrol của bạn:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
{ 
    if ((keyData == Keys.Right) || (keyData == Keys.Left) || 
     (keyData == Keys.Up) || (keyData == Keys.Down)) 
    { 
    //Do custom stuff 
    //true if key was processed by control, false otherwise 
    return true; 
    } 
    else 
    { 
    return base.ProcessCmdKey(ref msg, keyData); 
    } 
} 
Các vấn đề liên quan