Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplicativos do Windows que dão suporte ao Windows Ink podem serializar e desserializar traços de tinta em um arquivo ISF (Formato Serializado de Tinta). O arquivo ISF é uma imagem GIF com metadados adicionais para todas as propriedades e comportamentos de traço de tinta. Os aplicativos que não são compatíveis com tinta podem visualizar a imagem GIF estática, incluindo a transparência de fundo do canal alfa.
Observação
ISF é a representação persistente mais compacta da tinta. Ele pode ser inserido em um formato de documento binário, como um arquivo GIF, ou colocado diretamente na Área de Transferência.
A especificação de Formato Serializado de Tinta (ISF) pode ser baixada do Centro de Download da Microsoft.
APIs importantes: InkCanvas, Windows.UI.Input.Inking
Salvar traços de tinta em um arquivo
Aqui, demonstramos como salvar traços desenhados de tinta em um controle InkCanvas .
Baixe este exemplo de Salvar e carregar traços de tinta de um arquivo ISF (Formato Serializado de Tinta)
Primeiro, configuramos a interface do usuário.
A interface do usuário inclui botões "Salvar", "Carregar" e "Limpar" e o InkCanvas.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Row="0">
<TextBlock x:Name="Header"
Text="Basic ink store sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<Button x:Name="btnSave"
Content="Save"
Margin="50,0,10,0"/>
<Button x:Name="btnLoad"
Content="Load"
Margin="50,0,10,0"/>
<Button x:Name="btnClear"
Content="Clear"
Margin="50,0,10,0"/>
</StackPanel>
<Grid Grid.Row="1">
<InkCanvas x:Name="inkCanvas" />
</Grid>
</Grid>
Em seguida, definimos alguns comportamentos básicos de entrada de tinta.
O InkPresenter é configurado para interpretar dados de entrada tanto do mouse quanto da caneta como traços de tinta (InputDeviceTypes), e os escutadores para os eventos de clique nos botões são declarados.
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Listen for button click to initiate save.
btnSave.Click += btnSave_Click;
// Listen for button click to initiate load.
btnLoad.Click += btnLoad_Click;
// Listen for button click to clear ink canvas.
btnClear.Click += btnClear_Click;
}
Por fim, salvamos a tinta no manipulador de eventos de clique do botão Salvar.
Um FileSavePicker permite que o usuário selecione tanto o arquivo quanto o local em que os dados de tinta são salvos.
Depois que um arquivo é selecionado, abrimos um fluxo IRandomAccessStream definido como ReadWrite .
Em seguida, chamamos
para serializar os traços de tinta gerenciados peloSaveAsync InkStrokeContainer para o fluxo de dados.
// Save ink data to a file.
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
// Get all strokes on the InkCanvas.
IReadOnlyList<InkStroke> currentStrokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
// Strokes present on ink canvas.
if (currentStrokes.Count > 0)
{
// Let users choose their ink file using a file picker.
// Initialize the picker.
Windows.Storage.Pickers.FileSavePicker savePicker =
new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add(
"GIF with embedded ISF",
new List<string>() { ".gif" });
savePicker.DefaultFileExtension = ".gif";
savePicker.SuggestedFileName = "InkSample";
// Show the file picker.
Windows.Storage.StorageFile file =
await savePicker.PickSaveFileAsync();
// When chosen, picker returns a reference to the selected file.
if (file != null)
{
// Prevent updates to the file until updates are
// finalized with call to CompleteUpdatesAsync.
Windows.Storage.CachedFileManager.DeferUpdates(file);
// Open a file stream for writing.
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
// Write the ink strokes to the output stream.
using (IOutputStream outputStream = stream.GetOutputStreamAt(0))
{
await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(outputStream);
await outputStream.FlushAsync();
}
stream.Dispose();
// Finalize write so other apps can update file.
Windows.Storage.Provider.FileUpdateStatus status =
await Windows.Storage.CachedFileManager.CompleteUpdatesAsync(file);
if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
{
// File saved.
}
else
{
// File couldn't be saved.
}
}
// User selects Cancel and picker returns null.
else
{
// Operation cancelled.
}
}
}
Observação
GIF é o único formato de arquivo com suporte para salvar dados de tinta. No entanto, o método
Carregar traços de tinta de um arquivo
Aqui, demonstramos como carregar traços de tinta de um arquivo e renderizá-los em um controle InkCanvas .
Baixe este exemplo de Salvar e carregar traços de tinta de um arquivo ISF (Formato Serializado de Tinta)
Primeiro, configuramos a interface do usuário.
A interface do usuário inclui botões "Salvar", "Carregar" e "Limpar" e o InkCanvas.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Row="0">
<TextBlock x:Name="Header"
Text="Basic ink store sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<Button x:Name="btnSave"
Content="Save"
Margin="50,0,10,0"/>
<Button x:Name="btnLoad"
Content="Load"
Margin="50,0,10,0"/>
<Button x:Name="btnClear"
Content="Clear"
Margin="50,0,10,0"/>
</StackPanel>
<Grid Grid.Row="1">
<InkCanvas x:Name="inkCanvas" />
</Grid>
</Grid>
Em seguida, definimos alguns comportamentos básicos de entrada de tinta.
O InkPresenter é configurado para interpretar dados de entrada tanto do mouse quanto da caneta como traços de tinta (InputDeviceTypes), e os escutadores para os eventos de clique nos botões são declarados.
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Listen for button click to initiate save.
btnSave.Click += btnSave_Click;
// Listen for button click to initiate load.
btnLoad.Click += btnLoad_Click;
// Listen for button click to clear ink canvas.
btnClear.Click += btnClear_Click;
}
Por fim, carregamos a tinta no manipulador de eventos de clique do botão Carregar.
Um FileOpenPicker permite que o usuário selecione o arquivo e o local de onde recuperar os dados de tinta salvos.
Depois que um arquivo for selecionado, abriremos um fluxo de IRandomAccessStream definido como de Leitura .
Em seguida, chamamos LoadAsync para ler, desserializar e carregar os traços de tinta salvos no InkStrokeContainer . Carregar os traços no InkStrokeContainer faz com que o InkPresenter os renderize imediatamente para o InkCanvas .
Observação
Todos os traços existentes no InkStrokeContainer são limpos antes que novos traços sejam carregados.
// Load ink data from a file.
private async void btnLoad_Click(object sender, RoutedEventArgs e)
{
// Let users choose their ink file using a file picker.
// Initialize the picker.
Windows.Storage.Pickers.FileOpenPicker openPicker =
new Windows.Storage.Pickers.FileOpenPicker();
openPicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add(".gif");
// Show the file picker.
Windows.Storage.StorageFile file = await openPicker.PickSingleFileAsync();
// User selects a file and picker returns a reference to the selected file.
if (file != null)
{
// Open a file stream for reading.
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
// Read from file.
using (var inputStream = stream.GetInputStreamAt(0))
{
await inkCanvas.InkPresenter.StrokeContainer.LoadAsync(inputStream);
}
stream.Dispose();
}
// User selects Cancel and picker returns null.
else
{
// Operation cancelled.
}
}
Observação
GIF é o único formato de arquivo com suporte para salvar dados de tinta. No entanto, o método LoadAsync dá suporte aos seguintes formatos para compatibilidade com versões anteriores.
Formato | Descrição |
---|---|
InkSerializedFormat | Especifica a tinta que é persistida usando ISF. Esta é a representação persistente mais compacta da tinta. Ele pode ser inserido em um formato de documento binário ou colocado diretamente na Área de Transferência. |
Base64InkSerializedFormat | Especifica a tinta que é persistida codificando o ISF como um fluxo base64. Esse formato é fornecido para que a tinta possa ser codificada diretamente em um arquivo XML ou HTML. |
Gif | Especifica a tinta que é preservada por meio de um arquivo GIF que contém ISF como metadados incorporados ao arquivo. Isso permite que a tinta seja exibida em aplicativos que não são habilitados para tinta e mantêm sua fidelidade total à tinta quando ela retorna a um aplicativo habilitado para tinta. Esse formato é ideal ao transportar conteúdo de tinta em um arquivo HTML e para torná-lo utilizável por aplicativos de tinta e não tinta. |
Base64Gif | Especifica a tinta que é preservada por meio de um GIF protegido codificado em base64. Esse formato é fornecido quando a tinta deve ser codificada diretamente em um arquivo XML ou HTML para conversão posterior em uma imagem. Um possível uso disso está em um formato XML gerado para conter todas as informações de tinta e usado para gerar HTML por meio de XSLT (Extensible Stylesheet Language Transformations). |
Copiar e colar os traços de tinta usando a área de transferência
Aqui, demonstramos como usar a área de transferência para transferir trazos de tinta entre aplicativos.
Para dar suporte à funcionalidade da área de transferência, os comandos integrados de recortar e copiar do InkStrokeContainer exigem que um ou mais traços de tinta sejam selecionados.
Para este exemplo, habilitamos a seleção de traço quando a entrada é modificada com um botão de barril de caneta (ou botão direito do mouse). Para obter um exemplo completo de como implementar a seleção de traço, consulte a entrada de dados para processamento avançado em interações de caneta e stylus em .
Baixe este exemplo em Salvar e carregar traços de tinta da área de transferência
Primeiro, configuramos a interface do usuário.
A interface do usuário inclui botões "Recortar", "Copiar", "Colar" e "Limpar", juntamente com o InkCanvas e um canvas de seleção.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Row="0">
<TextBlock x:Name="tbHeader"
Text="Basic ink store sample"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<Button x:Name="btnCut"
Content="Cut"
Margin="20,0,10,0"/>
<Button x:Name="btnCopy"
Content="Copy"
Margin="20,0,10,0"/>
<Button x:Name="btnPaste"
Content="Paste"
Margin="20,0,10,0"/>
<Button x:Name="btnClear"
Content="Clear"
Margin="20,0,10,0"/>
</StackPanel>
<Grid x:Name="gridCanvas" Grid.Row="1">
<!-- Canvas for displaying selection UI. -->
<Canvas x:Name="selectionCanvas"/>
<!-- Inking area -->
<InkCanvas x:Name="inkCanvas"/>
</Grid>
</Grid>
Em seguida, definimos alguns comportamentos básicos de entrada de tinta.
O InkPresenter é configurado para interpretar dados de entrada tanto de caneta quanto de mouse como traços de tinta (InputDeviceTypes). Os ouvintes dos eventos de clique nos botões, bem como eventos de ponteiro e traço para a funcionalidade de seleção, também são declarados aqui.
Para obter um exemplo completo de como implementar a seleção de traço, consulte a entrada de dados para processamento avançado em interações de caneta e stylus em .
public MainPage()
{
this.InitializeComponent();
// Set supported inking device types.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Pen;
// Listen for button click to cut ink strokes.
btnCut.Click += btnCut_Click;
// Listen for button click to copy ink strokes.
btnCopy.Click += btnCopy_Click;
// Listen for button click to paste ink strokes.
btnPaste.Click += btnPaste_Click;
// Listen for button click to clear ink canvas.
btnClear.Click += btnClear_Click;
// By default, the InkPresenter processes input modified by
// a secondary affordance (pen barrel button, right mouse
// button, or similar) as ink.
// To pass through modified input to the app for custom processing
// on the app UI thread instead of the background ink thread, set
// InputProcessingConfiguration.RightDragAction to LeaveUnprocessed.
inkCanvas.InkPresenter.InputProcessingConfiguration.RightDragAction =
InkInputRightDragAction.LeaveUnprocessed;
// Listen for unprocessed pointer events from modified input.
// The input is used to provide selection functionality.
inkCanvas.InkPresenter.UnprocessedInput.PointerPressed +=
UnprocessedInput_PointerPressed;
inkCanvas.InkPresenter.UnprocessedInput.PointerMoved +=
UnprocessedInput_PointerMoved;
inkCanvas.InkPresenter.UnprocessedInput.PointerReleased +=
UnprocessedInput_PointerReleased;
// Listen for new ink or erase strokes to clean up selection UI.
inkCanvas.InkPresenter.StrokeInput.StrokeStarted +=
StrokeInput_StrokeStarted;
inkCanvas.InkPresenter.StrokesErased +=
InkPresenter_StrokesErased;
}
Por fim, depois de adicionar suporte à seleção de traços, implementamos a funcionalidade da área de transferência nos manipuladores de eventos de clique dos botões Recortar, Copiare Colar.
Para cortar, primeiro chamamos CopySelectedToClipboard no InkStrokeContainer do InkPresenter.
Em seguida, chamamos DeleteSelected para remover os traços da tela de tinta.
Por fim, excluímos todos os traços de seleção da tela de seleção.
private void btnCut_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
ClearSelection();
}
// Clean up selection UI.
private void ClearSelection()
{
var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
foreach (var stroke in strokes)
{
stroke.Selected = false;
}
ClearDrawnBoundingRect();
}
private void ClearDrawnBoundingRect()
{
if (selectionCanvas.Children.Any())
{
selectionCanvas.Children.Clear();
boundingRect = Rect.Empty;
}
}
Para copiar, basta chamar
private void btnCopy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
}
Para colar, chamamos CanPasteFromClipboard para garantir que o conteúdo na área de transferência possa ser colado na tela de tinta.
Nesse caso, chamamos PasteFromClipboard para inserir os traços de tinta da área de transferência no InkStrokeContainer do InkPresenter, que então renderiza os traços na tela de tinta.
private void btnPaste_Click(object sender, RoutedEventArgs e)
{
if (inkCanvas.InkPresenter.StrokeContainer.CanPasteFromClipboard())
{
inkCanvas.InkPresenter.StrokeContainer.PasteFromClipboard(
new Point(0, 0));
}
else
{
// Cannot paste from clipboard.
}
}
Artigos relacionados
exemplos de tópico
- Salvar e carregar traços de tinta de um arquivo ISF (Formato Serializado de Tinta)
- Salvar e carregar da área de transferência os traços de tinta
Outros exemplos
Windows developer