我正在创建一个类似于
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); } }