Как рисовать на экране для приложений в стиле Windows Metro на C #?

#c# #windows #coding-style #draw #microsoft-metro

#c# #Windows #стиль кодирования #рисовать #microsoft-metro

Вопрос:

Я просто хочу, чтобы пользователь мог рисовать на экране с помощью какого-либо указателя.

У меня уже есть работающий код, который фиксирует положение указателя, но я не могу понять, как разместить пиксели, фигуры или что-то еще на экране.

Я нашел это полезное руководство:
http://www.dotnetspeaks.com/DisplayArticle.aspx?ID=137

И я просматривал документацию здесь:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465055 (v = VS.85).aspx

Пока безуспешно. = ( Руководство предназначено для Windows Phone 7, поэтому оно немного отличается. = Помогите, пожалуйста? =)

И это то, что у меня есть на данный момент.

Часть рисования:

     private void Image_PointerPressed(object sender, PointerEventArgs e)
    {
        Debug.WriteLine("Image_PointerPressed");
        isTracing = true;
    }

    private void Image_PointerReleased(object sender, PointerEventArgs e)
    {
        Debug.WriteLine("Image_PointerReleased");
        isTracing = false;
    }

    private void Image_PointerMoved(object sender, PointerEventArgs e)
    {
        Debug.WriteLine("Image_PointerMoved");
        Debug.WriteLine(e.GetCurrentPoint(this).Position);
        if (isTracing)
        {
            Debug.WriteLine("isTracing");

            Point pos = e.GetCurrentPoint(this).Position;
            Color color = Colors.Green;
            Line line = new Line() { X1 = pos.X, X2 = pos.X   1, Y1 = pos.Y, Y2 = pos.Y   1 };
            line.Stroke = new SolidColorBrush(color);
            line.StrokeThickness = 15;
            //// So how do I draw this line onto the screen?? ////

        }

    }
  

Для справки, материал в другом месте кода:

 использование системы;
 использование System.Коллекции.Общий;
 использование System.Диагностика;
 использование System.Ввод-вывод; 
 используя System.Linq;
 использование System.Многопоточность.Задачи;
 использование мультимедиа.FFmpeg;
 использование Windows.Основа;
 использование Windows.Хранение;
 использование Windows.Хранение.Средства выбора;
 использование Windows.Хранение.Стримы;
 использование Windows.UI.Xaml;
 использование Windows.UI.Xaml.Controls;
 использование Windows.UI.Xaml.Shapes;
 использование Windows.UI.Xaml.Media;
 используя Windows.UI.Xaml.Ввод;
 использование Windows.UI.Input;

 bool isstracing = false;

Комментарии:

1. Я также нашел это руководство, но оно все равно не помогло. windowsphonegeek.com/tips /…

2. Что не работает правильно в коде, который у вас уже есть?

3. Я ничего не рисую на экране. Я не знаю, что использовать для этого. (Кстати, спасибо за комментарий!)

Ответ №1:

Краткая форма:

  • Добавьте Line s и Rectangle s на панель
  • Напрямую манипулировать растровым изображением
  • Используйте элемент Canvas HTML5 в проекте JavaScript / HTML
  • Напишите все это на C / DirectX

В Metro / XAML нет способа переопределить OnRender() метод или подобное. Вы можете добавлять существующие графические элементы (например, из пространства имен Shapes) на холст или другую панель или напрямую манипулировать пикселями в растровом изображении и помещать это растровое изображение в элемент изображения.

В Metro / C # сохранен только графический режим рисования, что означает, что единственное, что он будет отображать, — это объекты, которые были добавлены в иерархию представлений. То, что вы ищете, это какой-то графический рисунок в немедленном режиме, например

 myCanvas.DrawLine( fromPoint, toPoint );
  

Это можно сделать в проекте JavaScript / HTML, используя объект Canvas в HTML5. К сожалению, я склоняюсь к такому проекту. К сожалению, Microsoft не предоставляет элемент немедленного режима для проектов XAML, но так оно и есть. C / DirectX также является опцией для выполнения пользовательского рисования, но требует существенной переработки всего остального, что вы делаете в приложении.

Ответ №2:

Вот отличный пример кода о том, как это сделать, используя формы XAML.

http://www.codeproject.com/Articles/416878/Metro-Paint

Ответ №3:

Вы должны добавить строку к элементу пользовательского интерфейса, такому как холст.

Ответ №4:

Основная проблема в вашем коде заключается в том, что вы не прикрепляете строку к какому-либо элементу XAML, я предлагаю вам сделать это к элементу Canvas, примерно так:

 newCanvas.Children.Add(line);
  

Альтернативой является использование библиотеки рисования современных компонентов, она работает на WinRT, использует вызовы класса .NET Graphics like и рисует непосредственно на XAML Canvas, обратите внимание, что если вы хотите сохранить изображение в виде растрового изображения, вам может потребоваться также использовать WritableBitmapEx, поскольку XAML Canvas нельзя отобразить в виде растровых изображений.

Ответ №5:

В этом примере проекта есть код для рисования на экране для приложений магазина Win 8 на C # / XAML:

http://code.msdn.microsoft.com/windowsapps/Drawing-on-a-Canvas-with-33510ae6

Вот соответствующий файл C #:

 using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using Windows.Devices.Input; 
