您的位置:首页 > 其它

(WPF学习记录)第九章 Routed输入事件

2008-12-22 14:28 225 查看
输入事件是用delegate定义的,其第二个参数类型是RoutedEventArgs的后代类,中间经过InputEventArgs类。下面的类层次图完整的描绘出InputEventArgs以下的类别:

Object
EventArgs
RoutedEventArgs
InputEventArgs
KeyboardEventArgs
KeyboardFocusChangedEventArgs
KeyEventArgs
MouseEventArgs
MouseButtonEventArgs
MouseWheelEventArgs
QueryCursorEventArgs
StylusEventArgs
StylusButtonEventArgs
StylusDownEventArgs
StylusSystemGestureEventArgs
TextCompositionEventArgs

用户点击鼠标按钮,谁会得到事件?传统的答案是,“在鼠标游标位置下,前景的、可见的、且有效的控件”。如果某个按钮是在窗口中,且用户点击此按钮,则按钮得到事件。
但是在WPF中,这种简单的方式却无法运作良好。按钮不只是按钮,按钮含有内容,内容可以是面板,里面放置形状、图像和文字区块。这些元素都具有接收鼠标事件的能力。有时候让这些元素处理各自的鼠标事件很适当,有时候则不适当。如果一个按钮表面是由许多元素所组成,让按钮去处理事件似乎很合理。如果存在一个机制可以将此事件从形状、图像、文字区块的按钮的面板,一路route到按钮,这样子会很有帮助。
第01个小程序:Examine Routed Events(ExamineRoutedEvents.cs)

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

namespace Chapter09

{

public class ExamineRoutedEvents: Application

{

static readonly FontFamily fontfam = new FontFamily("Lucida Console");

const string strFormat = "{0,-30} {1,-15}{2,-15} {3,-15}";

StackPanel stackOutput;

DateTime dtLast;

[STAThread]

public static void Main()

{

ExamineRoutedEvents app = new ExamineRoutedEvents();

app.Run();

}

protected override void OnStartup(StartupEventArgs args)

{

base.OnStartup(args);

// 创建窗口

Window win = new Window();

win.Title = "Examine Routed Events";

// 创建Grid,作为窗口的Content

Grid grid = new Grid();

win.Content = grid;

// 3行

RowDefinition rowdef = new RowDefinition();

rowdef.Height = GridLength.Auto;

grid.RowDefinitions.Add(rowdef);

rowdef = new RowDefinition();

rowdef.Height = GridLength.Auto;

grid.RowDefinitions.Add(rowdef);

rowdef = new RowDefinition();

rowdef.Height = new GridLength(100, GridUnitType.Star);

grid.RowDefinitions.Add(rowdef);

// 创建按钮,加入到Grid

Button btn = new Button();

btn.HorizontalAlignment = HorizontalAlignment.Center;

btn.Margin = new Thickness(24);

btn.Padding = new Thickness(24);

grid.Children.Add(btn);

// 创建TextBlock,作为Button的Content

TextBlock text = new TextBlock();

text.FontSize = 24;

text.Text = win.Title;

btn.Content = text;

// 创建标题

TextBlock textHeadings = new TextBlock();

textHeadings.FontFamily = fontfam;

textHeadings.Inlines.Add(new Underline(new Run(

String.Format(strFormat,

"Routed Event", "sender", "Source", "OriginalSource"))));

grid.Children.Add(textHeadings);

Grid.SetRow(textHeadings, 1);

// 创建ScrollViewer.

ScrollViewer scroll = new ScrollViewer();

grid.Children.Add(scroll);

Grid.SetRow(scroll, 2);

// 创建StackPanel以显示事件

stackOutput = new StackPanel();

scroll.Content = stackOutput;

// 添加事件处理器

UIElement[] els = { win, grid, btn, text };

foreach (UIElement el in els)

{

// 键盘

el.PreviewKeyDown += AllPurposeEventHandler;

el.PreviewKeyUp += AllPurposeEventHandler;

el.PreviewTextInput += AllPurposeEventHandler;

el.KeyDown += AllPurposeEventHandler;

el.KeyUp += AllPurposeEventHandler;

el.TextInput += AllPurposeEventHandler;

// 鼠标

el.MouseDown += AllPurposeEventHandler;

el.MouseUp += AllPurposeEventHandler;

el.PreviewMouseDown += AllPurposeEventHandler;

el.PreviewMouseUp += AllPurposeEventHandler;

// 手写笔

el.StylusDown += AllPurposeEventHandler;

el.StylusUp += AllPurposeEventHandler;

el.PreviewStylusDown += AllPurposeEventHandler;

el.PreviewStylusUp += AllPurposeEventHandler;

// 点击

el.AddHandler(Button.ClickEvent,

new RoutedEventHandler(AllPurposeEventHandler));

}

// 显示窗口

win.Show();

}

void AllPurposeEventHandler(object sender, RoutedEventArgs args)

{

// 一定时间间隔(此处100m秒)后增加空白行

DateTime dtNow = DateTime.Now;

if (dtNow - dtLast > TimeSpan.FromMilliseconds(100))

stackOutput.Children.Add(new TextBlock(new Run(" ")));

dtLast = dtNow;

// 显示事件信息

TextBlock text = new TextBlock();

text.FontFamily = fontfam;

text.Text = String.Format(strFormat,

args.RoutedEvent.Name,

TypeWithoutNamespace(sender),

TypeWithoutNamespace(args.Source),

TypeWithoutNamespace(args.OriginalSource));

stackOutput.Children.Add(text);

(stackOutput.Parent as ScrollViewer).ScrollToBottom(); //滚动条滚动至最下

}

string TypeWithoutNamespace(object obj)

{

// 去掉字符串的前面赘余部分,如原为System.Windows.Window,

// 将其以“.”为标记分割处理,后返回Window

string[] astr = obj.GetType().ToString().Split('.');

return astr[astr.Length-1];

}

}

}

