2010-03-05 72 views
21

Tôi tự hỏi thuộc tính Form.KeyPreview thực sự tốt cho điều gì? Tại sao nó tồn tại và những gì tôi "nguy cơ" bằng cách đặt nó thành sự thật? Tôi đoán nó phải có một số hiệu ứng tiêu cực - nếu không nó sẽ không tồn tại chút nào (hoặc ít nhất là đúng theo mặc định)?Bất lợi của việc thiết lập Form.KeyPreview = true?

EDIT: Tôi biết hoàn toàn rõ ràng những gì. Tôi đang yêu cầu lý do tại sao. Tại sao tôi phải đặt nó thành true để làm cho các sự kiện bàn phím cháy? Tại sao các sự kiện bàn phím luôn luôn kích hoạt biểu mẫu. Điều gì không chỉ là hành vi tiêu chuẩn?

Lý do cụ thể tôi hỏi là: Tôi vừa đặt KeyPreview = true ở dạng cơ sở của ứng dụng, tất cả các biểu mẫu khác được kế thừa từ đó. Tôi có bất kỳ sự ngạc nhiên khó chịu nào không?

+1

** Bạn có thể sử dụng thuộc tính này để xử lý hầu hết các lần nhấn phím trong ứng dụng của bạn và xử lý thao tác gõ phím hoặc gọi điều khiển thích hợp để xử lý thao tác gõ phím. Ví dụ, khi một ứng dụng sử dụng các phím chức năng, bạn có thể muốn xử lý các tổ hợp phím ở cấp biểu mẫu thay vì viết mã cho mỗi điều khiển có thể nhận các sự kiện tổ hợp phím. ** Từ http://msdn.microsoft.com/en-us /library/system.windows.forms.form.keypreview.aspx – rahul

+3

Có. Và tại sao đây không phải là hành vi mặc định? –

+1

Tôi chỉ gặp một trường hợp mà tôi đã không nhận được một sự kiện KeyDown cho phím Escape khi tập trung vào một điều khiển bên thứ 3 nhất định, ngay cả khi KeyPreview được đặt thành True. Rất may tôi đã tìm thấy bài đăng này và đã cố gắng ghi đè ProcessCmdKey cho điều khiển tùy chỉnh, điều này đã cho phép tôi lấy sự kiện quan trọng trước khi điều khiển đã thực hiện. Cảm ơn! – stone

Trả lời

59

Form.KeyPreview là một bit của một lỗi thời, được kế thừa từ mô hình đối tượng Visual Basic để thiết kế biểu mẫu. Quay lại VB6 ngày, bạn cần KeyPreview để có thể thực hiện các lần nhấn phím ngắn. Đó là không cần thiết nữa trong Windows Forms, trọng các ProcessCmdKey() sự là giải pháp tốt hơn:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { 
    if (keyData == (Keys.Control | Keys.F)) { 
    DoSomething(); // Implement the Ctrl+F short-cut keystroke 
    return true;  // This keystroke was handled, don't pass to the control with the focus 
    } 
    return base.ProcessCmdKey(ref msg, keyData); 
} 

Nhưng KeyPreview đã được hỗ trợ để giúp các quân đoàn của các lập trình viên VB6 chuyển sang NET lại vào đầu những năm 2000. Điểm của KeyPreview hoặc ProcessCmdKey() là cho phép giao diện người dùng của bạn phản hồi các lần nhấn phím tắt. Thông báo bàn phím thường được gửi đến điều khiển có tiêu điểm. Vòng lặp tin nhắn của Windows Forms cho phép mã xem trước thông báo đó trước khi điều khiển nhìn thấy nó. Điều đó quan trọng đối với các phím tắt, thực hiện sự kiện KeyDown cho mọi điều khiển có thể lấy trọng tâm để phát hiện chúng là rất không thực tế.

Đặt KeyPreview thành True không gây ra sự cố. Sự kiện KeyDown của biểu mẫu sẽ chạy, sự kiện sẽ chỉ có ảnh hưởng nếu nó có mã thực hiện điều gì đó với tổ hợp phím. Nhưng hãy cẩn thận rằng nó chặt chẽ sau việc sử dụng VB6, bạn không thể nhìn thấy các loại tổ hợp phím được sử dụng để điều hướng. Giống như các phím con trỏ và Tab, EscapeEnter cho một hộp thoại. Không phải là vấn đề với ProcessCmdKey().

+0

+1 cho ProcessCmdKey. –

+0

Điều này đã giúp tôi ngày hôm nay. –

4

Từ MSDN

