diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs index e3af96002..54062be2b 100644 --- a/Greenshot/Forms/CaptureForm.cs +++ b/Greenshot/Forms/CaptureForm.cs @@ -23,10 +23,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; +using System.Drawing.Imaging; using System.Drawing.Printing; using System.IO; using System.Windows.Forms; - using Greenshot.Configuration; using Greenshot.Drawing; using Greenshot.Helpers; @@ -51,6 +51,7 @@ namespace Greenshot.Forms { private int mX; private int mY; + private Point mouseMovePos = Point.Empty; private Point cursorPos = Point.Empty; private Point cursorPosOnBitmap = Point.Empty; private CaptureMode captureMode = CaptureMode.None; @@ -59,6 +60,8 @@ namespace Greenshot.Forms { private bool mouseDown = false; private Rectangle captureRect = Rectangle.Empty; private ICapture capture = null; + private Image capturedImage = null; + private Timer timer = null; private Point previousMousePos = Point.Empty; private FixMode fixMode = FixMode.None; @@ -101,6 +104,14 @@ namespace Greenshot.Forms { Application.DoEvents(); } currentForm = this; + + // comment this out if the timer should not be used + timer = new Timer(); + + // Using 32bppPArgb speeds up the drawing. + capturedImage = ImageHelper.Clone(capture.Image, PixelFormat.Format32bppPArgb); + // comment the clone, uncomment the assignment and the original bitmap is used. + //capturedImage = capture.Image; // clean up this.FormClosed += delegate { @@ -125,6 +136,13 @@ namespace Greenshot.Forms { WindowDetails.RegisterIgnoreHandle(this.Handle); // Unregister at close this.FormClosing += delegate { + if (timer != null) { + timer.Stop(); + } + // remove the buffer if it was created inside this form + if (capturedImage != capture.Image) { + capturedImage.Dispose(); + } LOG.Debug("Closing captureform"); WindowDetails.UnregisterIgnoreHandle(this.Handle); }; @@ -143,13 +161,21 @@ namespace Greenshot.Forms { WindowDetails.ToForeground(this.Handle); this.TopMost = true; CreateZoom(); + if (timer != null) { + timer.Interval = 40; + timer.Tick += new EventHandler(timer_Tick); + timer.Start(); + } } private void CreateZoom() { if (zoomForm == null) { - zoomForm = new ZoomForm(capture); + zoomForm = new ZoomForm(capturedImage); zoomForm.Show(this); + zoomForm.MouseLocation = cursorPos; + zoomForm.ZoomLocation = cursorPosOnBitmap; + // Fix missing focus issue WindowDetails.ToForeground(this.Handle); } @@ -271,13 +297,30 @@ namespace Greenshot.Forms { } void OnMouseMove(object sender, MouseEventArgs e) { - Point lastPos = new Point(cursorPos.X, cursorPos.Y); - cursorPos = WindowCapture.GetCursorLocation(); // Make sure the mouse coordinates are fixed, when pressing shift - cursorPos = FixMouseCoordinates(cursorPos); + mouseMovePos = FixMouseCoordinates(WindowCapture.GetCursorLocation()); + // If the timer is used, the timer_Tick does the following. + // If the timer is not used, we need to call the update ourselves + if (timer == null) { + updateFrame(); + } + } + + void timer_Tick(object sender, EventArgs e) { + updateFrame(); + } + + void updateFrame() { + Point lastPos = cursorPos.Clone(); + cursorPos = mouseMovePos.Clone(); + if (lastPos.Equals(cursorPos)) { + return; + } + // As the cursorPos is not in Bitmap coordinates, we need to correct. cursorPosOnBitmap = new Point(cursorPos.X, cursorPos.Y); cursorPosOnBitmap.Offset(-capture.ScreenBounds.Location.X, -capture.ScreenBounds.Location.Y); + Rectangle lastCaptureRect = new Rectangle(captureRect.Location, captureRect.Size); WindowDetails lastWindow = selectedCaptureWindow; bool horizontalMove = false; @@ -390,6 +433,8 @@ namespace Greenshot.Forms { } } } + // Force update "now" + Update(); } /// @@ -402,7 +447,8 @@ namespace Greenshot.Forms { void OnPaint(object sender, PaintEventArgs e) { Graphics graphics = e.Graphics; Rectangle clipRectangle = e.ClipRectangle; - graphics.DrawImageUnscaled(capture.Image, Point.Empty); + //graphics.BitBlt((Bitmap)buffer, Point.Empty); + graphics.DrawImageUnscaled(capturedImage, Point.Empty); // Only draw Cursor if it's (partly) visible if (capture.Cursor != null && capture.CursorVisible && clipRectangle.IntersectsWith(new Rectangle(capture.CursorLocation, capture.Cursor.Size))) { graphics.DrawIcon(capture.Cursor, capture.CursorLocation.X, capture.CursorLocation.Y); diff --git a/Greenshot/Forms/ZoomForm.cs b/Greenshot/Forms/ZoomForm.cs index eee7f576d..d144404f4 100644 --- a/Greenshot/Forms/ZoomForm.cs +++ b/Greenshot/Forms/ZoomForm.cs @@ -32,14 +32,14 @@ namespace Greenshot.Forms { /// public class ZoomForm : FormWithoutActivation { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ZoomForm)); - private ICapture captureToZoom = null; + private Image imageToZoom = null; private Point zoomLocation = Point.Empty; private const int distanceX = 20; private const int distanceY = 20; - public ZoomForm(ICapture captureToZoom) { + public ZoomForm(Image imageToZoom) { InitializeComponent(); - this.captureToZoom = captureToZoom; + this.imageToZoom = imageToZoom; Zoom = 400; } @@ -103,7 +103,7 @@ namespace Greenshot.Forms { } protected override void OnPaint(PaintEventArgs e) { - if (captureToZoom == null || captureToZoom.Image == null) { + if (imageToZoom == null) { return; } Graphics graphics = e.Graphics; @@ -111,7 +111,7 @@ namespace Greenshot.Forms { graphics.SmoothingMode = SmoothingMode.None; graphics.InterpolationMode = InterpolationMode.NearestNeighbor; graphics.CompositingQuality = CompositingQuality.HighSpeed; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.None; Rectangle clipRectangle = e.ClipRectangle; float zoom = (float)100 / (float)Zoom; @@ -119,7 +119,7 @@ namespace Greenshot.Forms { int sourceHeight = (int)(Height * zoom); Rectangle sourceRectangle = new Rectangle(ZoomLocation.X - (sourceWidth / 2), ZoomLocation.Y - (sourceHeight / 2), sourceWidth, sourceHeight); Rectangle destinationRectangle = new Rectangle(0, 0, Width, Height); - graphics.DrawImage(captureToZoom.Image, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel); + graphics.DrawImage(imageToZoom, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel); int pixelThickness = Zoom / 100; using (Pen pen = new Pen(Color.Black, pixelThickness)) { diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs index cecb70d72..e0178cf74 100644 --- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs @@ -40,7 +40,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { /// /// GDI32 Helpers /// - public class GDI32 { + public static class GDI32 { [DllImport("gdi32", SetLastError=true)] public static extern bool BitBlt(IntPtr hObject,int nXDest,int nYDest, int nWidth,int nHeight,IntPtr hObjectSource, int nXSrc,int nYSrc, CopyPixelOperation dwRop); [DllImport("gdi32", SetLastError=true)] @@ -61,6 +61,29 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); [DllImport("gdi32")] public static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int cx, int cy); + + /// + /// + /// + /// + /// + public static void BitBlt(this Graphics target, Bitmap source, Point location) { + IntPtr hDCSrc = IntPtr.Zero; + IntPtr hDCDest = IntPtr.Zero; + try { + hDCDest = target.GetHdc(); + hDCSrc = CreateCompatibleDC(hDCDest); + SelectObject(hDCSrc, source.GetHbitmap()); + GDI32.BitBlt(hDCDest, location.X, location.Y, source.Width, source.Height, hDCSrc, 0, 0, CopyPixelOperation.SourceCopy); + } finally { + if (hDCSrc != IntPtr.Zero) { + DeleteDC(hDCSrc); + } + if (hDCDest != IntPtr.Zero) { + target.ReleaseHdc(hDCDest); + } + } + } } [StructLayout(LayoutKind.Sequential, Pack = 2)]