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