Khi thuộc tính này được thiết lập là true, hình thức sẽ nhận được tất cả KeyPress, KeyDown, và các sự kiện KeyUp. Sau khi trình xử lý sự kiện của biểu mẫu đã hoàn thành xử lý phím tắt, sau đó phím tắt được gán cho điều khiển có tiêu điểm. Ví dụ: nếu thuộc tính KeyPreview được đặt thành true và điều khiển hiện được chọn là một Hộp văn bản, sau khi gõ phím là do trình xử lý sự kiện của điều khiển hộp văn bản sẽ nhận được phím được nhấn. Để xử lý sự kiện bàn phím chỉ ở cấp biểu mẫu và không cho phép các điều khiển nhận được sự kiện bàn phím , hãy đặt KeyPressEventArgs.Handled property in xử lý sự kiện KeyPress của biểu mẫu của bạn thành đúng.

Bạn có thể sử dụng tài sản này để xử lý nhất tổ hợp phím trong ứng dụng của bạn và hoặc xử lý các tổ hợp phím hoặc gọi sự kiểm soát thích hợp để xử lý các tổ hợp phím. Ví dụ: khi một phím chức năng sử dụng ứng dụng , bạn có thể muốn xử lý các tổ hợp phím ở cấp biểu mẫu thay vì viết mã cho mỗi điều khiển có thể nhận các sự kiện tổ hợp phím.

Về cơ bản khi bạn đặt thành đúng, biểu mẫu của bạn có thể xử lý các sự kiện quan trọng cũng như kiểm soát của bạn.

E.G Người dùng nhấn phím K, trình xử lý sự kiện biểu mẫu được gọi (Khóa phím, Khóa phím, Bấm phím) và sau đó xử lý sự kiện trên điều khiển hiện đang hoạt động được gọi.

CHỈNH SỬA: Không có bất kỳ khó khăn hoặc bất ngờ khó chịu nào. Điều duy nhất tôi có thể nghĩ là một hiệu suất rất nhỏ giảm vì nó cần phải kiểm tra xử lý sự kiện trên biểu mẫu cho mỗi KeyDown, KeyUp, KeyPressed. Ngoài ra, trừ khi bạn đang thêm trình xử lý sự kiện vào biểu mẫu và thực hiện một việc có thể gây ra sự cố. bạn hoàn toàn ổn. Nếu bạn không cần phải xử lý toàn cục các sự kiện quan trọng ngoại trừ trên các điều khiển thì tôi sẽ đề nghị bạn để điều này là sai để ngăn chặn việc kiểm tra thêm. Trên PC hiện đại, điều này sẽ không có sự khác biệt rõ ràng.

+1

Hoàn toàn chính xác. Thật không may nó không theo bất kỳ cách nào trả lời những gì tôi hỏi. –

2

Mô hình sự kiện Windows chuẩn là cửa sổ có tiêu điểm bàn phím nhận tất cả các sự kiện bàn phím. Hãy nhớ rằng trong Windows, mọi thứ đều là một cửa sổ - một 'điều khiển' chỉ là một cửa sổ là con của một cửa sổ khác. Đó là vào cửa sổ đó để gửi tin nhắn cho cha mẹ của nó nếu nó chọn để làm như vậy, khi một số phím được nhấn.

Để chuẩn hóa điều hướng giữa các điều khiển trên hộp thoại, Windows cũng cung cấp 'trình quản lý hộp thoại'. Trong mã gốc, đối với các hộp thoại phương thức, điều này được xử lý bởi vòng lặp thông điệp phương thức bên trong hàm DialogBox. Đối với các hộp thoại không mod, bạn phải gọi IsDialogMessage trong vòng lặp tin nhắn của riêng bạn. Đây là cách nó đánh cắp các phím Tab và con trỏ để điều hướng giữa các điều khiển và nhấn Enter để nhấn nút mặc định. Điều này có tác dụng ngược lại là không cho phép các điều khiển xử lý Enter theo mặc định, điều khiển chỉnh sửa nhiều dòng thông thường sẽ xử lý. Để khám phá liệu một điều khiển có muốn xử lý một khóa hay không, mã trình quản lý hộp thoại sẽ gửi điều khiển được tập trung vào thông báo WM_GETDLGCODE; nếu điều khiển phản hồi một cách thích hợp, trình quản lý hộp thoại trả lại FALSE cho phép DispatchMessage thực sự phân phối nó đến quy trình cửa sổ, nếu không trình quản lý hộp thoại sẽ thực hiện điều đó.

Windows Forms chủ yếu chỉ kết thúc các kiểm soát gốc cũ, do đó, nó phải phù hợp với mô hình sự kiện của Win32. Nó thực hiện cách tiếp cận quản lý hộp thoại tương tự - do đó tại sao nó không, theo mặc định, cho phép bạn xem Tab, Return và các phím con trỏ.

Cách tiếp cận được khuyến nghị, nếu bạn muốn xử lý một trong các khóa đó, là ghi đè PreviewKeyDown và đặt thuộc tính PreviewKeyDownEventArgsIsInputKey thành true.

Các vấn đề liên quan