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)]