c# – 像剪切工具一样突出显示效果

我正在创建一个类似于 Windows 7剪切工具的新剪切工具.

但是我无法使高光效果起作用.

例如,剪切工具高亮显示如下:(突出显示在白色背景上非常明亮,看起来它没有透明度

我的剪切工具突出显示如下:

我确定使用的颜色是相同的(255,255,0),alpha通道为110.如果我降低透明度,那么它只是覆盖下面的文本.

我的剪辑是在白色顶部应用透明度,因为窗口剪切工具似乎更好地融合了它.

在这做错了什么?

我用于突出显示注释的代码是:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

    namespace Sicon.Snipper.Annotations
    {
        /// <summary>
        /// Highlight Annotation
        /// </summary>
        public class HighlightAnnotation : BaseAnnotation
        {
            #region Members

            protected Rectangle _selection = Rectangle.Empty;
            protected const int _transparancyAlpha = 110;
            private Brush _brush;

            #endregion Members

            #region Properties

            /// <summary>
            /// Gets or Sets the Brush
            /// </summary>
            protected Brush Brush
            {
                get { return _brush; }
                set { _brush = value; }
            }

            /// <summary>
            /// Gets the Selection
            /// </summary>
            public Rectangle Selection
            {
                get { return _selection; }
                protected set { _selection = value; }
            }

            #endregion Properties

            #region Constructors

            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="imageRef">Reference to the image</param>
            public HighlightAnnotation(Image imageRef,Control host)
                : base(imageRef,Pens.Yellow,host)
            {
                this.Brush = new SolidBrush(
                                Color.FromArgb(
                                _transparancyAlpha,this.Pen.Color));
            }

            #endregion Constructors

            #region Methods

            /// <summary>
            /// Handles on Mouse down
            /// </summary>
            /// <param name="e">args</param>
            public override void OnMouseDown(MouseEventArgs e)
            {
                if (base.Enabled)
                {
                    // Start the snip on mouse down
                    if (e.Button != MouseButtons.Left) return;
                    _startPoint = e.Location;
                    _selection = new Rectangle(e.Location,new Size(0,0));
                }
            }

            /// <summary>
            /// Handles Mouse Move
            /// </summary>
            /// <param name="e">args</param>
            public override void OnMouseMove(MouseEventArgs e)
            {
                if (base.Enabled)
                {
                    // Modify the selection on mouse move
                    if (e.Button != MouseButtons.Left) return;
                    int x1 = Math.Min(e.X,_startPoint.X);
                    int y1 = Math.Min(e.Y,_startPoint.Y);
                    int x2 = Math.Max(e.X,_startPoint.X);
                    int y2 = Math.Max(e.Y,_startPoint.Y);
                    _selection = new Rectangle(x1,y1,x2 - x1,y2 - y1);
                }
            }

            /// <summary>
            /// Handles on mouse up
            /// </summary>
            /// <param name="e">args</param>
            public override void onmouseup(MouseEventArgs e)
            {
                if (base.Enabled)
                {
                    if (_selection.Width <= 0 || _selection.Height <= 0) return;

                    using (Graphics g = Graphics.FromImage(this.ImageRef))
                    {
                        Rectangle dest = new Rectangle(
                            TranslateCenterImageMousePosition(_startPoint),_selection.Size);

                        g.FillRectangle(
                            this.Brush,dest);

                    }

                    this.Enabled = false;
                }
            }

            /// <summary>
            /// Hanles on paint
            /// </summary>
            /// <param name="g">graphics</param>
            public override void OnPaint(system.drawing.graphics g)
            {
                if (base.Enabled)
                    g.FillRectangle(this.Brush,_selection);
            }

            #endregion Methods
        }
    }

更新::

好吧,我做了一些改动,我也喜欢写意画的想法,但我做这个的主要原因是要有漂亮的整洁亮点等.

我现在的问题是,当我释放鼠标按钮时,矩形将被绘制为黑色,如下图所示.几乎就在那里!

GDI32.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Sicon.Snipper.Tools
{
    public static class GDI32
    {
        [DllImport("gdi32.dll")]
        public static extern int SetROP2(IntPtr hdc,int fnDrawMode);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreatePen(int fnPenStyle,int nWidth,uint crColor);

        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hdc,IntPtr hgdiobj);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);

        [DllImport("gdi32.dll")]
        public static extern bool MovetoEx(IntPtr hdc,int X,int Y,IntPtr lpPoint);

        [DllImport("gdi32.dll")]
        public static extern bool Lineto(IntPtr hdc,int nXEnd,int nYEnd);

        [DllImport("gdi32.dll")]
        public static extern bool Rectangle(IntPtr hdc,int nLeftRect,int nTopRect,int nRightRect,int nBottomrect);
    }
}

新的Hightlight Annotation.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Sicon.Snipper.Enums;
using Sicon.Snipper.Tools;

namespace Sicon.Snipper.Annotations
{
    /// <summary>
    /// Highlight Annotation
    /// </summary>
    public class HighlightAnnotation : BaseAnnotation
    {
        #region Members

