最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解WPF的InkCanvas選擇模式

 更新時間:2021年04月02日 10:09:11   作者:louzi  
這篇文章主要介紹了WPF InkCanvas選擇模式的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用c# wpf,感興趣的朋友可以了解下

InkCanvas是WPF中進(jìn)行墨跡繪制的控件,本文介紹下InkCanvas控件是如何進(jìn)行選擇操作的。文中有誤的地方希望大家進(jìn)行批評指正。

InkCanvas的選擇效果

使用WPF可以輕松實現(xiàn)白板功能,只需要添加一個InkCanvas控件。修改InkCanvas的EditingMode屬性可以控制InkCanvas的操作模式,如書寫、選擇、擦除等模式。
如下demo在窗口中添加一個InkCanvas,然后添加一個Button實現(xiàn)書寫與選擇模式的切換。

// xaml
<Grid>
  <InkCanvas x:Name="inkCanvas"/>
  <Button x:Name="btnChangeMode" Content="select" Click="Button_Click"
      Width="50" Height="30" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10"/>
</Grid>

// cs
private void Button_Click(object sender, RoutedEventArgs e)
{
	if(btnChangeMode.Content == "select")
	{
    inkCanvas.EditingMode = InkCanvasEditingMode.Select;
    btnChangeMode.Content = "write";
	}
	else
	{
    inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
    btnChangeMode.Content = "select";
	}
}

運(yùn)行demo,書寫后點(diǎn)擊按鈕進(jìn)行選擇,可以看到InkCanvas的選擇操作如下圖所示:

從圖中可以看出,InkCanvas的選擇效果有如下特點(diǎn):

  1. 選中后筆跡高亮;
  2. 選中后顯示選擇框;
  3. 拖動選擇框,選擇框隨著鼠標(biāo)移動,但選擇的筆跡并未移動。

接下來看下WPF是如何實現(xiàn)這種選擇操作的。

InkCanvas選擇模式的實現(xiàn)

首先,InkCanvas的編輯功能(書寫、擦除、選擇等)是通過EditingCoordinator管理的,該類包含一系列的EditingBehavior,實現(xiàn)選擇過程的為LassoSelectionBehavior類,實現(xiàn)選擇后對選擇框操作的為SelectionEditor與SelectionEditingBehavior。本文主要介紹選擇后對選擇框的操作過程,選擇過程以及筆跡的高亮顯示打算單獨(dú)寫一篇文章進(jìn)行介紹。

在InkCanvas中,與選擇功能相關(guān)的對象有InkCanvasSelection、InkCanvasSelectionAdorner及InkCanvasFeedbackAdorner。后兩者為裝飾器,裝飾器的介紹可參考官方文檔。

先看InkCanvasSelectionAdorner類,直接看其OnRender方法,代碼如下。首先繪制了選擇框的背景,然后繪制了選擇框(矩形虛線效果),最后繪制了選擇框上的9個小矩形按鈕。按鈕可以進(jìn)行拖動調(diào)節(jié),具體實現(xiàn)邏輯可以看代碼,本文不贅述。

protected override void OnRender(DrawingContext drawingContext)
{
  DrawBackground(drawingContext);

  Rect rectWireFrame = GetWireFrameRect()
  if(!rectWireFrame.IsEmpty)
  {
    drawingContext.DrawRectangle(null, _adornerBorderPen, rectWireFrame);

    DrawHandles(drawingContext, rectWireFrame);
  }
}

再看InkCanvasFeedbackAdorner類,同樣看OnRender方法,代碼如下。其僅繪制了矩形虛線選擇框,通過這兩個類的OnRender方法,結(jié)合上文中的動畫,可以知道選中后使用InkCanvasSelectionAdorner進(jìn)行裝飾,對選擇框的操作(拖動)使用InkCanvasFeedbackAdorner進(jìn)行裝飾。

protected override void OnRender(DrawingContext drawingContext)
{
  drawingContext.DrawRectangle(null, _adornerBorderPen,
    new Rect(CornerResizeHandleSize / 2, CornerResizeHandleSize / 2,
    _frameSize.Width - CornerResizeHandleSize, _frameSize.Height - CornerResizeHandleSize));
}

