本文介绍了突出显示效果,如剪切工具的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



然而,我无法得到突出效果的工作原理。



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



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





我确定使用的颜色与Alpha通道为110的颜色相同(255,255,0)。如果我减少透明度,那么它只是覆盖下面的文本。 / p>

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



我在这里做错了什么?



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

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

命名空间Sicon.Snipper.Annotations
{
///< summary>
///突出显示注释
///< / summary>
public class HighlightAnnotation:BaseAnnotation
{
#region Members

protected Rectangle _selection = Rectangle.Empty;
受保护的const int _transparancyAlpha = 110;
私人刷子_brush;

#endregion成员

#地区属性

///< summary>
///获取或设置画笔
///< / summary>
受保护的刷子刷子
{
get {return _brush; }
set {_brush = value; }
}

///< summary>
///获取选区
///< / summary>
public矩形选择
{
get {return _selection; }
protected set {_selection = value; }
}

#endregion属性

#region构造函数

///< summary>
///构造函数
///< / summary>
///< param name =imageRef>引用图片< / param>
public HighlightAnnotation(Image imageRef,Control host)
:base(imageRef,Pens.Yellow,host)
{
this.Brush = new SolidBrush(
Color。 FromArgb(
_transparancyAlpha,
this.Pen.Color));
}

#endregion构造函数

#region方法

///< summary>
///处理鼠标下降
///< / summary>
///< param name =e> args< / param>
public override void OnMouseDown(MouseEventArgs e)
{
if(base.Enabled)
{
//在鼠标上开始剪切
if( e.Button!= MouseButtons.Left)return;
_startPoint = e.Location;
_selection = new Rectangle(e.Location,new Size(0,0));
}
}

///< summary>
///处理鼠标移动
///< / summary>
///< param name =e> args< / param>
public override void OnMouseMove(MouseEventArgs e)
{
if(base.Enabled)
{
//修改鼠标移动的选择
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>
///处理鼠标
///< / summary>
///< param name =e> args< / param>
public override void OnMouseUp(MouseEventArgs e)
{
if(base.Enabled)
{
if(_selection.Width
使用(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>图形< / param>
public override void OnPaint(System.Drawing.Graphics g)
{
if(base.Enabled)
g.FillRectangle(this.Brush,_selection);
}

#endregion方法
}
}

UPDATE ::



好的,我做了一些修改,我也喜欢写意画的想法,但是主要原因即使这样做是有很好的整洁高亮等。



我现在的问题是,当我释放鼠标按钮矩形被绘制成黑色的下面的图像。它几乎在那里!

GDI32.cs

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

命名空间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; 
使用System.Collections.Generic;
使用System.Drawing;
使用System.Linq;
使用System.Text;
使用System.Windows.Forms;
使用Sicon.Snipper.Enums;
使用Sicon.Snipper.Tools;

命名空间Sicon.Snipper.Annotations
{
///< summary>
///突出显示注释
///< / summary>
public class HighlightAnnotation:BaseAnnotation
{
#region Members

protected Rectangle _selection = Rectangle.Empty;
受保护的const int _transparancyAlpha = 110;
private ShapeEnum _shape = ShapeEnum.Rectangle;
列表< Point> points = new List< Point>();
private const int PS_SOLID = 0;
private const int R2_MASKPEN = 9;
private const int R2_COPYPEN = 13;

#endregion成员

#地区属性

///< summary>
///获取或设置形状
///< / summary>
public ShapeEnum Shape
{
get {return _shape; }
set {_shape = value; }
}

///< summary>
///获取选区
///< / summary>
public矩形选择
{
get {return _selection; }
protected set {_selection = value; }
}

#endregion属性

#region构造函数

///< summary>
///构造函数
///< / summary>
///< param name =imageRef>引用图片< / param>
public HighlightAnnotation(Image imageRef,Control host,ShapeEnum shape)
:base(imageRef,new Pen(Color.Yellow,16),host)
{
_shape = shape;
}

#endregion构造函数

#region方法

///< summary>
///处理鼠标下降
///< / summary>
///< param name =e> args< / param>
public override void OnMouseDown(MouseEventArgs e)
{
if(base.Enabled)
{
//在鼠标上开始剪切
if( e.Button!= MouseButtons.Left)return;

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

///< summary>
///处理鼠标移动
///< / summary>
///< param name =e> args< / param>
public override void OnMouseMove(MouseEventArgs e)
{
if(base.Enabled)
{
//修改鼠标移动的选择
if( e.Button!= MouseButtons.Left)return;

//添加手绘点数
points.Add(新点(e.X,e.Y));

//更新选区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,y1,x2 - x1,y2 - y1);
}
}

///< summary>
///处理鼠标
///< / summary>
///< param name =e> args< / param>
public override void OnMouseUp(MouseEventArgs e)
{
if(base.Enabled)
{
if(_selection.Width
使用(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;

默认值:return;
}
}

this.Enabled = false;
}
}

///< summary>
/// Hanles on paint
///< / summary>
///< param name =g>图形< / 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;

默认值:return;
}
}
}

///< summary>
///绘制高亮
///< / summary>
///< param name =g>图形< / param>
///< param name =usePoints>指向绘制< / 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>
///绘制一个矩形
///< / summary>
///< param name =g>图形< / 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,(int)base.Pen.Width,(uint)useColor);
IntPtr hDC = g.GetHdc();
IntPtr xDC = GDI32.SelectObject(hDC,pen);
GDI32.SetROP2(hDC,R2_MASKPEN);
GDI32.Rectangle(hDC,dest.Left,dest.Top,dest.Right,dest.Bottom);
GDI32.SetROP2(hDC,R2_COPYPEN);
GDI32.SelectObject(hDC,xDC);
GDI32.DeleteObject(pen);
g.ReleaseHdc(hDC);
}

#endregion方法
}
}
解决方案

你不能使用alpha通道,因为这会淡化黄色。



我认为你必须老去学校和使用WIN32 API为此:

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

[DllImport(gdi32.dll)]
static extern IntPtr CreatePen(int fnPenStyle,int nWidth,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,int X,int Y,IntPtr lpPoint);

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

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

位图bmp =(位图)Image.FromFile(@c:\ .... png);
列表< Point> points = new List< Point>();

以下是我的突出显示功能:



<$ p (Graphics g,Point [] usePoints,
int brushSize,Color brushColor){
int useColor = System.Drawing.ColorTranslator.ToWin32(brushColor); $ p> private void DrawHighlight
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,p1.X,p1.Y,IntPtr.Zero);
LineTo(hDC,p2.X,p2.Y);
}
SetROP2(hDC,R2_COPYPEN);
SelectObject(hDC,xDC);
DeleteObject(pen);
g.ReleaseHdc(hDC);
}

我的测试代码:

 保护覆盖无效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);

$ / code>

结果:



直接绘制在图像而不是控件的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;

这是修改过的代码:

<$ p
使用(Graphics gBMP = Graphics.FromImage(bmp)){
IntPtr hBMP = bmp(){
使用(Graphics gBMP = Graphics.FromImage(bmp)){
private void DrawHighlight(Point [] usePoints,int brushSize,Color brushColor) .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,brushSize,(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,p1.X,p1.Y,IntPtr.Zero);
LineTo(mDC,p2.X,p2.Y);
}
SetROP2(mDC,R2_COPYPEN);

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


Im creating a new snipping tool similar to the windows 7 snipping tool.

however I cant get the highlight effect working the same.

for example, the snipping tool highlight works as follows: (The highlight is very bright on a white background, it looks like it has no transparency

and my snipping tool highlight looks as follows:

Im sure the color used is the same (255,255,0) with an alpha channel of 110. if i decrease the transparency then it just overwrites the text below.

my snip is applying the transparency over the top of the white, where as the windows snipping tool seems to blend it all better.

What am i doing wrong here?

the code I am using for my highlight annotation is:

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
        }
    }

UPDATE::

Ok, I have made a few changes, I like the idea of freehand drawing too, but the main reason im making this is to have nice tidy highlights etc.

The issue I have now is that when i release the mouse button the rectangle gets drawn in black as image below. its almost there!

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);
    }
}