运行结果如下:



第02个小程序:绘制椭圆(DrawCircles.cs)

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Shapes;

namespace chapter09

{

public class DrawCircles : Window

{

Canvas canv;

// 绘图相关的字段

bool isDrawing;

Ellipse elips;

Point ptCenter;

// 拖拽相关的字段

bool isDragging;

FrameworkElement elDragging;

Point ptMouseStart, ptElementStart;

[STAThread]

public static void Main()

{

Application app = new Application();

app.Run(new DrawCircles());

}

public DrawCircles()

{

Title = "绘制椭圆";

Content = canv = new Canvas();

}

// 按下鼠标左键时

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs args)

{

base.OnMouseLeftButtonDown(args);

if (isDragging)

return;

// 创建一新的椭圆对象,并加入到canvas中

ptCenter = args.GetPosition(canv);

elips = new Ellipse();

elips.Stroke = SystemColors.WindowTextBrush;

elips.StrokeThickness = 1;

elips.Width = 0;

elips.Height = 0;

canv.Children.Add(elips);

Canvas.SetLeft(elips, ptCenter.X);

Canvas.SetTop(elips, ptCenter.Y);

// 捕捉鼠标,为稍后作准备

CaptureMouse();

isDrawing = true;

}

// 按下鼠标右键时

protected override void OnMouseRightButtonDown(MouseButtonEventArgs args)

{

base.OnMouseRightButtonDown(args);

if (isDrawing)

return;

// 得到点击事件,为稍后作准备

ptMouseStart = args.GetPosition(canv);

elDragging = canv.InputHitTest(ptMouseStart) as FrameworkElement;

if (elDragging != null)

{

ptElementStart = new Point(Canvas.GetLeft(elDragging),

Canvas.GetTop(elDragging));

isDragging = true;

}

}

protected override void OnMouseDown(MouseButtonEventArgs args)

{

base.OnMouseDown(args);

// 按下鼠标中键,切换椭圆填充色(红色与透明色)

if (args.ChangedButton == MouseButton.Middle)

{

Shape shape = canv.InputHitTest(args.GetPosition(canv)) as Shape;

if (shape != null)

shape.Fill = (shape.Fill == Brushes.Red ?

Brushes.Transparent : Brushes.Red);

}

}

// 鼠标移动时

protected override void OnMouseMove(MouseEventArgs args)

{

base.OnMouseMove(args);

Point ptMouse = args.GetPosition(canv);

// 改变椭圆的位置和尺寸

if (isDrawing)

{

double dRadius = Math.Sqrt(Math.Pow(ptCenter.X - ptMouse.X, 2) +

Math.Pow(ptCenter.Y - ptMouse.Y, 2));

Canvas.SetLeft(elips, ptCenter.X - dRadius);

Canvas.SetTop(elips, ptCenter.Y - dRadius);

elips.Width = 2 * dRadius;

elips.Height = 2 * dRadius;

}

// 移动椭圆

else if (isDragging)

{

Canvas.SetLeft(elDragging,

ptElementStart.X + ptMouse.X - ptMouseStart.X);

Canvas.SetTop(elDragging,

ptElementStart.Y + ptMouse.Y - ptMouseStart.Y);

}

}

protected override void OnMouseUp(MouseButtonEventArgs args)

{

base.OnMouseUp(args);

// 结束绘图操作

if (isDrawing && args.ChangedButton == MouseButton.Left)

{

elips.Stroke = Brushes.Blue;

elips.StrokeThickness = Math.Min(20, elips.Width / 2);

elips.Fill = Brushes.Red;

isDrawing = false;

ReleaseMouseCapture();

}

// 结束捕捉操作

else if (isDragging && args.ChangedButton == MouseButton.Right)

{

isDragging = false;

}

}

protected override void OnTextInput(TextCompositionEventArgs args)

{

base.OnTextInput(args);

// 按下Escape,结束绘图或拖拽

if (args.Text.IndexOf('/x1B') != -1)

{

if (isDrawing)

ReleaseMouseCapture();

else if (isDragging)

{

Canvas.SetLeft(elDragging, ptElementStart.X);

Canvas.SetTop(elDragging, ptElementStart.Y);

isDragging = false;

}

}

}

protected override void OnLostMouseCapture(MouseEventArgs args)

{

base.OnLostMouseCapture(args);

// 不正常地结束绘图,将此椭圆删除

if (isDrawing)

{

canv.Children.Remove(elips);

isDrawing = false;

}

}

}

}

按下鼠标左键(拖拽)绘制椭圆;按下鼠标右键拖拽,移动椭圆;按下鼠标中键,改变填充色。

运行效果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: