• 14—VisualDrawing


    1,该项目分析:

    image

    2,wpf布局:

    <Window x:Class="Drawing.VisualLayer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="VisualLayer" Height="350.4" Width="496.8"
            xmlns:local="clr-namespace:Drawing"
        >
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
          </Grid.ColumnDefinitions>
          <ToolBarTray Orientation="Vertical">
          <ToolBar>
            <RadioButton Margin="0,3" Name="cmdSelectMove">
              <StackPanel>
                <Image Source="pointer.png" Width="35" Height="35"></Image>
                <TextBlock>Select/Move</TextBlock>
              </StackPanel>
            </RadioButton>
            <RadioButton Margin="0,3" IsChecked="True" Name="cmdAdd">
              <StackPanel>
                <Rectangle Width="30" Height="30" Stroke="SteelBlue" StrokeThickness="3" Fill="AliceBlue"></Rectangle>
                <TextBlock>Add Square</TextBlock>
              </StackPanel>
            </RadioButton>
            <RadioButton Margin="0,3" Name="cmdDelete">
              <StackPanel>
                <Path Stroke="SteelBlue" StrokeThickness="4" StrokeEndLineCap="Round" StrokeStartLineCap="Round"
                      Fill="Red" HorizontalAlignment="Center">
                  <Path.Data>
                    <GeometryGroup>
                      <PathGeometry>
                        <PathFigure StartPoint="0,0">
                          <LineSegment Point="18,18"></LineSegment>
                        </PathFigure>
                        <PathFigure StartPoint="0,18">
                          <LineSegment Point="18,0"></LineSegment>
                        </PathFigure>
                      </PathGeometry>
                    </GeometryGroup>
                  </Path.Data>
                </Path>
                <TextBlock>Delete Square</TextBlock>
              </StackPanel>
            </RadioButton>
            <RadioButton Margin="0,3" Name="cmdSelectMultiple">
              <StackPanel>
                <Image Source="pointer.png" Width="35" Height="35"></Image>
                <TextBlock>Select Multiple</TextBlock>
              </StackPanel>
            </RadioButton>
          </ToolBar>
          </ToolBarTray>
    
          <Border Grid.Column="1" Margin="3" BorderBrush="SteelBlue" BorderThickness="1">
    
            <local:DrawingCanvas x:Name="drawingSurface" Background="White" ClipToBounds="True"
                                 MouseLeftButtonDown="drawingSurface_MouseLeftButtonDown"
                    MouseLeftButtonUp="drawingSurface_MouseLeftButtonUp"
                    MouseMove="drawingSurface_MouseMove">
            </local:DrawingCanvas>
    
    
          </Border>
        </Grid>
    </Window>
    

       创建了左右两栏,1栏是工具栏,1栏是画图栏.

       右侧创建画图对象.


    1,添加图形对象的逻辑:(必须设置背景颜色)

                1,生成VisualDrawing对象.然后添加到Canvas对象之中

      private List<Visual> visuals = new List<Visual>();
    
            protected override Visual GetVisualChild(int index)
            {
                return visuals[index];
            }
            protected override int VisualChildrenCount
            {
                get
                {
                    return visuals.Count;
                }
            }
    
            public void AddVisual(Visual visual)
            {
                visuals.Add(visual);
    
                base.AddVisualChild(visual);
                base.AddLogicalChild(visual);
            }
    
            public void DeleteVisual(Visual visual)
            {
                visuals.Remove(visual);
    
                base.RemoveVisualChild(visual);
                base.RemoveLogicalChild(visual);
            }

         2 获取VisualDrawing对象.并且删除

      public DrawingVisual GetVisual(Point point)
            {
                HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
                return hitResult.VisualHit as DrawingVisual;
            }
    
            private List<DrawingVisual> hits = new List<DrawingVisual>();
            public List<DrawingVisual> GetVisuals(Geometry region)
            {
                hits.Clear();
                GeometryHitTestParameters parameters = new GeometryHitTestParameters(region);
                HitTestResultCallback callback = new HitTestResultCallback(this.HitTestCallback);
                VisualTreeHelper.HitTest(this, null, callback, parameters);
                return hits;
            }
    
            private HitTestResultBehavior HitTestCallback(HitTestResult result)
            {
                GeometryHitTestResult geometryResult = (GeometryHitTestResult)result;
                DrawingVisual visual = result.VisualHit as DrawingVisual;
                if (visual != null &&
                    geometryResult.IntersectionDetail == IntersectionDetail.FullyInside)
                {
                    hits.Add(visual);
                }
                return HitTestResultBehavior.Continue;
            }

    命中测试:

    删除操作:

     public void DeleteVisual(Visual visual)
            {
                visuals.Remove(visual);
    
                base.RemoveVisualChild(visual);
                base.RemoveLogicalChild(visual);
            }

      3,获得当前坐标的当前位置值:

    当获取Visual的ContentBounds的时候,其实际上包含了一半的线宽:

    Point curPos = new Point(visual.ContentBounds.TopLeft.X + pen.Thickness / 2, visual.ContentBounds.TopLeft.Y + pen.Thickness / 2);

    4  ,如何绘制虚线框:

      首先根据选择,在Down的时候,开始加入一个Visual对象

     else if (cmdSelectMultiple.IsChecked == true)
                {
    
                    selectionSquare = new DrawingVisual();
    
                    drawingSurface.AddVisual(selectionSquare);
    
                    selectionSquareTopLeft = pointClicked;
                    isMultiSelecting = true;
    
                    // Make sure we get the MouseLeftButtonUp event even if the user
                    // moves off the Canvas. Otherwise, two selection squares could be drawn at once.
                    drawingSurface.CaptureMouse();
                }


    ,然后在移动的过程中绘制该对象

    if (isDragging)
                {
                    Point pointDragged = e.GetPosition(drawingSurface) + clickOffset;
                    DrawSquare(selectedVisual, pointDragged, true);
                }
                else if (isMultiSelecting)
                {
                    Point pointDragged = e.GetPosition(drawingSurface);
                    DrawSelectionSquare(selectionSquareTopLeft, pointDragged);
                }
    l

    //

    另外理解下OffSet 的含义:

    首先 定义了 OffSetPoint=元素左上角1-鼠标点击1;

                  定义

                         元素左上角2=鼠标点击2+OffSetPoint;

    注意:OffSetPoint是相对于鼠标点击的位置,所以,可以所示 元素对应鼠标的偏移值,所以,元素位置2,可以用 鼠标位置2+相对值来求出来.

              可以定义表达式  : 元素左上角2-元素左上角1=鼠标点击2-鼠标点击1;

    二:效果

    三:位图:

      格局格式决定每个像素点的字节数:

    image

    其中 Stride是每行占用字节数的4的取整. 可以使用 (Nums+3)/4*4来获取.


    32位RGB:假设X、Y为位图中像素的坐标,则其在内存中的地址为scan0+Ystride+X4。此时指针指向蓝色,其后分别是绿色、红色,alpha分量。
    24位RGB:scan0+Ystride+X3。此时指针指向蓝色,其后分别是绿色和红色。
    8位索引:scan0+Ystride+X。当前指针指向图像的调色盘。
    4位索引:scan0+Ystride+(X/2)。当前指针所指的字节包括两个像素,通过高位和低位索引16色调色盘,其中高位表示左边的像素,低位表示右边的像素。
    1位索引:scan0+Y*stride+X/8。当前指针所指的字节中的每一位都表示一个像素的索引颜色,调色盘为两色,最左边的像素为8,最右边的像素为0。

    使用LockBits方法进行将Bitmap 转换为writebleBitmap的方式

     private  WriteableBitmap ConvertFromBitmap(System.Drawing.Bitmap bitmap)
            {
                var tt = bitmap;
              var   dt = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly,bitmap.PixelFormat);
    
                Byte* p = (Byte *)dt.Scan0;
    
                WriteableBitmap bitmap1 = new WriteableBitmap(bitmap.Width, bitmap.Height, 96, 96, PixelFormats.Bgra32, null);
                Int32Rect rect = new Int32Rect(0, 0, bitmap.Width, bitmap.Height);
                Byte[] pixels = new Byte[bitmap.Width * bitmap.Height * 4];
    
                for(var i=0;i<pixels.Length;i++)
                {
                    pixels[i] = *(p + i);
                }
                bitmap.UnlockBits(dt);
                bitmap1.WritePixels(rect, pixels, dt.Stride, 0);
                pixels = null;
                return bitmap1;
            }


    本质上操作位图就是操作一个bytes数组.只要注意颜色.是按照(B,G,R,A)格式来就可以了.


    四 自定义效果以及实现 https://blog.csdn.net/WPwalter/article/details/90575912

    1,下载并安装软件https://gitee.com/mao_qin_bin/download/tree/master/Shazzam

    2,认识该编辑器:

    .fx 是 着色语言生成文件.

  • 相关阅读:
    JavaScript 闭包(转)
    JavaScript 获取键盘扫描码
    前台网站优化方案
    设计模式之装饰者模式
    设计模式之蝇量模式
    设计模式之策略模式
    Algorithm学习之any_of
    Algorithm学习之all_of学习
    Algorithm学习之adjacent_find学习
    数据结构-表达式求值
  • 原文地址:https://www.cnblogs.com/frogkiller/p/13151791.html
Copyright © 2020-2023  润新知