接下來看下這兩個Adorner是對誰進(jìn)行裝飾的,首先看InkCanvas的OnPreApplyTemplate方法,代碼如下。注釋部分是InkCanvas的Visual Tree,可以了解到InkCanvas的內(nèi)部結(jié)構(gòu)。再看下SelectionAdorner的初始化,可以看出是對InnerCanvas進(jìn)行裝飾,InnerCanvas是InkCanvas的內(nèi)部容器,放置筆跡及其它UIElement。SelectionAdorner添加了對ActiveEditingMode的綁定,當(dāng)Mode為None時,隱藏,否則顯示。FeedbackAdorner的裝飾對象通過其構(gòu)造函數(shù)可以看出,也是裝飾的InnerCanvas。

internal override void OnPreApplyTemplate()
{
  base.OnPreApplyTemplate();

  // Build our visual tree here.
  // <InkCanvas>
  //   <AdornerDecorator>
  //     <InkPresenter>
  //       <InnerCanvas/>
  //       <ContainerVisual/>
  //       <HostVisual/>
  //     </InkPresenter>
  //     <AdornerLayer>
  //       <InkCanvasSelectionAdorner/>
  //       <InkCanvasFeedbackAdorner/>
  //     </AdornerLayer>
  //   </AdornerDecorator>
  // </InkCanvas>

  if(_localAdornerDecorator == null)
  {
    _localAdornerDecorator = new AdornerDecorator();
    InkPresenter inkPresenter = InkPresenter;

    AddVisualChild(_localAdornerDecorator);
    _localAdornerDecorator.Child = inkPresenter;
    inkPresenter.Child = InnerCanvas;

    _localAdornerDecorator.AdornerLayer.Add(SelectionAdorner);
  }
}

internal InkCanvasSelectionAdorner SelectionAdorner
{
  get
  {
    if(_selectionAdorner == null)
    {
      _selectionAdorner = new InkCanvasSelectionAdorner(InnerCanvas);

      Binding activedEditingModeBinding = new Binding();
      activedEditingModeBinding.Path = new PropertyPath(InkCanvas.ActiveEditingModeProperty);
      activedEditingModeBinding.Mode = BindingMode.OneWay;
      activedEditingModeBinding.Source = this;
      activedEditingModeBinding.Converter = new ActiveEditingMode2VisibilityConverter();
      _selectionAdorner.SetBinding(UIElement.VisibilityProperty, activedEditingModeBinding);
    }

    return _selectionAdorner;
  }
}

// InkCanvasFeedbackAdorner
internal InkCanvasFeedbackAdorner(InkCanvas inkCanvas)
  : base((inkCanvas != null ? inkCanvas.InnerCanvas : null))
  {...}

最后,我們看下對選擇框進(jìn)行的操作是如何實現(xiàn)的。選擇后會激活SelectionEditingBehavior,在其OnActivate方法中,綁定了SelectionAdorner的MouseMove/MouseUp/LostMouseCapture事件,并調(diào)用InkCanvasSelection.StartFeedbackAdorner()方法對FeedbackAdorner進(jìn)行初始化,將其添加到AdornerLayer中。然后通過響應(yīng)MouseMove,調(diào)用InkSelection.UpdateFeedbackAdorner()方法更新FeedbackAdorner的位置。最后在MouseUp響應(yīng)中釋放FeedbackAdorner。刪減代碼如下,具體的實現(xiàn)邏輯可以看WPF源碼。

protected override void OnActive()
{
  // ...
  InkCanvas.InkCanvasSelection.StartFeedbackAdorner(_selectionRect, _hitResult);

  InkCanvas.SelectionAdorner.AddHandler(Mouse.MouseUpEvent, new MouseButtonEventHandler(OnMouseUp));
  InkCanvas.SelectionAdorner.AddHandler(Mouse.MouseMoveEvent, new MouseEventHandler(OnMouseMove));
  InkCanvas.SelectionAdorner.AddHandler(Mouse.LostMouseCaptureEvent, new MouseEventHandler(OnLostMouseCapture));
}

