Windows Phone 7 多点触摸编程
一、基本的程序結構
一個需要響應多點觸控的 Silverlight 應用程序必須將一個處理程序連接到靜態 Touch.FrameReported 事件:
? Touch.FrameReported += OnTouchFrameReported;
FrameReported 事件是靜態 Touch 類的唯一公共成員。處理程序如下所示:
?void OnTouchFrameReported(
? object sender, TouchFrameEventArgs args) {
? ...
}
您可以在應用程序中安裝多個 Touch.FrameReported 事件處理程序,所有這些事件處理程序都會報告應用程序中任何位置的所有觸控事件。
二、事件傳入參數TouchFrameEventArgs
TouchFrameEventArgs 有一個名為 TimeStamp 的公共屬性(我還沒有機會使用)和三個重要的公共方法:
TouchPoint GetPrimaryTouchPoint(UIElement relativeTo)
TouchPointCollection GetTouchPoints(UIElement relativeTo)
void SuspendMousePromotionUntilTouchUp()
GetPrimaryTouchPoint 或 GetTouchPoints 的參數僅用于報告 TouchPoint 對象的位置信息。您可以將空值用于此參數,位置信息相對于整個 Silverlight 應用程序的左上角。
多點觸控支持多個手指同時觸摸屏幕,觸摸屏幕的每個手指(數量存在上限,當前通常為兩個)都是一個觸摸點。主要觸摸點是指在沒有其他手指觸摸屏幕并且未按下鼠標按鈕時觸摸屏幕的手指。用一個手指觸摸屏幕。這是主要觸摸點。
在第一個手指仍觸摸著屏幕時,將第二個手指放在屏幕上。很顯然,第二手指不是主要觸摸點。但現在仍將第二個手指放在屏幕上,抬起第一個手指,然后再將其放回到屏幕上。這是主要觸摸點嗎?不,都不是。僅當沒有其他手指觸摸屏幕時,才會出現主要觸摸點。
在實際的多點觸控應用程序中,您應該注意不要依賴主要觸摸點,因為用戶通常不會重視第一次觸摸的特定意義。僅為實際觸摸屏幕的手指激發事件。對非常接近屏幕但并未觸摸屏幕的手指,不會進行懸停檢測。
基于一個觸摸點或多個觸摸點激發一個特殊的 Touch.FrameReported 事件。從 GetTouchPoints 方法返回的 TouchPointCollection 包含與特定事件關聯的所有觸摸點。從 GetPrimaryTouchPoint 返回的 TouchPoint 始終是一個主要觸摸點。如果沒有與該特定事件關聯的主要觸摸點,GetPrimaryTouchPoint 將返回 null。即使從 GetPrimaryTouchPoint 返回的 TouchPoint 不是 null,它也不會與從 GetTouchPoints 返回的其中一個 TouchPoint 對象是相同對象,但在傳遞給這些方法的參數相同時所有屬性將相同。
TouchPoint 類定義以下四個只讀屬性,這些屬性都由依賴屬性支持:
Action 屬性,類型為 TouchAction(一個具有 Down、Move 和 Up 成員的枚舉)。
Position 屬性,類型為 Point,它相對于作為參數傳遞給 GetPrimaryTouchPoint 或 GetTouchPoints 方法的元素(或相對于參數為 null 的應用程序的左上角)。
Size 屬性,類型為 Size。
TouchDevice 屬性,類型為 TouchDevice。
TouchDevice 對象具有兩個也由依賴屬性支持的只讀屬性:
DirectlyOver 屬性,類型為 DirectlyOver(手指下最上面的元素)。
Id 屬性,類型為 int。
DirectlyOver 不必是傳遞給 GetPrimaryTouchPoint 或 GetTouchPoints 的元素的子項。如果手指在 Silverlight 應用程序內(由 Silverlight 插件對象的尺寸定義),但不在可點擊測試控件覆蓋的范圍內,則此屬性可以為空。(具有空背景刷的面板不可點擊測試。)
若要在多個手指之間區分,ID 屬性至關重要。在特定手指觸摸屏幕時,與該手指關聯的一系列特定事件總是以 Down 操作開始,接著是 Move 事件,最后是 Up 事件。所有這些事件都將與相同的 ID 關聯。(但不要以為主要觸摸點的 ID 值將為 0 或 1。)
大多數重要的多點觸控代碼都會使用 Dictionary 集合,其中 TouchDevice 的 ID 屬性是字典鍵。這是跨事件存儲特定手指信息的方式。
三、涂鴉板例子?
?涂鴉板例子 綜合運用ApplicationBar菜單、多點觸摸和IsolatedStorageFile本地存儲
xaml
View Code <phone:PhoneApplicationPagex:Class="Jot.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"
Orientation="Horizontal">
<TextBlock x:Name="ApplicationTitle" Text="JOT"
Style="{StaticResource PhoneTextNormalStyle}"
Margin="12 0 0 0" />
<TextBlock Name="pageInfoTitle"
Style="{StaticResource PhoneTextNormalStyle}"
Margin="0" />
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<InkPresenter Name="inkPresenter" />
</Grid>
</Grid>
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar>
<!--工具條-->
<shell:ApplicationBarIconButton x:Name="appbarAddButton"
IconUri="/Images/appbar.add.rest.png"
Text="add page"
Click="OnAppbarAddClick" />
<shell:ApplicationBarIconButton x:Name="appbarLastButton"
IconUri="/Images/appbar.back.rest.png"
Text="last page"
Click="OnAppbarLastClick" />
<shell:ApplicationBarIconButton x:Name="appbarNextButton"
IconUri="/Images/appbar.next.rest.png"
Text="next page"
Click="OnAppbarNextClick" />
<shell:ApplicationBarIconButton x:Name="appbarDeleteButton"
IconUri="/Images/appbar.delete.rest.png"
Text="delete page"
Click="OnAppbarDeleteClick" />
<!--菜單欄-->
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="swap colors"
Click="OnAppbarSwapColorsClick" />
<shell:ApplicationBarMenuItem Text="light stroke width"
Click="OnAppbarSetStrokeWidthClick" />
<shell:ApplicationBarMenuItem Text="medium stroke width"
Click="OnAppbarSetStrokeWidthClick" />
<shell:ApplicationBarMenuItem Text="heavy stroke width"
Click="OnAppbarSetStrokeWidthClick" />
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>
cs
View Code using System;using System.Collections.Generic;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
namespace Jot
{
public partial class MainPage : PhoneApplicationPage
{
JotAppSettings appSettings = (Application.Current as App).AppSettings;
Dictionary<int, Stroke> activeStrokes = new Dictionary<int, Stroke>();
public MainPage()
{
InitializeComponent();
inkPresenter.Strokes = appSettings.StrokeCollections[appSettings.PageNumber];
inkPresenter.Background = new SolidColorBrush(appSettings.Background);
// Re-assign ApplicationBar button names
appbarLastButton = this.ApplicationBar.Buttons[1] as ApplicationBarIconButton;
appbarNextButton = this.ApplicationBar.Buttons[2] as ApplicationBarIconButton;
appbarDeleteButton = this.ApplicationBar.Buttons[3] as ApplicationBarIconButton;
TitleAndAppbarUpdate();
Touch.FrameReported += OnTouchFrameReported;
//一個需要響應多點觸控的 Silverlight 應用程序必須將一個處理程序連接到靜態 Touch.FrameReported 事件
}
//處理多點觸摸事件
void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
{
TouchPoint primaryTouchPoint = args.GetPrimaryTouchPoint(null);
if (primaryTouchPoint != null && primaryTouchPoint.Action == TouchAction.Down)
args.SuspendMousePromotionUntilTouchUp();
/*
* foreach 循環枚舉從 GetTouchPoints 返回的 TouchPointCollection 的 TouchPoint 成員。
* (您會希望多點觸控感知 Silverlight 程序能處理多個手指,但您不會希望它在檢測到太多手指時出現故障!)ID 將添加到 Down 事件的字典中,然后從 Up 事件的字典中刪除。
* */
TouchPointCollection touchPoints = args.GetTouchPoints(inkPresenter);
foreach (TouchPoint touchPoint in touchPoints)
{
Point pt = touchPoint.Position;
int id = touchPoint.TouchDevice.Id;
switch (touchPoint.Action)
{
case TouchAction.Down:
Stroke stroke = new Stroke();
stroke.DrawingAttributes.Color = appSettings.Foreground;
stroke.DrawingAttributes.Height = appSettings.StrokeWidth;
stroke.DrawingAttributes.Width = appSettings.StrokeWidth;
stroke.StylusPoints.Add(new StylusPoint(pt.X, pt.Y));
inkPresenter.Strokes.Add(stroke);
activeStrokes.Add(id, stroke);
break;
case TouchAction.Move:
activeStrokes[id].StylusPoints.Add(new StylusPoint(pt.X, pt.Y));
break;
case TouchAction.Up:
activeStrokes[id].StylusPoints.Add(new StylusPoint(pt.X, pt.Y));
activeStrokes.Remove(id);
TitleAndAppbarUpdate();
break;
}
}
}
//新增一個頁面
void OnAppbarAddClick(object sender, EventArgs args)
{
StrokeCollection strokes = new StrokeCollection();
appSettings.PageNumber += 1;
appSettings.StrokeCollections.Insert(appSettings.PageNumber, strokes);
inkPresenter.Strokes = strokes;
TitleAndAppbarUpdate();
}
//上一個頁面
void OnAppbarLastClick(object sender, EventArgs args)
{
appSettings.PageNumber -= 1;
inkPresenter.Strokes = appSettings.StrokeCollections[appSettings.PageNumber];
TitleAndAppbarUpdate();
}
//下一個頁面
void OnAppbarNextClick(object sender, EventArgs args)
{
appSettings.PageNumber += 1;
inkPresenter.Strokes = appSettings.StrokeCollections[appSettings.PageNumber];
TitleAndAppbarUpdate();
}
//刪除當前的頁面
void OnAppbarDeleteClick(object sender, EventArgs args)
{
MessageBoxResult result = MessageBox.Show("Delete this page?", "Jot",
MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
if (appSettings.StrokeCollections.Count == 1)
{
appSettings.StrokeCollections[0].Clear();
}
else
{
appSettings.StrokeCollections.RemoveAt(appSettings.PageNumber);
if (appSettings.PageNumber == appSettings.StrokeCollections.Count)
appSettings.PageNumber -= 1;
inkPresenter.Strokes = appSettings.StrokeCollections[appSettings.PageNumber];
}
TitleAndAppbarUpdate();
}
}
//設置畫筆背景顏色
void OnAppbarSwapColorsClick(object sender, EventArgs args)
{
Color foreground = appSettings.Background;
appSettings.Background = appSettings.Foreground;
appSettings.Foreground = foreground;
inkPresenter.Background = new SolidColorBrush(appSettings.Background);
foreach (StrokeCollection strokeCollection in appSettings.StrokeCollections)
foreach (Stroke stroke in strokeCollection)
stroke.DrawingAttributes.Color = appSettings.Foreground;
}
//設置畫筆的粗細
void OnAppbarSetStrokeWidthClick(object sender, EventArgs args)
{
ApplicationBarMenuItem item = sender as ApplicationBarMenuItem;
if (item.Text.StartsWith("light"))
appSettings.StrokeWidth = 1;
else if (item.Text.StartsWith("medium"))
appSettings.StrokeWidth = 3;
else if (item.Text.StartsWith("heavy"))
appSettings.StrokeWidth = 5;
}
void TitleAndAppbarUpdate()
{
pageInfoTitle.Text = String.Format(" - PAGE {0} OF {1}",
appSettings.PageNumber + 1,
appSettings.StrokeCollections.Count);
appbarLastButton.IsEnabled = appSettings.PageNumber > 0;
appbarNextButton.IsEnabled =
appSettings.PageNumber < appSettings.StrokeCollections.Count - 1;
appbarDeleteButton.IsEnabled = (appSettings.StrokeCollections.Count > 1) ||
(appSettings.StrokeCollections[0].Count > 0);
}
}
}
本地存儲功能封裝的類
View Code using System;using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Media;
using System.Xml.Serialization;
namespace Jot
{
public class JotAppSettings
{
public JotAppSettings()
{
this.PageNumber = 0;
this.Foreground = (Color)Application.Current.Resources["PhoneForegroundColor"];
this.Background = (Color)Application.Current.Resources["PhoneBackgroundColor"];
this.StrokeWidth = 3;
}
// Public properties -- the actual application settins
public List<StrokeCollection> StrokeCollections { get; set; }
public int PageNumber { set; get; }
public Color Foreground { set; get; }
public Color Background { set; get; }
public int StrokeWidth { set; get; }
public static JotAppSettings Load()
{
JotAppSettings settings;
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
if (iso.FileExists("settings.xml"))
{
IsolatedStorageFileStream stream = iso.OpenFile("settings.xml", FileMode.Open);
StreamReader reader = new StreamReader(stream);
XmlSerializer ser = new XmlSerializer(typeof(JotAppSettings));
settings = ser.Deserialize(reader) as JotAppSettings;
reader.Close();
}
else
{
// Create and initialize new JotAppSettings object
settings = new JotAppSettings();
settings.StrokeCollections = new List<StrokeCollection>();
settings.StrokeCollections.Add(new StrokeCollection());
}
iso.Dispose();
return settings;
}
public void Save()
{
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = iso.CreateFile("settings.xml");
StreamWriter writer = new StreamWriter(stream);
XmlSerializer ser = new XmlSerializer(typeof(JotAppSettings));
ser.Serialize(writer, this);
writer.Close();
iso.Dispose();
}
}
}
app.xaml
View Code <Applicationx:Class="Jot.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
<!--Application Resources-->
<Application.Resources>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>
app.xaml.cs
View Code using System;using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
namespace Jot
{
public partial class App : Application
{
// Application Settings
public JotAppSettings AppSettings { set; get; }
// Easy access to the root frame
public PhoneApplicationFrame RootFrame { get; private set; }
// Constructor
public App()
{
// Global handler for uncaught exceptions.
// Note that exceptions thrown by ApplicationBarItem.Click will not get caught here.
UnhandledException += Application_UnhandledException;
// Standard Silverlight initialization
InitializeComponent();
// Phone-specific initialization
InitializePhoneApplication();
}
// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
AppSettings = JotAppSettings.Load();
}
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
AppSettings = JotAppSettings.Load();
}
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
AppSettings.Save();
}
// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
AppSettings.Save();
}
// Code to execute if a navigation fails
void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// A navigation has failed; break into the debugger
System.Diagnostics.Debugger.Break();
}
}
// Code to execute on Unhandled Exceptions
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// An unhandled exception has occurred; break into the debugger
System.Diagnostics.Debugger.Break();
}
}
#region Phone application initialization
// Avoid double-initialization
private bool phoneApplicationInitialized = false;
// Do not add any additional code to this method
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
// Create the frame but don't set it as RootVisual yet; this allows the splash
// screen to remain active until the application is ready to render.
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
// Handle navigation failures
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
// Ensure we don't initialize again
phoneApplicationInitialized = true;
}
// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
#endregion
}
}
轉載于:https://www.cnblogs.com/linzheng/archive/2011/02/17/1957446.html
總結
以上是生活随笔為你收集整理的Windows Phone 7 多点触摸编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 两台Oracle服务器,使用udl测试连
- 下一篇: 数据库入门浅析:ASP.NET与MySQ