        protected Rectangle _selection = Rectangle.Empty;
        protected const int _transparancyAlpha = 110;
        private ShapeEnum _shape = ShapeEnum.Rectangle;
        List<Point> points = new List<Point>();
        private const int PS_SOLID = 0;
        private const int R2_MASKPEN = 9;
        private const int R2_copYPEN = 13;

        #endregion Members

        #region Properties

        /// <summary>
        /// Gets or Sets the Shape
        /// </summary>
        public ShapeEnum Shape
        {
            get { return _shape; }
            set { _shape = value; }
        }

        /// <summary>
        /// Gets the Selection
        /// </summary>
        public Rectangle Selection
        {
            get { return _selection; }
            protected set { _selection = value; }
        }

        #endregion Properties

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="imageRef">Reference to the image</param>
        public HighlightAnnotation(Image imageRef,Control host,ShapeEnum shape)
            : base(imageRef,new Pen(Color.Yellow,16),host)
        {
            _shape = shape;
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Handles on Mouse down
        /// </summary>
        /// <param name="e">args</param>
        public override void OnMouseDown(MouseEventArgs e)
        {
            if (base.Enabled)
            {
                // Start the snip on mouse down
                if (e.Button != MouseButtons.Left) return;

                _startPoint = e.Location;
                _selection = new Rectangle(e.Location,0));
            }
        }

        /// <summary>
        /// Handles Mouse Move
        /// </summary>
        /// <param name="e">args</param>
        public override void OnMouseMove(MouseEventArgs e)
        {
            if (base.Enabled)
            {
                // Modify the selection on mouse move
                if (e.Button != MouseButtons.Left) return;

                //Add freehand points
                points.Add(new Point(e.X,e.Y));

                //Update selection rectangele
                int x1 = Math.Min(e.X,_startPoint.X);
                int y1 = Math.Min(e.Y,_startPoint.Y);
                int x2 = Math.Max(e.X,_startPoint.X);
                int y2 = Math.Max(e.Y,_startPoint.Y);
                _selection = new Rectangle(x1,y2 - y1);
            }
        }

        /// <summary>
        /// Handles on mouse up
        /// </summary>
        /// <param name="e">args</param>
        public override void onmouseup(MouseEventArgs e)
        {
            if (base.Enabled)
            {
                if (_selection.Width <= 0 || _selection.Height <= 0) return;

                using (Graphics g = Graphics.FromImage(this.ImageRef))
                {
                    switch (this.Shape)
                    {
                        case ShapeEnum.Freehand:

                            DrawHighlight(g,points.ToArray());

                            break;

                        case ShapeEnum.Rectangle:

                            Rectangle dest = new Rectangle(
                                TranslateCenterImageMousePosition(_startPoint),_selection.Size);

                            DrawRectange(g);

                            break;

                        default: return;
                    }
                }

                this.Enabled = false;
            }
        }

        /// <summary>
        /// Hanles on paint
        /// </summary>
        /// <param name="g">graphics</param>
        public override void OnPaint(system.drawing.graphics g)
        {
            if (base.Enabled)
            {
                switch (this.Shape)
                {
                    case ShapeEnum.Freehand:

                        DrawHighlight(g,points.ToArray());

                        break;

                    case ShapeEnum.Rectangle:

                        DrawRectange(g);

                        break;

                    default: return;
                }
            }
        }

        /// <summary>
        /// Draws a highlight
        /// </summary>
        /// <param name="g">graphics</param>
        /// <param name="usePoints">points to draw</param>
        private void DrawHighlight(Graphics g,Point[] usePoints)
        {
            int useColor = System.Drawing.ColorTranslator.ToWin32(base.Pen.Color);
            IntPtr pen = GDI32.CreatePen(PS_SOLID,(int)base.Pen.Width,(uint)useColor);
            IntPtr hDC = g.GetHdc();
            IntPtr xDC = GDI32.SelectObject(hDC,pen);
            GDI32.SetROP2(hDC,R2_MASKPEN);
            for (int i = 1; i <= usePoints.Length - 1; i++)
            {
                Point p1 = usePoints[i - 1];
                Point p2 = usePoints[i];
                GDI32.MovetoEx(hDC,p1.X,p1.Y,IntPtr.Zero);
                GDI32.Lineto(hDC,p2.X,p2.Y);
            }
            GDI32.SetROP2(hDC,R2_copYPEN);
            GDI32.SelectObject(hDC,xDC);
            GDI32.DeleteObject(pen);
            g.ReleaseHdc(hDC);
        }

