mirror of
https://github.com/greenshot/greenshot
synced 2025-08-19 21:13:23 -07:00
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:
parent
3b9cc41832
commit
ce632b1496
4 changed files with 248 additions and 37 deletions
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue