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
This commit is contained in:
RKrom 2012-12-02 12:49:44 +00:00
commit ce632b1496
4 changed files with 248 additions and 37 deletions

View file

@ -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;
/// <summary>
/// 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()));
Rectangle zoomArea = zoomAnimator.Current;
zoomArea.Offset(lastPos);
Invalidate(zoomArea);
// 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;
//}
zoomArea = AnimateZoomArea(cursorPos);
zoomArea.Offset(cursorPos);
Invalidate(zoomArea);
}
// Force update "now"
Update();
@ -513,31 +522,36 @@ namespace Greenshot.Forms {
}
/// <summary>
/// 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.
/// </summary>
/// <param name="pos"></param>
/// <param name="size"></param>
/// <returns></returns>
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();
}
/// <summary>
@ -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);
}
}

View file

@ -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;

View file

@ -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 {
/// <summary>
/// Device driver version
/// </summary>
DRIVERVERSION = 0,
/// <summary>
/// Device classification
/// </summary>
TECHNOLOGY = 2,
/// <summary>
/// Horizontal size in millimeters
/// </summary>
HORZSIZE = 4,
/// <summary>
/// Vertical size in millimeters
/// </summary>
VERTSIZE = 6,
/// <summary>
/// Horizontal width in pixels
/// </summary>
HORZRES = 8,
/// <summary>
/// Vertical height in pixels
/// </summary>
VERTRES = 10,
/// <summary>
/// Number of bits per pixel
/// </summary>
BITSPIXEL = 12,
/// <summary>
/// Number of planes
/// </summary>
PLANES = 14,
/// <summary>
/// Number of brushes the device has
/// </summary>
NUMBRUSHES = 16,
/// <summary>
/// Number of pens the device has
/// </summary>
NUMPENS = 18,
/// <summary>
/// Number of markers the device has
/// </summary>
NUMMARKERS = 20,
/// <summary>
/// Number of fonts the device has
/// </summary>
NUMFONTS = 22,
/// <summary>
/// Number of colors the device supports
/// </summary>
NUMCOLORS = 24,
/// <summary>
/// Size required for device descriptor
/// </summary>
PDEVICESIZE = 26,
/// <summary>
/// Curve capabilities
/// </summary>
CURVECAPS = 28,
/// <summary>
/// Line capabilities
/// </summary>
LINECAPS = 30,
/// <summary>
/// Polygonal capabilities
/// </summary>
POLYGONALCAPS = 32,
/// <summary>
/// Text capabilities
/// </summary>
TEXTCAPS = 34,
/// <summary>
/// Clipping capabilities
/// </summary>
CLIPCAPS = 36,
/// <summary>
/// Bitblt capabilities
/// </summary>
RASTERCAPS = 38,
/// <summary>
/// Length of the X leg
/// </summary>
ASPECTX = 40,
/// <summary>
/// Length of the Y leg
/// </summary>
ASPECTY = 42,
/// <summary>
/// Length of the hypotenuse
/// </summary>
ASPECTXY = 44,
/// <summary>
/// Shading and Blending caps
/// </summary>
SHADEBLENDCAPS = 45,
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90,
/// <summary>
/// Number of entries in physical palette
/// </summary>
SIZEPALETTE = 104,
/// <summary>
/// Number of reserved entries in palette
/// </summary>
NUMRESERVED = 106,
/// <summary>
/// Actual color resolution
/// </summary>
COLORRES = 108,
// Printing related DeviceCaps. These replace the appropriate Escapes
/// <summary>
/// Physical Width in device units
/// </summary>
PHYSICALWIDTH = 110,
/// <summary>
/// Physical Height in device units
/// </summary>
PHYSICALHEIGHT = 111,
/// <summary>
/// Physical Printable Area x margin
/// </summary>
PHYSICALOFFSETX = 112,
/// <summary>
/// Physical Printable Area y margin
/// </summary>
PHYSICALOFFSETY = 113,
/// <summary>
/// Scaling factor x
/// </summary>
SCALINGFACTORX = 114,
/// <summary>
/// Scaling factor y
/// </summary>
SCALINGFACTORY = 115,
/// <summary>
/// Current vertical refresh rate of the display device (for displays only) in Hz
/// </summary>
VREFRESH = 116,
/// <summary>
/// Horizontal width of entire desktop in pixels
/// </summary>
DESKTOPVERTRES = 117,
/// <summary>
/// Vertical height of entire desktop in pixels
/// </summary>
DESKTOPHORZRES = 118,
/// <summary>
/// Preferred blt alignment
/// </summary>
BLTALIGNMENT = 119
}
}

View file

@ -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);
/// <summary>
/// Doesn't work?