private void OnMouseMove(object sender, MouseEventArgs args)
{
  // ...
  InkCanvas.InkCanvasSelection.UpdateFeedbackAdorner(newRect);
  // ...
}

以上就是詳解WPF的InkCanvas選擇模式的詳細(xì)內(nèi)容,更多關(guān)于WPF的InkCanvas選擇模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#異步下載文件

    C#異步下載文件

    這篇文章主要介紹了C#異步下載文件的相關(guān)資料,需要的朋友可以參考下
    2016-01-01
  • C#中父窗口和子窗口之間控件互操作實例

    C#中父窗口和子窗口之間控件互操作實例

    這篇文章主要介紹了C#中父窗口和子窗口之間控件互操作的方法,實例分析了父窗口與子窗口互操作的技巧,需要的朋友可以參考下
    2015-01-01
  • Unity3D UGUI實現(xiàn)縮放循環(huán)拖動卡牌展示效果

    Unity3D UGUI實現(xiàn)縮放循環(huán)拖動卡牌展示效果

    這篇文章主要為大家詳細(xì)介紹了Unity3D UGUI實現(xiàn)縮放循環(huán)拖動展示卡牌效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • WINFORM 窗體間的傳值實現(xiàn)解析

    WINFORM 窗體間的傳值實現(xiàn)解析

    這篇文章主要介紹了WINFORM 窗體間的傳值實現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • C#實現(xiàn)將千分位字符串轉(zhuǎn)換成數(shù)字的方法

    C#實現(xiàn)將千分位字符串轉(zhuǎn)換成數(shù)字的方法

    這篇文章主要介紹了C#實現(xiàn)將千分位字符串轉(zhuǎn)換成數(shù)字的方法,很適合初學(xué)者更好的理解C#字符串原理,需要的朋友可以參考下
    2014-08-08
  • 輕松學(xué)習(xí)C#的String類

    輕松學(xué)習(xí)C#的String類

    輕松學(xué)習(xí)C#的String類,小編也是第一次接觸C#的String類,感興趣的小伙伴們可以參考一下,大家一起學(xué)習(xí)
    2015-11-11
  • WPF實現(xiàn)動畫效果(一)之基本概念

    WPF實現(xiàn)動畫效果(一)之基本概念

    這篇文章介紹了WPF實現(xiàn)動畫效果之基本概念,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Unity3D開發(fā)之獲取所有的子對象的方法詳解

    Unity3D開發(fā)之獲取所有的子對象的方法詳解

    這篇文章主要為大家詳細(xì)介紹了三種Unity3D中獲取所有的子對象(child)的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • C# Hashtable/Dictionary寫入和讀取對比詳解

    C# Hashtable/Dictionary寫入和讀取對比詳解

    本文中將從基礎(chǔ)角度講解HashTable、Dictionary的構(gòu)造和通過程序進(jìn)行插入讀取對比
    2013-11-11
  • 解決Unity urp級聯(lián)陰影接縫問題

    解決Unity urp級聯(lián)陰影接縫問題

    通過從unity內(nèi)部函數(shù)中抽幾個出來改造,強(qiáng)制取某個裁切球的級聯(lián)陰影映射,通過案例給大家詳細(xì)介紹,文中給出了完整的urp shader代碼,對Unity級聯(lián)陰影知識感興趣的朋友一起看看吧
    2021-06-06

最新評論

新津县| 乐安县| 玛多县| 钟祥市| 光泽县| 洞头县| 巍山| 九龙县| 渝北区| 清丰县| 扎兰屯市| 晋中市| 西畴县| 金华市| 湘西| 康马县| 大埔区| 鲁山县| 黔江区| 山西省| 集安市| 宁德市| 武宣县| 清新县| 威远县| 浦东新区| 罗平县| 阳高县| 泾阳县| 肃南| 闸北区| 五大连池市| 临安市| 鄂托克前旗| 上杭县| 遂昌县| 肇庆市| 三明市| 垦利县| 南澳县| 余姚市|