using Windows.Foundation; 
using Windows.Foundation.Collections; 
using Windows.UI; 
using Windows.UI.Input; 
using Windows.UI.Input.Inking; //we need to add this name space in order to have many functions  
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Controls.Primitives; 
using Windows.UI.Xaml.Data; 
using Windows.UI.Xaml.Input; 
using Windows.UI.Xaml.Media; 
using Windows.UI.Xaml.Navigation; 
using Windows.UI.Xaml.Shapes; 
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 

namespace DrawingOnCanvasWithInkPen 
{ 
/// <summary> 
/// An empty page that can be used on its own or navigated to within a Frame. 
/// </summary> 
public sealed partial class MainPage : Page 
{ 
    InkManager _inkKhaled = new Windows.UI.Input.Inking.InkManager(); 
    private uint _penID; 
    private uint _touchID; 
    private Point _previousContactPt; 
    private Point currentContactPt; 
    private double x1; 
    private double y1; 
    private double x2; 
    private double y2; 


    public MainPage() 
    { 
        this.InitializeComponent(); 

        MyCanvas.PointerPressed  = new PointerEventHandler(MyCanvas_PointerPressed); 
        MyCanvas.PointerMoved  = new PointerEventHandler(MyCanvas_PointerMoved); 
        MyCanvas.PointerReleased  = new PointerEventHandler(MyCanvas_PointerReleased); 
        MyCanvas.PointerExited  = new PointerEventHandler(MyCanvas_PointerReleased); 
    } 


    #region PointerEvents 
    private void MyCanvas_PointerReleased(object sender, PointerRoutedEventArgs e) 
    { 
        if (e.Pointer.PointerId == _penID) 
        { 
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(MyCanvas); 

            // Pass the pointer information to the InkManager.  
            _inkKhaled.ProcessPointerUp(pt); 
        } 

        else if (e.Pointer.PointerId == _touchID) 
        { 
            // Process touch input 
        } 

        _touchID = 0; 
        _penID = 0; 

        // Call an application-defined function to render the ink strokes. 


        e.Handled = true; 
    } 

    private void MyCanvas_PointerMoved(object sender, PointerRoutedEventArgs e) 
    { 
        if (e.Pointer.PointerId == _penID) 
        { 
            PointerPoint pt = e.GetCurrentPoint(MyCanvas); 

            // Render a red line on the canvas as the pointer moves.  
            // Distance() is an application-defined function that tests 
            // whether the pointer has moved far enough to justify  
            // drawing a new line. 
            currentContactPt = pt.Position; 
            x1 = _previousContactPt.X; 
            y1 = _previousContactPt.Y; 
            x2 = currentContactPt.X; 
            y2 = currentContactPt.Y; 

            if (Distance(x1, y1, x2, y2) > 2.0) // We need to developp this method now  
            { 
                Line line = new Line() 
                { 
                    X1 = x1, 
                    Y1 = y1, 
                    X2 = x2, 
                    Y2 = y2, 
                    StrokeThickness = 4.0, 
                    Stroke = new SolidColorBrush(Colors.Green) 
                }; 

                _previousContactPt = currentContactPt; 

                // Draw the line on the canvas by adding the Line object as 
                // a child of the Canvas object. 
                MyCanvas.Children.Add(line); 

                // Pass the pointer information to the InkManager. 
                _inkKhaled.ProcessPointerUpdate(pt); 
            } 
        } 

        else if (e.Pointer.PointerId == _touchID) 
        { 
            // Process touch input 
        } 

    } 

    private double Distance(double x1, double y1, double x2, double y2) 
    { 
        double d = 0; 
        d = Math.Sqrt(Math.Pow((x2 - x1), 2)   Math.Pow((y2 - y1), 2)); 
        return d; 
    } 

    private void MyCanvas_PointerPressed(object sender, PointerRoutedEventArgs e) 
    { 
        // Get information about the pointer location. 
        PointerPoint pt = e.GetCurrentPoint(MyCanvas); 
        _previousContactPt = pt.Position; 

        // Accept input only from a pen or mouse with the left button pressed.  
        PointerDeviceType pointerDevType = e.Pointer.PointerDeviceType; 
        if (pointerDevType == PointerDeviceType.Pen || 
                pointerDevType == PointerDeviceType.Mouse amp;amp; 
                pt.Properties.IsLeftButtonPressed) 
        { 
            // Pass the pointer information to the InkManager. 
            _inkKhaled.ProcessPointerDown(pt); 
            _penID = pt.PointerId; 

            e.Handled = true; 
        } 

        else if (pointerDevType == PointerDeviceType.Touch) 
        { 
            // Process touch input 
        } 
    } 

    #endregion 

    /// <summary> 
    /// Invoked when this page is about to be displayed in a Frame. 
    /// </summary> 
    /// <param name="e">Event data that describes how this page was reached.  The Parameter 
    /// property is typically used to configure the page.</param> 
    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
    } 
} 
  

}

и файл xaml:

 <Page 

x:Class="DrawingOnCanvasWithInkPen.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:DrawingOnCanvasWithInkPen" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d"> 

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 
    <Canvas Name="MyCanvas" Background="White" HorizontalAlignment="Left" Height="513" Margin="83,102,0,0" VerticalAlignment="Top" Width="1056"/> 

</Grid> 
  

В своем текущем состоянии он обрабатывает только ввод с помощью пера или мыши — но я также заставил его работать для touch с небольшими изменениями.