Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Important
InkCanvas, InkToolbarve InkPresenter deneysel API'lerdir. Mürekkeple ek açıklama desteği Windows Uygulama SDK'sı 2.4.1-experimental sürümüne eklendi. Bu makalede, bir bağlama şeklinizi değiştiren InkToolbar açıklanmaktadır. Bu API'ler kararlı kanalda kullanılamaz. Bunlar gelecekteki bir sürümde değişebilir veya kaldırılabilir. Bunları üretim uygulamalarında kullanmayın.
Kullanıcıların kalem, fare veya dokunmayla mürekkep çizmesine izin vermek için deneysel InkCanvas denetimi kullanın. Kullanıcılara renk ve boyut seçenekleriyle tükenmez kalem, kurşun kalem, vurgulayıcı ve silgi vermek için bir InkToolbar ekleyin. Her tuvalin mürekkep girişini toplayan ve görselleştiren bir InkPresenter öğesi vardır. Sunucunun InkStrokeContainer çizgileri depolar, böylece kodda mürekkep kaydedebilir, yükleyebilir, kopyalayabilir ve oluşturabilirsiniz.
Denetimleri denemek için Windows Uygulama SDK'sı 2.5.4 deneysel paketini ve eşleşen çalışma zamanını yükleyin. İndirme bağlantıları ve kurulum bilgileri için bkz. En son Windows Uygulama SDK'sı indirmeleri.
Doğru kontrol bu mu?
Kullanıcılar şu durumlarda mürekkep tuvaline ihtiyaç duyduğunda:
- El yazısıyla not alın veya içeriğe açıklamalar ekleyin.
- Eskiz çizin, diyagram çizin veya adını imzalayın.
- Uygulamanızda kaydedebileceğiniz ve daha sonra düzenlemenize olanak tanıyan serbest içerik oluşturun.
Deneysel mürekkepleme API'leri el yazısı veya şekil tanıma içermez. Metin toplamak için bir metin kutusu kullanın.
Üretim uygulamasında mürekkeple yazma gerekiyorsa, kararlı kanalda bu denetimlerin durumu ve alternatifler için Bilinen denetim boşlukları bölümüne bakın.
Mürekkeple yazma modelini anlama
Mürekkep oluşturma API'leri birlikte çalışır:
| API | Rol |
|---|---|
InkCanvas |
Mürekkep görüntüleyen ve mürekkep girişi alan XAML öğesi.
InkPresenter özelliği, tuvalin sunumlayıcısını döndürür. |
InkPresenter |
Mürekkep girişi toplar, çizgileri oluşturur ve giriş ayarlarını ve varsayılan çizim özniteliklerini tutar. Kendiniz InkPresenter oluşturamazsınız.
InkCanvas.InkPresenter üzerinden alın. |
InkStrokeContainer |
Tuş vuruşlarını depolar. Bunu kullanarak mürekkep kaydedin, yükleyin, seçin, kopyalayın ve yapıştırın.
InkPresenter.StrokeContainer'den alın. |
InkToolbar |
Kullanıcıların kalem, kurşun kalem, vurgulayıcı veya silgi seçmesini ve mürekkep rengini ve boyutunu değiştirmesini sağlayan isteğe bağlı araç çubuğu. |
InkCanvas öğesinin Background özelliği yoktur. Çizim alanına bir arka plan ve kenarlık vermek için, tuvali örneğin bir Border kapsayıcısının içine yerleştirin ve boyutu kapsayıcıda ayarlayın. Varsayılan mürekkep rengi siyahtır, bu nedenle bu makaledeki örneklerde beyaz arka plan kullanılır.
Bu türlerden birkaçı, Windows.UI.Input.Inking ad alanındaki türlerle aynı adlara sahiptir; örneğin InkPresenter, InkStrokeContainer ve InkHighContrastAdjustment. Mürekkep oluşturma denetimleri Microsoft.UI.Xaml.Controls sürümlerini kullanır. Vuruşlar ve çizim öznitelikleri, Windows Çalışma Zamanı türlerini, örneğin InkDrawingAttributes, InkStrokeBuilder ve InkStroke gibi, kullanmaya devam eder. Her iki ad alanını da içeri aktarır ve belirsiz bir ad kullanırsanız, C# derleyicisi CS0104 hatasını bildirir.
Bu makaledeki örnekler, Windows.UI.Input.Inking içeri aktarır ve ihtiyaç duydukları Microsoft.UI.Xaml.Controls türleri için diğer ad yönergelerini kullanır:
using Microsoft.UI.Xaml.Controls;
using InkDrawingAttributes = Windows.UI.Input.Inking.InkDrawingAttributes;
using InkStroke = Windows.UI.Input.Inking.InkStroke;
WinUI 3 Galerisi örneğinde olduğu gibi, hem ad alanlarını içeri aktarabilir hem de belirsiz türler için tam adları kullanabilirsiniz.
InkPresenter ayrıca, bu makalenin kapsamadığı alt düzey API'ler de sağlar:
-
StrokeInputbir çizgi başladığında, devam ettiğinde, sona erdiğinde veya iptal edildiğinde olayları tetikler. -
UnprocessedInputpresenter’ın mürekkep olarak işlemediği giriş için işaretçi olaylarını tetikler. -
InputConfigurationsunum bileşeninin kalemin silgisinden ve birincil gövde düğmesinden gelen girişleri işleyip işlemediğini ayarlar. -
InputProcessingConfigurationgirişin mürekkep çizip çizmediğini, mürekkebi silip silmediğini veya işlenmediğini ve sunanın sağ sürükleme girişini nasıl işlediğini ayarlar. -
ActivateCustomDrying, kaydedilmiş mürekkebi kendileri işleyen uygulamalar için birInkSynchronizerdöndürür.
Projenizi ayarlayın
Mürekkepleme API'leri deneysel olarak işaretlenmiştir. Bunları bir C# projesinde kullandığınızda, C# derleyicisi cs8305 uyarısını ve XAML derleyicisi uyarı WMC1501 bildirir. Projeniz uyarıları hata olarak ele alırsa, bu uyarılar derlemeyi durdurur.
Deneysel API'leri kullanmaya karar verdikten sonra bu uyarıları gizleyebilirsiniz. C# proje dosyanıza (.csproj) aşağıdaki özellikleri ekleyin:
<PropertyGroup>
<NoWarn>$(NoWarn);CS8305</NoWarn>
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);WMC1501</MSBuildWarningsAsMessages>
</PropertyGroup>
Bu makaledeki örneklerde C# kullanılır. Her eksiksiz örnek, bir sayfanın XAML'sini ve sayfanın code-behind sınıfını, MainPage, gösterir.
Mürekkep tuvali oluşturun
![]()
WinUI 3 Galeri uygulaması, WinUI denetimlerinin ve özelliklerinin etkileşimli örneklerini içerir. uygulamayı Microsoft Store adresinden alın veya GitHub üzerindeki kaynak koduna göz atın.
Aşağıdaki örnek, bir tuvali beyaz bir Border içine yerleştirir. Code-behind kodu, kullanıcıların kalem, fare veya dokunmayla çizim yapabilecekleri giriş cihazı türlerini ayarlar.
<Border
Height="300"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
using Microsoft.UI.Xaml.Controls;
using Windows.UI.Core;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
// Mouse input doesn't draw ink by default. Choose every device type that can draw ink.
inkCanvas.InkPresenter.InputDeviceTypes =
CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
}
}
Bunları kısa tutmak için, daha sonraki bazı örnekler bu kodu yinelemez. Kullanıcıların fareyle çizim yaptığı her sayfada InputDeviceTypes ayarlayın.
Mürekkep araç çubuğunu bağlayın
Tuvalin yakınına bir InkToolbar yerleştirin ve ikisini bağlayacak şekilde InkToolbar öğesinin TargetInkCanvas özelliğini ayarlayın:
<StackPanel Spacing="8">
<InkToolbar
x:Name="inkToolbar"
AutomationProperties.Name="Drawing tools"
TargetInkCanvas="{x:Bind inkCanvas}" />
<Border
Height="300"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
Windows Uygulama SDK'sı 2.5.4-experimental sürümünden başlayarak, bunun yerine TargetInkPresenter özelliğini ayarlayarak bir araç çubuğunu doğrudan bir InkPresenter öğesine bağlayabilirsiniz. Bunu kodda ayarlayın:
inkToolbar.TargetInkPresenter = inkCanvas.InkPresenter;
XAML'de de ayarlayabilirsiniz: TargetInkPresenter="{x:Bind inkCanvas.InkPresenter}". İki hedef özelliğinden yalnızca birini ayarlayın.
Araç çubuğu varsayılan olarak tükenmez kalem, kalem, vurgulayıcı, silgi ve şablon (cetvel) düğmelerini gösterir. Hangi düğmelerin görüneceğini değiştirmek için bkz. Mürekkep araç çubuğunu özelleştirme.
Giriş cihazlarını seçin
InputDeviceTypes özelliği, Windows.UI.Core ad alanındaki CoreInputDeviceTypes bayrak numaralandırmasını kullanır. Fare girişi varsayılan olarak mürekkeple çizim yapmaz. Mürekkebi hangi cihazların kullanacağını seçmek için değerleri birleştirin:
// Add mouse input and keep the other device types.
inkCanvas.InkPresenter.InputDeviceTypes |= CoreInputDeviceTypes.Mouse;
// Stop accepting ink from touch input.
inkCanvas.InkPresenter.InputDeviceTypes &= ~CoreInputDeviceTypes.Touch;
// Check whether pen input is enabled.
bool isPenEnabled = inkCanvas.InkPresenter.InputDeviceTypes.HasFlag(CoreInputDeviceTypes.Pen);
Her cihazdan mürekkep toplamayı durdurmak, örneğin kullanıcıların değiştiremediği bir çizimi göstermek için, IsInputEnabled öğesini false olarak ayarlayın:
inkCanvas.InkPresenter.IsInputEnabled = false;
Kullanıcıların araç çubuğundan bir giriş cihazını açmasına veya kapatmasına izin vermek için bkz. Özel geçiş anahtarı ekleme.
Çizim özniteliklerini ayarlama
Renk, boyut ve kalem ucu şekli gibi çizim öznitelikleri, vuruşların nasıl görüneceğini denetler. Windows Çalışma Zamanı InkDrawingAttributes sınıfını kullanırlar. Yeni vuruşların özniteliklerini değiştirmek için CopyDefaultDrawingAttributes öğesini çağırın, kopyayı değiştirin ve UpdateDefaultDrawingAttributes öğesine iletin:
InkDrawingAttributes attributes = inkCanvas.InkPresenter.CopyDefaultDrawingAttributes();
attributes.Color = Colors.DarkBlue;
attributes.Size = new Size(4, 4);
inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(attributes);
Colors, Microsoft.UI ad alanındadır ve Size, Windows.Foundation ad alanındadır. Yeni öznitelikler, kullanıcıların işlev çağrısından sonra çizecekleri vuruşlar için geçerlidir. Mevcut çizgiler özniteliklerini korur.
Bir InkToolbar bağladığınızda, çizim özniteliklerini etkin araç ve onun renk ve boyut ayarları belirler. Geçerli öznitelikleri okumak için araç çubuğunun InkDrawingAttributes özelliğini kullanın.
Kalem ön ayarları oluştur
Araç çubuğu kullanmıyorsanız, kendi kalem ön ayarlarınızı sunabilirsiniz. Aşağıdaki örnek, kullanıcı ön ayar seçtiğinde veya boyutu değiştirdiğinde tükenmez kalem, kurşun kalem, vurgulayıcı veya hat özniteliklerini uygular.
<StackPanel Spacing="12">
<RadioButtons
x:Name="presetButtons"
Header="Pen preset"
MaxColumns="4"
SelectedIndex="0"
SelectionChanged="PresetButtons_SelectionChanged">
<x:String>Ballpoint</x:String>
<x:String>Pencil</x:String>
<x:String>Highlighter</x:String>
<x:String>Calligraphy</x:String>
</RadioButtons>
<Slider
x:Name="sizeSlider"
Width="240"
HorizontalAlignment="Left"
Header="Size"
Maximum="16"
Minimum="1"
Value="4"
ValueChanged="SizeSlider_ValueChanged" />
<Border
Width="480"
Height="280"
HorizontalAlignment="Left"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
using System;
using System.Numerics;
using Microsoft.UI;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Windows.Foundation;
using Windows.UI.Core;
using InkDrawingAttributes = Windows.UI.Input.Inking.InkDrawingAttributes;
using PenTipShape = Windows.UI.Input.Inking.PenTipShape;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
inkCanvas.InkPresenter.InputDeviceTypes =
CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
ApplyPreset();
}
private void PresetButtons_SelectionChanged(object sender, SelectionChangedEventArgs e) => ApplyPreset();
private void SizeSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e) => ApplyPreset();
private void ApplyPreset()
{
// SelectionChanged and ValueChanged can occur while the page is still loading.
if (inkCanvas is null || presetButtons is null || sizeSlider is null)
{
return;
}
double size = sizeSlider.Value;
InkDrawingAttributes attributes;
switch (presetButtons.SelectedItem as string)
{
case "Pencil":
// CreateForPencil returns attributes for pencil-style strokes.
attributes = InkDrawingAttributes.CreateForPencil();
attributes.Color = Colors.DimGray;
attributes.Size = new Size(size, size);
break;
case "Highlighter":
attributes = new InkDrawingAttributes
{
Color = Colors.Yellow,
DrawAsHighlighter = true,
PenTip = PenTipShape.Rectangle,
Size = new Size(size, size * 3),
};
break;
case "Calligraphy":
attributes = new InkDrawingAttributes
{
Color = Colors.DarkBlue,
PenTip = PenTipShape.Rectangle,
Size = new Size(Math.Max(1, size / 2), size * 2),
// Rotate the nib 45 degrees so the stroke width changes with the stroke direction.
PenTipTransform = Matrix3x2.CreateRotation(MathF.PI / 4),
};
break;
default:
attributes = new InkDrawingAttributes
{
Color = Colors.Black,
PenTip = PenTipShape.Circle,
Size = new Size(size, size),
};
break;
}
// The new attributes apply to strokes that the user draws after this call.
inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(attributes);
}
}
-
InkDrawingAttributes.CreateForPencilkalem vuruşlarının özniteliklerini döndürür.Kindözelliği salt okunur olduğundan kalem öznitelikleri oluşturmak için bu yöntemi kullanın. -
DrawAsHighlighterçizgiyi vurgulayıcı katmanı olarak işler. -
PenTipkalem ucunun şeklini ayarlar vePenTipTransformonu döndürür veya ölçeklendirir. Döndürülmüş dikdörtgen uç, kaligrafi tarzı çizgiler üretir.
Mürekkep ek açıklamalarındaki değişikliklere yanıt verme
Sunucu, kullanıcı vuruşlar çizdikten sonra StrokesErased ve kullanıcı bunları sildikten sonra StrokesCollected yükseltir. Her olayın argümanlarındaki Strokes özelliği etkilenen vuruşları içerir. Aşağıdaki kod, TextBlock adlı bir strokeCountText içinde vuruş sayısını güncel tutar:
inkCanvas.InkPresenter.StrokesCollected += (sender, args) => UpdateStrokeCount();
inkCanvas.InkPresenter.StrokesErased += (sender, args) => UpdateStrokeCount();
private void UpdateStrokeCount()
{
int count = inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count;
strokeCountText.Text = $"{count} strokes";
}
Bu olaylar, kullanıcılar mürekkeple çizim yaptığında veya mürekkebi sildiğinde gerçekleşir. Koddaki çizgileri değiştirdiğinizde, örneğin LoadAsync, AddStroke veya Clear ile, aramadan sonra kullanıcı arabiriminizi güncelleştirin.
Mürekkebi kaydet ve yükle
InkStrokeContainer mürekkebi Ink Serialized Format (ISF) biçiminde kaydeder. Verilerin nasıl depolandığını seçmek için SaveAsync öğesine bir InkPersistenceFormat değeri geçirin:
| Format | Çıkış |
|---|---|
GifWithEmbeddedIsf |
Mürekkep verilerini içeren bir GIF görüntüsü. Resim görüntüleyicileri dosyayı görüntüleyebilir ve uygulamanız mürekkep verisini düzenlemek üzere yeniden yükleyebilir. |
Isf |
Görüntü olmadan yalnızca mürekkep verileri. Bu en kompakt biçimdir. |
Adı InkCanvas olan inkCanvas içeren bir sayfanın arkasındaki koda aşağıdaki yöntemleri ekleyin.
SaveInkAsync, bir dosyaya mürekkep yazar ve LoadInkAsync tuvaldeki mürekkebi bir dosyadaki mürekkeple değiştirir.
LoadAsync yüklü vuruşları eklemeden önce mevcut vuruşları kaldırır, bu nedenle önce Clear çağrısı yapmanız gerekmez.
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.UI.Xaml.Controls;
using Windows.Storage.Streams;
using InkPersistenceFormat = Windows.UI.Input.Inking.InkPersistenceFormat;
public sealed partial class MainPage : Page
{
private async Task SaveInkAsync(string path)
{
InkStrokeContainer container = inkCanvas.InkPresenter.StrokeContainer;
// File.Create replaces any existing file, so the file contains only the new ink.
using FileStream fileStream = File.Create(path);
using IOutputStream output = fileStream.AsOutputStream();
// GifWithEmbeddedIsf writes a GIF image that also contains the editable ink data.
await container.SaveAsync(output, InkPersistenceFormat.GifWithEmbeddedIsf);
await output.FlushAsync();
}
private async Task LoadInkAsync(string path)
{
InkStrokeContainer container = inkCanvas.InkPresenter.StrokeContainer;
using FileStream fileStream = File.OpenRead(path);
using IInputStream input = fileStream.AsInputStream();
// LoadAsync removes the current strokes before it adds the loaded strokes.
await container.LoadAsync(input);
}
}
AsOutputStream ve AsInputStream, .NET akışlarını SaveAsync ve LoadAsync'ün kullandığı Windows Çalışma Zamanı akış türlerine dönüştürür. Bu Windows Çalışma Zamanı yöntemlerini beklemek için dosyanın using System; yönergesine ihtiyacı vardır. Bu olmadan, derleyici CS4036 hatasını bildirir.
Kullanıcıların dosya seçmesine izin vermek için, seçilen dosyanın yolunu döndüren Windows Uygulama SDK'sı dosya seçicilerini kullanın. Daha fazla bilgi için bkz. Windows Uygulama SDK'sı seçiciyle dosya kaydetme ve Windows Uygulama SDK'sı seçicilerle dosya ve klasörleri açma.
Mürekkebi bellekte tutmak için, örneğin aynı oturumda daha sonra geri yüklemek üzere, bunu bir InMemoryRandomAccessStream içine kaydedin. Akışın GetOutputStreamAt(0) sonucunu SaveAsync öğesine geçirin ve LoadAsync sonucunu GetInputStreamAt(0) öğesine geçirin. WinUI 3 Galerisi örneği bu yaklaşımı kullanır.
Mürekkebi kopyala ve yapıştır
InkStrokeContainer vuruşları panoya kopyalayıp panodaki mürekkep girişini yapıştırabilir.
CopySelectedToClipboard yalnızca seçili çizgileri kopyalar; bu nedenle aşağıdaki örnek, sol tuvaldeki her çizgiyi kopyalamadan önce seçer.
CanPasteFromClipboard Pano'nun mürekkep içerip içermediğini denetler.
PasteFromClipboard, ilettiğiniz konuma mürekkep ekler ve değişen alanın sınırlayıcı dikdörtgenini döndürür.
<StackPanel Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Click="CopyButton_Click" Content="Copy left canvas" />
<Button
x:Name="pasteButton"
Click="PasteButton_Click"
Content="Paste into right canvas"
IsEnabled="False" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="12">
<Border
Width="300"
Height="220"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="sourceCanvas" AutomationProperties.Name="Source drawing surface" />
</Border>
<Border
Width="300"
Height="220"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="targetCanvas" AutomationProperties.Name="Target drawing surface" />
</Border>
</StackPanel>
<TextBlock x:Name="statusText" Text="Draw on the left canvas, then copy it." TextWrapping="Wrap" />
</StackPanel>
using System.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;
using Windows.UI.Core;
using InkStroke = Windows.UI.Input.Inking.InkStroke;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
foreach (InkCanvas canvas in new[] { sourceCanvas, targetCanvas })
{
canvas.InkPresenter.InputDeviceTypes =
CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
}
}
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
InkStrokeContainer source = sourceCanvas.InkPresenter.StrokeContainer;
IReadOnlyList<InkStroke> strokes = source.GetStrokes();
if (strokes.Count == 0)
{
statusText.Text = "Draw on the left canvas first.";
return;
}
// CopySelectedToClipboard copies only selected strokes, so select all strokes first.
foreach (InkStroke stroke in strokes)
{
stroke.Selected = true;
}
source.CopySelectedToClipboard();
foreach (InkStroke stroke in strokes)
{
stroke.Selected = false;
}
pasteButton.IsEnabled = targetCanvas.InkPresenter.StrokeContainer.CanPasteFromClipboard();
statusText.Text = $"Copied {strokes.Count} stroke(s) to the clipboard.";
}
private void PasteButton_Click(object sender, RoutedEventArgs e)
{
InkStrokeContainer target = targetCanvas.InkPresenter.StrokeContainer;
if (!target.CanPasteFromClipboard())
{
statusText.Text = "The clipboard doesn't contain ink.";
return;
}
// Place the pasted ink near the upper-left corner of the target canvas.
Rect pasted = target.PasteFromClipboard(new Point(16, 16));
statusText.Text = $"Pasted ink into a {pasted.Width:0} x {pasted.Height:0} area.";
}
}
Bazı vuruşlarla çalışmak için, istediğiniz her vuruşun Selected özelliğini ayarlayın veya SelectWithPolyLine ya da SelectWithLine çağırın. Seçili vuruşları silmek veya taşımak için MoveSelected veya DeleteSelected komutunu çağırın.
Kodda çizgiler oluşturma
Noktalardan vuruşlar oluşturmak ve bunları InkStrokeBuilder ile tuvale eklemek için Windows Çalışma Zamanı AddStroke sınıfını kullanın. Aşağıdaki örnek bir yıldız ve imza çizgisi ekler.
<StackPanel Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Click="AddStarButton_Click" Content="Add star" />
<Button Click="AddSignatureLineButton_Click" Content="Add signature line" />
<Button Click="ClearButton_Click" Content="Clear" />
</StackPanel>
<Border
Width="480"
Height="280"
HorizontalAlignment="Left"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;
using Windows.UI;
using InkDrawingAttributes = Windows.UI.Input.Inking.InkDrawingAttributes;
using InkPoint = Windows.UI.Input.Inking.InkPoint;
using InkStroke = Windows.UI.Input.Inking.InkStroke;
using InkStrokeBuilder = Windows.UI.Input.Inking.InkStrokeBuilder;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
}
private void AddStarButton_Click(object sender, RoutedEventArgs e)
{
// Alternate between outer and inner points to draw a five-pointed star.
Point center = new(inkCanvas.ActualWidth / 2, 90);
List<Point> points = new();
for (int i = 0; i <= 10; i++)
{
double radius = i % 2 == 0 ? 70 : 28;
double angle = -Math.PI / 2 + i * Math.PI / 5;
points.Add(new Point(center.X + radius * Math.Cos(angle), center.Y + radius * Math.Sin(angle)));
}
AddStroke(points, Colors.Goldenrod, 4);
}
private void AddSignatureLineButton_Click(object sender, RoutedEventArgs e)
{
double left = 40;
double right = inkCanvas.ActualWidth - 40;
double baseline = inkCanvas.ActualHeight - 40;
AddStroke(new[] { new Point(left, baseline), new Point(right, baseline) }, Colors.Gray, 2);
AddStroke(new[] { new Point(left, baseline - 28), new Point(left + 18, baseline - 10) }, Colors.Gray, 2);
AddStroke(new[] { new Point(left + 18, baseline - 28), new Point(left, baseline - 10) }, Colors.Gray, 2);
}
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.Clear();
}
private void AddStroke(IEnumerable<Point> points, Color color, double size)
{
InkStrokeBuilder builder = new();
builder.SetDefaultDrawingAttributes(new InkDrawingAttributes
{
Color = color,
Size = new Size(size, size),
// Keep straight segments and sharp corners instead of smoothing them into curves.
FitToCurve = false,
});
// Give every point the same pressure so that the stroke has a uniform width.
IEnumerable<InkPoint> inkPoints = points.Select(point => new InkPoint(point, 0.5f));
InkStroke stroke = builder.CreateStrokeFromInkPoints(inkPoints, Matrix3x2.Identity);
inkCanvas.InkPresenter.StrokeContainer.AddStroke(stroke);
}
}
-
CreateStrokeFromInkPointsInkPointdeğerlerinden bir vuruş oluşturur. Her nokta, tuvaldeki bir konumu basınç değeriyle birleştirir. - Windows Çalışma Zamanı belgeleri, mürekkep sunucusuna eklediğiniz vuruşlar için
CreateStrokeFromInkPointsyerineCreateStrokekullanılmasını önerir. -
FitToCurve,falseolduğunda, çizgi eğriler yerine noktalar arasındaki düz kesimleri kullanır.
Vuruş yalnızca bir kapsayıcıya ait olabilir. Vuruşları başka bir tuvale kopyalamak için vuruşların klonlarını ekleyin:
private void CopyStrokesTo(InkCanvas target)
{
foreach (InkStroke stroke in inkCanvas.InkPresenter.StrokeContainer.GetStrokes())
{
target.InkPresenter.StrokeContainer.AddStroke(stroke.Clone());
}
}
Mürekkep araç çubuğunu özelleştirin
İlk kontrolleri seçin
InitialControls özelliği, araç çubuğunun hangi yerleşik düğmeleri oluşturduğunu belirler:
| Değer | Yerleşik düğmeler |
|---|---|
All (varsayılan) |
Tükenmez kalem, kalem, fosforlu kalem, silgi ve şablon (cetvel) |
PensOnly |
Tükenmez kalem, kurşun kalem ve vurgulayıcı |
AllExceptPens |
Silgi ve şablon (cetvel) |
None |
None. İstediğiniz düğmeleri araç çubuğunun alt öğeleri olarak tanımlayın. |
Aşağıdaki örnek, WinUI 3 Galerisi örneğiyle aynı dört düğmeyi bildirir, her birine erişilebilir bir ad verir ve araç çubuğu yüklendiğinde tükenmez kalemi seçer:
<StackPanel Spacing="8">
<InkToolbar
x:Name="inkToolbar"
AutomationProperties.Name="Drawing tools"
InitialControls="None"
TargetInkCanvas="{x:Bind inkCanvas}">
<InkToolbarBallpointPenButton x:Name="ballpointButton" AutomationProperties.Name="Ballpoint pen" />
<InkToolbarPencilButton AutomationProperties.Name="Pencil" />
<InkToolbarHighlighterButton AutomationProperties.Name="Highlighter" />
<InkToolbarEraserButton AutomationProperties.Name="Eraser" />
</InkToolbar>
<Border
Height="300"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
using Microsoft.UI.Xaml.Controls;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
// Select a starting tool after the toolbar loads.
inkToolbar.Loaded += (sender, args) =>
{
if (inkToolbar.ActiveTool is null)
{
inkToolbar.ActiveTool = ballpointButton;
}
};
}
}
Tüm mürekkepleri silen bir komut göstermek için silgi düğmesinin IsClearAllVisible özelliğini true olarak ayarlayın. Araç çubuğu, kullanıcı komutu seçtiğinde EraseAllClicked olayını tetikler.
Kalemin renklerini ve genişliklerini özelleştirin
Her kalem düğmesinde bir Palette fırça ve vuruş genişliği ayarları vardır. Kodda Palette ayarlayın. Ayrıntılar için bkz . Bilinen sınırlamalar. Aşağıdaki örnek, tükenmez kalemin paletini dört marka rengiyle değiştirir, vuruş genişliğini sınırlar ve etkin kalemin özniteliklerini gösterir.
<StackPanel Spacing="12">
<InkToolbar
x:Name="inkToolbar"
AutomationProperties.Name="Drawing tools"
InitialControls="AllExceptPens"
TargetInkCanvas="{x:Bind inkCanvas}">
<InkToolbarBallpointPenButton
x:Name="brandPen"
AutomationProperties.Name="Brand pen"
MaxStrokeWidth="16"
MinStrokeWidth="2"
SelectedStrokeWidth="6" />
</InkToolbar>
<RadioButtons
x:Name="colorButtons"
Header="Pen color"
MaxColumns="4"
SelectedIndex="0"
SelectionChanged="ColorButtons_SelectionChanged">
<x:String>Blue</x:String>
<x:String>Green</x:String>
<x:String>Orange</x:String>
<x:String>Purple</x:String>
</RadioButtons>
<TextBlock x:Name="penInfo" />
<Border
Width="480"
Height="240"
HorizontalAlignment="Left"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
using System.Linq;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Windows.UI;
public sealed partial class MainPage : Page
{
private static readonly Color[] BrandColors =
{
Color.FromArgb(0xFF, 0x00, 0x78, 0xD4), // Blue
Color.FromArgb(0xFF, 0x10, 0x7C, 0x10), // Green
Color.FromArgb(0xFF, 0xD8, 0x3B, 0x01), // Orange
Color.FromArgb(0xFF, 0x5C, 0x2D, 0x91), // Purple
};
public MainPage()
{
InitializeComponent();
// Replace the pen's default palette and select the first color.
brandPen.Palette = BrandColors.Select(color => (Brush)new SolidColorBrush(color)).ToList();
brandPen.SelectedBrushIndex = 0;
inkToolbar.InkDrawingAttributesChanged += (sender, args) => ShowPenInfo();
// The toolbar sets up its buttons when it loads, so select the starting tool then.
inkToolbar.Loaded += (sender, args) =>
{
inkToolbar.ActiveTool = brandPen;
ShowPenInfo();
};
}
private void ColorButtons_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// SelectionChanged can occur while the page is still loading.
if (brandPen is null || colorButtons is null || penInfo is null || colorButtons.SelectedIndex < 0)
{
return;
}
// SelectedBrushIndex selects an entry in Palette, like choosing a color in the pen flyout.
brandPen.SelectedBrushIndex = colorButtons.SelectedIndex;
inkToolbar.ActiveTool = brandPen;
ShowPenInfo();
}
private void ShowPenInfo()
{
// InkDrawingAttributes describes the ink that the active tool draws.
if (inkToolbar.InkDrawingAttributes is { } attributes)
{
penInfo.Text = $"Color {attributes.Color}, width {attributes.Size.Width:0} (range {brandPen.MinStrokeWidth:0}-{brandPen.MaxStrokeWidth:0})";
}
}
}
SelectedBrushIndex, Palette içinden bir renk seçer.
SelectedStrokeWidth, MinStrokeWidth ve MaxStrokeWidth, geçerli vuruş genişliğini ve kullanıcıların aralarından seçim yapabilecekleri aralığı ayarlar. Etkin aracın öznitelikleri değiştiğinde araç çubuğu InkDrawingAttributesChanged tetikler.
Etkin aracı seçin
Bir araç seçmek için ActiveTool ayarını yapın ve kullanıcı başka bir araç seçtiğinde yanıt vermek için ActiveToolChanged işleyin.
GetToolButton geçirdiğiniz türde yerleşik bir araç düğmesi döndürür. Yerleşik düğmeler araç çubuğu yüklenene kadar mevcut olmayabilir, bu nedenle araç çubuğunun Loaded olay işleyicisinde bir başlangıç aracı seçin.
<StackPanel Spacing="12">
<InkToolbar
x:Name="inkToolbar"
AutomationProperties.Name="Drawing tools"
TargetInkCanvas="{x:Bind inkCanvas}" />
<TextBlock x:Name="toolInfo" />
<Border
Width="480"
Height="280"
HorizontalAlignment="Left"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
using Microsoft.UI.Xaml.Controls;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
inkToolbar.ActiveToolChanged += (sender, args) => ShowToolInfo();
inkToolbar.InkDrawingAttributesChanged += (sender, args) => ShowToolInfo();
// The toolbar creates its built-in buttons when it loads, so select the starting tool then.
inkToolbar.Loaded += (sender, args) =>
{
inkToolbar.ActiveTool = inkToolbar.GetToolButton(InkToolbarTool.Pencil);
ShowToolInfo();
};
}
private void ShowToolInfo()
{
if (inkToolbar.ActiveTool is not { } tool)
{
toolInfo.Text = "No active tool";
return;
}
toolInfo.Text = inkToolbar.InkDrawingAttributes is { } attributes
? $"{tool.ToolKind}: {attributes.Kind} ink, color {attributes.Color}, size {attributes.Size.Width:0}"
: $"{tool.ToolKind}";
}
}
Yönü değiştir
Araç çubuğunu dikey olarak, örneğin tuvalin yanında, göstermek için Vertical değerini Orientation olarak ayarlayın:
<Grid HorizontalAlignment="Left" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<InkToolbar
VerticalAlignment="Top"
AutomationProperties.Name="Drawing tools"
Orientation="Vertical"
TargetInkCanvas="{x:Bind inkCanvas}" />
<Border
Grid.Column="1"
Width="440"
Height="320"
VerticalAlignment="Top"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</Grid>
ButtonFlyoutPlacement özelliği, düğme açılır penceresinin araç çubuğuna göre açıldığı yeri ayarlar. Varsayılan değer olan Auto, araç çubuğunun konumu seçmesini sağlar.
Özel anahtar düğmesi ekle
Kullanıcıların araç çubuğundan açıp kapatacağı bir ayar eklemek için InkToolbarCustomToggleButton kullanın. Aşağıdaki örnek, dokunmatik girişi denetleen bir geçiş düğmesi ekler. Kalem ve fare girişi her zaman mürekkep oluşturur.
<StackPanel Spacing="12">
<InkToolbar AutomationProperties.Name="Drawing tools" TargetInkCanvas="{x:Bind inkCanvas}">
<InkToolbarCustomToggleButton
x:Name="touchWritingToggle"
AutomationProperties.Name="Touch writing"
Checked="TouchWritingToggle_Changed"
ToolTipService.ToolTip="Touch writing"
Unchecked="TouchWritingToggle_Changed">
<SymbolIcon Symbol="TouchPointer" />
</InkToolbarCustomToggleButton>
</InkToolbar>
<TextBlock x:Name="deviceInfo" />
<Border
Width="480"
Height="280"
HorizontalAlignment="Left"
Background="White"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="1">
<InkCanvas x:Name="inkCanvas" AutomationProperties.Name="Drawing surface" />
</Border>
</StackPanel>
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.UI.Core;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
// Pen and mouse input always draw ink. The custom toggle controls touch input.
inkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Mouse;
ShowDevices();
}
private void TouchWritingToggle_Changed(object sender, RoutedEventArgs e)
{
if (touchWritingToggle.IsChecked == true)
{
inkCanvas.InkPresenter.InputDeviceTypes |= CoreInputDeviceTypes.Touch;
}
else
{
inkCanvas.InkPresenter.InputDeviceTypes &= ~CoreInputDeviceTypes.Touch;
}
ShowDevices();
}
private void ShowDevices()
{
deviceInfo.Text = $"InputDeviceTypes = {inkCanvas.InkPresenter.InputDeviceTypes}";
}
}
İki durumlu düğmede yalnızca bir simge gösterildiğinden, örnek ona erişilebilir bir ad ve araç ipucu verir. Bu örnekte, araç çubuğu varsayılan düğmelerini de oluşturur ve özel geçiş düğmesi onlardan sonra görünür.
Araç çubuğu diğer özel düğmeleri destekler:
-
InkToolbarCustomToolButtonsize ait bir araç ekler. -
InkToolbarCustomPenButtonkendi çizim özniteliklerini oluşturan bir kalem ekler.CustomPenözelliğini,InkToolbarCustomPenöğesinden türeyen veCreateInkDrawingAttributesCoreyöntemini geçersiz kılan bir sınıfın örneğine ayarlayın.
Kodda araç çubuğunu oluşturun
Ayrıca tuvali ve araç çubuğunu kodda da oluşturabilirsiniz. Aşağıdaki örnek bunları Border adlı bir inkHost öğesine ekler, araç çubuğunu TargetInkPresenter ile bağlar ve araç çubuğu yüklendiğinde kalemi seçer.
<Border x:Name="inkHost" HorizontalAlignment="Left" />
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Windows.UI.Core;
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
CreateInkingUI();
}
private void CreateInkingUI()
{
InkCanvas canvas = new();
AutomationProperties.SetName(canvas, "Drawing surface");
canvas.InkPresenter.InputDeviceTypes =
CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
InkToolbar toolbar = new() { TargetInkPresenter = canvas.InkPresenter };
AutomationProperties.SetName(toolbar, "Drawing tools");
// The toolbar creates its built-in buttons when it loads.
toolbar.Loaded += (sender, args) => toolbar.ActiveTool = toolbar.GetToolButton(InkToolbarTool.Pencil);
Border canvasFrame = new()
{
Width = 480,
Height = 280,
Background = new SolidColorBrush(Colors.White),
BorderBrush = new SolidColorBrush(Colors.DarkGray),
BorderThickness = new Thickness(1),
Child = canvas,
};
StackPanel layout = new() { Spacing = 8 };
layout.Children.Add(toolbar);
layout.Children.Add(canvasFrame);
inkHost.Child = layout;
}
}
Bilinen sınırlamalar
- Mürekkep denetimleri yalnızca Windows Uygulama SDK'sı'nin deneysel sürümlerinde kullanılabilir. Bunlar kararlı kanalda kullanılamaz.
- Dijital mürekkep API'leri el yazısı veya şekil tanıma içermez.
- Fare girişi,
CoreInputDeviceTypes.MouseöğesiniInputDeviceTypesöğesine ekleyene kadar mürekkep çizmez.
aşağıdaki sorunlar Windows Uygulama SDK'sı 2.4.1-experimental ile bildirilmiştir. 2.5.4 deneysel sürüm notları bunları düzeltilmiş olarak listelemez:
- Cetvel ve protraktör şablonları çalışmaz.
-
RenderTargetBitmapmürekkebi algılamaz. Mürekkep görüntüsünü oluşturmak içinGifWithEmbeddedIsfbiçiminde kaydedin. - XAML'de kalem düğmesinin
Paletteözelliğini ayarlamak bir XAML ayrıştırma hatasına neden olur. Bunun yerine,Palettebölümünde gösterildiği gibi kodda ayarlayın. - Düğme açılırları boş görünebilir ve
ButtonFlyoutPlacementöğesini değiştirmek, açıldıkları yeri değiştirmeyebilir.
2.4.1-deneysel sürümündeki değişiklikler
Windows Uygulama SDK'sı 2.4.1-experimental'da mürekkep oluşturma API'lerini kullandıysanız, kodunuzu 2.5.4-experimental'daki bu değişikliklere göre güncelleyin:
| API in 2.4.1-experimental | 2.5.4-experimental sürümündeki değişiklik |
|---|---|
InkToolbar.TargetInkPresenter (yazın Object) |
Özellik türü InkPresenter. |
InkPresenter.GetHighContrastAdjustment ve InkPresenter.SetHighContrastAdjustment yöntemleri |
InkPresenter.HighContrastAdjustment özelliği tarafından değiştirildi. |
InkStrokeInput.GetInkPresenter ve InkUnprocessedInput.GetInkPresenter yöntemleri |
Her sınıfta bulunan bir InkPresenter özelliğiyle değiştirildi. |
InkToolbarEraserButton.SelectedEraser, IsStrokeEraserVisibleve ArePrecisionErasersVisible özellikleri; InkToolbar.EraserFlyoutItemClicked olay; InkToolbarEraserKind, InkToolbarEraserFlyoutItemKindve InkToolbarEraserFlyoutItemClickedEventArgs türleri |
Kaldırıldı. |
| Mevcut değil |
InkPresenter.ActivateCustomDrying yöntemi ve InkSynchronizer sınıfı eklendi. |
Erişilebilirlik ve yüksek karşıtlık
Mürekkep görsel içerik olduğundan tüm kullanıcıların mürekkep oluşturma özelliklerinizi nasıl kullanabileceğini planlayın:
- Bu makaledeki örneklerde olduğu gibi her tuvale ve araç çubuğuna
AutomationProperties.Nameile erişilebilir bir ad verin. Yalnızca simgeyi gösteren özel düğmelere ad ve araç ipucu verin. -
InkCanvasAutomationPeertuvali UI Otomasyonu'a sunar, ancak vuruşları açıklamaz. Mürekkebin imza veya etiketli diyagram gibi bir anlamı varsa bir metin alternatifi sağlayın. - Mürekkeple çizim için işaretçi girişi gerekir. Bir görevi tamamlamanın tek yolu mürekkep olmasın. Örneğin, kullanıcıların imzalamaya alternatif olarak adlarını yazmasına izin verin.
- Yerleşik araç düğmelerinin otomasyon yardımcıları SelectionItem ve ExpandCollapse denetim desenlerini destekler. Klavye gezintisini ve uygulamanızın kullandığı araç çubuğu yapılandırmasına sahip düğme açılır menülerini test edin.
Karşıtlık teması etkin olduğunda, sunucu mürekkep renklerini sistem renkleriyle değiştirebilir. Bu davranışı seçmek için InkHighContrastAdjustment özelliğini, HighContrastAdjustment ad alanından bir Microsoft.UI.Xaml.Controls değerine ayarlayın.
Aynı ada sahip numaralandırma türünün Windows Çalışma Zamanı belgelerinde değerler şu şekilde açıklanmaktadır:
| Değer | Karşıtlık temasında mürekkep rengi |
|---|---|
UseSystemColorsWhenNecessary |
Arka planla yeterince kontrast oluşturuyorsa mürekkebin kendi rengi. Aksi halde sistem rengi kullanılır. |
UseSystemColors |
Sistem rengi. Vurgulayıcı mürekkep sistem vurgulayıcı rengini kullanır. |
UseOriginalColors |
Mürekkebin kendi rengi. |
inkCanvas.InkPresenter.HighContrastAdjustment = InkHighContrastAdjustment.UseSystemColorsWhenNecessary;
Kısa tutmak için, bu makaledeki örneklerde doğrudan beyaz bir arka plan ayarlanır. Uygulamanızda tuval arka planını tema sözlüklerinde tanımlayıp Karşıt temalar'da açıklandığı gibi etkin temayı takip etmesini sağlayın. Ardından uygulamanızı her karşıtlık temasıyla test edin ve ön planın, arka planın ve kenarlığın ayırt edilebilir kalıp kalmadığını denetleyin.
Daha fazla bilgi için bkz. Temel erişilebilirlik bilgilerini kullanıma sunma ve Klavye erişilebilirliği.
Ayrıca bkz.
- WinUI 3 Galerisi InkCanvas örnek kaynak kodu
- Windows Uygulama SDK'sı 2.5.4 deneysel sürüm notları
- Microsoft.UI.Xaml.Controls ad alanı
- Windows.UI.Input.Inking ad alanı
- Windows uygulamalarında kalem için dokunsal geri bildirim
- Kalem etkileşimleri ve Windows Ink (UWP)
- Mürekkep girişi denetimleri (UWP)
- UWP'den WinUI 3'e geçiş sırasında desteklenenler
Windows developer