        /// <summary>
        /// Draws a rectangle
        /// </summary>
        /// <param name="g">Graphics</param>
        private void DrawRectange(Graphics g)
        {
            Rectangle dest = new Rectangle(
                                TranslateCenterImageMousePosition(_startPoint),_selection.Size);

            int useColor = System.Drawing.ColorTranslator.ToWin32(base.Pen.Color);
            IntPtr pen = GDI32.CreatePen(PS_SOLID,R2_MASKPEN);
            GDI32.Rectangle(hDC,dest.Left,dest.Top,dest.Right,dest.Bottom);
            GDI32.SetROP2(hDC,xDC);
            GDI32.DeleteObject(pen);
            g.ReleaseHdc(hDC);
        }

        #endregion Methods
    }
}

解决方法

您不能使用Alpha通道,因为这会淡化黄色.

我认为你必须上学并使用WIN32 API:

[DllImport("gdi32.dll")]
static extern int SetROP2(IntPtr hdc,int fnDrawMode);

[DllImport("gdi32.dll")]
static extern IntPtr CreatePen(int fnPenStyle,uint crColor);

[DllImport("gdi32.dll")]
static extern IntPtr SelectObject(IntPtr hdc,IntPtr hgdiobj);

[DllImport("gdi32.dll")]
static extern bool DeleteObject(IntPtr hObject);

[DllImport("gdi32.dll")]
static extern bool MovetoEx(IntPtr hdc,IntPtr lpPoint);

[DllImport("gdi32.dll")]
static extern bool Lineto(IntPtr hdc,int nYEnd);

private const int PS_SOLID = 0;
private const int R2_MASKPEN = 9;
private const int R2_copYPEN = 13;

Bitmap bmp = (Bitmap)Image.FromFile(@"c:\....png");
List<Point> points = new List<Point>();

这是我的亮点功能

private void DrawHighlight(Graphics g,Point[] usePoints,int brushSize,Color brushColor) {
  int useColor = System.Drawing.ColorTranslator.ToWin32(brushColor);
  IntPtr pen = CreatePen(PS_SOLID,brushSize,(uint)useColor);
  IntPtr hDC = g.GetHdc();
  IntPtr xDC = SelectObject(hDC,pen);
  SetROP2(hDC,R2_MASKPEN);
  for (int i = 1; i <= usePoints.Length - 1; i++) {
    Point p1 = usePoints[i - 1];
    Point p2 = usePoints[i];
    MovetoEx(hDC,IntPtr.Zero);
    Lineto(hDC,p2.Y);
  }
  SetROP2(hDC,R2_copYPEN);
  SelectObject(hDC,xDC);
  DeleteObject(pen);
  g.ReleaseHdc(hDC);
}

我的测试代码

protected override void OnMouseMove(MouseEventArgs e) {
  base.OnMouseMove(e);
  if (e.Button == MouseButtons.Left) {
    points.Add(new Point(e.X,e.Y));
    this.Invalidate();
  }
}

protected override void OnPaint(PaintEventArgs e) {
  base.OnPaint(e);
  e.Graphics.Clear(Color.White);
  e.Graphics.DrawImage(bmp,Point.Empty);
  DrawHighlight(e.Graphics,points.ToArray(),16,Color.Yellow);
}

结果:

要直接在图像上绘制而不是控件的Graphic对象,需要更多的API调用

[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hdcDst,int x1,int y1,int cx,int cy,IntPtr hdcSrc,int x2,int y2,int rop);

[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hdc);

private const int SRCcopY = 0x00CC0020;

这是修改后的代码

private void DrawHighlight(Point[] usePoints,Color brushColor) {
  using (Graphics gBMP = Graphics.FromImage(bmp)) {
    IntPtr hBMP = bmp.GetHbitmap();
    IntPtr bDC = gBMP.GetHdc();
    IntPtr mDC = CreateCompatibleDC(bDC);
    IntPtr oDC = SelectObject(mDC,hBMP);

    int useColor = System.Drawing.ColorTranslator.ToWin32(brushColor);
    IntPtr pen = CreatePen(PS_SOLID,(uint)useColor);
    IntPtr xDC = SelectObject(mDC,pen);

    SetROP2(mDC,R2_MASKPEN);
    for (int i = 1; i <= usePoints.Length - 1; i++) {
      Point p1 = usePoints[i - 1];
      Point p2 = usePoints[i];
      MovetoEx(mDC,IntPtr.Zero);
      Lineto(mDC,p2.Y);
    }
    SetROP2(mDC,R2_copYPEN);

    BitBlt(bDC,bmp.Width,bmp.Height,mDC,SRCcopY);
    SelectObject(mDC,xDC);
    DeleteObject(pen);
    gBMP.ReleaseHdc(bDC);
    SelectObject(mDC,oDC);
    DeleteDC(mDC);
    DeleteObject(hBMP);
  }
}

相关文章

C#项目进行IIS部署过程中报错及其一般解决方案_c#iis执行语句...
微信扫码登录PC端网站应用的案例(C#)_c# 微信扫码登录
原文地址:http://msdn.microsoft.com/en-us/magazine/cc163...
前言 随着近些年微服务的流行,有越来越多的开发者和团队所采...
最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下...
在多核CPU在今天和不久的将来,计算机将拥有更多的内核,Mic...