2009年4月7日 星期二

[WPF] Routed 輸入事件

Routed Event

假設 element tree 如下:

Window
|
Grid
|
---------------------------
| | |
Button TextBlock ScrollViewer
| |
TextBlock StackPanel
|
TextBlock


而 Routed Event Handler 大概長以下這樣:
void functionName(object sender, RoutedEventArgs args)
{ ....(事件處理)... }
其中參數的部份有幾個重點:
  • sender:此物件將 event 送到 application 中

  • args.Source:真正導致 event 發生的 element


若是在 element tree 中左下角的 TextBlock 按一下滑鼠右鍵,分別會產生出以下的 event:
PreviewMouseDown -> MouseDown
其中 sender 的部份,觸發 event 順序如下:
  • PreviewMouseDown:Window -> Grid -> Button -> TextBlock

  • MouseDown:TextBlock -> Button -> Grid -> Window

因此從上面可以知道,PreviewMouseDown 是屬於 tunneling eventMouseDown 屬於 bubbling event

而透過 Event Routing 的特性,若是要讓較上層的 element 先處理 mouse down 的動作,可以撰寫在 PreviewMouseDown 中。



Mouse Event

MouseDown 與 MouseUp 不一定會同時出現

例如:在視窗中按下按鈕,會發生 MouseDown event,但如果持續按著不放,再離開視窗的範圍後再放開滑鼠,不會出現 MouseUp event。

因此,若要解決此問題,可以透過在 UIElementContentElement 中所定義的 CaptureMouse 方法來解決。

當呼叫了 CaptureMouse 方法後,即使滑鼠離開視窗,視窗也會持續的接收 MouseMove 與 MouseUp 事件。

最後當 MouseUp 事件處理完成後,可以呼叫 ReleaseMouseCapture 或是設定 Mouse.Capture 為 null 來釋放所捕捉的滑鼠。



Keyboard Event

在 WPF 中,keyboard event 都會下放到 TextBox、RichTextBox、ScrollViewer 這一類的控制項中作處理。

需要注意的是,只有當 element 或是控制項具有鍵盤焦點時,才會是 keyboard event 的來源。

此外,keyboard event 亦屬於 routed event,因此具有焦點的 element 的所有上層 element,都可以參與 keyboard event,且其 IsKeyboardFocusWithin 屬性都會是 true。

當 element 獲得 or 失去焦點時,會觸發 GotKeyboardFocusLostKeyboardfocus 事件,也都是 routed event;此外,由於兩個事件屬於 tunneling event,因此在 element tree 中上方的 element 可以先察覺到焦點的改變。

而 Keyboard 的輸入包含了三種 event,發生順序如下:
  1. KeyDown (參數型態為 KeyEventArgs)

  2. TextInput (參數型態為 TextCompositionEventArgs)

  3. KeyUp (參數型態為 KeyEventArgs)

但比較需要注意的是,若按下的是「Shift」、方向鍵、或是其他功能鍵,並不會產生 TextInput 事件。舉例來說,或先按下 Shift 再按 A,一共會觸發兩次 KeyDown 事件、一次 TextInput 事件、兩次 KeyUp 事件。

沒有留言:

張貼留言