2012-08-25 27 views
7

Tôi đã nhìn thấy một số câu trả lời cho thấy việc sử dụng Keyboard.Modifiers để xác định xem sự kiện KeyDown có dành cho khóa có bộ sửa đổi hay không. Thật không may, vì Keyboard.Modifiers trả lại trạng thái hiện tại của các công cụ sửa đổi (thay vì trạng thái của công cụ sửa đổi khi phím được nhấn), điều này dẫn đến một lỗi liên tục gây phiền nhiễu cho người đánh máy nhanh.Cách lấy đúng các phím bổ trợ trong sự kiện WPF KeyDown?

Cụ thể, hãy tưởng tượng ai đó nhấn Ctrl + A và giải phóng Ctrl chỉ sau vài giây sau khi nhấn A. Bây giờ hãy tưởng tượng rằng hệ thống đang chịu tải nặng; trình xử lý khóa bắt đầu thực hiện nhưng được ưu tiên 50ms. Vào thời điểm trình xử lý khóa đang thực hiện lại, trạng thái hiện tại của trạng thái là "được giải phóng". Trình xử lý khóa giờ đây sẽ nghĩ rằng "A" được nhấn mà không có Ctrl và đây là xấu.

Tương tự, nếu một nhân viên đánh máy nhanh vào A, Ctrl + End và ứng dụng của tôi sử dụng Keyboard.Modifiers, nó thay vì có thể sẽ quan sát Ctrl + A ...

Trong WinForms, sự kiện KeyDown nói với tôi tình trạng Ctrl chính xác, ngay cả khi nó đã được phát hành vào thời điểm sự kiện đang được xử lý. Làm thế nào tôi có thể có được hành vi tương tự trong WPF?

Chỉnh sửa: có thể là Keyboard.Modifiers không thực sự truy xuất các phím bổ trợ "hiện tại", mà thay vào đó các phím bổ trợ liên quan đến thông báo chính hiện đang được xử lý. Trong WinAPI, đây là sự khác biệt giữa các hàm trạng thái khóa "không đồng bộ" và không đồng bộ. Thật không may, the documentation không đề cập đến chính xác "hiện tại". Nếu có ai biết, hãy nói như vậy.

+0

bạn có chắc chắn không? Tôi không tìm thấy bất kỳ gợi ý nào về msdn, điều đó sẽ chứng minh lý thuyết của bạn ... nó sẽ thực sự lạ, các đối số xử lý không bao gồm các phím được nhấn ORIGINALLY ... nếu bạn liên kết với "onkeyDown" và người dùng nhấn CONTROL (giữ) và sau đó a, sau đó phát hành CONTROL, sự kiện sẽ được kích hoạt 2 lần! trước tiên chỉ bằng "Điều khiển", sau đó với CONTROL + A ... một chút lạ - imho, chúng tôi có thể tìm ra dễ dàng với thread.sleep ... tôi có phải khởi động VS không ngay bây giờ? ;) – TheHe

+1

@TheHe Các đối số trình xử lý bao gồm _key_ được nhấn ban đầu, nhưng không phải là thông tin khóa bổ trợ. Trong WinAPI cũ tốt, các phím bổ trợ được truyền cùng với thông điệp. Điều tương tự cũng xảy ra trong WinForms. Tài liệu thực sự cảnh báo bạn không nên thử và xử lý trạng thái _current_; ví dụ: nếu ứng dụng không phản hồi vì bất kỳ lý do gì (ví dụ: HDD thrashing), trình xử lý có thể được gọi _seconds_ sau khi thực tế. –

Trả lời

3

Vì dường như không có bất kỳ thông tin bổ trợ nào trong sự kiện, bạn có thể tự theo dõi trạng thái của mình trong một số trường và xử lý cả hai KeyUpKeyDown để cập nhật chúng cho phù hợp.

ví dụ:

private bool ctrl = false; 
private void This_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.LeftCtrl) //or switch, also: `LeftCtrl` & `RightCtrl` are treated as separate keys 
     ctrl = true; 
    //etc.. 
} 

private void This_KeyUp(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.LeftCtrl) 
     ctrl = false; 
    //etc.. 
} 

Cho dù điều này thực sự là một ý tưởng tốt tôi không thể nói ...


Nếu bạn muốn xử lý những cử chỉ quan trọng tôi sẽ đề nghị sử dụng phương pháp chuyên dụng như KeyBindings họ chỉ nên bắn khi cử chỉ xảy ra . Đối với các đầu vào khác, bạn cũng có thể muốn xem TextInput trừu tượng hơn và trả về văn bản mà đầu vào được dịch sang.

+0

Điểm tốt về KeyBindings; sẽ điều tra điều đó. –

+0

sry cho câu trả lời kép của tôi - tôi hoàn toàn overread này! – TheHe

2

xin lỗi vì câu trả lời tiêu cực này nhưng ...

sau một chút nghiên cứu nó trở nên rõ ràng với tôi ... sự kiện này được gọi là "KeyDown" không "KeyCombinationDown" vì vậy nó là hoàn toàn không phụ thuộc vào bất kỳ Các sửa đổi được nhấn TRƯỚC KHI ...

Thực ra có một cách phù hợp để đạt được mục tiêu của bạn: Sử dụng mẫu lệnh.

Bạn xác định COMMAND (xem google cho WPF-Commanding) và thêm một KeyBinding vào ứng dụng của bạn, nơi bạn xác định khóa hoặc phím/tổ hợp phím sẽ kích hoạt lệnh ...

Xem ví dụ ở đây: http://msdn.microsoft.com/en-us/library/system.windows.input.keybinding.aspx

IMHO, đây là chỉ cách và ngữ nghĩa tao nhã hơn, quá.

(nếu mẫu này sẽ không hoạt động đối với bạn trong CHUNG, bạn có thể phải sử dụng api gốc với pinvoke).

cổ vũ.

+0

Tôi không thấy điều này là phá hoại. Bạn đề nghị một thay thế, sau khi tất cả. Nó chỉ là nếu bạn google xung quanh, bạn sẽ chỉ nhìn thấy "sử dụng Keyboard.Modifiers", do đó câu hỏi này ... –

+0

Thật không may này có một tác dụng phụ (lỗi?): Khi các ràng buộc khóa phù hợp, sự kiện chính là * luôn luôn * được đánh dấu là đã xử lý, ngay cả khi lệnh không thể thực thi. Vì vậy, trong trường hợp đó, nhấn phím sẽ không bao giờ được dịch sang TextInput. –

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