(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;
}
}
}
}
按下鼠标左键(拖拽)绘制椭圆;按下鼠标右键拖拽,移动椭圆;按下鼠标中键,改变填充色。
运行效果如下:
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;
}
}
}
}
按下鼠标左键(拖拽)绘制椭圆;按下鼠标右键拖拽,移动椭圆;按下鼠标中键,改变填充色。
运行效果如下:
相关文章推荐
- WPF学习系列024: 3.3 路由事件
- (WPF学习记录)第八章 Dependency Property
- 汇编语言学习记录--输入输出字符串
- WPF学习总结和记录(五)-Menu
- 流畅的python第九章符合Python风格的对象学习记录
- JavaScript Event学习第九章 鼠标事件
- 天天记录 - Android Touch事件学习 - 修改MotionEvent的值
- PyQt5学习记录(7)---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果
- WPF 学习记录——Application
- WPF 学习记录——The Concept of Content
- ios学习记录 day27 UI 5 事件处理
- CocosCreator项目学习系列<二>关于Button(添加事件)输入控制交互条件的触发_实现虚拟按钮控制_JavaScript
- Unity学习笔记 之 触发Unity UI 的 Button 事件 的代码记录
- 学习记录-对Qt的QLineEdit进行输入字符限制
- wpf学习笔记(1)《都是自己根据网络资源学习记录的仅供参考》
- wpf学习笔记(3)《都是自己根据网络资源学习记录的仅供参考》
- wpf学习笔记(2)《都是自己根据网络资源学习记录的仅供参考》
- input子系统学习笔记九 evdev输入事件驱动分析
- WPF 学习笔记 - 6. RoutedEvent
- WPF学习总结和记录(七)-尺寸缩放 定位 上