From ce632b14968bace5cdd20cef8ad3217872669be6 Mon Sep 17 00:00:00 2001 From: RKrom Date: Sun, 2 Dec 2012 12:49:44 +0000 Subject: [PATCH] Added changes for the zoom to animate relative to the cursor position. Also made the first changes to make sure the animation has a frame rate equal to the screen refresh. git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2341 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- Greenshot/Forms/CaptureForm.cs | 89 ++++++---- Greenshot/Helpers/AnimationHelper.cs | 28 +++ .../UnmanagedHelpers/Enumerations.cs | 164 ++++++++++++++++++ GreenshotPlugin/UnmanagedHelpers/GDI32.cs | 4 +- 4 files changed, 248 insertions(+), 37 deletions(-) diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs index 4f8693535..4b691352e 100644 --- a/Greenshot/Forms/CaptureForm.cs +++ b/Greenshot/Forms/CaptureForm.cs @@ -71,8 +71,10 @@ namespace Greenshot.Forms { private bool isZooming = true; private Point previousMousePos = Point.Empty; private FixMode fixMode = FixMode.None; - private RectangleAnimator windowAnimator = new RectangleAnimator(Rectangle.Empty, Rectangle.Empty, 0, EasingType.Linear); - private SizeAnimator zoomAnimator = new SizeAnimator(Size.Empty, new Size(200, 200), 30, EasingType.Quintic); + private RectangleAnimator windowAnimator = new RectangleAnimator(Rectangle.Empty, Rectangle.Empty, 0, EasingType.Quadratic); + private Size zoomSize = new Size(200, 200); + private Point zoomOffset = new Point(20, 20); + private RectangleAnimator zoomAnimator; /// /// Property to access the selected capture rectangle @@ -126,6 +128,14 @@ namespace Greenshot.Forms { } currentForm = this; + // get te hDC of the desktop to get the VREFRESH + IntPtr hDCDesktop = User32.GetWindowDC(User32.GetDesktopWindow()); + int vRefesh = GDI32.GetDeviceCaps(hDCDesktop, DeviceCaps.VREFRESH); + User32.ReleaseDC(hDCDesktop); + LOG.DebugFormat("VRefresh {0}", vRefesh); + + zoomAnimator = new RectangleAnimator(Rectangle.Empty, new Rectangle(zoomOffset, zoomSize), 20, EasingType.Quintic); + // comment this out if the timer should not be used timer = new Timer(); @@ -180,7 +190,7 @@ namespace Greenshot.Forms { this.TopMost = true; if (timer != null) { - timer.Interval = 30; + timer.Interval = 1000/vRefesh; timer.Tick += new EventHandler(timer_Tick); timer.Start(); } @@ -455,7 +465,7 @@ namespace Greenshot.Forms { } if (selectedCaptureWindow != null && !selectedCaptureWindow.Equals(lastWindow)) { // Window changes, make new animation from current to target - windowAnimator = new RectangleAnimator(windowAnimator.Current,captureRect, 18, EasingType.Quintic); + windowAnimator.ChangeDestination(captureRect, 14); Rectangle invalidateRectangle = new Rectangle(lastCaptureRect.Location, lastCaptureRect.Size); invalidateRectangle.Inflate(SAFETY_SIZE, SAFETY_SIZE); Invalidate(invalidateRectangle); @@ -481,14 +491,13 @@ namespace Greenshot.Forms { } } if (isZooming && captureMode != CaptureMode.Window) { - Invalidate(ZoomArea(lastPos, zoomAnimator.Current)); - Invalidate(ZoomArea(cursorPos, zoomAnimator.Next())); - - // TODO: Move this to the Animator, but we need to check how to make sure we have an exact result. - //if (zoomSize.Width < 200) { - // zoomSize.Width += (220-zoomSize.Width)/5; - // zoomSize.Height += (220-zoomSize.Height)/5; - //} + Rectangle zoomArea = zoomAnimator.Current; + zoomArea.Offset(lastPos); + Invalidate(zoomArea); + + zoomArea = AnimateZoomArea(cursorPos); + zoomArea.Offset(cursorPos); + Invalidate(zoomArea); } // Force update "now" Update(); @@ -513,31 +522,36 @@ namespace Greenshot.Forms { } /// - /// Get the area of where the zoom can be drawn + /// Checks if the Zoom area can move there where it wants to go + /// Change direction if not. /// - /// - /// - /// - private Rectangle ZoomArea(Point pos, Size size) { - Rectangle ret; - const int distanceX = 20; - const int distanceY = 20; - Rectangle tl = new Rectangle(pos.X - (distanceX + size.Width), pos.Y - (distanceY + size.Height), size.Width, size.Height); - Rectangle tr = new Rectangle(pos.X + distanceX, pos.Y - (distanceY + size.Height), size.Width, size.Height); - Rectangle bl = new Rectangle(pos.X - (distanceX + size.Width), pos.Y + distanceY, size.Width, size.Height); - Rectangle br = new Rectangle(pos.X + distanceX, pos.Y + distanceY, size.Width, size.Height); - Rectangle screenBounds = Screen.GetBounds(pos); - if (screenBounds.Contains(br)) { - ret = br; - } else if (screenBounds.Contains(bl)) { - ret = bl; - } else if (screenBounds.Contains(tr)) { - ret = tr; - } else { - ret = tl; + private Rectangle AnimateZoomArea(Point pos) { + Rectangle screenBounds = Screen.GetBounds(MousePosition); + + Rectangle targetRectangle = zoomAnimator.Last; + targetRectangle.Offset(pos); + + if (screenBounds.Contains(targetRectangle)) { + // All okay + return zoomAnimator.Next(); } - ret.Offset(-capture.ScreenBounds.Location.X, -capture.ScreenBounds.Location.Y); - return ret; + + Point destinationLocation; + Rectangle tl = new Rectangle(pos.X - (zoomOffset.X + zoomSize.Width), pos.Y - (zoomOffset.Y + zoomSize.Height), zoomSize.Width, zoomSize.Height); + Rectangle tr = new Rectangle(pos.X + zoomOffset.X, pos.Y - (zoomOffset.Y + zoomSize.Height), zoomSize.Width, zoomSize.Height); + Rectangle bl = new Rectangle(pos.X - (zoomOffset.X + zoomSize.Width), pos.Y + zoomOffset.Y, zoomSize.Width, zoomSize.Height); + Rectangle br = new Rectangle(pos.X + zoomOffset.X, pos.Y + zoomOffset.Y, zoomSize.Width, zoomSize.Height); + if (screenBounds.Contains(br)) { + destinationLocation = new Point(zoomOffset.X, zoomOffset.Y); + } else if (screenBounds.Contains(bl)) { + destinationLocation = new Point(-zoomOffset.X - zoomSize.Width, zoomOffset.Y); + } else if (screenBounds.Contains(tr)) { + destinationLocation = new Point(zoomOffset.X, -zoomOffset.Y - zoomSize.Width); + } else { + destinationLocation = new Point(-zoomOffset.X - zoomSize.Width, -zoomOffset.Y - zoomSize.Width); + } + zoomAnimator.ChangeDestination(new Rectangle(destinationLocation, zoomSize)); + return zoomAnimator.Next(); } /// @@ -772,7 +786,10 @@ namespace Greenshot.Forms { const int zoomSourceHeight = 25; Rectangle sourceRectangle = new Rectangle(cursorPosOnBitmap.X - (zoomSourceWidth / 2), cursorPosOnBitmap.Y - (zoomSourceHeight / 2), zoomSourceWidth, zoomSourceHeight); - DrawZoom(graphics, sourceRectangle, ZoomArea(cursorPos, zoomAnimator.Current)); + + Rectangle destinationRectangle = zoomAnimator.Current; + destinationRectangle.Offset(cursorPos); + DrawZoom(graphics, sourceRectangle, destinationRectangle); } } diff --git a/Greenshot/Helpers/AnimationHelper.cs b/Greenshot/Helpers/AnimationHelper.cs index a35e37ada..3a6796026 100644 --- a/Greenshot/Helpers/AnimationHelper.cs +++ b/Greenshot/Helpers/AnimationHelper.cs @@ -34,6 +34,34 @@ namespace Greenshot.Helpers { protected T current; protected double frames; protected double currentFrame = 0; + + public double Frames { + get { return frames; } + } + + public double CurrentFrame { + get { return currentFrame; } + } + + public T First { + get { return first; } + } + + public T Last { + get { return last; } + } + + public void ChangeDestination(T last) { + ChangeDestination(last, frames); + } + + public void ChangeDestination(T last, double frames) { + this.first = current; + this.currentFrame = 0; + this.frames = frames; + this.last = last; + } + public EasingType EasingType { get; set; diff --git a/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs b/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs index 7d55d4a3f..81a4c16a5 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs @@ -961,4 +961,168 @@ namespace GreenshotPlugin.UnmanagedHelpers { SND_ALIAS_ID = 0x00110000, // alias is a predefined id SND_FILENAME = 0x00020000, // name is file name } + + public enum DeviceCaps { + /// + /// Device driver version + /// + DRIVERVERSION = 0, + /// + /// Device classification + /// + TECHNOLOGY = 2, + /// + /// Horizontal size in millimeters + /// + HORZSIZE = 4, + /// + /// Vertical size in millimeters + /// + VERTSIZE = 6, + /// + /// Horizontal width in pixels + /// + HORZRES = 8, + /// + /// Vertical height in pixels + /// + VERTRES = 10, + /// + /// Number of bits per pixel + /// + BITSPIXEL = 12, + /// + /// Number of planes + /// + PLANES = 14, + /// + /// Number of brushes the device has + /// + NUMBRUSHES = 16, + /// + /// Number of pens the device has + /// + NUMPENS = 18, + /// + /// Number of markers the device has + /// + NUMMARKERS = 20, + /// + /// Number of fonts the device has + /// + NUMFONTS = 22, + /// + /// Number of colors the device supports + /// + NUMCOLORS = 24, + /// + /// Size required for device descriptor + /// + PDEVICESIZE = 26, + /// + /// Curve capabilities + /// + CURVECAPS = 28, + /// + /// Line capabilities + /// + LINECAPS = 30, + /// + /// Polygonal capabilities + /// + POLYGONALCAPS = 32, + /// + /// Text capabilities + /// + TEXTCAPS = 34, + /// + /// Clipping capabilities + /// + CLIPCAPS = 36, + /// + /// Bitblt capabilities + /// + RASTERCAPS = 38, + /// + /// Length of the X leg + /// + ASPECTX = 40, + /// + /// Length of the Y leg + /// + ASPECTY = 42, + /// + /// Length of the hypotenuse + /// + ASPECTXY = 44, + /// + /// Shading and Blending caps + /// + SHADEBLENDCAPS = 45, + + /// + /// Logical pixels inch in X + /// + LOGPIXELSX = 88, + /// + /// Logical pixels inch in Y + /// + LOGPIXELSY = 90, + + /// + /// Number of entries in physical palette + /// + SIZEPALETTE = 104, + /// + /// Number of reserved entries in palette + /// + NUMRESERVED = 106, + /// + /// Actual color resolution + /// + COLORRES = 108, + + // Printing related DeviceCaps. These replace the appropriate Escapes + /// + /// Physical Width in device units + /// + PHYSICALWIDTH = 110, + /// + /// Physical Height in device units + /// + PHYSICALHEIGHT = 111, + /// + /// Physical Printable Area x margin + /// + PHYSICALOFFSETX = 112, + /// + /// Physical Printable Area y margin + /// + PHYSICALOFFSETY = 113, + /// + /// Scaling factor x + /// + SCALINGFACTORX = 114, + /// + /// Scaling factor y + /// + SCALINGFACTORY = 115, + + /// + /// Current vertical refresh rate of the display device (for displays only) in Hz + /// + VREFRESH = 116, + /// + /// Horizontal width of entire desktop in pixels + /// + DESKTOPVERTRES = 117, + /// + /// Vertical height of entire desktop in pixels + /// + DESKTOPHORZRES = 118, + /// + /// Preferred blt alignment + /// + BLTALIGNMENT = 119 + } } diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs index f9c4f875a..56c8d4205 100644 --- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs @@ -61,8 +61,10 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern int GetClipBox(IntPtr hdc, out RECT lprc); [DllImport("gdi32", SetLastError = true)] public static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); - [DllImport("gdi32")] + [DllImport("gdi32", SetLastError = true)] public static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int cx, int cy); + [DllImport("gdi32", SetLastError = true)] + public static extern int GetDeviceCaps(IntPtr hdc, DeviceCaps nIndex); /// /// Doesn't work?