ShareX/ShareX.ScreenCaptureLib/Forms/RegionCaptureForm.cs

1593 lines
60 KiB
C#
Raw Normal View History

2013-11-03 23:53:49 +13:00
#region License Information (GPL v3)
/*
ShareX - A program that allows you to take screenshots and share any file type
2017-01-11 21:39:40 +13:00
Copyright (c) 2007-2017 ShareX Team
2013-11-03 23:53:49 +13:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
*/
#endregion License Information (GPL v3)
2014-12-11 09:25:20 +13:00
using ShareX.HelpersLib;
using ShareX.ScreenCaptureLib.Properties;
using System;
using System.Collections.Generic;
using System.Diagnostics;
2013-11-03 23:53:49 +13:00
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
2013-11-03 23:53:49 +13:00
using System.Windows.Forms;
2014-12-11 09:25:20 +13:00
namespace ShareX.ScreenCaptureLib
2013-11-03 23:53:49 +13:00
{
2016-09-05 04:22:27 +12:00
public sealed class RegionCaptureForm : Form
2013-11-03 23:53:49 +13:00
{
2016-09-05 05:17:09 +12:00
public static GraphicsPath LastRegionFillPath { get; private set; }
2017-12-17 20:30:39 +13:00
public event Action<Image, string> SaveImageRequested;
public event Action<Image, string> SaveImageAsRequested;
public event Action<Image> CopyImageRequested;
public event Action<Image> UploadImageRequested;
public event Action<Image> PrintImageRequested;
2017-11-07 05:01:02 +13:00
public RegionCaptureOptions Options { get; set; }
public Rectangle ClientArea { get; private set; }
public Image Canvas { get; private set; }
public Rectangle CanvasRectangle { get; private set; }
public RegionResult Result { get; private set; }
public int FPS { get; private set; }
public int MonitorIndex { get; set; }
public string ImageFilePath { get; set; }
public bool IsFullscreen { get; private set; }
public RegionCaptureMode Mode { get; private set; }
public bool IsEditorMode => Mode == RegionCaptureMode.Editor || Mode == RegionCaptureMode.TaskEditor;
public bool IsAnnotationMode => Mode == RegionCaptureMode.Annotation || IsEditorMode;
public bool IsAnnotated => ShapeManager != null && ShapeManager.IsAnnotated;
public Point CurrentPosition { get; private set; }
public Point PanningStrech = new Point();
public Color CurrentColor
{
get
{
if (bmpBackgroundImage != null)
{
Point position = CaptureHelpers.ScreenToClient(CurrentPosition);
if (position.X.IsBetween(0, bmpBackgroundImage.Width - 1) && position.Y.IsBetween(0, bmpBackgroundImage.Height - 1))
{
return bmpBackgroundImage.GetPixel(position.X, position.Y);
}
}
return Color.Empty;
}
}
public SimpleWindowInfo SelectedWindow { get; private set; }
2017-11-09 16:00:27 +13:00
public Vector2 CanvasCenterOffset { get; set; } = new Vector2(0f, 0f);
2017-10-25 07:53:31 +13:00
internal ShapeManager ShapeManager { get; private set; }
internal bool IsClosing { get; private set; }
2017-10-30 21:20:03 +13:00
internal Image CustomNodeImage = Resources.CircleNode;
internal int ToolbarHeight;
2017-10-24 10:40:37 +13:00
private InputManager InputManager => ShapeManager.InputManager;
private TextureBrush backgroundBrush, backgroundHighlightBrush;
private GraphicsPath regionFillPath, regionDrawPath;
private Pen borderPen, borderDotPen, borderDotStaticPen, textOuterBorderPen, textInnerBorderPen, markerPen, canvasBorderPen;
private Brush nodeBackgroundBrush, textBackgroundBrush;
private Font infoFont, infoFontMedium, infoFontBig;
private Stopwatch timerStart, timerFPS;
private int frameCount;
private bool pause, isKeyAllowed;
2017-04-03 19:55:54 +12:00
private RectangleAnimation regionAnimation;
private TextAnimation editorPanTipAnimation;
private Bitmap bmpBackgroundImage;
2017-10-18 03:54:19 +13:00
private Cursor defaultCursor;
2017-12-09 03:21:44 +13:00
private ScrollbarManager scrollbarManager;
public RegionCaptureForm(RegionCaptureMode mode, RegionCaptureOptions options, Image canvas = null)
2013-11-03 23:53:49 +13:00
{
2016-05-14 20:58:24 +12:00
Mode = mode;
2017-11-07 05:01:02 +13:00
Options = options;
2016-05-14 20:58:24 +12:00
2017-12-27 02:40:36 +13:00
if (canvas == null)
{
canvas = new Screenshot().CaptureFullscreen();
}
2017-12-27 02:40:36 +13:00
IsFullscreen = !IsEditorMode || Options.ImageEditorStartMode == ImageEditorStartMode.Fullscreen;
2017-11-07 05:01:02 +13:00
ClientArea = CaptureHelpers.GetScreenBounds0Based();
CanvasRectangle = ClientArea;
timerStart = new Stopwatch();
timerFPS = new Stopwatch();
2017-04-03 22:49:00 +12:00
regionAnimation = new RectangleAnimation()
{
2017-05-30 17:52:07 +12:00
Duration = TimeSpan.FromMilliseconds(200)
2017-04-03 22:49:00 +12:00
};
2017-12-09 03:21:44 +13:00
if (IsEditorMode)
{
2017-12-09 03:21:44 +13:00
scrollbarManager = new ScrollbarManager(this);
if (Options.ShowEditorPanTip)
{
2017-12-09 03:21:44 +13:00
editorPanTipAnimation = new TextAnimation()
{
Duration = TimeSpan.FromMilliseconds(5000),
FadeOutDuration = TimeSpan.FromMilliseconds(1000),
Text = Resources.RegionCaptureForm_TipYouCanPanImageByHoldingMouseMiddleButtonAndDragging
};
}
}
borderPen = new Pen(Color.Black);
2016-09-05 05:17:09 +12:00
borderDotPen = new Pen(Color.White) { DashPattern = new float[] { 5, 5 } };
borderDotStaticPen = new Pen(Color.White) { DashPattern = new float[] { 5, 5 } };
nodeBackgroundBrush = new SolidBrush(Color.White);
infoFont = new Font("Verdana", 9);
infoFontMedium = new Font("Verdana", 12);
infoFontBig = new Font("Verdana", 16, FontStyle.Bold);
textBackgroundBrush = new SolidBrush(Color.FromArgb(150, Color.FromArgb(42, 131, 199)));
textOuterBorderPen = new Pen(Color.FromArgb(150, Color.White));
textInnerBorderPen = new Pen(Color.FromArgb(150, Color.FromArgb(0, 81, 145)));
markerPen = new Pen(Color.FromArgb(200, Color.Red));
canvasBorderPen = new Pen(Color.FromArgb(30, Color.Black));
Prepare(canvas);
InitializeComponent();
}
private void InitializeComponent()
{
SuspendLayout();
AutoScaleMode = AutoScaleMode.None;
defaultCursor = Helpers.CreateCursor(Resources.Crosshair);
2017-10-18 03:54:19 +13:00
SetDefaultCursor();
2016-09-05 05:17:09 +12:00
Icon = ShareXResources.Icon;
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
UpdateTitle();
2017-10-29 22:49:25 +13:00
StartPosition = FormStartPosition.Manual;
if (IsFullscreen)
{
FormBorderStyle = FormBorderStyle.None;
Bounds = CaptureHelpers.GetScreenBounds();
ShowInTaskbar = false;
#if !DEBUG
TopMost = true;
#endif
}
else
{
FormBorderStyle = FormBorderStyle.Sizable;
2017-12-04 13:32:38 +13:00
MinimumSize = new Size(800, 550);
if (Options.ImageEditorStartMode == ImageEditorStartMode.PreviousState)
{
Options.ImageEditorWindowState.ApplyFormState(this);
}
else
{
Rectangle activeScreenWorkingArea = CaptureHelpers.GetActiveScreenWorkingArea();
2017-10-29 22:49:25 +13:00
Size size = new Size(900, 700);
bool isMaximized = Options.ImageEditorStartMode == ImageEditorStartMode.Maximized;
if (Options.ImageEditorStartMode == ImageEditorStartMode.AutoSize)
{
int margin = 100;
Size canvasWindowSize = new Size(Canvas.Width + SystemInformation.BorderSize.Width * 2 + margin,
Canvas.Height + SystemInformation.CaptionHeight + SystemInformation.BorderSize.Height * 2 + margin);
canvasWindowSize = new Size(Math.Max(MinimumSize.Width, canvasWindowSize.Width), Math.Max(MinimumSize.Height, canvasWindowSize.Height));
if (canvasWindowSize.Width < activeScreenWorkingArea.Width && canvasWindowSize.Height < activeScreenWorkingArea.Height)
{
size = canvasWindowSize;
}
else
{
isMaximized = true;
}
}
Bounds = new Rectangle(activeScreenWorkingArea.X + (activeScreenWorkingArea.Width / 2) - (size.Width / 2),
activeScreenWorkingArea.Y + (activeScreenWorkingArea.Height / 2) - (size.Height / 2), size.Width, size.Height);
2017-10-29 22:49:25 +13:00
if (isMaximized)
2017-10-29 22:49:25 +13:00
{
WindowState = FormWindowState.Maximized;
}
else
{
WindowState = FormWindowState.Normal;
}
}
ShowInTaskbar = true;
}
2016-09-05 05:17:09 +12:00
Shown += RegionCaptureForm_Shown;
KeyDown += RegionCaptureForm_KeyDown;
KeyUp += RegionCaptureForm_KeyUp;
MouseDown += RegionCaptureForm_MouseDown;
2017-10-24 11:40:20 +13:00
Resize += RegionCaptureForm_Resize;
LocationChanged += RegionCaptureForm_LocationChanged;
FormClosing += RegionCaptureForm_FormClosing;
2016-09-05 05:17:09 +12:00
ResumeLayout(false);
2013-11-03 23:53:49 +13:00
}
2017-11-08 13:47:22 +13:00
internal void UpdateTitle()
{
string text;
if (IsEditorMode)
{
text = "ShareX - " + Resources.RegionCaptureForm_InitializeComponent_ImageEditor;
2017-11-07 05:01:02 +13:00
if (Canvas != null)
{
2017-11-07 05:01:02 +13:00
text += $" - {Canvas.Width}x{Canvas.Height}";
}
string filename = Helpers.GetFilenameSafe(ImageFilePath);
if (!string.IsNullOrEmpty(filename))
{
text += " - " + filename;
}
2017-11-08 13:47:22 +13:00
if (!IsFullscreen && Options.ShowFPS)
{
text += " - FPS: " + FPS.ToString();
}
}
else
{
text = "ShareX - " + Resources.BaseRegionForm_InitializeComponent_Region_capture;
}
Text = text;
}
private void Prepare(Image canvas = null)
{
ShapeManager = new ShapeManager(this);
2017-11-07 05:01:02 +13:00
ShapeManager.WindowCaptureMode = !IsEditorMode && Options.DetectWindows;
ShapeManager.IncludeControls = Options.DetectControls;
2017-12-27 02:40:36 +13:00
InitBackground(canvas);
2017-10-24 10:40:37 +13:00
if (Mode == RegionCaptureMode.OneClick || ShapeManager.WindowCaptureMode)
{
IntPtr handle = Handle;
TaskEx.Run(() =>
{
WindowsRectangleList wla = new WindowsRectangleList();
wla.IgnoreHandle = handle;
wla.IncludeChildWindows = ShapeManager.IncludeControls;
ShapeManager.Windows = wla.GetWindowInfoListAsync(5000);
});
}
}
internal void InitBackground(Image canvas)
{
2017-11-07 05:01:02 +13:00
if (Canvas != null) Canvas.Dispose();
if (backgroundBrush != null) backgroundBrush.Dispose();
if (backgroundHighlightBrush != null) backgroundHighlightBrush.Dispose();
Canvas = canvas;
2016-09-05 00:51:03 +12:00
if (IsEditorMode)
2016-09-05 00:51:03 +12:00
{
UpdateTitle();
2017-11-07 05:01:02 +13:00
CanvasRectangle = new Rectangle(CanvasRectangle.X, CanvasRectangle.Y, Canvas.Width, Canvas.Height);
2017-10-25 07:53:31 +13:00
2017-11-07 05:01:02 +13:00
using (Bitmap background = new Bitmap(Canvas.Width, Canvas.Height))
using (Graphics g = Graphics.FromImage(background))
{
2017-11-07 05:01:02 +13:00
Rectangle sourceRect = new Rectangle(0, 0, Canvas.Width, Canvas.Height);
2017-10-18 02:41:08 +13:00
2017-11-07 05:01:02 +13:00
using (Image checkers = ImageHelpers.DrawCheckers(Canvas.Width, Canvas.Height))
{
2017-10-18 02:41:08 +13:00
g.DrawImage(checkers, sourceRect);
}
2016-09-05 00:51:03 +12:00
2017-11-07 05:01:02 +13:00
g.DrawImage(Canvas, sourceRect);
2017-10-18 02:41:08 +13:00
backgroundBrush = new TextureBrush(background) { WrapMode = WrapMode.Clamp };
backgroundBrush.TranslateTransform(CanvasRectangle.X, CanvasRectangle.Y);
}
CenterCanvas();
2016-09-05 00:51:03 +12:00
}
2017-11-07 05:01:02 +13:00
else if (!IsEditorMode && Options.UseDimming)
2016-09-05 00:51:03 +12:00
{
2017-11-07 05:01:02 +13:00
using (Bitmap darkBackground = (Bitmap)Canvas.Clone())
2016-09-05 00:51:03 +12:00
using (Graphics g = Graphics.FromImage(darkBackground))
using (Brush brush = new SolidBrush(Color.FromArgb(30, Color.Black)))
2016-09-05 00:51:03 +12:00
{
g.FillRectangle(brush, 0, 0, darkBackground.Width, darkBackground.Height);
2016-09-05 00:51:03 +12:00
backgroundBrush = new TextureBrush(darkBackground) { WrapMode = WrapMode.Clamp };
}
2017-11-07 05:01:02 +13:00
backgroundHighlightBrush = new TextureBrush(Canvas) { WrapMode = WrapMode.Clamp };
2016-09-05 00:51:03 +12:00
}
else
{
2017-11-07 05:01:02 +13:00
backgroundBrush = new TextureBrush(Canvas) { WrapMode = WrapMode.Clamp };
2016-09-05 00:51:03 +12:00
}
2017-11-07 05:01:02 +13:00
if (Options.UseCustomInfoText || Mode == RegionCaptureMode.ScreenColorPicker)
{
if (bmpBackgroundImage != null) bmpBackgroundImage.Dispose();
2017-11-07 05:01:02 +13:00
bmpBackgroundImage = new Bitmap(Canvas);
}
}
private void OnMoved()
{
if (ShapeManager != null)
{
UpdateCoordinates();
if (IsAnnotationMode && ShapeManager.ToolbarCreated)
{
ShapeManager.UpdateMenuPosition();
}
}
}
private void Pan(int deltaX, int deltaY, bool usePanningStretch = true)
2017-10-24 15:31:02 +13:00
{
if (usePanningStretch)
{
PanningStrech.X -= deltaX;
PanningStrech.Y -= deltaY;
}
Size panLimitSize = new Size(
Math.Min((int)Math.Round(ClientArea.Width * 0.25f), CanvasRectangle.Width),
Math.Min((int)Math.Round(ClientArea.Height * 0.25f), CanvasRectangle.Height));
Rectangle limitRectangle = new Rectangle(
ClientArea.X + panLimitSize.Width, ClientArea.Y + panLimitSize.Height,
ClientArea.Width - panLimitSize.Width * 2, ClientArea.Height - panLimitSize.Height * 2);
deltaX = Math.Max(deltaX, limitRectangle.Left - CanvasRectangle.Right);
deltaX = Math.Min(deltaX, limitRectangle.Right - CanvasRectangle.Left);
deltaY = Math.Max(deltaY, limitRectangle.Top - CanvasRectangle.Bottom);
deltaY = Math.Min(deltaY, limitRectangle.Bottom - CanvasRectangle.Top);
if (usePanningStretch)
{
deltaX -= Math.Min(Math.Max(deltaX, 0), Math.Max(0, PanningStrech.X));
deltaX -= Math.Max(Math.Min(deltaX, 0), Math.Min(0, PanningStrech.X));
deltaY -= Math.Min(Math.Max(deltaY, 0), Math.Max(0, PanningStrech.Y));
deltaY -= Math.Max(Math.Min(deltaY, 0), Math.Min(0, PanningStrech.Y));
PanningStrech.X += deltaX;
PanningStrech.Y += deltaY;
}
CanvasRectangle = CanvasRectangle.LocationOffset(deltaX, deltaY);
2017-10-25 11:47:40 +13:00
if (backgroundBrush != null)
{
backgroundBrush.TranslateTransform(deltaX, deltaY);
}
if (ShapeManager != null)
{
ShapeManager.MoveAll(deltaX, deltaY);
}
2017-10-25 07:53:31 +13:00
}
2017-10-24 15:31:02 +13:00
private void Pan(Point delta)
2017-10-25 07:53:31 +13:00
{
Pan(delta.X, delta.Y);
2017-10-25 07:53:31 +13:00
}
2017-11-09 16:00:27 +13:00
private void AutomaticPan(Vector2 centerOffset)
2017-10-25 07:53:31 +13:00
{
if (IsEditorMode)
{
2017-11-09 16:00:27 +13:00
int x = (int)Math.Round(ClientArea.Width * 0.5f + centerOffset.X);
int y = (int)Math.Round(ClientArea.Height * 0.5f + centerOffset.Y);
int newX = x - CanvasRectangle.Width / 2;
int newY = y - CanvasRectangle.Height / 2;
int deltaX = newX - CanvasRectangle.X;
int deltaY = newY - CanvasRectangle.Y;
Pan(deltaX, deltaY, false);
}
2017-10-25 07:53:31 +13:00
}
2017-10-24 15:31:02 +13:00
2017-10-25 11:47:40 +13:00
private void AutomaticPan()
2017-10-25 07:53:31 +13:00
{
2017-11-09 16:00:27 +13:00
AutomaticPan(CanvasCenterOffset);
2017-10-25 07:53:31 +13:00
}
2017-10-24 15:31:02 +13:00
2017-11-09 16:00:27 +13:00
private void UpdateCenterOffset()
2017-10-25 07:53:31 +13:00
{
2017-11-09 16:00:27 +13:00
CanvasCenterOffset = new Vector2(
(CanvasRectangle.X + CanvasRectangle.Width / 2f) - ClientArea.Width / 2f,
(CanvasRectangle.Y + CanvasRectangle.Height / 2f) - ClientArea.Height / 2f);
2017-10-25 07:53:31 +13:00
}
public void CenterCanvas()
2017-10-25 07:53:31 +13:00
{
2017-11-12 22:11:20 +13:00
CanvasCenterOffset = new Vector2(0f, ToolbarHeight / 2f);
2017-10-25 11:47:40 +13:00
AutomaticPan();
2017-10-24 15:31:02 +13:00
}
2017-10-18 03:54:19 +13:00
public void SetDefaultCursor()
{
2017-10-18 08:39:22 +13:00
if (Cursor != defaultCursor)
{
Cursor = defaultCursor;
}
2017-10-18 03:54:19 +13:00
}
2016-09-05 05:17:09 +12:00
private void RegionCaptureForm_Shown(object sender, EventArgs e)
{
2016-09-05 05:17:09 +12:00
this.ForceActivate();
OnMoved();
CenterCanvas();
if (IsEditorMode && Options.ShowEditorPanTip && editorPanTipAnimation != null)
{
editorPanTipAnimation.Start();
}
}
2017-10-24 11:40:20 +13:00
private void RegionCaptureForm_Resize(object sender, EventArgs e)
{
OnMoved();
2017-10-25 11:47:40 +13:00
AutomaticPan();
}
private void RegionCaptureForm_LocationChanged(object sender, EventArgs e)
{
OnMoved();
2017-10-24 11:40:20 +13:00
}
private void RegionCaptureForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (IsEditorMode && Options.ImageEditorStartMode == ImageEditorStartMode.PreviousState)
{
Options.ImageEditorWindowState.UpdateFormState(this);
}
}
internal void RegionCaptureForm_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyData)
{
case Keys.Control | Keys.C:
CopyAreaInfo();
break;
}
}
internal void RegionCaptureForm_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Escape)
{
Close();
return;
}
if (!isKeyAllowed && timerStart.ElapsedMilliseconds < 1000)
{
return;
}
isKeyAllowed = true;
if (e.KeyData >= Keys.D0 && e.KeyData <= Keys.D9)
{
MonitorKey(e.KeyData - Keys.D0);
return;
}
switch (e.KeyData)
{
case Keys.Space:
Close(RegionResult.Fullscreen);
break;
case Keys.Enter:
Close(RegionResult.Region);
break;
case Keys.Oemtilde:
Close(RegionResult.ActiveMonitor);
break;
}
}
2016-09-05 05:17:09 +12:00
private void RegionCaptureForm_MouseDown(object sender, MouseEventArgs e)
2013-11-03 23:53:49 +13:00
{
if ((Mode == RegionCaptureMode.OneClick || Mode == RegionCaptureMode.ScreenColorPicker) && e.Button == MouseButtons.Left)
2013-11-03 23:53:49 +13:00
{
2015-07-11 21:47:38 +12:00
CurrentPosition = InputManager.MousePosition;
if (Mode == RegionCaptureMode.OneClick)
{
SelectedWindow = ShapeManager.FindSelectedWindow();
}
Close(RegionResult.Region);
2013-11-03 23:53:49 +13:00
}
}
private void MonitorKey(int index)
2013-11-03 23:53:49 +13:00
{
if (index == 0)
2013-11-03 23:53:49 +13:00
{
index = 10;
}
index--;
MonitorIndex = index;
Close(RegionResult.Monitor);
}
internal void Close(RegionResult result)
{
Result = result;
Close();
}
internal void Pause()
{
pause = true;
}
internal void Resume()
{
pause = false;
Invalidate();
}
private void CopyAreaInfo()
{
string clipboardText;
if (ShapeManager.IsCurrentShapeValid)
{
clipboardText = GetAreaText(ShapeManager.CurrentRectangle);
2013-11-03 23:53:49 +13:00
}
else
{
CurrentPosition = InputManager.MousePosition;
clipboardText = GetInfoText();
}
ClipboardHelpers.CopyText(clipboardText);
2013-11-03 23:53:49 +13:00
}
public WindowInfo GetWindowInfo()
{
return ShapeManager.FindSelectedWindowInfo(CurrentPosition);
}
public void AddCursor(IntPtr cursorHandle, Point position)
{
if (ShapeManager != null)
{
ShapeManager.AddCursor(cursorHandle, position);
}
}
private void UpdateCoordinates()
{
2017-11-07 05:01:02 +13:00
ClientArea = ClientRectangle;
InputManager.Update(this);
}
2016-09-05 05:17:09 +12:00
private new void Update()
2013-11-03 23:53:49 +13:00
{
if (!timerStart.IsRunning)
{
timerStart.Start();
timerFPS.Start();
}
UpdateCoordinates();
ShapeManager.UpdateObjects();
2017-12-10 23:49:16 +13:00
if (ShapeManager.IsPanning)
{
Pan(InputManager.MouseVelocity);
UpdateCenterOffset();
}
borderDotPen.DashOffset = (float)timerStart.Elapsed.TotalSeconds * -15;
ShapeManager.Update();
if (scrollbarManager != null)
{
scrollbarManager.Update();
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//base.OnPaintBackground(e);
}
protected override void OnPaint(PaintEventArgs e)
{
Update();
Graphics g = e.Graphics;
if (IsEditorMode && !CanvasRectangle.Contains(ClientArea))
2017-10-18 03:44:46 +13:00
{
g.Clear(Options.ImageEditorBackgroundColor);
g.DrawRectangleProper(canvasBorderPen, CanvasRectangle.Offset(1));
2017-10-18 03:44:46 +13:00
}
g.CompositingMode = CompositingMode.SourceCopy;
g.FillRectangle(backgroundBrush, CanvasRectangle);
g.CompositingMode = CompositingMode.SourceOver;
2017-10-18 03:44:46 +13:00
Draw(g);
2017-11-07 05:01:02 +13:00
if (Options.ShowFPS)
{
CheckFPS();
2017-11-08 13:47:22 +13:00
if (IsFullscreen)
{
DrawFPS(g, 10);
}
}
if (!pause)
{
Invalidate();
}
}
private void Draw(Graphics g)
2013-11-03 23:53:49 +13:00
{
// Draw snap rectangles
if (ShapeManager.IsCreating && ShapeManager.IsSnapResizing)
{
BaseShape shape = ShapeManager.CurrentShape;
2016-08-15 12:47:54 +12:00
if (shape != null && shape.ShapeType != ShapeType.RegionFreehand && shape.ShapeType != ShapeType.DrawingFreehand)
{
2017-11-07 05:01:02 +13:00
foreach (Size size in Options.SnapSizes)
{
Rectangle snapRect = CaptureHelpers.CalculateNewRectangle(shape.StartPosition, shape.EndPosition, size);
g.DrawRectangleProper(markerPen, snapRect);
}
}
}
List<BaseShape> areas = ShapeManager.ValidRegions.ToList();
2013-11-03 23:53:49 +13:00
if (areas.Count > 0)
2013-11-03 23:53:49 +13:00
{
// Create graphics path from all regions
2013-11-03 23:53:49 +13:00
UpdateRegionPath();
// If background is dimmed then draw non dimmed background to region selections
2017-11-07 05:01:02 +13:00
if (!IsEditorMode && Options.UseDimming)
2013-11-03 23:53:49 +13:00
{
using (Region region = new Region(regionDrawPath))
{
g.Clip = region;
2017-11-07 05:01:02 +13:00
g.FillRectangle(backgroundHighlightBrush, ClientArea);
g.ResetClip();
}
}
2013-11-03 23:53:49 +13:00
g.DrawPath(borderPen, regionDrawPath);
g.DrawPath(borderDotStaticPen, regionDrawPath);
2016-05-03 22:06:58 +12:00
}
2013-11-03 23:53:49 +13:00
2016-05-11 10:17:51 +12:00
// Draw effect shapes
foreach (BaseEffectShape effectShape in ShapeManager.EffectShapes)
2016-05-11 10:17:51 +12:00
{
effectShape.OnDraw(g);
2016-05-11 10:17:51 +12:00
}
// Draw drawing shapes
foreach (BaseDrawingShape drawingShape in ShapeManager.DrawingShapes)
2016-05-03 22:06:58 +12:00
{
drawingShape.OnDraw(g);
2016-05-03 22:06:58 +12:00
}
// Draw tools
foreach (BaseTool toolShape in ShapeManager.ToolShapes)
{
toolShape.OnDraw(g);
}
// Draw animated rectangle on hover area
if (ShapeManager.IsCurrentHoverShapeValid)
2016-05-03 22:06:58 +12:00
{
2017-11-07 05:01:02 +13:00
if (Options.EnableAnimations)
2017-04-03 19:55:54 +12:00
{
if (!ShapeManager.PreviousHoverRectangle.IsEmpty && ShapeManager.CurrentHoverShape.Rectangle != ShapeManager.PreviousHoverRectangle)
{
regionAnimation.FromRectangle = ShapeManager.PreviousHoverRectangle;
regionAnimation.ToRectangle = ShapeManager.CurrentHoverShape.Rectangle;
regionAnimation.Start();
}
2017-04-03 19:55:54 +12:00
regionAnimation.Update();
}
2017-04-03 19:55:54 +12:00
using (GraphicsPath hoverDrawPath = new GraphicsPath { FillMode = FillMode.Winding })
2013-11-03 23:53:49 +13:00
{
2017-11-07 05:01:02 +13:00
if (Options.EnableAnimations && regionAnimation.IsActive && regionAnimation.CurrentRectangle.Width > 2 && regionAnimation.CurrentRectangle.Height > 2)
2017-04-03 19:55:54 +12:00
{
ShapeManager.CurrentHoverShape.OnShapePathRequested(hoverDrawPath, regionAnimation.CurrentRectangle.SizeOffset(-1));
}
else
{
ShapeManager.CurrentHoverShape.AddShapePath(hoverDrawPath, -1);
}
2013-11-03 23:53:49 +13:00
g.DrawPath(borderPen, hoverDrawPath);
g.DrawPath(borderDotPen, hoverDrawPath);
2013-11-03 23:53:49 +13:00
}
}
2013-11-03 23:53:49 +13:00
// Draw animated rectangle on selection area
if (ShapeManager.IsCurrentShapeTypeRegion && ShapeManager.IsCurrentShapeValid)
{
if (Mode == RegionCaptureMode.Ruler)
2013-11-03 23:53:49 +13:00
{
using (SolidBrush brush = new SolidBrush(Color.FromArgb(100, 255, 255, 255)))
{
g.FillRectangle(brush, ShapeManager.CurrentRectangle);
}
DrawRuler(g, ShapeManager.CurrentRectangle, borderPen, 5, 10);
DrawRuler(g, ShapeManager.CurrentRectangle, borderPen, 15, 100);
2014-04-12 04:29:19 +12:00
2017-12-25 23:37:25 +13:00
g.DrawCross(borderPen, ShapeManager.CurrentRectangle.Center(), 10);
}
DrawRegionArea(g, ShapeManager.CurrentRectangle, true);
}
2014-04-12 05:12:13 +12:00
// Draw all regions rectangle info
2017-11-07 05:01:02 +13:00
if (Options.ShowInfo)
{
// Add hover area to list so rectangle info can be shown
if (ShapeManager.IsCurrentShapeTypeRegion && ShapeManager.IsCurrentHoverShapeValid && areas.All(area => area.Rectangle != ShapeManager.CurrentHoverShape.Rectangle))
{
areas.Add(ShapeManager.CurrentHoverShape);
2013-11-03 23:53:49 +13:00
}
foreach (BaseShape regionInfo in areas)
2013-11-03 23:53:49 +13:00
{
if (regionInfo.Rectangle.IsValid())
2013-11-03 23:53:49 +13:00
{
string areaText = GetAreaText(regionInfo.Rectangle);
DrawAreaText(g, areaText, regionInfo.Rectangle);
2013-11-03 23:53:49 +13:00
}
}
}
// Draw resize nodes
ShapeManager.DrawObjects(g);
// Draw F1 tips
2017-11-07 05:01:02 +13:00
if (!IsEditorMode && Options.ShowHotkeys)
{
DrawTips(g);
}
// Draw magnifier
2017-11-07 05:01:02 +13:00
if (Options.ShowMagnifier || Options.ShowInfo)
2013-11-03 23:53:49 +13:00
{
DrawCursorGraphics(g);
2013-11-03 23:53:49 +13:00
}
// Draw screen wide crosshair
2017-11-07 05:01:02 +13:00
if (Options.ShowCrosshair)
2013-11-03 23:53:49 +13:00
{
DrawCrosshair(g);
}
2016-10-03 05:01:55 +13:00
// Draw image editor bottom tip
if (IsEditorMode && Options.ShowEditorPanTip && editorPanTipAnimation != null && editorPanTipAnimation.Update())
{
DrawBottomTipAnimation(g, editorPanTipAnimation);
}
2016-10-03 05:01:55 +13:00
// Draw menu tooltips
if (IsAnnotationMode && ShapeManager.MenuTextAnimation.Update())
{
DrawTextAnimation(g, ShapeManager.MenuTextAnimation);
}
2017-12-07 09:04:06 +13:00
2017-12-09 03:21:44 +13:00
// Draw scroll bars
if (scrollbarManager != null)
2017-12-07 09:04:06 +13:00
{
2017-12-09 03:21:44 +13:00
scrollbarManager.Draw(g);
2017-12-07 09:04:06 +13:00
}
2013-11-03 23:53:49 +13:00
}
internal void DrawRegionArea(Graphics g, Rectangle rect, bool isAnimated)
{
g.DrawRectangleProper(borderPen, rect);
if (isAnimated)
{
g.DrawRectangleProper(borderDotPen, rect);
}
else
{
g.DrawRectangleProper(borderDotStaticPen, rect);
}
}
private void CheckFPS()
{
frameCount++;
if (timerFPS.ElapsedMilliseconds >= 1000)
{
FPS = (int)(frameCount / timerFPS.Elapsed.TotalSeconds);
frameCount = 0;
timerFPS.Reset();
timerFPS.Start();
2017-11-08 13:47:22 +13:00
if (!IsFullscreen)
{
UpdateTitle();
}
}
}
private void DrawFPS(Graphics g, int offset)
{
Point textPosition = new Point(offset, offset);
if (IsFullscreen)
{
Rectangle rectScreen = CaptureHelpers.GetActiveScreenBounds0Based();
textPosition = textPosition.Add(rectScreen.Location);
}
g.DrawTextWithShadow(FPS.ToString(), textPosition, infoFontBig, Brushes.White, Brushes.Black, new Point(0, 1));
}
private void DrawInfoText(Graphics g, string text, Rectangle rect, Font font, int padding)
2015-05-13 04:27:21 +12:00
{
DrawInfoText(g, text, rect, font, padding, textBackgroundBrush, textOuterBorderPen, textInnerBorderPen, Brushes.White, Brushes.Black);
}
2015-05-13 04:27:21 +12:00
private void DrawInfoText(Graphics g, string text, Rectangle rect, Font font, int padding,
Brush backgroundBrush, Pen outerBorderPen, Pen innerBorderPen, Brush textBrush, Brush textShadowBrush)
{
g.FillRectangle(backgroundBrush, rect.Offset(-2));
g.DrawRectangleProper(innerBorderPen, rect.Offset(-1));
g.DrawRectangleProper(outerBorderPen, rect);
2016-11-13 06:22:49 +13:00
g.DrawTextWithShadow(text, rect.Offset(-padding).Location, font, textBrush, textShadowBrush);
2015-05-13 04:27:21 +12:00
}
2015-05-10 04:59:19 +12:00
private void DrawAreaText(Graphics g, string text, Rectangle area)
2015-05-08 11:31:08 +12:00
{
int offset = 6;
2015-05-13 04:27:21 +12:00
int backgroundPadding = 3;
2015-05-10 04:59:19 +12:00
Size textSize = g.MeasureString(text, infoFont).ToSize();
2015-05-08 11:31:08 +12:00
Point textPos;
2017-11-07 05:01:02 +13:00
if (area.Y - offset - textSize.Height - backgroundPadding * 2 < ClientArea.Y)
2015-05-08 11:31:08 +12:00
{
2015-05-13 04:27:21 +12:00
textPos = new Point(area.X + offset + backgroundPadding, area.Y + offset + backgroundPadding);
2015-05-08 11:31:08 +12:00
}
else
{
2015-05-13 04:27:21 +12:00
textPos = new Point(area.X + backgroundPadding, area.Y - offset - backgroundPadding - textSize.Height);
2015-05-08 11:31:08 +12:00
}
2017-11-07 05:01:02 +13:00
if (textPos.X + textSize.Width + backgroundPadding >= ClientArea.Width)
2015-06-04 00:49:29 +12:00
{
2017-11-07 05:01:02 +13:00
textPos.X = ClientArea.Width - textSize.Width - backgroundPadding;
2015-06-04 00:49:29 +12:00
}
2015-05-13 04:27:21 +12:00
Rectangle backgroundRect = new Rectangle(textPos.X - backgroundPadding, textPos.Y - backgroundPadding, textSize.Width + backgroundPadding * 2, textSize.Height + backgroundPadding * 2);
2015-05-08 11:31:08 +12:00
DrawInfoText(g, text, backgroundRect, infoFont, backgroundPadding);
2015-05-08 11:31:08 +12:00
}
private void DrawTips(Graphics g)
{
StringBuilder sb = new StringBuilder();
WriteTips(sb);
string tipText = sb.ToString().Trim();
2015-05-08 11:31:08 +12:00
Size textSize = g.MeasureString(tipText, infoFont).ToSize();
int offset = 10;
int padding = 10;
int rectWidth = textSize.Width + padding * 2 + 2;
int rectHeight = textSize.Height + padding * 2;
2016-05-10 08:22:28 +12:00
Rectangle screenBounds = CaptureHelpers.GetActiveScreenBounds0Based();
Rectangle textRectangle = new Rectangle(screenBounds.X + screenBounds.Width - rectWidth - offset, screenBounds.Y + offset, rectWidth, rectHeight);
2017-11-07 05:01:02 +13:00
if (textRectangle.Offset(10).Contains(InputManager.ClientMousePosition))
{
2016-05-10 08:22:28 +12:00
textRectangle.Y = screenBounds.Height - rectHeight - offset;
}
DrawInfoText(g, tipText, textRectangle, infoFont, padding);
}
2016-10-03 05:01:55 +13:00
private void DrawTextAnimation(Graphics g, TextAnimation textAnimation)
{
2016-10-03 05:01:55 +13:00
Size textSize = g.MeasureString(textAnimation.Text, infoFontMedium).ToSize();
int padding = 3;
textSize.Width += padding * 2;
textSize.Height += padding * 2;
Rectangle textRectangle = new Rectangle(textAnimation.Position.X, textAnimation.Position.Y, textSize.Width, textSize.Height);
DrawTextAnimation(g, textAnimation, textRectangle, padding);
}
private void DrawTextAnimation(Graphics g, TextAnimation textAnimation, Rectangle textRectangle, int padding)
{
2016-10-03 05:01:55 +13:00
using (Brush backgroundBrush = new SolidBrush(Color.FromArgb((int)(textAnimation.Opacity * 175), Color.FromArgb(44, 135, 206))))
using (Pen outerBorderPen = new Pen(Color.FromArgb((int)(textAnimation.Opacity * 175), Color.White)))
using (Pen innerBorderPen = new Pen(Color.FromArgb((int)(textAnimation.Opacity * 175), Color.FromArgb(0, 81, 145))))
using (Brush textBrush = new SolidBrush(Color.FromArgb((int)(textAnimation.Opacity * 255), Color.White)))
using (Brush textShadowBrush = new SolidBrush(Color.FromArgb((int)(textAnimation.Opacity * 255), Color.Black)))
{
2016-10-03 05:01:55 +13:00
DrawInfoText(g, textAnimation.Text, textRectangle, infoFontMedium, padding, backgroundBrush, outerBorderPen, innerBorderPen, textBrush, textShadowBrush);
}
}
private void DrawBottomTipAnimation(Graphics g, TextAnimation textAnimation)
{
Size textSize = g.MeasureString(textAnimation.Text, infoFontMedium).ToSize();
int padding = 5;
textSize.Width += padding * 2;
textSize.Height += padding * 2;
int margin = 20;
Rectangle textRectangle = new Rectangle(ClientArea.Width / 2 - textSize.Width / 2, ClientArea.Height - textSize.Height - margin, textSize.Width, textSize.Height);
DrawTextAnimation(g, textAnimation, textRectangle, padding);
}
2016-08-08 21:00:06 +12:00
private void WriteTips(StringBuilder sb)
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__F1__Hide_tips);
sb.AppendLine();
if (ShapeManager.IsCreating)
{
2015-08-21 04:29:10 +12:00
sb.AppendLine(Resources.RectangleRegion_WriteTips__Insert__Stop_region_selection);
sb.AppendLine(Resources.RectangleRegion_WriteTips__Right_click__Cancel_region_selection);
}
else
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Hold_Left_click__Start_region_selection);
sb.AppendLine(Resources.RegionCaptureForm_WriteTips_RightClickCancelCaptureRemoveRegion);
}
sb.AppendLine(Resources.RectangleRegion_WriteTips__Esc__Cancel_capture);
2017-11-07 05:01:02 +13:00
if (!ShapeManager.IsCreating && !Options.QuickCrop && ShapeManager.Regions.Length > 0)
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Double_Left_click___Enter__Capture_regions);
}
sb.AppendLine();
2017-11-07 05:01:02 +13:00
if ((!Options.QuickCrop || !ShapeManager.IsCurrentShapeTypeRegion) && ShapeManager.CurrentShape != null && !ShapeManager.IsCreating)
{
2016-05-09 04:08:35 +12:00
sb.AppendLine(Resources.RectangleRegion_WriteTips__Right_click_on_selection___Delete__Remove_region);
sb.AppendLine(Resources.RegionCaptureForm_WriteTips_ArrowKeysResizeRegionFromBottomRightCorner);
sb.AppendLine(Resources.RegionCaptureForm_WriteTips_HoldAltArrowKeysResizeRegionFromTopLeftCorner);
2016-07-13 13:14:54 +12:00
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Hold_Ctrl___Arrow_keys__Move_region);
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Hold_Shift___Arrow_keys__Resize_or_move_region_faster);
sb.AppendLine(Resources.RectangleRegion_WriteTips__Hold_Left_click_on_selection__Move_region);
}
else
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Arrow_keys__Move_cursor_position);
2016-07-13 13:14:54 +12:00
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Hold_Shift___Arrow_keys__Move_cursor_position_faster);
}
if (ShapeManager.IsCreating)
{
2016-07-13 13:14:54 +12:00
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Hold_Ctrl__Move_selection);
sb.AppendLine(Resources.RectangleRegion_WriteTips__Hold_Shift__Proportional_resizing);
2016-08-08 21:00:06 +12:00
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool != ShapeType.RegionFreehand && ShapeManager.CurrentTool != ShapeType.DrawingFreehand)
2016-08-08 21:00:06 +12:00
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Hold_Alt__Snap_resizing_to_preset_sizes);
}
}
2016-08-17 09:15:08 +12:00
if (ShapeManager.Shapes.Count > 0)
{
sb.AppendLine(Resources.RegionCaptureForm_WriteTips_CtrlZUndoShape);
2016-08-17 09:15:08 +12:00
}
2016-06-13 04:32:33 +12:00
sb.AppendLine();
if (ShapeManager.IsCurrentShapeValid)
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Ctrl___C__Copy_position_and_size);
}
2017-11-07 05:01:02 +13:00
else if (Options.UseCustomInfoText)
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Ctrl___C__Copy_info);
}
else
{
sb.AppendLine(Resources.RectangleRegion_WriteTips__Ctrl___C__Copy_position);
}
2016-09-28 10:30:41 +13:00
if (IsAnnotationMode)
{
sb.AppendLine(Resources.RegionCaptureForm_WriteTips_CtrlVPasteImageOrText);
2016-09-28 10:30:41 +13:00
}
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Mouse_wheel__Change_current_tool);
2016-05-16 21:48:53 +12:00
sb.AppendLine();
sb.AppendLine(Resources.RectangleRegion_WriteTips__Space__Fullscreen_capture);
sb.AppendLine(Resources.RectangleRegion_WriteTips__1__2__3_____0__Monitor_capture);
sb.AppendLine(Resources.RectangleRegion_WriteTips_____Active_monitor_capture);
if (Mode == RegionCaptureMode.Annotation && !ShapeManager.IsCreating)
{
sb.AppendLine();
2016-06-13 04:32:33 +12:00
if (ShapeManager.IsCurrentShapeTypeRegion)
{
2016-07-13 13:14:54 +12:00
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Tab___Mouse_4_click__Select_last_annotation_tool);
2016-06-13 04:32:33 +12:00
}
else
{
2016-07-13 13:14:54 +12:00
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Tab___Mouse_4_click__Select_last_region_tool);
2016-06-13 04:32:33 +12:00
}
2016-09-28 10:30:41 +13:00
sb.AppendLine(Resources.RectangleRegionForm_WriteTips__Ctrl___Mouse_wheel__Change_magnifier_size);
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.RegionRectangle) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 0", ShapeType.RegionRectangle.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.RegionEllipse) sb.Append("-> ");
sb.AppendLine(ShapeType.RegionEllipse.GetLocalizedDescription());
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.RegionFreehand) sb.Append("-> ");
2016-08-08 21:00:06 +12:00
sb.AppendLine(ShapeType.RegionFreehand.GetLocalizedDescription());
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingRectangle) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 1", ShapeType.DrawingRectangle.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingEllipse) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 2", ShapeType.DrawingEllipse.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingFreehand) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 3", ShapeType.DrawingFreehand.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingLine) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 4", ShapeType.DrawingLine.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingArrow) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 5", ShapeType.DrawingArrow.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingTextOutline) sb.Append("-> ");
2017-02-16 13:49:13 +13:00
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 6", ShapeType.DrawingTextOutline.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingSpeechBalloon) sb.Append("-> ");
2016-09-28 10:30:41 +13:00
sb.AppendLine(ShapeType.DrawingSpeechBalloon.GetLocalizedDescription());
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingStep) sb.Append("-> ");
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 7", ShapeType.DrawingStep.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.DrawingImage) sb.Append("-> ");
2016-09-28 10:30:41 +13:00
sb.AppendLine(ShapeType.DrawingImage.GetLocalizedDescription());
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.EffectBlur) sb.Append("-> ");
2016-09-02 18:16:52 +12:00
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 8", ShapeType.EffectBlur.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.EffectPixelate) sb.Append("-> ");
2016-09-02 18:16:52 +12:00
sb.AppendLine(string.Format("[{0}] {1}", "Numpad 9", ShapeType.EffectPixelate.GetLocalizedDescription()));
2017-11-07 05:01:02 +13:00
if (ShapeManager.CurrentTool == ShapeType.EffectHighlight) sb.Append("-> ");
2016-09-02 18:16:52 +12:00
sb.AppendLine(ShapeType.EffectHighlight.GetLocalizedDescription());
}
2016-08-17 09:15:08 +12:00
sb.AppendLine();
sb.AppendLine(Resources.RegionCaptureForm_WriteTips_NoteHidingTheseTipsWillIncreaseFPSGreatly);
}
private string GetAreaText(Rectangle area)
{
if (Mode == RegionCaptureMode.Ruler)
2015-05-10 04:59:19 +12:00
{
Point endPos = new Point(area.Right - 1, area.Bottom - 1);
return string.Format(Resources.RectangleRegion_GetRulerText_Ruler_info, area.X, area.Y, endPos.X, endPos.Y,
area.Width, area.Height, MathHelpers.Distance(area.Location, endPos), MathHelpers.LookAtDegree(area.Location, endPos));
}
return string.Format(Resources.RectangleRegion_GetAreaText_Area, area.X, area.Y, area.Width, area.Height);
}
private string GetInfoText()
{
if (IsEditorMode)
{
2017-11-07 05:01:02 +13:00
Point canvasRelativePosition = new Point(InputManager.ClientMousePosition.X - CanvasRectangle.X, InputManager.ClientMousePosition.Y - CanvasRectangle.Y);
return $"X: {canvasRelativePosition.X} Y: {canvasRelativePosition.Y}";
}
2017-11-07 05:01:02 +13:00
else if (Mode == RegionCaptureMode.ScreenColorPicker || Options.UseCustomInfoText)
{
Color color = CurrentColor;
2017-11-07 05:01:02 +13:00
if (Mode != RegionCaptureMode.ScreenColorPicker && !string.IsNullOrEmpty(Options.CustomInfoText))
{
2017-11-07 05:01:02 +13:00
return CodeMenuEntryPixelInfo.Parse(Options.CustomInfoText, color, CurrentPosition);
}
return string.Format(Resources.RectangleRegion_GetColorPickerText, color.R, color.G, color.B, ColorHelpers.ColorToHex(color), CurrentPosition.X, CurrentPosition.Y);
}
return $"X: {CurrentPosition.X} Y: {CurrentPosition.Y}";
}
2013-11-03 23:53:49 +13:00
private void DrawCrosshair(Graphics g)
{
2014-07-25 17:54:24 +12:00
int offset = 5;
2017-11-07 05:01:02 +13:00
Point mousePos = InputManager.ClientMousePosition;
2013-11-03 23:53:49 +13:00
Point left = new Point(mousePos.X - offset, mousePos.Y), left2 = new Point(0, mousePos.Y);
2017-11-07 05:01:02 +13:00
Point right = new Point(mousePos.X + offset, mousePos.Y), right2 = new Point(ClientArea.Width - 1, mousePos.Y);
2013-11-03 23:53:49 +13:00
Point top = new Point(mousePos.X, mousePos.Y - offset), top2 = new Point(mousePos.X, 0);
2017-11-07 05:01:02 +13:00
Point bottom = new Point(mousePos.X, mousePos.Y + offset), bottom2 = new Point(mousePos.X, ClientArea.Height - 1);
2013-11-03 23:53:49 +13:00
if (left.X - left2.X > 10)
{
2014-07-25 17:54:24 +12:00
g.DrawLine(borderPen, left, left2);
2013-11-03 23:53:49 +13:00
g.DrawLine(borderDotPen, left, left2);
}
if (right2.X - right.X > 10)
{
2014-07-25 17:54:24 +12:00
g.DrawLine(borderPen, right, right2);
2013-11-03 23:53:49 +13:00
g.DrawLine(borderDotPen, right, right2);
}
if (top.Y - top2.Y > 10)
{
2014-07-25 17:54:24 +12:00
g.DrawLine(borderPen, top, top2);
2013-11-03 23:53:49 +13:00
g.DrawLine(borderDotPen, top, top2);
}
if (bottom2.Y - bottom.Y > 10)
{
2014-07-25 17:54:24 +12:00
g.DrawLine(borderPen, bottom, bottom2);
2013-11-03 23:53:49 +13:00
g.DrawLine(borderDotPen, bottom, bottom2);
}
}
private void DrawCursorGraphics(Graphics g)
2013-11-03 23:53:49 +13:00
{
2017-11-07 05:01:02 +13:00
Point mousePos = InputManager.ClientMousePosition;
Rectangle currentScreenRect0Based = CaptureHelpers.GetActiveScreenBounds0Based();
int cursorOffsetX = 10, cursorOffsetY = 10, itemGap = 10, itemCount = 0;
Size totalSize = Size.Empty;
int magnifierPosition = 0;
Bitmap magnifier = null;
2017-11-07 05:01:02 +13:00
if (Options.ShowMagnifier)
{
if (itemCount > 0) totalSize.Height += itemGap;
magnifierPosition = totalSize.Height;
2017-11-07 05:01:02 +13:00
magnifier = Magnifier(Canvas, mousePos, Options.MagnifierPixelCount, Options.MagnifierPixelCount, Options.MagnifierPixelSize);
totalSize.Width = Math.Max(totalSize.Width, magnifier.Width);
totalSize.Height += magnifier.Height;
itemCount++;
}
int infoTextPadding = 3;
int infoTextPosition = 0;
2015-05-13 04:27:21 +12:00
Rectangle infoTextRect = Rectangle.Empty;
2016-05-25 06:15:45 +12:00
string infoText = "";
2015-05-13 04:27:21 +12:00
2017-11-07 05:01:02 +13:00
if (Options.ShowInfo)
2015-05-13 04:27:21 +12:00
{
if (itemCount > 0) totalSize.Height += itemGap;
infoTextPosition = totalSize.Height;
2015-05-13 05:02:51 +12:00
CurrentPosition = InputManager.MousePosition;
infoText = GetInfoText();
2015-05-13 04:27:21 +12:00
Size textSize = g.MeasureString(infoText, infoFont).ToSize();
infoTextRect.Size = new Size(textSize.Width + infoTextPadding * 2, textSize.Height + infoTextPadding * 2);
totalSize.Width = Math.Max(totalSize.Width, infoTextRect.Width);
2013-11-03 23:53:49 +13:00
totalSize.Height += infoTextRect.Height;
itemCount++;
}
2013-11-03 23:53:49 +13:00
int x = mousePos.X + cursorOffsetX;
2013-11-03 23:53:49 +13:00
if (x + totalSize.Width > currentScreenRect0Based.Right)
{
x = mousePos.X - cursorOffsetX - totalSize.Width;
}
2013-11-03 23:53:49 +13:00
int y = mousePos.Y + cursorOffsetY;
2015-05-13 04:27:21 +12:00
if (y + totalSize.Height > currentScreenRect0Based.Bottom)
{
y = mousePos.Y - cursorOffsetY - totalSize.Height;
}
2013-11-03 23:53:49 +13:00
2017-11-07 05:01:02 +13:00
if (Options.ShowMagnifier)
{
using (GraphicsQualityManager quality = new GraphicsQualityManager(g))
2014-07-25 13:14:48 +12:00
using (TextureBrush brush = new TextureBrush(magnifier))
{
brush.TranslateTransform(x, y + magnifierPosition);
2015-08-08 01:36:18 +12:00
2017-11-07 05:01:02 +13:00
if (Options.UseSquareMagnifier)
2015-08-08 01:36:18 +12:00
{
g.FillRectangle(brush, x, y + magnifierPosition, magnifier.Width, magnifier.Height);
g.DrawRectangleProper(Pens.White, x - 1, y + magnifierPosition - 1, magnifier.Width + 2, magnifier.Height + 2);
g.DrawRectangleProper(Pens.Black, x, y + magnifierPosition, magnifier.Width, magnifier.Height);
2015-08-08 01:36:18 +12:00
}
else
{
g.FillEllipse(brush, x, y + magnifierPosition, magnifier.Width, magnifier.Height);
g.DrawEllipse(Pens.White, x - 1, y + magnifierPosition - 1, magnifier.Width + 2 - 1, magnifier.Height + 2 - 1);
g.DrawEllipse(Pens.Black, x, y + magnifierPosition, magnifier.Width - 1, magnifier.Height - 1);
2015-08-08 01:36:18 +12:00
}
2014-07-25 13:14:48 +12:00
}
2013-11-03 23:53:49 +13:00
}
2017-11-07 05:01:02 +13:00
if (Options.ShowInfo)
{
infoTextRect.Location = new Point(x + (totalSize.Width / 2) - (infoTextRect.Width / 2), y + infoTextPosition);
DrawInfoText(g, infoText, infoTextRect, infoFont, infoTextPadding);
}
2013-11-03 23:53:49 +13:00
}
private Bitmap Magnifier(Image img, Point position, int horizontalPixelCount, int verticalPixelCount, int pixelSize)
{
horizontalPixelCount = (horizontalPixelCount | 1).Between(1, 101);
verticalPixelCount = (verticalPixelCount | 1).Between(1, 101);
pixelSize = pixelSize.Between(1, 1000);
2017-11-07 05:01:02 +13:00
if (horizontalPixelCount * pixelSize > ClientArea.Width || verticalPixelCount * pixelSize > ClientArea.Height)
2013-11-03 23:53:49 +13:00
{
horizontalPixelCount = verticalPixelCount = 15;
pixelSize = 10;
}
int width = horizontalPixelCount * pixelSize;
int height = verticalPixelCount * pixelSize;
2014-07-25 13:14:48 +12:00
Bitmap bmp = new Bitmap(width - 1, height - 1);
2013-11-03 23:53:49 +13:00
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = PixelOffsetMode.Half;
g.DrawImage(img, new Rectangle(0, 0, width, height), new Rectangle(position.X - horizontalPixelCount / 2 - CanvasRectangle.X,
position.Y - verticalPixelCount / 2 - CanvasRectangle.Y, horizontalPixelCount, verticalPixelCount), GraphicsUnit.Pixel);
2013-11-03 23:53:49 +13:00
g.PixelOffsetMode = PixelOffsetMode.None;
2014-07-25 13:14:48 +12:00
using (SolidBrush crosshairBrush = new SolidBrush(Color.FromArgb(125, Color.LightBlue)))
2013-11-03 23:53:49 +13:00
{
g.FillRectangle(crosshairBrush, new Rectangle(0, (height - pixelSize) / 2, (width - pixelSize) / 2, pixelSize)); // Left
g.FillRectangle(crosshairBrush, new Rectangle((width + pixelSize) / 2, (height - pixelSize) / 2, (width - pixelSize) / 2, pixelSize)); // Right
g.FillRectangle(crosshairBrush, new Rectangle((width - pixelSize) / 2, 0, pixelSize, (height - pixelSize) / 2)); // Top
g.FillRectangle(crosshairBrush, new Rectangle((width - pixelSize) / 2, (height + pixelSize) / 2, pixelSize, (height - pixelSize) / 2)); // Bottom
}
using (Pen pen = new Pen(Color.FromArgb(75, Color.Black)))
{
for (int x = 1; x < horizontalPixelCount; x++)
{
2014-07-25 13:14:48 +12:00
g.DrawLine(pen, new Point(x * pixelSize - 1, 0), new Point(x * pixelSize - 1, height - 1));
2013-11-03 23:53:49 +13:00
}
for (int y = 1; y < verticalPixelCount; y++)
{
2014-07-25 13:14:48 +12:00
g.DrawLine(pen, new Point(0, y * pixelSize - 1), new Point(width - 1, y * pixelSize - 1));
2013-11-03 23:53:49 +13:00
}
}
2014-07-25 13:14:48 +12:00
g.DrawRectangle(Pens.Black, (width - pixelSize) / 2 - 1, (height - pixelSize) / 2 - 1, pixelSize, pixelSize);
if (pixelSize >= 6)
{
g.DrawRectangle(Pens.White, (width - pixelSize) / 2, (height - pixelSize) / 2, pixelSize - 2, pixelSize - 2);
}
2013-11-03 23:53:49 +13:00
}
return bmp;
}
2014-04-12 04:29:19 +12:00
private void DrawRuler(Graphics g, Rectangle rect, Pen pen, int rulerSize, int rulerWidth)
{
if (rect.Width >= rulerSize && rect.Height >= rulerSize)
{
for (int x = 1; x <= rect.Width / rulerWidth; x++)
{
g.DrawLine(pen, new Point(rect.X + x * rulerWidth, rect.Y), new Point(rect.X + x * rulerWidth, rect.Y + rulerSize));
g.DrawLine(pen, new Point(rect.X + x * rulerWidth, rect.Bottom), new Point(rect.X + x * rulerWidth, rect.Bottom - rulerSize));
}
for (int y = 1; y <= rect.Height / rulerWidth; y++)
{
g.DrawLine(pen, new Point(rect.X, rect.Y + y * rulerWidth), new Point(rect.X + rulerSize, rect.Y + y * rulerWidth));
g.DrawLine(pen, new Point(rect.Right, rect.Y + y * rulerWidth), new Point(rect.Right - rulerSize, rect.Y + y * rulerWidth));
}
}
}
internal void UpdateRegionPath()
2013-11-03 23:53:49 +13:00
{
if (regionFillPath != null)
{
regionFillPath.Dispose();
regionFillPath = null;
}
if (regionDrawPath != null)
{
regionDrawPath.Dispose();
regionDrawPath = null;
}
BaseShape[] areas = ShapeManager.ValidRegions;
2013-11-03 23:53:49 +13:00
if (areas != null && areas.Length > 0)
2013-11-03 23:53:49 +13:00
{
regionFillPath = new GraphicsPath { FillMode = FillMode.Winding };
regionDrawPath = new GraphicsPath { FillMode = FillMode.Winding };
foreach (BaseShape regionShape in ShapeManager.ValidRegions)
{
regionShape.AddShapePath(regionFillPath);
regionShape.AddShapePath(regionDrawPath, -1);
}
2013-11-03 23:53:49 +13:00
}
}
public Image GetResultImage()
{
if (IsEditorMode)
{
foreach (BaseShape shape in ShapeManager.Shapes)
{
shape.Move(-CanvasRectangle.X, -CanvasRectangle.Y);
}
Image img = GetOutputImage();
foreach (BaseShape shape in ShapeManager.Shapes)
{
shape.Move(CanvasRectangle.X, CanvasRectangle.Y);
}
return img;
}
else if (Result == RegionResult.Region || Result == RegionResult.LastRegion)
{
GraphicsPath gp;
if (Result == RegionResult.LastRegion)
{
gp = LastRegionFillPath;
}
else
{
gp = regionFillPath;
}
using (Image img = GetOutputImage())
{
return RegionCaptureTasks.ApplyRegionPathToImage(img, gp);
}
}
else if (Result == RegionResult.Fullscreen)
{
return GetOutputImage();
}
else if (Result == RegionResult.Monitor)
{
Screen[] screens = Screen.AllScreens;
if (MonitorIndex < screens.Length)
{
Screen screen = screens[MonitorIndex];
Rectangle screenRect = CaptureHelpers.ScreenToClient(screen.Bounds);
using (Image img = GetOutputImage())
{
return ImageHelpers.CropImage(img, screenRect);
}
}
}
else if (Result == RegionResult.ActiveMonitor)
{
Rectangle activeScreenRect = CaptureHelpers.GetActiveScreenBounds0Based();
using (Image img = GetOutputImage())
{
return ImageHelpers.CropImage(img, activeScreenRect);
}
}
return null;
}
private Image GetOutputImage()
2016-05-03 23:54:02 +12:00
{
2017-11-07 05:01:02 +13:00
return ShapeManager.RenderOutputImage(Canvas);
2016-05-03 23:54:02 +12:00
}
2017-12-17 20:30:39 +13:00
internal void OnSaveImageRequested()
{
if (SaveImageRequested != null)
{
Image img = GetResultImage();
if (Options.AutoCloseEditorOnTask)
{
Close();
TaskEx.Run(() => SaveImageRequested(img, ImageFilePath));
}
else
{
SaveImageRequested(img, ImageFilePath);
}
2017-12-17 20:30:39 +13:00
}
}
internal void OnSaveImageAsRequested()
{
if (SaveImageAsRequested != null)
{
Image img = GetResultImage();
if (Options.AutoCloseEditorOnTask)
{
Close();
TaskEx.Run(() => SaveImageAsRequested(img, ImageFilePath));
}
else
{
SaveImageAsRequested(img, ImageFilePath);
}
2017-12-17 20:30:39 +13:00
}
}
internal void OnCopyImageRequested()
{
if (CopyImageRequested != null)
{
Image img = GetResultImage();
if (Options.AutoCloseEditorOnTask)
{
Close();
TaskEx.Run(() => CopyImageRequested(img));
}
else
{
CopyImageRequested(img);
}
2017-12-17 20:30:39 +13:00
}
}
internal void OnUploadImageRequested()
{
if (UploadImageRequested != null)
{
Image img = GetResultImage();
if (Options.AutoCloseEditorOnTask)
{
Close();
TaskEx.Run(() => UploadImageRequested(img));
}
else
{
UploadImageRequested(img);
}
2017-12-17 20:30:39 +13:00
}
}
internal void OnPrintImageRequested()
{
if (PrintImageRequested != null)
{
Image img = GetResultImage();
if (Options.AutoCloseEditorOnTask)
{
Close();
TaskEx.Run(() => PrintImageRequested(img));
}
else
{
PrintImageRequested(img);
}
2017-12-17 20:30:39 +13:00
}
}
protected override void Dispose(bool disposing)
{
IsClosing = true;
2017-10-30 21:20:03 +13:00
ShapeManager?.Dispose();
bmpBackgroundImage?.Dispose();
backgroundBrush?.Dispose();
backgroundHighlightBrush?.Dispose();
borderPen?.Dispose();
borderDotPen?.Dispose();
borderDotStaticPen?.Dispose();
nodeBackgroundBrush?.Dispose();
infoFont?.Dispose();
infoFontMedium?.Dispose();
infoFontBig?.Dispose();
textBackgroundBrush?.Dispose();
textOuterBorderPen?.Dispose();
textInnerBorderPen?.Dispose();
markerPen?.Dispose();
canvasBorderPen?.Dispose();
2017-10-30 21:20:03 +13:00
defaultCursor?.Dispose();
CustomNodeImage?.Dispose();
if (regionFillPath != null)
{
if (Result == RegionResult.Region)
{
2017-10-30 21:20:03 +13:00
LastRegionFillPath?.Dispose();
LastRegionFillPath = regionFillPath;
}
else
{
regionFillPath.Dispose();
}
}
2017-10-30 21:20:03 +13:00
regionDrawPath?.Dispose();
2017-11-07 05:01:02 +13:00
Canvas?.Dispose();
base.Dispose(disposing);
}
2013-11-03 23:53:49 +13:00
}
2014-10-21 08:37:51 +13:00
}