diff --git a/Greenshot/Forms/ZoomForm.cs b/Greenshot/Controls/ZoomControl.cs similarity index 66% rename from Greenshot/Forms/ZoomForm.cs rename to Greenshot/Controls/ZoomControl.cs index d144404f4..7837b8ff3 100644 --- a/Greenshot/Forms/ZoomForm.cs +++ b/Greenshot/Controls/ZoomControl.cs @@ -25,35 +25,75 @@ using System.Drawing; using Greenshot.Plugin; using System.Drawing.Drawing2D; using GreenshotPlugin.Controls; +using GreenshotPlugin.UnmanagedHelpers; namespace Greenshot.Forms { /// - /// This form will show the area around the mouse of the current capture + /// This control will show the area around the mouse of the current capture /// - public class ZoomForm : FormWithoutActivation { - private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ZoomForm)); + public class ZoomControl : Control { + private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ZoomControl)); private Image imageToZoom = null; private Point zoomLocation = Point.Empty; private const int distanceX = 20; private const int distanceY = 20; - public ZoomForm(Image imageToZoom) { + /// + /// Create a zoom control for the image and with the size + /// + /// + /// + public ZoomControl(Image imageToZoom, Size zoomSize) { InitializeComponent(); + this.Width = zoomSize.Width; + this.Height = zoomSize.Height; this.imageToZoom = imageToZoom; Zoom = 400; } /// - /// Prevent the clipping of the child (this Form is a child of another) + /// Override some special form parameters /// protected override CreateParams CreateParams { get { var parms = base.CreateParams; - parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN + parms.Style &= ~((int)WindowStyleFlags.WS_CLIPCHILDREN); // Turn off WS_CLIPCHILDREN which prevents the screen to be cleared behind this form + parms.ExStyle |= (int)ExtendedWindowStyleFlags.WS_EX_NOACTIVATE | (int)ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW | (int)ExtendedWindowStyleFlags.WS_EX_TOPMOST; + //parms.ExStyle |= (int)ExtendedWindowStyleFlags.WS_EX_TRANSPARENT; + parms.Parent = IntPtr.Zero; // Make parentless return parms; } } + /// + /// Shows the control as a floating Window child + /// of the desktop. To hide the control again, + /// use the property. + /// + public void ShowFloating() { + if (this.Handle == IntPtr.Zero) { + base.CreateControl(); + } + User32.SetParent(base.Handle, IntPtr.Zero); + User32.ShowWindow(base.Handle, ShowWindowCommand.Show); + } + + /// + /// Make the mouse events pass through + /// + /// + protected override void WndProc(ref Message m) { + const int HTTRANSPARENT = (-1); + switch (m.Msg) { + case (int)WindowsMessages.WM_NCHITTEST: + m.Result = (IntPtr) HTTRANSPARENT; + break; + default: + base.WndProc(ref m); + break; + } + } + /// /// Sets the location of the mouse on the screen (using screen coordinates, which might differ from bitmap coordindates in a multi screen setup) /// @@ -91,10 +131,14 @@ namespace Greenshot.Forms { } + /// + /// The zoom property + /// public int Zoom { get; set; } + /// /// This makes sure there is no background painted, as we have complete "paint" control it doesn't make sense to do otherwise. /// @@ -102,6 +146,10 @@ namespace Greenshot.Forms { protected override void OnPaintBackground(PaintEventArgs pevent) { } + /// + /// Paint the zoom area and the cross + /// + /// protected override void OnPaint(PaintEventArgs e) { if (imageToZoom == null) { return; @@ -111,14 +159,15 @@ namespace Greenshot.Forms { graphics.SmoothingMode = SmoothingMode.None; graphics.InterpolationMode = InterpolationMode.NearestNeighbor; graphics.CompositingQuality = CompositingQuality.HighSpeed; - graphics.PixelOffsetMode = PixelOffsetMode.None; + graphics.PixelOffsetMode = PixelOffsetMode.Half; Rectangle clipRectangle = e.ClipRectangle; - float zoom = (float)100 / (float)Zoom; + float zoomFactor = (float)100 / (float)Zoom; - int sourceWidth = (int)(Width * zoom); - int sourceHeight = (int)(Height * zoom); - Rectangle sourceRectangle = new Rectangle(ZoomLocation.X - (sourceWidth / 2), ZoomLocation.Y - (sourceHeight / 2), sourceWidth, sourceHeight); + int sourceWidth = (int)(Width * zoomFactor); + int sourceHeight = (int)(Height * zoomFactor); + Rectangle sourceRectangle = new Rectangle(ZoomLocation.X - (sourceWidth / 2) + 1, ZoomLocation.Y - (sourceHeight / 2) + 1, sourceWidth, sourceHeight); Rectangle destinationRectangle = new Rectangle(0, 0, Width, Height); + //graphics.StretchBlt((Bitmap)imageToZoom, sourceRectangle, destinationRectangle); graphics.DrawImage(imageToZoom, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel); int pixelThickness = Zoom / 100; @@ -136,25 +185,10 @@ namespace Greenshot.Forms { private void InitializeComponent() { this.SuspendLayout(); - // - // ZoomForm - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; - this.ClientSize = new System.Drawing.Size(100, 100); - this.ControlBox = false; // Only double-buffer when we are not in a TerminalServerSession this.DoubleBuffered = !System.Windows.Forms.SystemInformation.TerminalServerSession; - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.MinimumSize = ClientSize; this.Name = "Zoom"; - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; - this.TopMost = true; this.ResumeLayout(false); } } diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs index 54062be2b..7729c0057 100644 --- a/Greenshot/Forms/CaptureForm.cs +++ b/Greenshot/Forms/CaptureForm.cs @@ -37,7 +37,7 @@ using Greenshot.IniFile; namespace Greenshot.Forms { /// - /// Description of CaptureForm. + /// The capture form is used to select a part of the capture /// public partial class CaptureForm : Form { private enum FixMode {None, Initiated, Horizontal, Vertical}; @@ -65,20 +65,29 @@ namespace Greenshot.Forms { private Point previousMousePos = Point.Empty; private FixMode fixMode = FixMode.None; - private ZoomForm zoomForm = null; + private ZoomControl zoomControl = null; + /// + /// Property to access the selected capture rectangle + /// public Rectangle CaptureRectangle { get { return captureRect; } } + /// + /// Property to access the used capture mode + /// public CaptureMode UsedCaptureMode { get { return captureMode; } } + /// + /// Get the selected window + /// public WindowDetails SelectedCaptureWindow { get { return selectedCaptureWindow; @@ -96,6 +105,11 @@ namespace Greenshot.Forms { } } + /// + /// This creates the capture form + /// + /// + /// public CaptureForm(ICapture capture, List windows) { if (currentForm != null) { LOG.Debug("Found currentForm, Closing already opened CaptureForm"); @@ -109,9 +123,9 @@ namespace Greenshot.Forms { timer = new Timer(); // Using 32bppPArgb speeds up the drawing. - capturedImage = ImageHelper.Clone(capture.Image, PixelFormat.Format32bppPArgb); + //capturedImage = ImageHelper.Clone(capture.Image, PixelFormat.Format32bppPArgb); // comment the clone, uncomment the assignment and the original bitmap is used. - //capturedImage = capture.Image; + capturedImage = capture.Image; // clean up this.FormClosed += delegate { @@ -160,36 +174,43 @@ namespace Greenshot.Forms { // Fix missing focus WindowDetails.ToForeground(this.Handle); this.TopMost = true; - CreateZoom(); if (timer != null) { - timer.Interval = 40; + timer.Interval = 30; timer.Tick += new EventHandler(timer_Tick); timer.Start(); } } + /// + /// Create the zoom control + /// private void CreateZoom() { - if (zoomForm == null) { - zoomForm = new ZoomForm(capturedImage); - zoomForm.Show(this); - - zoomForm.MouseLocation = cursorPos; - zoomForm.ZoomLocation = cursorPosOnBitmap; - - // Fix missing focus issue - WindowDetails.ToForeground(this.Handle); + if (zoomControl == null) { + zoomControl = new ZoomControl(capturedImage, new Size(200, 200)); + zoomControl.MouseLocation = cursorPos; + zoomControl.ZoomLocation = cursorPosOnBitmap; + zoomControl.ShowFloating(); } } + /// + /// Hide the zoom control + /// private void RemoveZoom() { - if (zoomForm != null) { - zoomForm.Close(); - // Fix missing focus issue - WindowDetails.ToForeground(this.Handle); - zoomForm = null; + if (zoomControl != null) { + zoomControl.Hide(); } } + /// + /// Create the zoom after the window is showing + /// + /// + protected override void OnShown(EventArgs e) { + base.OnShown(e); + CreateZoom(); + } + #region key handling void CaptureFormKeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.ShiftKey) { @@ -220,7 +241,7 @@ namespace Greenshot.Forms { Invalidate(); } else if (e.KeyCode == Keys.Z) { // Toggle zoom - if (zoomForm == null) { + if (zoomControl == null) { CreateZoom(); } else { RemoveZoom(); @@ -327,9 +348,9 @@ namespace Greenshot.Forms { bool verticalMove = false; // Change the zoom location - if (zoomForm != null) { - zoomForm.MouseLocation = cursorPos; - zoomForm.ZoomLocation = cursorPosOnBitmap; + if (zoomControl != null) { + zoomControl.MouseLocation = cursorPos; + zoomControl.ZoomLocation = cursorPosOnBitmap; } if (lastPos.X != cursorPos.X) { diff --git a/Greenshot/Greenshot.csproj b/Greenshot/Greenshot.csproj index e877121ad..3d1a94946 100644 --- a/Greenshot/Greenshot.csproj +++ b/Greenshot/Greenshot.csproj @@ -67,6 +67,9 @@ Component + + Form + @@ -181,9 +184,6 @@ - - Form - diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs index e0178cf74..f9c4f875a 100644 --- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs @@ -44,6 +44,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { [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)] + public static extern bool StretchBlt(IntPtr hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, CopyPixelOperation dwRop ); + [DllImport("gdi32", SetLastError=true)] public static extern IntPtr CreateCompatibleDC(IntPtr hDC); [DllImport("gdi32", SetLastError=true)] public static extern bool DeleteDC(IntPtr hDC); @@ -63,18 +65,43 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int cx, int cy); /// - /// + /// Doesn't work? /// /// /// - public static void BitBlt(this Graphics target, Bitmap source, Point location) { + public static void StretchBlt(this Graphics target, Bitmap sourceBitmap, Rectangle source, Rectangle destination) { 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); + IntPtr pOrig = SelectObject(hDCSrc, sourceBitmap.GetHbitmap()); + StretchBlt(hDCDest, destination.X, destination.Y, destination.Width, destination.Height, hDCSrc, source.Left, source.Top, source.Width, source.Height, CopyPixelOperation.SourceCopy); + IntPtr pNew = SelectObject(hDCDest, pOrig); + } finally { + if (hDCSrc != IntPtr.Zero) { + DeleteDC(hDCSrc); + } + if (hDCDest != IntPtr.Zero) { + target.ReleaseHdc(hDCDest); + } + } + } + + /// + /// + /// + /// + /// + public static void BitBlt(this Graphics target, Bitmap sourceBitmap, Rectangle source, Point destination) { + IntPtr hDCSrc = IntPtr.Zero; + IntPtr hDCDest = IntPtr.Zero; + try { + hDCDest = target.GetHdc(); + hDCSrc = CreateCompatibleDC(hDCDest); + IntPtr pOrig = SelectObject(hDCSrc, sourceBitmap.GetHbitmap()); + BitBlt(hDCDest, destination.X, destination.Y, source.Width, source.Height, hDCSrc, source.Left, source.Top, CopyPixelOperation.SourceCopy); + IntPtr pNew = SelectObject(hDCDest, pOrig); } finally { if (hDCSrc != IntPtr.Zero) { DeleteDC(hDCSrc); diff --git a/GreenshotPlugin/UnmanagedHelpers/User32.cs b/GreenshotPlugin/UnmanagedHelpers/User32.cs index 10981d469..fb7252b29 100644 --- a/GreenshotPlugin/UnmanagedHelpers/User32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/User32.cs @@ -309,10 +309,14 @@ namespace GreenshotPlugin.UnmanagedHelpers { public extern static bool IsWindowVisible(IntPtr hWnd); [DllImport("user32", SetLastError = true)] public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr processId); - [DllImport("user32", SetLastError = true, ExactSpelling=true, CharSet=CharSet.Auto)] + [DllImport("user32", SetLastError = true)] public static extern IntPtr GetParent(IntPtr hWnd); [DllImport("user32", SetLastError = true)] + public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent); + [DllImport("user32", SetLastError = true)] public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCommand uCmd); + [DllImport("user32", SetLastError = true)] + public static extern int ShowWindow(IntPtr hWnd, ShowWindowCommand nCmdShow); [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)] public extern static int GetWindowText(IntPtr hWnd, StringBuilder lpString, int cch); [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]