diff --git a/Greenshot/Drawing/DrawableContainerList.cs b/Greenshot/Drawing/DrawableContainerList.cs index 3b0808ad3..849cf5ddc 100644 --- a/Greenshot/Drawing/DrawableContainerList.cs +++ b/Greenshot/Drawing/DrawableContainerList.cs @@ -104,8 +104,8 @@ namespace Greenshot.Drawing { return null; } set { - ParentID = value.ID; - foreach(var drawableContainer in this) { + ParentID = value?.ID ?? Guid.NewGuid(); + foreach (var drawableContainer in this) { var dc = (DrawableContainer) drawableContainer; dc.Parent = value; } diff --git a/Greenshot/Drawing/Fields/AbstractFieldHolder.cs b/Greenshot/Drawing/Fields/AbstractFieldHolder.cs index 1a31e073e..6be20aa92 100644 --- a/Greenshot/Drawing/Fields/AbstractFieldHolder.cs +++ b/Greenshot/Drawing/Fields/AbstractFieldHolder.cs @@ -132,7 +132,7 @@ namespace Greenshot.Drawing.Fields public object GetFieldValue(IFieldType fieldType) { - return GetField(fieldType).Value; + return GetField(fieldType)?.Value; } #region convenience methods to save us some casts outside @@ -166,9 +166,9 @@ namespace Greenshot.Drawing.Fields return Convert.ToBoolean(GetFieldValue(fieldType)); } - public Color GetFieldValueAsColor(IFieldType fieldType) + public Color GetFieldValueAsColor(IFieldType fieldType, Color defaultColor = default(Color)) { - return (Color)GetFieldValue(fieldType); + return (Color)(GetFieldValue(fieldType) ?? defaultColor); } #endregion diff --git a/Greenshot/Drawing/FreehandContainer.cs b/Greenshot/Drawing/FreehandContainer.cs index e8654bc4e..ccff8a690 100644 --- a/Greenshot/Drawing/FreehandContainer.cs +++ b/Greenshot/Drawing/FreehandContainer.cs @@ -36,7 +36,10 @@ namespace Greenshot.Drawing { public class FreehandContainer : DrawableContainer { private static readonly float [] PointOffset = {0.5f, 0.25f, 0.75f}; - [NonSerialized] + [NonSerialized] + private readonly object _freehandPathLock = new object(); + + [NonSerialized] private GraphicsPath freehandPath = new GraphicsPath(); private Rectangle myBounds = Rectangle.Empty; private Point lastMouse = Point.Empty; @@ -104,15 +107,21 @@ namespace Greenshot.Drawing { if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= 2*EditorConfig.FreehandSensitivity) { capturePoints.Add(new Point(mouseX, mouseY)); } - if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity) { - //path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)}); - freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY)); - lastMouse = new Point(mouseX, mouseY); - // Only re-calculate the bounds & redraw when we added something to the path - myBounds = Rectangle.Round(freehandPath.GetBounds()); - Invalidate(); - } - return true; + if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) < EditorConfig.FreehandSensitivity) + { + return true; + } + //path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)}); + lastMouse = new Point(mouseX, mouseY); + lock (_freehandPathLock) + { + freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY)); + // Only re-calculate the bounds & redraw when we added something to the path + myBounds = Rectangle.Round(freehandPath.GetBounds()); + } + + Invalidate(); + return true; } /// @@ -130,25 +139,34 @@ namespace Greenshot.Drawing { /// Here we recalculate the freehand path by smoothing out the lines with Beziers. /// private void RecalculatePath() { - isRecalculated = true; - // Dispose the previous path, if we have one - freehandPath?.Dispose(); - freehandPath = new GraphicsPath(); + lock (_freehandPathLock) + { + isRecalculated = true; + // Dispose the previous path, if we have one + freehandPath?.Dispose(); + freehandPath = new GraphicsPath(); - // Here we can put some cleanup... like losing all the uninteresting points. - if (capturePoints.Count >= 3) { - int index = 0; - while ((capturePoints.Count - 1) % 3 != 0) { - // duplicate points, first at 50% than 25% than 75% - capturePoints.Insert((int)(capturePoints.Count*PointOffset[index]), capturePoints[(int)(capturePoints.Count*PointOffset[index++])]); - } - freehandPath.AddBeziers(capturePoints.ToArray()); - } else if (capturePoints.Count == 2) { - freehandPath.AddLine(capturePoints[0], capturePoints[1]); - } + // Here we can put some cleanup... like losing all the uninteresting points. + if (capturePoints.Count >= 3) + { + int index = 0; + while ((capturePoints.Count - 1) % 3 != 0) + { + // duplicate points, first at 50% than 25% than 75% + capturePoints.Insert((int)(capturePoints.Count * PointOffset[index]), capturePoints[(int)(capturePoints.Count * PointOffset[index++])]); + } + freehandPath.AddBeziers(capturePoints.ToArray()); + } + else if (capturePoints.Count == 2) + { + freehandPath.AddLine(capturePoints[0], capturePoints[1]); + } + + // Recalculate the bounds + myBounds = Rectangle.Round(freehandPath.GetBounds()); + + } - // Recalculate the bounds - myBounds = Rectangle.Round(freehandPath.GetBounds()); } /// @@ -157,41 +175,48 @@ namespace Greenshot.Drawing { /// /// public override void Draw(Graphics graphics, RenderMode renderMode) { - graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - using (Pen pen = new Pen(lineColor)) { + using (var pen = new Pen(lineColor)) { pen.Width = lineThickness; - if (pen.Width > 0) { - // Make sure the lines are nicely rounded - pen.EndCap = LineCap.Round; - pen.StartCap = LineCap.Round; - pen.LineJoin = LineJoin.Round; + if (!(pen.Width > 0)) + { + return; + } + // Make sure the lines are nicely rounded + pen.EndCap = LineCap.Round; + pen.StartCap = LineCap.Round; + pen.LineJoin = LineJoin.Round; + // Move to where we need to draw + graphics.TranslateTransform(Left, Top); + lock (_freehandPathLock) + { + if (isRecalculated && Selected && renderMode == RenderMode.EDIT) + { + DrawSelectionBorder(graphics, pen, freehandPath); + } + graphics.DrawPath(pen, freehandPath); + } - // Move to where we need to draw - graphics.TranslateTransform(Left,Top); - if (isRecalculated && Selected && renderMode == RenderMode.EDIT) { - DrawSelectionBorder(graphics, pen); - } - graphics.DrawPath(pen, freehandPath); - // Move back, otherwise everything is shifted - graphics.TranslateTransform(-Left,-Top); - } + // Move back, otherwise everything is shifted + graphics.TranslateTransform(-Left,-Top); } } - - /// - /// Draw a selectionborder around the freehand path - /// - /// - /// - protected void DrawSelectionBorder(Graphics graphics, Pen linePen) { - using (Pen selectionPen = (Pen) linePen.Clone()) { - using (GraphicsPath selectionPath = (GraphicsPath) freehandPath.Clone()) { + + /// + /// Draw a selectionborder around the freehand path + /// + /// Graphics + /// Pen + /// GraphicsPath + protected static void DrawSelectionBorder(Graphics graphics, Pen linePen, GraphicsPath path) { + using (var selectionPen = (Pen) linePen.Clone()) { + using (var selectionPath = (GraphicsPath)path.Clone()) { selectionPen.Width += 5; selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen); graphics.DrawPath(selectionPen, selectionPath); @@ -218,34 +243,42 @@ namespace Greenshot.Drawing { } } - /// - /// FreehandContainer are regarded equal if they are of the same type and their paths are equal. - /// - /// - /// - public override bool Equals(object obj) { + /// + /// FreehandContainer are regarded equal if they are of the same type and their paths are equal. + /// + /// object + /// bool + public override bool Equals(object obj) { bool ret = false; - if(obj != null && GetType() == obj.GetType()) { - FreehandContainer other = obj as FreehandContainer; - if(other != null && freehandPath.Equals(other.freehandPath)) { - ret = true; - } - } - return ret; + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + var other = obj as FreehandContainer; + if (other != null && Equals(freehandPath, other.freehandPath)) { + ret = true; + } + return ret; } public override int GetHashCode() { - return freehandPath.GetHashCode(); + lock (_freehandPathLock) + { + return freehandPath?.GetHashCode() ?? 0; + } } public override bool ClickableAt(int x, int y) { bool returnValue = base.ClickableAt(x, y); if (returnValue) { int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - using (Pen pen = new Pen(Color.White)) { + using (var pen = new Pen(Color.White)) { pen.Width = lineThickness + 10; - returnValue = freehandPath.IsOutlineVisible(x-Left,y-Top, pen); - } + lock (_freehandPathLock) + { + returnValue = freehandPath.IsOutlineVisible(x - Left, y - Top, pen); + } + } } return returnValue; } diff --git a/Greenshot/Drawing/RectangleContainer.cs b/Greenshot/Drawing/RectangleContainer.cs index d7e2cb37e..92261ca7e 100644 --- a/Greenshot/Drawing/RectangleContainer.cs +++ b/Greenshot/Drawing/RectangleContainer.cs @@ -62,8 +62,8 @@ namespace Greenshot.Drawing { public override void Draw(Graphics graphics, RenderMode rm) { int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); + Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR, Color.Red); + Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR, Color.Transparent); bool shadow = GetFieldValueAsBool(FieldType.SHADOW); Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); diff --git a/Greenshot/Drawing/TextContainer.cs b/Greenshot/Drawing/TextContainer.cs index 0c72b464b..d352aa056 100644 --- a/Greenshot/Drawing/TextContainer.cs +++ b/Greenshot/Drawing/TextContainer.cs @@ -35,572 +35,594 @@ using System.Windows.Forms; namespace Greenshot.Drawing { - /// - /// Represents a textbox (extends RectangleContainer for border/background support - /// - [Serializable] - public class TextContainer : RectangleContainer, ITextContainer - { - // If makeUndoable is true the next text-change will make the change undoable. - // This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack - // Although the name is wrong, we can't change it due to file serialization - // ReSharper disable once InconsistentNaming - private bool makeUndoable; - [NonSerialized] - private Font _font; - public Font Font => _font; + /// + /// Represents a textbox (extends RectangleContainer for border/background support + /// + [Serializable] + public class TextContainer : RectangleContainer, ITextContainer + { + // If makeUndoable is true the next text-change will make the change undoable. + // This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack + // Although the name is wrong, we can't change it due to file serialization + // ReSharper disable once InconsistentNaming + private bool makeUndoable; + [NonSerialized] + private Font _font; + public Font Font => _font; - [NonSerialized] - private TextBox _textBox; + [NonSerialized] + private TextBox _textBox; - /// - /// The StringFormat object is not serializable!! - /// - [NonSerialized] - private StringFormat _stringFormat = new StringFormat(); + /// + /// The StringFormat object is not serializable!! + /// + [NonSerialized] + private StringFormat _stringFormat = new StringFormat(); - public StringFormat StringFormat => _stringFormat; + public StringFormat StringFormat => _stringFormat; - // Although the name is wrong, we can't change it due to file serialization - // ReSharper disable once InconsistentNaming - private string text; - // there is a binding on the following property! - public string Text - { - get { return text; } - set - { - ChangeText(value, true); - } - } + // Although the name is wrong, we can't change it due to file serialization + // ReSharper disable once InconsistentNaming + private string text; + // there is a binding on the following property! + public string Text + { + get { return text; } + set + { + ChangeText(value, true); + } + } - internal void ChangeText(string newText, bool allowUndoable) - { - if ((text == null && newText != null) || !string.Equals(text, newText)) - { - if (makeUndoable && allowUndoable) - { - makeUndoable = false; - _parent.MakeUndoable(new TextChangeMemento(this), false); - } - text = newText; - OnPropertyChanged("Text"); - } - } + internal void ChangeText(string newText, bool allowUndoable) + { + if ((text == null && newText != null) || !string.Equals(text, newText)) + { + if (makeUndoable && allowUndoable) + { + makeUndoable = false; + _parent.MakeUndoable(new TextChangeMemento(this), false); + } + text = newText; + OnPropertyChanged("Text"); + } + } - public TextContainer(Surface parent) : base(parent) - { - Init(); - } + public TextContainer(Surface parent) : base(parent) + { + Init(); + } - protected override void InitializeFields() - { - AddField(GetType(), FieldType.LINE_THICKNESS, 2); - AddField(GetType(), FieldType.LINE_COLOR, Color.Red); - AddField(GetType(), FieldType.SHADOW, true); - AddField(GetType(), FieldType.FONT_ITALIC, false); - AddField(GetType(), FieldType.FONT_BOLD, false); - AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent); - AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name); - AddField(GetType(), FieldType.FONT_SIZE, 11f); - AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center); - AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center); - } + protected override void InitializeFields() + { + AddField(GetType(), FieldType.LINE_THICKNESS, 2); + AddField(GetType(), FieldType.LINE_COLOR, Color.Red); + AddField(GetType(), FieldType.SHADOW, true); + AddField(GetType(), FieldType.FONT_ITALIC, false); + AddField(GetType(), FieldType.FONT_BOLD, false); + AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent); + AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name); + AddField(GetType(), FieldType.FONT_SIZE, 11f); + AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center); + AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center); + } - /// - /// Do some logic to make sure all field are initiated correctly - /// - /// StreamingContext - protected override void OnDeserialized(StreamingContext streamingContext) - { - base.OnDeserialized(streamingContext); - Init(); - } + /// + /// Do some logic to make sure all field are initiated correctly + /// + /// StreamingContext + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (_font != null) - { - _font.Dispose(); - _font = null; - } - if (_stringFormat != null) - { - _stringFormat.Dispose(); - _stringFormat = null; - } - if (_textBox != null) - { - _textBox.Dispose(); - _textBox = null; - } - } - base.Dispose(disposing); - } + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_font != null) + { + _font.Dispose(); + _font = null; + } + if (_stringFormat != null) + { + _stringFormat.Dispose(); + _stringFormat = null; + } + if (_textBox != null) + { + _textBox.Dispose(); + _textBox = null; + } + } + base.Dispose(disposing); + } - private void Init() - { - _stringFormat = new StringFormat - { - Trimming = StringTrimming.EllipsisWord - }; + private void Init() + { + _stringFormat = new StringFormat + { + Trimming = StringTrimming.EllipsisWord + }; - CreateTextBox(); + CreateTextBox(); - UpdateFormat(); - UpdateTextBoxFormat(); + UpdateFormat(); + UpdateTextBoxFormat(); - PropertyChanged += TextContainer_PropertyChanged; - FieldChanged += TextContainer_FieldChanged; - } + PropertyChanged += TextContainer_PropertyChanged; + FieldChanged += TextContainer_FieldChanged; + } - public override void Invalidate() - { - base.Invalidate(); - if (_textBox != null && _textBox.Visible) - { - _textBox.Invalidate(); - } - } + public override void Invalidate() + { + base.Invalidate(); + if (_textBox != null && _textBox.Visible) + { + _textBox.Invalidate(); + } + } - public void FitToText() - { - Size textSize = TextRenderer.MeasureText(text, _font); - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Width = textSize.Width + lineThickness; - Height = textSize.Height + lineThickness; - } + public void FitToText() + { + Size textSize = TextRenderer.MeasureText(text, _font); + int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); + Width = textSize.Width + lineThickness; + Height = textSize.Height + lineThickness; + } - private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (_textBox == null) - { - return; - } + private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (_textBox == null) + { + return; + } - if (_textBox.Visible) - { - _textBox.Invalidate(); - } + if (_textBox.Visible) + { + _textBox.Invalidate(); + } - UpdateTextBoxPosition(); - UpdateTextBoxFormat(); - if (e.PropertyName.Equals("Selected")) - { - if (!Selected && _textBox.Visible) - { - HideTextBox(); - } - else if (Selected && Status == EditStatus.DRAWING) - { - ShowTextBox(); - } - else if (_parent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible) - { - // Fix (workaround) for BUG-1698 - _parent.KeysLocked = true; - } - } - if (_textBox.Visible) - { - _textBox.Invalidate(); - } - } + UpdateTextBoxPosition(); + UpdateTextBoxFormat(); + if (e.PropertyName.Equals("Selected")) + { + if (!Selected && _textBox.Visible) + { + HideTextBox(); + } + else if (Selected && Status == EditStatus.DRAWING) + { + ShowTextBox(); + } + else if (_parent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible) + { + // Fix (workaround) for BUG-1698 + _parent.KeysLocked = true; + } + } + if (_textBox.Visible) + { + _textBox.Invalidate(); + } + } - private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e) - { - if (_textBox == null) - { - return; - } - if (_textBox.Visible) - { - _textBox.Invalidate(); - } - // Only dispose the font, and re-create it, when a font field has changed. - if (e.Field.FieldType.Name.StartsWith("FONT")) - { - if (_font != null) - { - _font.Dispose(); - _font = null; - } - UpdateFormat(); - } - else - { - UpdateAlignment(); - } - UpdateTextBoxFormat(); + private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e) + { + if (_textBox == null) + { + return; + } + if (_textBox.Visible) + { + _textBox.Invalidate(); + } + // Only dispose the font, and re-create it, when a font field has changed. + if (e.Field.FieldType.Name.StartsWith("FONT")) + { + if (_font != null) + { + _font.Dispose(); + _font = null; + } + UpdateFormat(); + } + else + { + UpdateAlignment(); + } + UpdateTextBoxFormat(); - if (_textBox.Visible) - { - _textBox.Invalidate(); - } - } + if (_textBox.Visible) + { + _textBox.Invalidate(); + } + } - public override void OnDoubleClick() - { - ShowTextBox(); - } + public override void OnDoubleClick() + { + ShowTextBox(); + } - private void CreateTextBox() - { - _textBox = new TextBox - { - ImeMode = ImeMode.On, - Multiline = true, - AcceptsTab = true, - AcceptsReturn = true, - BorderStyle = BorderStyle.None, - Visible = false - }; + private void CreateTextBox() + { + _textBox = new TextBox + { + ImeMode = ImeMode.On, + Multiline = true, + AcceptsTab = true, + AcceptsReturn = true, + BorderStyle = BorderStyle.None, + Visible = false + }; - _textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged); - _textBox.LostFocus += textBox_LostFocus; - _textBox.KeyDown += textBox_KeyDown; - } + _textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged); + _textBox.LostFocus += textBox_LostFocus; + _textBox.KeyDown += textBox_KeyDown; + } - private void ShowTextBox() - { - if (_parent != null) - { - _parent.KeysLocked = true; - _parent.Controls.Add(_textBox); - } - EnsureTextBoxContrast(); - if (_textBox != null) - { - _textBox.Show(); - _textBox.Focus(); - } - } + private void ShowTextBox() + { + if (_parent != null) + { + _parent.KeysLocked = true; + _parent.Controls.Add(_textBox); + } + EnsureTextBoxContrast(); + if (_textBox != null) + { + _textBox.Show(); + _textBox.Focus(); + } + } - /// - /// Makes textbox background dark if text color is very bright - /// - private void EnsureTextBoxContrast() - { - if (_textBox == null) - { - return; - } - Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR); - if (lc.R > 203 && lc.G > 203 && lc.B > 203) - { - _textBox.BackColor = Color.FromArgb(51, 51, 51); - } - else - { - _textBox.BackColor = Color.White; - } - } + /// + /// Makes textbox background dark if text color is very bright + /// + private void EnsureTextBoxContrast() + { + if (_textBox == null) + { + return; + } + Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR); + if (lc.R > 203 && lc.G > 203 && lc.B > 203) + { + _textBox.BackColor = Color.FromArgb(51, 51, 51); + } + else + { + _textBox.BackColor = Color.White; + } + } - private void HideTextBox() - { - _parent.Focus(); - _textBox?.Hide(); - _parent.KeysLocked = false; - _parent.Controls.Remove(_textBox); - } + private void HideTextBox() + { + _parent.Focus(); + _textBox?.Hide(); + _parent.KeysLocked = false; + _parent.Controls.Remove(_textBox); + } - /// - /// Make sure the size of the font is scaled - /// - /// - public override void Transform(Matrix matrix) - { - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - int pixelsBefore = rect.Width * rect.Height; + /// + /// Make sure the size of the font is scaled + /// + /// + public override void Transform(Matrix matrix) + { + Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + int pixelsBefore = rect.Width * rect.Height; - // Transform this container - base.Transform(matrix); - rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + // Transform this container + base.Transform(matrix); + rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - int pixelsAfter = rect.Width * rect.Height; - float factor = pixelsAfter / (float)pixelsBefore; + int pixelsAfter = rect.Width * rect.Height; + float factor = pixelsAfter / (float)pixelsBefore; - float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); - fontSize *= factor; - SetFieldValue(FieldType.FONT_SIZE, fontSize); - UpdateFormat(); - } + float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); + fontSize *= factor; + SetFieldValue(FieldType.FONT_SIZE, fontSize); + UpdateFormat(); + } - private Font CreateFont(string fontFamilyName, bool fontBold, bool fontItalic, float fontSize) - { - FontStyle fontStyle = FontStyle.Regular; + private Font CreateFont(string fontFamilyName, bool fontBold, bool fontItalic, float fontSize) + { + FontStyle fontStyle = FontStyle.Regular; - bool hasStyle = false; - using (var fontFamily = new FontFamily(fontFamilyName)) - { - bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold); - if (fontBold && boldAvailable) - { - fontStyle |= FontStyle.Bold; - hasStyle = true; - } + bool hasStyle = false; + using (var fontFamily = new FontFamily(fontFamilyName)) + { + bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold); + if (fontBold && boldAvailable) + { + fontStyle |= FontStyle.Bold; + hasStyle = true; + } - bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic); - if (fontItalic && italicAvailable) - { - fontStyle |= FontStyle.Italic; - hasStyle = true; - } + bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic); + if (fontItalic && italicAvailable) + { + fontStyle |= FontStyle.Italic; + hasStyle = true; + } - if (!hasStyle) - { - bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular); - if (regularAvailable) - { - fontStyle = FontStyle.Regular; - } - else - { - if (boldAvailable) - { - fontStyle = FontStyle.Bold; - } - else if (italicAvailable) - { - fontStyle = FontStyle.Italic; - } - } - } - return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); - } - } + if (!hasStyle) + { + bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular); + if (regularAvailable) + { + fontStyle = FontStyle.Regular; + } + else + { + if (boldAvailable) + { + fontStyle = FontStyle.Bold; + } + else if (italicAvailable) + { + fontStyle = FontStyle.Italic; + } + } + } + return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); + } + } - /// - /// Generate the Font-Formal so we can draw correctly - /// - protected void UpdateFormat() - { - if (_textBox == null) - { - return; - } - string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY); - bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD); - bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC); - float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); - try - { - var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize); - _font?.Dispose(); - _font = newFont; - _textBox.Font = _font; - } - catch (Exception ex) - { - // Problem, try again with the default - try - { - fontFamily = FontFamily.GenericSansSerif.Name; - SetFieldValue(FieldType.FONT_FAMILY, fontFamily); - var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize); - _font?.Dispose(); - _font = newFont; - _textBox.Font = _font; - } - catch (Exception) - { - // When this happens... the PC is broken - ex.Data.Add("fontFamilyName", fontFamily); - ex.Data.Add("fontBold", fontBold); - ex.Data.Add("fontItalic", fontItalic); - ex.Data.Add("fontSize", fontSize); - throw ex; - } - } + /// + /// Generate the Font-Formal so we can draw correctly + /// + protected void UpdateFormat() + { + if (_textBox == null) + { + return; + } + string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY); + bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD); + bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC); + float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); + try + { + var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize); + _font?.Dispose(); + _font = newFont; + _textBox.Font = _font; + } + catch (Exception ex) + { + // Problem, try again with the default + try + { + fontFamily = FontFamily.GenericSansSerif.Name; + SetFieldValue(FieldType.FONT_FAMILY, fontFamily); + var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize); + _font?.Dispose(); + _font = newFont; + _textBox.Font = _font; + } + catch (Exception) + { + // When this happens... the PC is broken + ex.Data.Add("fontFamilyName", fontFamily); + ex.Data.Add("fontBold", fontBold); + ex.Data.Add("fontItalic", fontItalic); + ex.Data.Add("fontSize", fontSize); + throw ex; + } + } - UpdateAlignment(); - } + UpdateAlignment(); + } - private void UpdateAlignment() - { - _stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); - _stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); - } + private void UpdateAlignment() + { + _stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); + _stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); + } - /// - /// This will create the textbox exactly to the inner size of the element - /// is a bit of a hack, but for now it seems to work... - /// - private void UpdateTextBoxPosition() - { - if (_textBox == null) - { - return; - } - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); + /// + /// This will create the textbox exactly to the inner size of the element + /// is a bit of a hack, but for now it seems to work... + /// + private void UpdateTextBoxPosition() + { + if (_textBox == null) + { + return; + } + int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - int lineWidth = (int)Math.Floor(lineThickness / 2d); - int correction = (lineThickness + 1) % 2; - if (lineThickness <= 1) - { - lineWidth = 1; - correction = -1; - } - Rectangle absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - _textBox.Left = absRectangle.Left + lineWidth; - _textBox.Top = absRectangle.Top + lineWidth; - if (lineThickness <= 1) - { - lineWidth = 0; - } - _textBox.Width = absRectangle.Width - 2 * lineWidth + correction; - _textBox.Height = absRectangle.Height - 2 * lineWidth + correction; - } + int lineWidth = (int)Math.Floor(lineThickness / 2d); + int correction = (lineThickness + 1) % 2; + if (lineThickness <= 1) + { + lineWidth = 1; + correction = -1; + } + Rectangle absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + _textBox.Left = absRectangle.Left + lineWidth; + _textBox.Top = absRectangle.Top + lineWidth; + if (lineThickness <= 1) + { + lineWidth = 0; + } + _textBox.Width = absRectangle.Width - 2 * lineWidth + correction; + _textBox.Height = absRectangle.Height - 2 * lineWidth + correction; + } - public override void ApplyBounds(RectangleF newBounds) - { - base.ApplyBounds(newBounds); - UpdateTextBoxPosition(); - } + public override void ApplyBounds(RectangleF newBounds) + { + base.ApplyBounds(newBounds); + UpdateTextBoxPosition(); + } - private void UpdateTextBoxFormat() - { - if (_textBox == null) - { - return; - } - var alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); - switch (alignment) - { - case StringAlignment.Near: - _textBox.TextAlign = HorizontalAlignment.Left; - break; - case StringAlignment.Far: - _textBox.TextAlign = HorizontalAlignment.Right; - break; - case StringAlignment.Center: - _textBox.TextAlign = HorizontalAlignment.Center; - break; - } + private void UpdateTextBoxFormat() + { + if (_textBox == null) + { + return; + } + var alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); + switch (alignment) + { + case StringAlignment.Near: + _textBox.TextAlign = HorizontalAlignment.Left; + break; + case StringAlignment.Far: + _textBox.TextAlign = HorizontalAlignment.Right; + break; + case StringAlignment.Center: + _textBox.TextAlign = HorizontalAlignment.Center; + break; + } - var lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - _textBox.ForeColor = lineColor; - } + var lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); + _textBox.ForeColor = lineColor; + } - private void textBox_KeyDown(object sender, KeyEventArgs e) - { - // ESC and Enter/Return (w/o Shift) hide text editor - if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None)) - { - HideTextBox(); - e.SuppressKeyPress = true; - } - } + private void textBox_KeyDown(object sender, KeyEventArgs e) + { + // ESC and Enter/Return (w/o Shift) hide text editor + if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None)) + { + HideTextBox(); + e.SuppressKeyPress = true; + } - private void textBox_LostFocus(object sender, EventArgs e) - { - // next change will be made undoable - makeUndoable = true; - HideTextBox(); - } + if (e.Control && e.KeyCode == Keys.A) + { + _textBox.SelectAll(); + } + // Added for FEATURE-1064 + if (e.KeyCode == Keys.Back && e.Control) + { + e.SuppressKeyPress = true; + int selStart = _textBox.SelectionStart; + while (selStart > 0 && _textBox.Text.Substring(selStart - 1, 1) == " ") + { + selStart--; + } + int prevSpacePos = -1; + if (selStart != 0) + { + prevSpacePos = _textBox.Text.LastIndexOf(' ', selStart - 1); + } + _textBox.Select(prevSpacePos + 1, _textBox.SelectionStart - prevSpacePos - 1); + _textBox.SelectedText = ""; + } + } - public override void Draw(Graphics graphics, RenderMode rm) - { - base.Draw(graphics, rm); + private void textBox_LostFocus(object sender, EventArgs e) + { + // next change will be made undoable + makeUndoable = true; + HideTextBox(); + } - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - graphics.TextRenderingHint = TextRenderingHint.SystemDefault; + public override void Draw(Graphics graphics, RenderMode rm) + { + base.Draw(graphics, rm); - Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - if (Selected && rm == RenderMode.EDIT) - { - DrawSelectionBorder(graphics, rect); - } + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.None; + graphics.TextRenderingHint = TextRenderingHint.SystemDefault; - if (string.IsNullOrEmpty(text)) - { - return; - } + Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + if (Selected && rm == RenderMode.EDIT) + { + DrawSelectionBorder(graphics, rect); + } - // we only draw the shadow if there is no background - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty); + if (string.IsNullOrEmpty(text)) + { + return; + } - DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font); - } + // we only draw the shadow if there is no background + bool shadow = GetFieldValueAsBool(FieldType.SHADOW); + Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR); + int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); + Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); + bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty); - /// - /// This method can be used from other containers - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font) - { + DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font); + } + + /// + /// This method can be used from other containers + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font) + { #if DEBUG - Debug.Assert(font != null); + Debug.Assert(font != null); #else - if (font == null) - { - return; - } + if (font == null) + { + return; + } #endif - int textOffset = lineThickness > 0 ? (int)Math.Ceiling(lineThickness / 2d) : 0; - // draw shadow before anything else - if (drawShadow) - { - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = 1; - while (currentStep <= steps) - { - int offset = currentStep; - Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height); - if (lineThickness > 0) - { - shadowRect.Inflate(-textOffset, -textOffset); - } - using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) - { - graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat); - currentStep++; - alpha = alpha - basealpha / steps; - } - } - } + int textOffset = lineThickness > 0 ? (int)Math.Ceiling(lineThickness / 2d) : 0; + // draw shadow before anything else + if (drawShadow) + { + int basealpha = 100; + int alpha = basealpha; + int steps = 5; + int currentStep = 1; + while (currentStep <= steps) + { + int offset = currentStep; + Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height); + if (lineThickness > 0) + { + shadowRect.Inflate(-textOffset, -textOffset); + } + using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) + { + graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat); + currentStep++; + alpha = alpha - basealpha / steps; + } + } + } - if (lineThickness > 0) - { - drawingRectange.Inflate(-textOffset, -textOffset); - } - using (Brush fontBrush = new SolidBrush(fontColor)) - { - if (stringFormat != null) - { - graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat); - } - else - { - graphics.DrawString(text, font, fontBrush, drawingRectange); - } - } - } + if (lineThickness > 0) + { + drawingRectange.Inflate(-textOffset, -textOffset); + } + using (Brush fontBrush = new SolidBrush(fontColor)) + { + if (stringFormat != null) + { + graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat); + } + else + { + graphics.DrawString(text, font, fontBrush, drawingRectange); + } + } + } - public override bool ClickableAt(int x, int y) - { - Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - r.Inflate(5, 5); - return r.Contains(x, y); - } - } + public override bool ClickableAt(int x, int y) + { + Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + r.Inflate(5, 5); + return r.Contains(x, y); + } + } } diff --git a/Greenshot/Languages/help-nl-NL.html b/Greenshot/Languages/help-nl-NL.html index d4e90dee9..236d2f304 100644 --- a/Greenshot/Languages/help-nl-NL.html +++ b/Greenshot/Languages/help-nl-NL.html @@ -23,15 +23,15 @@ - Versie 1.0 - Nederlandse vertaling van de help door Jurjen Ladenius en Stephan Paternotte + Versie 1.2.10 - Nederlandse vertaling door Jurjen Ladenius en Stephan Paternotte

Inhoud

  1. Een schermopname maken
    1. Interactief kader
    2. -
    3. Laastgebruikte schermopname
    4. -
    5. Actief venster
    6. +
    7. Laaste schermopname herhalen
    8. +
    9. Actief vensteropname
    10. Volledige schermopname
    11. Internet Explorer schermopname
    @@ -69,23 +69,23 @@

    Een schermopname maken

    U kunt een schermopname maken door op uw toetsenbord de Print-toets te drukken of - een rechtermuisklik op het Greenshot-icoon in het systeemvak te geven
    + door middel van een rechtermuisklik op het Greenshot-icoon in het systeemvak.
    Er zijn meerdere mogelijkheden om een schermopname te maken:

    Interactief kader Print

    - De "regio-opname" modus maakt het mogelijk om een gebied van het beeldscherm te markeren voor een schermopname.
    - Nadat de regio vastlegen modus gestart wordt verandert de mouse-cursor in een kruis. - Positioneer de muis naar een hoek van het gebied waarvan u een schermopname wilt hebben en + Deze "regio"-opnamemodus maakt het mogelijk om een gebied van het beeldscherm te selecteren voor een schermopname.
    + Bij het vastleggen van het opnamegebied verandert de mouse-cursor in een haarkruis. + Positioneer de muis naar een hoek van het gebied waarvan u een schermopname wilt maken en druk op de linkermuisknop en houd deze ingedrukt. Beweeg nu de muis naar de diagonale hoek van uw doelgebied. Tijdens het bewegen ontstaat een groeiende groene rechthoek. Op het moment dat u de linkermuisknop loslaat wordt van het groene gebied een schermopname gemaakt.

    - U kunt de spatie toets gebruiken om wisselen tussen de modi "regio-opname" en - venster. Met de Esc-toets breekt u de schermopname af. + Met de spatie-balk kunt u wisselen tussen de modi "Interactief kader" en + Actief vensteropname. Met Esc breekt u de schermopname af.

    Als u een zeer exact gebied wilt vastleggen is het misschien eenvoudiger om eerst van een groter @@ -94,30 +94,30 @@

    -

    Laatstgebruikte schermopnameShift + Print

    +

    Laatste schermopname herhalen Shift + Print

    - Als u al een keer een schermopname heeft gemaakt van een kader - of een venster, dan heeft u met deze optie de mogelijkheid hetzelfde gebied nog eens vast te leggen. + Als u al een keer een schermopname heeft gemaakt van een Interactief kader + of een Actief venster, dan kunt u met deze optie hetzelfde gebied nog eens vastleggen.

    -

    Actief venster Alt + Print

    +

    Actief vensteropname Alt + Print

    Maakt een schermopname van het aktieve venster.

    Gebruik bij Windows 7 of Vista de Schermopname-instellingen om te bepalen - hoe Greenshot omgaat met transparante (Aero) vensterranden, etc. het vervangen - van transparanties door een vaste kleur. + hoe Greenshot omgaat met transparante (Aero) vensterranden, door bijv. transparanties + te vervangen door een vaste kleur.

    De instellingendialoog biedt de mogelijkheid om niet direct het actieve venster te fotograferen, maar een venster interactief te selecteren. - Als deze optie geactiveerd is, kunt u een venster selecteren door het te klikken (zoals bij + Als deze optie geactiveerd is, kunt u een venster selecteren door het te klikken. Net als bij Interactief kader, zal Greenshot het te fotograferen - gebied markeren).
    Als u een deelvenster wilt fotograferen, zoals bijv. een browservenster + gebied markeren.
    Wilt u een deelvenster fotograferen, zoals bijv. een browservenster zonder menu of gereedschapsbalk of een enkel onderdeel in een webpagina, - positioneer dan de muis over het deelvenster en druk de PgDown-toets. Hierna + positioneer dan de muis over het deelvenster en druk de Page Down-toets. Hierna kunt u de specifieke vensterelementen selecteren voor de schermopname.

    @@ -125,19 +125,19 @@ "Venster"-schermopname zal het contextmenu verdwijnen en dat zal ook gebeuren als u Greenshot's contextmenu gebruikt om de schermopname te maken. Wilt u een schermopname maken van een contextmenu dat u zojuist met een rechtermuisklik hebt geopend, - gebruik dan eenvoudig "Interactief kader" Print en druk dan de Spatie-balk. + gebruik dan eenvoudig "Interactief kader" Print en druk dan de spatie-balk.

    -

    Volledige schermopname Control + Print

    +

    Volledige schermopname Ctrl + Print

    - Hierbij wordt een schermopname gemaakt van het gehele scherm, ook als meerdere monitoren gebruikt worden. + Greenshot maakt een schermopname van het gehele scherm.

    -

    Internet Explorer schermopnameControl + Shift + Print

    +

    Internet Explorer schermopname Ctrl + Shift + Print

    - Deze funcie maakt eenvoudig een schermopname van een webpagina die geopend is in Internet Explorer. + Deze funcie maakt op eenvoudige wijze een schermopname van een webpagina die geopend is in Internet Explorer. Gebruik Greenshot's contextmenu om de tab in Internet Explorer te selecteren voor schermopname, of druk Crtl + Shift + Print om een schermopname te maken van de actieve tab.

    @@ -147,18 +147,18 @@

    De Greenshot beeldbewerker gebruiken

    Greenshot heeft een eenvoudig te gebruiken beeldbewerkingsprogramma met verschillende handige functies en - mogelijkheden om een schermopname te voorzien van vormen en annotaties. Het is ook mogelijk om bepaalde delen van - uw screenshot onherkenbaar te maken of te markeren waardoor het beter opvalt. + mogelijkheden om een schermopname te voorzien van vormen en annotaties. Het biedt ook mogelijkheden om + delen van een schermopname onherkenbaar te maken of te markeren zodat het beter opvalt.

    De Greenshot beeldbewerker is niet alleen handig voor schermopnamen, maar is ook te gebruiken voor andere afbeeldingen uit bestanden of het klembord. Klik hiervoor met de rechter muisknop op het Greenshot-icoon - in het systeemvak en selecteer Afbeelding uit bestand openen of - Afbeelding laden van het klembord. + in het systeemvak en selecteer Afbeeldingsbestand openen of + Afbeelding van het klembord laden.

    - Wanneer een schermopname is gemaakt wordt standaard de beeldbewerker geopend. - Indien u dit niet wenst, kunt u dit gedrag in het instellingen-venster + Na het maken van een schermopname, wordt de afbeelding standaard in de beeldbewerker geopend. + Indien u dit niet wenst, kunt u dit gedrag bij de Instellingen afschakelen.

    @@ -168,16 +168,16 @@

    Kies een van de vormen in de gereedschapsbalk aan de linkerzijde van de beeldbewerker of van het menu Object. Aan elke toets is tevens een sneltoets gekoppeld - voor snelle toegang via het toetsenbord.
    + voor snelle toegang via het toetsenbord.
    Beschikbare vormen zijn: rechthoek R, ellips E, lijn L - pijl A en vrije vorm F.
    + pijl A en vrije vorm F.
    Klik en sleep de muis om de positie en de grootte van de vorm te bepalen. Laat de muisknop los als de vorm van de juiste afmetingen is.

    - Getekende vormen kunnen worden verplaatst en vergroot met behulp van de knop Selectie - ESC op de gereedschapsbalk.
    Voor elk vormtype zijn specifieke - opties beschikbaar om het uiterlijk aan te passen (bijv. lijndikte, + Getekende vormen kunnen worden verplaatst en vergroot met behulp van de knop Selectie + ESC op de gereedschapsbalk.
    Voor elk vormtype zijn specifieke + opties beschikbaar om de karakteristieken aan te passen (bijv. lijndikte, lijnkleur, vulkleur). U kunt het uiterlijk veranderen voor een bestaand geselecteerd object, maar u kunt ook de eigenschappen instellen voor de volgende te tekenen vorm.

    @@ -188,7 +188,7 @@

    Wilt u een symmetrische vorm tekenen (bijv. een vierkant of een cirkel)? Houd dan tijdens het tekenen de Shift-toets ingedrukt. Bij het tekenen van pijlen, beperkt de Shift-toets - de mogelijke hoeken tot veelvouden van 15°.
    + de mogelijke hoeken tot veelvouden van 15°.
    Bij het vergroten van een bestaand object zorgt de Shift-toets ervoor dat de verhoudingen behouden blijven.

    @@ -201,9 +201,9 @@

    Tekst toevoegen

    Het gebruik van de Tekst-functie T is vergelijkbaar met dat van - Vormen toevoegen. Plaats een tekst-element van de gewenste grootte - en typ de tekst.
    - Dubbelklik een bestaande tekst om deze te bewerken.
    + Vormen toevoegen. Plaats een tekstkader van de gewenste grootte + en typ de tekst.
    + Dubbelklik een bestaande tekst om deze te bewerken.
    Gebruik Return of Enter als u klaar bent met bewerken.

    @@ -215,7 +215,7 @@

    Markeren

    Met de Markeer-functie H, kunt u een gebied markeren op precies dezelfde wijze - als waarmee u een vorm shape tekent.
    + als waarmee u een vorm shape tekent.
    De volgende opties bij het markeren zijn beschilbaar via de meest linkse knop in de gereedschapsbalk:

    @@ -231,8 +231,8 @@

    Maskeren

    Delen van een schermopname maskeren is een goed gebruik wanneer persoonlijke gegevens in beeld zijn - die beter privé kunnen blijven, zoals bijv. bankgegevens, namen, wachtwoorden of herkenbare personen.
    - De functie Maskeren O gebruikt u net als het Markeren.
    + die beter privé kunnen blijven, zoals bijv. bankgegevens, namen, wachtwoorden of herkenbare personen.
    + De functie Maskeren O gebruikt u net als het Markeren.
    Beschikbare opties voor Maskeren zijn:

    @@ -245,15 +245,15 @@ * Afhankelijk van uw computer kan het vervagingseffect de werking van Greenshot's beeldbewerker trager maken. Merkt u dat de beeldbewerker bij de toepassing van Vervagen traag en sloom wordt, probeer dan de kwaliteit van de voorvertoning in de gereedschapsbalk te verminderen of - verlaag de waarde voor de Vervagings-radius.
    + verlaag de waarde voor de Vervagings-radius.
    Blijft de functie Vervagen traag reageren, probeer dan de functie Pixeleren te gebuiken.

    -

    Effecten toevoegen

    +

    Effecten toepassen

    - U kunt aan uw schermopname verschillende effecten toevoegen. Zo kunt u bijvoorbeeld een lijst toevoegen - of een schaduw of het effect van gescheurde randen om de afbeelding meer nadruk te geven. + U kunt op uw schermopname verschillende effecten toepassen. Zo kunt u de afbeelding meer nadruk te geven door + bijvoorbeeld een lijst of een schaduw of het effect van gescheurde randen toe te voegen. De effecten Grijstinten en Negatief zijn met name nuttig voor het afdrukken en de besparing van inkt of toner bij kleurrijke of donkere schermopnames.

    @@ -262,22 +262,22 @@

    Schermopname bijsnijden

    Als u maar een deel van de schermopname nodig hebt, gebruik dan de functie bijsnijden C - om de overtollige delen weg te snijden.
    - Na het activeren van de functie bijsnijden, tekent u een rechthoek om het gebied van de schermopname dat behouden - moet worden. U kunt de afmetingen van het geselecteerde gebied naar wens aanpassen.
    - Bent u tevreden over het geselecteerde gebied, bevestig het bijsnijden dan in de gereedschapsbalk of type Enter. + om overtollige delen weg te snijden.
    + Teken hiertoe een rechthoek om het gebied van de schermopname dat behouden moet worden. + U kunt de afmetingen van het geselecteerde gebied naar wens aanpassen.
    + Bent u tevreden over het geselecteerde gebied, bevestig het bijsnijden dan in de gereedschapsbalk of toets Enter. U kunt het bijsnijden afbreken met de toets ESC.

    - Automatisch Bijsnijden: Als u een schermopname wilt bijsnijden tot een rand of vlakke achtergrondkleur, + Automatisch bijsnijden: Als u een schermopname wilt bijsnijden tot een rand of vlakke achtergrondkleur, gebruik dan Automatisch bijsnijden in het menu Bewerken en Greenshot zal het bij te snijden gebied automatisch bepalen.

    - Gebruik de functie Roteren om een schermopname linksom of rechtsom te draaien. + Gebruik de functie Draaien om een schermopname linksom of rechtsom te roteren.

    @@ -286,7 +286,7 @@ U kunt eenvoudig afbeeldingen aan een schermopname toevoegen door een afbeeldingsbestand in het venster van de beeldbewerker te slepen. U kunt ook schermopnames van andere vensters invoegen met behulp van de functie Venster invoegen in het menu Bewerken. Een lijst van alle geopende vensters biedt u - de gelegenheid er een te kiezen om in te voegen. + de mogelijkheid er een te kiezen om in te voegen.

    @@ -294,7 +294,7 @@

    Als u regelmatig dezelfde elementen toepast in de bewerking van uw schermopnamen (bijv. een tekstkader met browsertype en versienummer, of het maskeren van hetzelfde - element in verschillende schermopnamen) dan kunt u deze elementen hergebruiken.
    + element in verschillende schermopnamen) dan kunt u deze elementen hergebruiken.
    Kies in het menu Objecten, Objecten opslaan om de huidige elementen op te slaan voor later gebruik. Objecten laden past deze eerder opgeslagen elementen toe op een andere schermopname. @@ -308,15 +308,15 @@ de bovenste gereedschapsbalk of via de sneltoetsen:

    - Er zijn plugins om schermopnamen te exporteren naar andere bestemmingen, zoald DropBox, Picasa, Flickr. - Selecteer de relevante plugins tijdens de installatie van Greenshot. + Er zijn plugins om schermopnamen te exporteren naar andere bestemmingen, zoals DropBox, Picasa, Flickr. + Selecteer de gewenste plugins tijdens de installatie van Greenshot.

    Klik, nadat u de afbeelding hebt opgeslagen, de statusbalk onderaan de beeldbewerker @@ -331,25 +331,25 @@

    Algemene instellingen

    -

    Opname-instellingen

    +

    Schermopname-instellingen

    -

    Resultaat-instellingen

    +

    Uitvoer

    Bestemming

    - Na de schermopname vertoont Greenshot een eenvoudig menu waarmee u zelf een bestemmingsmap kiezen. - Is er geen noodzaak of heeft u geen behoefte om de bestemminsmap aan te passen, - dan kunt Greenshot instellen de schermopnames direct naar meerdrere bestemmingen op te slaan, zonder - tussenkomst van het keuzemenu.
    - Opmerking: Net als bij het exporteren vanuit het beeldbewerkingsvenster, zullen mogelijke bestemmingen - afhangen van de plugins welke met Greenshot zijn geïnstalleerd. + Na de schermopname vertoont Greenshot een eenvoudig menu waarmee u zelf een bestemmingsmap kunt kiezen. + Heeft u geen behoefte om deze aan te passen, dan kunt Greenshot instellen de schermopnames direct naar + meerdrere bestemmingen op te slaan, zonder tussenkomst van het keuzemenu.
    + Opmerking: Net als bij het exporteren van schermopnamen, + zullen beschikbare bestemmingen afhangen van de plugins welke met Greenshot zijn geïnstalleerd.

    Printer-instellingen

    Plugin-instellingen

    - Hier wordt de lijst met geïnstalleerde Greenshot-plugins weergegeven. Selecteer een plugin van de lijst and klik Instellingen + Hier wordt de lijst met geïnstalleerde Greenshot-plugins weergegeven. Selecteer een plugin van de lijst en klik Instellingen om de instellingen van de plugin aan te passen.

    @@ -414,8 +413,8 @@

    U wilt helpen?

    - Op dit moment zoeken we geen hulp bij de ontwikkeling. Maar u kunt wel iets doen om - het Greenshot ontwikkelteam te ondersteunen.
    + Op dit moment zoeken we geen hulp bij de ontwikkeling. + Maar dit betekent niet dat u niets kunt doen om het Greenshot ontwikkelteam te ondersteunen.
    Bij voorbaat dank :)

    @@ -426,8 +425,8 @@ goede software gratis en vrij toegankelijk te houden. Als Greenshot u helpt in uw werkzaamheden, als het u (of uw bedrijf) tijd en geld bespaart, of u vindt het gewoon een fijn programma en - u staat positief tegenover het concept van open source software: Ondersteun ons werk dan met een donatie.
    - Bezoek onze website en lees daar hoe u het Greenshot team kunt ondersteunen:
    + u staat positief tegenover het concept van open source software: Ondersteun ons werk dan met een donatie.
    + Bezoek onze website en lees daar hoe u het Greenshot-team kunt ondersteunen:
    http://getgreenshot.org/support/

    @@ -435,19 +434,19 @@

    Vertel het door

    Bevalt Greenshot u? Vertel het dan door: vertel uw vrienden en collega's over Greenshot. - En ook uw aanhang en achterban ! :)
    - Bespreek Greenshot met goede kritieken in software portals of plaats een verwijzing naar Greenshot in uw blog of op uw website. + En ook uw aanhang en achterban ! :)
    + Bespreek Greenshot met goede kritieken op software portals of plaats een verwijzing naar Greenshot in uw blog of op uw website.

    Maak een vertaling

    - Is Greenshot niet beschikbaar in uw favoriete taal en u denkt dat u software kunt vertalen dan bent u welkom! + Is Greenshot niet beschikbaar in uw favoriete taal en u denkt dat u software kunt vertalen dan bent u van harte welkom! Als geregisteerde gebruiker bij sourceforge.net kunt u uw vertaling in onze - vertalings tracker aanmelden.
    + vertalings tracker aanmelden.
    Voordat u begint is het verstandig om te kijken of Greenshot niet al in de taal vertaald is, zie de downloads pagina. Ook kunt u op onze vertalings tracker kijken. - Het zou namelijk kunnen dat iemand al aan de vertaling werkt of misschien hierover heeft gecommuniceerd.
    + Het zou namelijk kunnen zijn dat iemand al aan de vertaling werkt of misschien hierover heeft gecommuniceerd.
    Merk op dat vertalingen alleen kunnen worden geaccepteerd als ze afkomstig zijn van een geregistreerde sourceforge.net-gebruiker. Wij kunnen niet elke vertaling doorgronden en daarom is het belangrijk dat we diff --git a/Greenshot/Languages/language-installer-uk-UA.xml b/Greenshot/Languages/language-installer-uk-UA.xml index 84ad5b792..d10360622 100644 --- a/Greenshot/Languages/language-installer-uk-UA.xml +++ b/Greenshot/Languages/language-installer-uk-UA.xml @@ -1,4 +1,4 @@ - + Запускати {#ExeName} під час запуску Windows @@ -9,6 +9,6 @@ Плагін OCR (потребує Microsoft Office Document Imaging (MODI)) Плагін Imgur (див.: http://imgur.com) Додаткові мови - Оптимізація продуктивності, це може забрати час. + Оптимізація продуктивності, це може зайняти певний час. diff --git a/Greenshot/Languages/language-nl-NL.xml b/Greenshot/Languages/language-nl-NL.xml index 6b56c3339..77b7e9aab 100644 --- a/Greenshot/Languages/language-nl-NL.xml +++ b/Greenshot/Languages/language-nl-NL.xml @@ -2,10 +2,10 @@ Meld problemen bij - Als Greenshot u bevalt, wilt u ons misschien ondersteunen: + Als Greenshot u bevalt, wilt u ons wellicht ondersteunen: Greenshot wordt uitgegeven door sourceforge.net op Iconen afkomstig van Yusuke Kamiyamane's Fugue (Creative Commons Attribution 3.0 license) - Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + Copyright (C) 2007-2017 Thomas Braun, Jens Klingen, Robin Krom Greenshot komt zonder enige garantie! Dit is gratis software en het staat u vrij het onder bepaalde voorwaarden te verspreiden. Details over de GNU General Public License: Over Greenshot @@ -24,7 +24,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti Een onverwachte fout is opgetreden bij het kopiëren naar het klembord. Greenshot kon niet naar het klembord kopiëren vanwege een blokkade door het proces {0}. Geen klembord-afbeelding gevonden. - Windows Bitmap + Windows Bitmap (BMP) Device Independent Bitmap (DIB) HTML HTML met ingebedde afbeeldingen @@ -53,7 +53,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti Internet Explorer vensteropname Internet Explorer vensteropname uit lijst Laatste schermopname herhalen - Vensteropname + Actief vensteropname Vensteropname uit lijst Greenshot ondersteunen Afsluiten @@ -61,7 +61,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti Afbeeldingsbestand openen Locatie laatste schermopname openen Snelle instellingen - Voorkeuren… + Instellingen… Fout bij het exporteren naar {0}. Probeer het opnieuw. Onder Midden @@ -125,7 +125,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti Cursief Objecten uit bestand laden Vergrotingsfactor - Grootte aanpassen aan schermopname + Canvas aanpassen aan schermopname Maskeren (O) Vervagen Maskeringswijze @@ -140,8 +140,8 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti Afmetingen herstellen Procent Pixels - Linksom roteren (Control + ,) - Rechtsom roteren (Control + .) + Linksom draaien (Control + ,) + Rechtsom draaien (Control + .) Opslaan Objecten in bestand opslaan Opslaan als… @@ -167,15 +167,15 @@ Controleer de toegangsrechten voor de betreffende locatie. De schermopname kon niet worden opgeslagen, kies een andere bestemming. De bestandsnaam of bestemmingsmap is niet geldig. Corrigeer het bestandsnaampatroon en probeer het opnieuw. Expert - Afbeeldingen met minder dan 256 kleuren tot 8 bit reduceren + Afbeeldingen met minder dan 256 kleuren reduceren tot 8 bit Ook op test-versies controleren Klembordformaten Het ${NUM} nummer in de bestandsnaam Ik weet wat ik doe! - Voetnoot bij het afdrukken - Geheugengebruik verminderen ten koste van snelheid (niet aangeraden). - Optimaliseren voor Remote Desktop gebruik - Beeldbewerker weer gebruiken + Voettekst bij het afdrukken + Geheugengebruik verminderen ten koste van snelheid (niet aangeraden) + Optimaliseren voor Remote Desktop-gebruik + Beeldbewerker hergebruiken indien mogelijk Bij het sluiten van de beeldbewerker niet vragen om op te slaan Schermvoorbeelden tonen in het context menu Geëxporteerd: {0} @@ -187,40 +187,40 @@ Controleer de toegangsrechten voor de betreffende locatie. Er is een fout opgetreden bij het afdrukken Afdruk op het papier centreren Afdruk vergroten en aanpassen aan de papiergrootte - Afdruk roteren en aanpassen aan het papier + Afdruk draaien en aanpassen aan het papier Afdruk verkleinen en aanpassen aan de papiergrootte Kleurinstellingen Instellingen opslaan als standaard en niet meer vragen Afdrukken in negatief-kleuren - Papieroriëntatie + Afdrukinstellingen Kleurenafdruk Afdruk in grijstinten - Zwart-witafdruk forceren + Grijstinten forceren Datum / tijd onderaan de pagina afdrukken Greenshot afdrukvoorkeuren Opslaan met de standaardkwaliteit en niet meer vragen Greenshot kwaliteit - Direct opslaan (met de standaardinstellingen) - Afdrukvoorkeuren tonen wanneer een afbeelding wordt afgedrukt - Vraag iedere keer dat een beeld opgeslagen wordt om de beeldkwaliteit + Direct opslaan (met standaardinstellingen) + Afdrukinstellingen tonen wanneer een afbeelding wordt afgedrukt + Bij het opslaan altijd de beeldkwaliteit instellen Programmainstellingen Greenshot met Windows opstarten Schermopname Muisaanwijzer opnemen Interactieve schemopname - Controleren op nieuwe versies [dagen] (0=geen controle) + Interval versiecontrole in dagen (0=geen controle) Instellingen - Bestandslocatie naar het klembord kopiëren wanneer een afbeelding wordt opgeslagen + Bestandslocatie tevens naar het klembord kopiëren Bestemming Naar klembord In beeldbewerker E-mail Direct opslaan (Onderstaande instellingen gebruiken) Opslaan als… (via dialoog) - Bestemming dynamisch kiezen + Bestemming interactief selecteren Naar printer Beeldbewerker - Bestandsnaam patroon + Bestandsnaam Algemeen Internet Explorer vensteropname JPEG-kwaliteit @@ -243,16 +243,16 @@ Voorbeeld: Het patroon ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss} genereert een map voor de huidige dag in uw standaard opslaglocatie, b.v. 2008-06-29, de naam van het bestand bevat dan de tijd , b.v. 11-58-32 (plus de extensie zoals in de voorkeursinstellingen staat) Netwerk en bijwerken - Uitvoer + Opslaan Camerageluid afspelen Plugins - Door + Maker DLL-pad Naam Versie - Voorkeursinstellingen voor opslaan van bestanden + Instellingen voor opslaan van bestanden Afbeeldingsformaat - Printer + Afdrukken Afdrukinstellingen Kwaliteitsinstellingen Kleuren verminderen tot maximaal 256 @@ -267,16 +267,16 @@ genereert een map voor de huidige dag in uw standaard opslaglocatie, b.v. 2008-0 Standaard afbeeldingsformaat Definieert of de sneltoetsen Prnt, Ctrl + Print, Alt + Prnt door Greenshot worden gereserveerd. Standaardlocatie waar schermopnamen worden opgeslagen (leeg laten voor het bureaublad) - De standaard systeem proxy gebruiken + Standaard systeem-proxy gebruiken Effecten Milliseconden vertraging voor schermopname Vensteropname-modus - Vensteropname + Actief vensteropname Klik hier met de rechtermuisknop of druk op de {0} knop. Een nieuwe versie van Greenshot is beschikbaar! Wilt u Greenshot {0} downloaden? Wacht terwijl de Internet Explorer pagina wordt vastgelegd… Waarschuwing - De sneltoetsen "{0}" kunnen worden aangemeld. Dit probleem komt waarschijnlijk doordat een ander programma deze al gebruikt. U kunt de sneltoetsinstellingen van Greenshot aanpassen of het andere programma stoppen/aanpassen. + De sneltoets "{0}" kan niet worden aangemeld. Dit probleem komt waarschijnlijk omdat een ander programma {1} deze al gebruikt! U kunt de sneltoetsinstellingen van Greenshot aanpassen of het andere programma stoppen/aanpassen. Alle Greenshot functies werken ook zonder sneltoetsen via het context menu. Aangepaste kleur diff --git a/Greenshot/Languages/language-uk-UA.xml b/Greenshot/Languages/language-uk-UA.xml index f238d536c..f05ffd078 100644 --- a/Greenshot/Languages/language-uk-UA.xml +++ b/Greenshot/Languages/language-uk-UA.xml @@ -1,12 +1,12 @@ - + Про помилки повідомляйте на - Якщо Вам подобається Greenshot, то можете підтримати нас: - Greenshot is розташовується на GitHub - Набір іконок Fugue від Yusuke Kamiyamane (ліцензія Creative Commons Attribution 3.0) + Якщо Вам подобається Greenshot, можете підтримати нас: + Greenshot розташовується на GitHub + Набір піктограм Fugue від Yusuke Kamiyamane (ліцензія Creative Commons Attribution 3.0) Авторство © 2007-2016 Thomas Braun, Jens Klingen, Robin Krom -Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. Це вільне програмне забезпечення, Ви можете розповсюджувати його за певних умов. +Greenshot постачається АБСОЛЮТНО БЕЗ ГАРАНТІЇ. Це вільне програмне забезпечення, Ви можете розповсюджувати його за певних умов. Подробиці Загальної Публічної Ліцензії GNU: Про Greenshot Greenshot – революційна утиліта для отримання знімків екрану @@ -37,12 +37,12 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. Червоний Вибір кольору Прозорий - Призначення {0} відхилило доступ Greenshot, можливо через відкрите діалогове вікно. Зайкрийте діалогове вікно та спробуйте знову. + Призначення {0} відхилило доступ Greenshot, можливо через відкрите діалогове вікно. Закрийте діалогове вікно та спробуйте знову. Доступ Greenshot відхилено Неможливо зберегти файл налаштувань Greenshot. Будь ласка, перевірте доступ до „{0}“. Про Greenshot - Захоплення області - Відкрити зображення з буферу обміну + Захопити область + Відкрити зображення з буфера обміну Захопити весь екран все знизу @@ -51,8 +51,8 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. згори Захопити Internet Explorer Захопити Internet Explorer зі списку - Захоплення останньої області - Захоплення вікна + Захопити останню область + Захопити вікно Захопити вікно зі списку Підтримати Greenshot Вихід @@ -61,7 +61,7 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. Відкрити місце збереження останнього знімку Швидкі параметри Параметри... - Помилка експорту {0}. Будь ласка, спробуйте ще. + Помилка експорту до {0}. Спробуйте знову. Знизу По центру Горизонтальне вирівнювання @@ -130,11 +130,11 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. Режим затемнення Пікселізація Об’єкт - Відкрити катлог у Провіднику Windows + Відкрити каталог у Провіднику Windows Вставити - Розмір піксела - Якість попереднього перегляду - Роздрукувати + Розмір пікселя + Якість перегляду + Друк Повторити {0} Скинути розмір відсотків @@ -144,7 +144,7 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. Зберегти Зберегти об’єкти в файл Зберегти як... - Виділити все + Вибрати все Завдання друку надіслано на „{0}“. Тінь Зображення надіслано в буфер обміну. @@ -164,6 +164,7 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ҐАРАНТІЇ. Неможливо відкрити файл „{0}“. Неможливо відкрити посилання „{0}“. Неможливо зберегти знімок. Будь ласка, знайдіть відповідне місце. + Згенерована назва файла чи теки неприпустима. Будь ласка, виправте шаблон назви файла та спробуйте ще. Експертні Створити 8-бітне зображення, якщо більш ніж 8-бітне має менше 256 кольорів Перевірити наявність нестабільних оновлень @@ -238,7 +239,8 @@ ${hostname} назва комп’ютера Ви також можете примусити Greenshot створювати динамічні каталоги, просто використовуючи символ похилої риски (\) як роздільник між теками та назвою файла. Наприклад, шаблон ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss} -створюватиме у стандартній теці теку для поточного дня (наприклад, 2012-01-27), в якій будуть знімки з назвою файла, що базуватиметься на поточному часі (наприклад, 11_58_32) (плюс зазначене у параметрах розширення). +створюватиме у стандартній теці теку для поточного дня (наприклад, 2012-01-27), в якій будуть знімки з назвою файла, що базуватиметься на поточному +часі (наприклад, 11_58_32) (плюс зазначене у параметрах розширення). Мережа та оновлення Виведення Відтворити звук камери @@ -273,9 +275,9 @@ ${hostname} назва комп’ютера Доступна новіша версія Greenshot! Чи хочете Ви завантажити Greenshot {0}? Будь ласка, зачекайте поки захоплюється сторінка в Internet Explorer... Попередження - Неможливо зареєструвати гарячі клавіші „{0}“. Можливо, вони вже використовуються іншою програмою! Ви можете змінити гарячі клавіші або вимкнути/змінити програму, що використовує такі ж комбінації клавіш. + Неможливо зареєструвати гарячі клавіші „{0}“. Можливо, вони вже використовуються іншою програмою {1}! Ви можете змінити гарячі клавіші або вимкнути/змінити програму, що використовує такі ж комбінації клавіш. -Всі функції Greenshot досі працюють безпосередньо з контекстного меню іконки у лотку без застосування гарячих клавіш. +Всі функції Greenshot досі працюють безпосередньо з контекстного меню піктограми в системні панелі без застосування гарячих клавіш. Використовувати користувацький колір Зберігати прозорість Автоматично @@ -307,7 +309,7 @@ ${hostname} назва комп’ютера Зберігати пропорції Ширина Висота - Розмір іконки + Розмір піктограми diff --git a/Greenshot/Languages/language-website-uk-UA.xml b/Greenshot/Languages/language-website-uk-UA.xml index c710c0eb7..ef3dfe65c 100644 --- a/Greenshot/Languages/language-website-uk-UA.xml +++ b/Greenshot/Languages/language-website-uk-UA.xml @@ -1,4 +1,4 @@ - + Завантаження @@ -12,8 +12,8 @@ Швидке створення знімків вибраної області, вікна або всього екрану; Ви навіть можете захоплювати всю (з прокручуванням) Інтернет-сторінку в Internet Explorer. Легке коментування, підсвічування або виділення частин знімку. Greenshot — це невеличка програма для створення знімків екрану для Windows з такими основними можливостями: - ...та чимало інших можливостей, що спрощують свторення та обробку знімків. - Кілька варіантів експорту знімків: збереження в файл, друк, копіювання в буфер обміну, долучення до електронного листа, надсилання до офісних програм або вивантаження на фото-хостинги штибу Flickr або Picasa тощо. - Будучи зручним в налаштуванні та розумінні, Greenshot є ефективним інструментом для менеджерів проектів, розробників програмного забезепечення, технарів-письменників, тестерів та будь-кого іншого, кому потрібно створювати знімки. + ...та чимало інших можливостей, що спрощують створення та обробку знімків. + Кілька варіантів експорту знімків: збереження в файл, друк, копіювання в буфер обміну, долучення до електронного листа, надсилання до офісних програм або вивантаження на фото-хостинги на зразок Flickr, Picasa та інші. + Завдяки простоті налаштування та інтуїтивності, Greenshot є ефективним інструментом для керівників проектів, розробників програмного забезпечення, технічних авторів, тестерів та будь-кого іншого, кому потрібно створювати знімки. - \ No newline at end of file + diff --git a/Greenshot/releases/additional_files/readme.txt.template b/Greenshot/releases/additional_files/readme.txt.template index 802efa9fa..af435f2b2 100644 --- a/Greenshot/releases/additional_files/readme.txt.template +++ b/Greenshot/releases/additional_files/readme.txt.template @@ -9,6 +9,23 @@ All details to our tickets can be found here: https://greenshot.atlassian.net @DETAILVERSION@ +Bugs fixed: +* [BUG-2235] - Imgur authentication issues due to imgur api change +* [BUG-2227] - NullReferenceException when accessing the Imgur History +* [BUG-2225] - NullReferenceException when changing the color of text +* [BUG-2219] - Korean is spelled incorrectly in the installer +* [BUG-2213] - NullReferenceException in the Freehand tool +* [BUG-2203] - ArgumentNullException in the Freehand tool +* [BUG-2141] - Imgur authentication issues due to old embedded IE +* [BUG-2172] - NullReferenceException when using the speech bubble +* [BUG-2246] - Login issues with the Atlassian Jira Cloud + +Features: +* [FEATURE-1064] - Added CTRL+Backspace & CTRL+A to the text tool + + +Greenshot 1.2.9.129-569de71 RELEASE + Bugs fixed: * [BUG-2051] - Scroll-lock button not usable as hotkey * [BUG-2056] - Cannot export to external command Paint.NET if .greenshot format is used diff --git a/Greenshot/releases/innosetup/setup.iss.template b/Greenshot/releases/innosetup/setup.iss.template index 9c7db6920..55449f635 100644 --- a/Greenshot/releases/innosetup/setup.iss.template +++ b/Greenshot/releases/innosetup/setup.iss.template @@ -391,7 +391,7 @@ Name: "languages\huHU"; Description: "Magyar"; Types: full custom; Flags: disabl Name: "languages\idID"; Description: "Bahasa Indonesia"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1') Name: "languages\itIT"; Description: "Italiano"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1') Name: "languages\jaJP"; Description: "日本語"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('7') -Name: "languages\koKR"; Description: "한국의"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('8') +Name: "languages\koKR"; Description: "한국어"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('8') Name: "languages\kabDZ"; Description: "Taqbaylit"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('8') Name: "languages\ltLT"; Description: "Lietuvių"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('3') Name: "languages\lvLV"; Description: "Latviski"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('3') diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs index ec1d41b9e..00af89c19 100644 --- a/GreenshotImgurPlugin/ImgurPlugin.cs +++ b/GreenshotImgurPlugin/ImgurPlugin.cs @@ -123,9 +123,14 @@ namespace GreenshotImgurPlugin { } private void UpdateHistoryMenuItem() { - try { + if (_historyMenuItem == null) + { + return; + } + try + { _host.GreenshotForm.BeginInvoke((MethodInvoker)delegate { - if (_config.ImgurUploadHistory.Count > 0) { + if (_config.ImgurUploadHistory != null && _config.ImgurUploadHistory.Count > 0) { _historyMenuItem.Enabled = true; } else { _historyMenuItem.Enabled = false; diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index 95bbfc806..c2f002ccc 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -36,7 +36,7 @@ namespace GreenshotImgurPlugin { private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils)); private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg"; private static readonly ImgurConfiguration Config = IniConfig.GetIniSection(); - private const string AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}"; + private const string AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}"; private const string TokenUrl = "https://api.imgur.com/oauth2/token"; ///

    diff --git a/GreenshotJiraPlugin/JiraConnector.cs b/GreenshotJiraPlugin/JiraConnector.cs index 6d9c933f3..c786f4b46 100644 --- a/GreenshotJiraPlugin/JiraConnector.cs +++ b/GreenshotJiraPlugin/JiraConnector.cs @@ -107,10 +107,9 @@ namespace GreenshotJiraPlugin { _jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height }); _issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient); - LoginInfo loginInfo; try { - loginInfo = await _jiraClient.Session.StartAsync(user, password, cancellationToken); + await _jiraClient.Session.StartAsync(user, password, cancellationToken); Monitor = new JiraMonitor(); await Monitor.AddJiraInstanceAsync(_jiraClient, cancellationToken); @@ -129,7 +128,7 @@ namespace GreenshotJiraPlugin { { return false; } - return loginInfo != null; + return true; } /// diff --git a/GreenshotPlugin/Controls/OAuthLoginForm.cs b/GreenshotPlugin/Controls/OAuthLoginForm.cs index 3f370b543..a3c5ffea2 100644 --- a/GreenshotPlugin/Controls/OAuthLoginForm.cs +++ b/GreenshotPlugin/Controls/OAuthLoginForm.cs @@ -39,6 +39,9 @@ namespace GreenshotPlugin.Controls { public bool IsOk => DialogResult == DialogResult.OK; public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) { + // Make sure Greenshot uses the correct browser version + IEHelper.FixBrowserVersion(false); + _callbackUrl = callbackUrl; // Fix for BUG-2071 if (callbackUrl.EndsWith("/")) @@ -85,7 +88,9 @@ namespace GreenshotPlugin.Controls { private void CheckUrl() { if (_browser.Url.ToString().StartsWith(_callbackUrl)) { - string queryParams = _browser.Url.Query; + var correctedUri = new Uri(_browser.Url.AbsoluteUri.Replace("#", "&")); + + string queryParams = correctedUri.Query; if (queryParams.Length > 0) { queryParams = NetworkHelper.UrlDecode(queryParams); //Store the Token and Token Secret diff --git a/GreenshotPlugin/Core/IEHelper.cs b/GreenshotPlugin/Core/IEHelper.cs index 01a806422..92ffa2816 100644 --- a/GreenshotPlugin/Core/IEHelper.cs +++ b/GreenshotPlugin/Core/IEHelper.cs @@ -18,7 +18,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using System; using System.Collections.Generic; +using System.IO; +using System.Reflection; +using log4net; using Microsoft.Win32; namespace GreenshotPlugin.Core { @@ -26,24 +31,124 @@ namespace GreenshotPlugin.Core { /// Description of IEHelper. /// public static class IEHelper { + private static readonly ILog Log = LogManager.GetLogger(typeof(IEHelper)); // Internet explorer Registry key - private const string IE_KEY = @"Software\Microsoft\Internet Explorer"; + private const string IeKey = @"Software\Microsoft\Internet Explorer"; + /// - /// Helper method to get the IE version + /// Get the current browser version /// - /// - public static int IEVersion() { - int version = 7; - // Seeing if IE 9 is used, here we need another offset! - using (RegistryKey ieKey = Registry.LocalMachine.OpenSubKey(IE_KEY, false)) { - object versionKey = ieKey?.GetValue("Version"); - if (versionKey != null) { - int.TryParse(versionKey.ToString().Substring(0,1), out version); + /// int with browser version + public static int IEVersion + { + get + { + var maxVer = 7; + using (var ieKey = Registry.LocalMachine.OpenSubKey(IeKey, false)) + { + foreach (var value in new[] { "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" }) + { + var objVal = ieKey.GetValue(value, "0"); + var strVal = Convert.ToString(objVal); + + var iPos = strVal.IndexOf('.'); + if (iPos > 0) + { + strVal = strVal.Substring(0, iPos); + } + + int res; + if (int.TryParse(strVal, out res)) + { + maxVer = Math.Max(maxVer, res); + } + } } + + return maxVer; } - return version; } - + + /// + /// Get the highest possible version for the embedded browser + /// + /// true to ignore the doctype when loading a page + /// IE Feature + public static int GetEmbVersion(bool ignoreDoctype = true) + { + var ieVersion = IEVersion; + + if (ieVersion > 9) + { + return ieVersion * 1000 + (ignoreDoctype ? 1 : 0); + } + + if (ieVersion > 7) + { + return ieVersion * 1111; + } + + return 7000; + } + + /// + /// Fix browser version to the highest possible + /// + /// true to ignore the doctype when loading a page + public static void FixBrowserVersion(bool ignoreDoctype = true) + { + var applicationName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); + FixBrowserVersion(applicationName, ignoreDoctype); + } + + /// + /// Fix the browser version for the specified application + /// + /// Name of the process + /// true to ignore the doctype when loading a page + public static void FixBrowserVersion(string applicationName, bool ignoreDoctype = true) + { + FixBrowserVersion(applicationName, GetEmbVersion(ignoreDoctype)); + } + + /// + /// Fix the browser version for the specified application + /// + /// Name of the process + /// + /// Version, see + /// Browser Emulation + /// + public static void FixBrowserVersion(string applicationName, int ieVersion) + { + ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".exe", ieVersion); +#if DEBUG + ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".vshost.exe", ieVersion); +#endif + } + + /// + /// Make the change to the registry + /// + /// HKEY_CURRENT_USER or something + /// Name of the executable + /// Version to use + private static void ModifyRegistry(string root, string applicationName, int ieFeatureVersion) + { + var regKey = root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"; + try + { + Registry.SetValue(regKey, applicationName, ieFeatureVersion); + } + catch (Exception ex) + { + // some config will hit access rights exceptions + // this is why we try with both LOCAL_MACHINE and CURRENT_USER + Log.Error(ex); + Log.ErrorFormat("couldn't modify the registry key {0}", regKey); + } + } + /// /// Find the DirectUI window for MSAA (Accessible) /// @@ -55,7 +160,7 @@ namespace GreenshotPlugin.Core { } WindowDetails tmpWd = browserWindowDetails; // Since IE 9 the TabBandClass is less deep! - if (IEVersion() < 9) { + if (IEVersion < 9) { tmpWd = tmpWd.GetChild("CommandBarClass"); tmpWd = tmpWd?.GetChild("ReBarWindow32"); } diff --git a/GreenshotPlugin/Core/ImageOutput.cs b/GreenshotPlugin/Core/ImageOutput.cs index cbd4cec9b..125ec0dda 100644 --- a/GreenshotPlugin/Core/ImageOutput.cs +++ b/GreenshotPlugin/Core/ImageOutput.cs @@ -127,26 +127,20 @@ namespace GreenshotPlugin.Core { imageFormat = ImageFormat.Icon; break; default: - // Problem with non-seekable streams most likely doesn't happen with Windows 7 (OS Version 6.1 and later) - // http://stackoverflow.com/questions/8349260/generic-gdi-error-on-one-machine-but-not-the-other - if (!stream.CanSeek) { - if (!Environment.OSVersion.IsWindows7OrLater()) - { - useMemoryStream = true; - Log.Warn("Using memorystream prevent an issue with saving to a non seekable stream."); - } - } imageFormat = ImageFormat.Png; break; } Log.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat); - // Check if we want to use a memory stream, to prevent a issue which happens with Windows before "7". + // Check if we want to use a memory stream, to prevent issues with non seakable streams // The save is made to the targetStream, this is directed to either the MemoryStream or the original Stream targetStream = stream; - if (useMemoryStream) { - memoryStream = new MemoryStream(); - targetStream = memoryStream; + if (!stream.CanSeek) + { + useMemoryStream = true; + Log.Warn("Using memorystream prevent an issue with saving to a non seekable stream."); + memoryStream = new MemoryStream(); + targetStream = memoryStream; } if (Equals(imageFormat, ImageFormat.Jpeg)) @@ -213,18 +207,20 @@ namespace GreenshotPlugin.Core { } // Output the surface elements, size and marker to the stream - if (outputSettings.Format == OutputFormat.greenshot) { - using (MemoryStream tmpStream = new MemoryStream()) { - long bytesWritten = surface.SaveElementsToStream(tmpStream); - using (BinaryWriter writer = new BinaryWriter(tmpStream)) { - writer.Write(bytesWritten); - Version v = Assembly.GetExecutingAssembly().GetName().Version; - byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}"); - writer.Write(marker); - tmpStream.WriteTo(stream); - } - } - } + if (outputSettings.Format != OutputFormat.greenshot) + { + return; + } + using (MemoryStream tmpStream = new MemoryStream()) { + long bytesWritten = surface.SaveElementsToStream(tmpStream); + using (BinaryWriter writer = new BinaryWriter(tmpStream)) { + writer.Write(bytesWritten); + Version v = Assembly.GetExecutingAssembly().GetName().Version; + byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}"); + writer.Write(marker); + tmpStream.WriteTo(stream); + } + } } finally { diff --git a/GreenshotPlugin/Core/Language.cs b/GreenshotPlugin/Core/Language.cs index 024f40055..986623659 100644 --- a/GreenshotPlugin/Core/Language.cs +++ b/GreenshotPlugin/Core/Language.cs @@ -44,7 +44,7 @@ namespace GreenshotPlugin.Core { private const string LanguageFilenamePattern = @"language*.xml"; private static readonly Regex PrefixRegexp = new Regex(@"language_([a-zA-Z0-9]+).*"); private static readonly Regex IetfCleanRegexp = new Regex(@"[^a-zA-Z]+"); - private static readonly Regex IetfRegexp = new Regex(@"^.*([a-zA-Z]{2,3}-[a-zA-Z]{2})\.xml$"); + private static readonly Regex IetfRegexp = new Regex(@"^.*([a-zA-Z]{2,3}-[a-zA-Z]{1,2})\.xml$"); private const string LanguageGroupsKey = @"SYSTEM\CurrentControlSet\Control\Nls\Language Groups"; private static readonly IList UnsupportedLanguageGroups = new List(); private static readonly IDictionary Resources = new Dictionary(); diff --git a/GreenshotPlugin/Core/OAuthHelper.cs b/GreenshotPlugin/Core/OAuthHelper.cs index 6a34c58d9..eb0f90353 100644 --- a/GreenshotPlugin/Core/OAuthHelper.cs +++ b/GreenshotPlugin/Core/OAuthHelper.cs @@ -1002,16 +1002,59 @@ Greenshot received information from CloudServiceName. You can close this browser // "expires_in":3920, // "token_type":"Bearer", // "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" - settings.AccessToken = (string)refreshTokenResult[AccessToken]; - settings.RefreshToken = (string)refreshTokenResult[RefreshToken]; - - object seconds = refreshTokenResult[ExpiresIn]; - if (seconds != null) { - settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds); + if (refreshTokenResult.ContainsKey(AccessToken)) + { + settings.AccessToken = (string)refreshTokenResult[AccessToken]; + } + if (refreshTokenResult.ContainsKey(RefreshToken)) + { + settings.RefreshToken = (string)refreshTokenResult[RefreshToken]; + } + if (refreshTokenResult.ContainsKey(ExpiresIn)) + { + object seconds = refreshTokenResult[ExpiresIn]; + if (seconds != null) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds); + } } settings.Code = null; } + /// + /// Used to update the settings with the callback information + /// + /// OAuth2Settings + /// IDictionary + /// true if the access token is already in the callback + private static bool UpdateFromCallback(OAuth2Settings settings, IDictionary callbackParameters) + { + if (!callbackParameters.ContainsKey(AccessToken)) + { + return false; + } + if (callbackParameters.ContainsKey(RefreshToken)) + { + // Refresh the refresh token :) + settings.RefreshToken = callbackParameters[RefreshToken]; + } + if (callbackParameters.ContainsKey(ExpiresIn)) + { + var expiresIn = callbackParameters[ExpiresIn]; + settings.AccessTokenExpires = DateTimeOffset.MaxValue; + if (expiresIn != null) + { + double seconds; + if (double.TryParse(expiresIn, out seconds)) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds(seconds); + } + } + } + settings.AccessToken = callbackParameters[AccessToken]; + return true; + } + /// /// Go out and retrieve a new access token via refresh-token with the TokenUrl in the settings /// Will upate the access token, refresh token, expire date @@ -1054,16 +1097,22 @@ Greenshot received information from CloudServiceName. You can close this browser } } - settings.AccessToken = (string)accessTokenResult[AccessToken]; + if (accessTokenResult.ContainsKey(AccessToken)) + { + settings.AccessToken = (string) accessTokenResult[AccessToken]; + settings.AccessTokenExpires = DateTimeOffset.MaxValue; + } if (accessTokenResult.ContainsKey(RefreshToken)) { // Refresh the refresh token :) settings.RefreshToken = (string)accessTokenResult[RefreshToken]; } - object seconds = accessTokenResult[ExpiresIn]; - if (seconds != null) { - settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds); - } else { - settings.AccessTokenExpires = DateTimeOffset.MaxValue; + if (accessTokenResult.ContainsKey(ExpiresIn)) + { + object seconds = accessTokenResult[ExpiresIn]; + if (seconds != null) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double) seconds); + } } } @@ -1109,6 +1158,7 @@ Greenshot received information from CloudServiceName. You can close this browser GenerateRefreshToken(settings); return true; } + return UpdateFromCallback(settings, loginForm.CallbackParameters); } return false; } diff --git a/appveyor12.yml b/appveyor12.yml index d2613de6f..112aff0be 100644 --- a/appveyor12.yml +++ b/appveyor12.yml @@ -1,7 +1,7 @@ -version: 1.2.9.{build} +version: 1.2.10.{build} branches: only: - - release/1.2.9BF2 + - release/1.2.10 skip_tags: true configuration: Release platform: Any CPU