New 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, 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;

                //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, 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))
                {
                    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, (int)base.Pen.Width, (uint)useColor);
            IntPtr hDC = g.GetHdc();
            IntPtr xDC = GDI32.SelectObject(hDC, pen);
            GDI32.SetROP2(hDC, R2_MASKPEN);
            GDI32.Rectangle(hDC, dest.Left, dest.Top, dest.Right, dest.Bottom);
            GDI32.SetROP2(hDC, R2_COPYPEN);
            GDI32.SelectObject(hDC, xDC);
            GDI32.DeleteObject(pen);
            g.ReleaseHdc(hDC);
        }

        #endregion Methods
    }
}
解决方案

You can't use an alpha channel for that since that would fade the yellow color.

I think you have to go old school and use the WIN32 API for this:

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

[DllImport("gdi32.dll")]
static extern IntPtr CreatePen(int fnPenStyle, int nWidth, 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, int X, int Y, IntPtr lpPoint);

[DllImport("gdi32.dll")]
static extern bool LineTo(IntPtr hdc, int nXEnd, 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>();

Here is my Highlight function:

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, p1.X, p1.Y, IntPtr.Zero);
    LineTo(hDC, p2.X, p2.Y);
  }
  SetROP2(hDC, R2_COPYPEN);
  SelectObject(hDC, xDC);
  DeleteObject(pen);
  g.ReleaseHdc(hDC);
}

My testing code:

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);
}

The result:

To draw directly on an image instead of control's Graphic object would require a few more API calls:

[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;

This is the modified code:

private void DrawHighlight(Point[] usePoints, int brushSize, 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, brushSize, (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, p1.X, p1.Y, IntPtr.Zero);
      LineTo(mDC, p2.X, p2.Y);
    }
    SetROP2(mDC, R2_COPYPEN);

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

这篇关于突出显示效果,如剪切工具的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 20:27