protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs E) { void AddCustomStroke(Stroke CustomStroke) { Strokes.Remove(E.Stroke); // Remove two history items if (DataContext is ImageEditorViewModel vm) { vm.RemoveLastHistory(); vm.RemoveLastHistory(); } Strokes.Add(CustomStroke); var args = new InkCanvasStrokeCollectedEventArgs(CustomStroke); base.OnStrokeCollected(args); } if (DynamicRenderer is IDynamicRenderer renderer) { AddCustomStroke(renderer.GetStroke(E.Stroke.StylusPoints, E.Stroke.DrawingAttributes)); } else { base.OnStrokeCollected(E); } }
public void Cut() { if (SelectedStrokesIds.Count == 0) { return; } Clipboard = new StrokeList(SelectedStrokes); Clipboard.ForEach(x => Strokes.Remove(x)); SelectedStrokesIds.Clear(); EditingMode = InkCanvasEditingMode.Select; }
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e) { Strokes.Remove(e.Stroke); var customStroke = new SmoothableStroke(e.Stroke.GetBezierStylusPoints()); Strokes.Add(customStroke); InkCanvasStrokeCollectedEventArgs args = new InkCanvasStrokeCollectedEventArgs(customStroke); base.OnStrokeCollected(args); }
public void Undo() { lock (StrokesLock) { var currentUserLatestStroke = StrokeCollection.GetMergedStrokeMaps()?.FindLast(x => x.AuthorId == UserId); if (currentUserLatestStroke == null) { return; } Strokes.Remove(currentUserLatestStroke); StrokeCollection.UpdateStroke(currentUserLatestStroke.Id, null); UndoneStrokes.Push(currentUserLatestStroke); } }
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs E) { void AddCustomStroke(Stroke CustomStroke) { Strokes.Remove(E.Stroke); // Remove two history items if (DataContext is ImageEditorViewModel vm) { vm.RemoveLastHistory(); vm.RemoveLastHistory(); } Strokes.Add(CustomStroke); var args = new InkCanvasStrokeCollectedEventArgs(CustomStroke); base.OnStrokeCollected(args); } switch (DynamicRenderer) { case LineDynamicRenderer _: AddCustomStroke(new Stroke(new StylusPointCollection(new [] { E.Stroke.StylusPoints.First(), E.Stroke.StylusPoints.Last() }), E.Stroke.DrawingAttributes)); break; case RectangleDynamicRenderer _: AddCustomStroke(new RectangleStroke(E.Stroke.StylusPoints, E.Stroke.DrawingAttributes)); break; case EllipseDynamicRenderer _: AddCustomStroke(new EllipseStroke(E.Stroke.StylusPoints, E.Stroke.DrawingAttributes)); break; default: base.OnStrokeCollected(E); break; } }
public DrawingRoomViewModel(Chat chat) { this.chat = chat; strokes = new StrokeCollection(); chat.OnStrokeRecieved += StrokeHandle; NewStrokeCommand = new RelayCommand(x => { var stroke = Strokes.LastOrDefault(); Strokes.Remove(stroke); chat.Send(stroke); //MessageBox.Show(stroke?.ToString()); }); InkCanvasDrawingAttributes = new DrawingAttributes(); InkCanvasDrawingAttributes.Color = Color.FromArgb(255, 0, 0, 0); InkCanvasDrawingAttributes.Height = 3; InkCanvasDrawingAttributes.Width = 3; OnPropertyChanged("InkCanvasDrawingAttributes"); }
/// <summary> /// Helper method that performs a hit test using the specified point. /// It deletes all strokes that were hit by the point /// </summary> /// <param name="pt">The point to use for hit testing</param> private void EraseStrokes(Point pt, Stroke currentStroke) { // Use HitTest to find the collection of strokes that are intersected // by the point. The HitTestRadius constant is used to specify the // radius of the hit test circle in ink space coordinates (1 unit = .01mm). Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius); if (null != currentStroke && strokesHit.Contains(currentStroke)) { strokesHit.Remove(currentStroke); } // Delete all strokes that were hit by the point myInkCollector.Ink.DeleteStrokes(strokesHit); if (strokesHit.Count > 0) { // Repaint the screen to reflect the change this.Refresh(); } }
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs E) { void AddCustomStroke(Stroke CustomStroke) { Strokes.Remove(E.Stroke); Strokes.Add(CustomStroke); var args = new InkCanvasStrokeCollectedEventArgs(CustomStroke); base.OnStrokeCollected(args); } if (DynamicRenderer is IDynamicRenderer renderer) { AddCustomStroke(renderer.GetStroke(E.Stroke.StylusPoints, E.Stroke.DrawingAttributes)); } else { base.OnStrokeCollected(E); } }
/// <summary> /// Undo edit actions performed /// </summary> internal void Undo() { int index = undoActions.Count - 1; if (index < 0) { return; } if (undoActions[index] == InkCanvasEditingMode.Ink) { Strokes.RemoveAt(Strokes.Count - 1); } else if (undoActions[index] == InkCanvasEditingMode.EraseByStroke) { Strokes.Add(undoStrokes[index]); } else if (undoActions[index] == InkCanvasEditingMode.None) { for (int i = 0; i < index; i++) { if (undoActions[i] == InkCanvasEditingMode.Ink) { Strokes.Add(undoStrokes[i]); } else if (undoActions[i] == InkCanvasEditingMode.EraseByStroke) { Strokes.Remove(undoStrokes[i]); } else if (undoActions[i] == InkCanvasEditingMode.None) { Strokes.Clear(); } } } redoActions.Add(undoActions[index]); redoStrokes.Add(undoStrokes[index]); undoActions.RemoveAt(index); undoStrokes.RemoveAt(index); }
public void Paint(Graphics g, Rectangle bounds) { // Lock the sheet and strokes using (Synchronizer.Lock(this.m_Sheet.SyncRoot)) { using (Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) { if (this.m_Sheet.Ink.Strokes.Count <= 0) { return; } // Make a copy of the set of all strokes to be painted. // The selected strokes will be removed from this and painted separately. Strokes strokes = this.m_Sheet.Ink.Strokes; Strokes selection = this.m_Sheet.Selection; if (selection != null) { strokes.Remove(selection); } // Create an image using temporary graphics and graphics buffer object Bitmap imageForPrinting = new Bitmap(bounds.Width, bounds.Height); using (Graphics graphicsImage = Graphics.FromImage(imageForPrinting)) using (DibGraphicsBuffer dib = new DibGraphicsBuffer()) { // Create temporary screen Graphics System.Windows.Forms.Form tempForm = new System.Windows.Forms.Form(); Graphics screenGraphics = tempForm.CreateGraphics(); // Create temporary Graphics from the Device Independent Bitmap using (Graphics graphicsTemp = dib.RequestBuffer(screenGraphics, bounds.Width, bounds.Height)) { graphicsTemp.Clear(System.Drawing.Color.Transparent); // Draw the unselected ink! // (Ink is not a published property of the InkSheetModel, so no need to obtain a lock.) this.m_Renderer.Draw(graphicsTemp, strokes); if (selection != null) { // Draw each stroke individually, adjusting its DrawingAttributes. // TODO: This is very inefficient compared to drawing them all as a group (make a selection of several hundred strokes to see -- a big slow-down). foreach (Stroke stroke in selection) { // It's possible to erase ink while it's selected, // either with the inverted end of the stylus or via the Undo service. // But even though the deleted ink won't be part of the main Ink.Strokes collection, // it won't have been removed from the selection Strokes collection. // TODO: Being able to delete strokes while they are selected might break more than this. // Evaluate what needs to change in the eraser and undo service to make this less hacky. if (stroke.Deleted) { continue; } // First draw a highlighted background for all the strokes. DrawingAttributes atts = stroke.DrawingAttributes.Clone(); float width = atts.Width, height = atts.Height; atts.RasterOperation = RasterOperation.CopyPen; atts.Color = SystemColors.Highlight; atts.Width += SELECTED_BORDER_WIDTH__HIMETRIC; atts.Height += SELECTED_BORDER_WIDTH__HIMETRIC; this.m_Renderer.Draw(graphicsTemp, stroke, atts); } foreach (Stroke stroke in selection) { if (stroke.Deleted) { continue; } // Second, draw the stroke itself, but with a contrastive color. DrawingAttributes atts = stroke.DrawingAttributes.Clone(); atts.RasterOperation = RasterOperation.CopyPen; atts.Color = SystemColors.HighlightText; this.m_Renderer.Draw(graphicsTemp, stroke, atts); } } // Use the buffer to paint onto the final image dib.PaintBuffer(graphicsImage, 0, 0); // Draw this image onto the printer graphics, // adjusting for printer margins g.DrawImage(imageForPrinting, bounds.Top, bounds.Left); } } } } }
public override void Paint(PaintEventArgs args) { using (Synchronizer.Lock(this.m_Sheet.SyncRoot)) { using (Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) { if (this.m_Sheet.Ink.Strokes.Count <= 0) { return; } Graphics g = args.Graphics; // Make a copy of the set of all strokes to be painted. // The selected strokes will be removed from this and painted separately. Strokes strokes = this.m_Sheet.Ink.Strokes; Strokes selection = this.m_Sheet.Selection; if (selection != null) { strokes.Remove(selection); } // Note: The Renderer.Draw(Graphics,...) method is buggy (as of TabletPC API version 1.7), // and it causes all sorts of corruption when used in conjunction with double-buffering. // The problem is actually due to the renderer not restoring the state of the DC when it // is finished (specifically due to not resetting the the clipping region, AFAICT). // The workaround is to save and restore the state of the DC ourselves, and also to set // the clip rectangle manually via some Win32 GDI interop calls. IntPtr rgn = g.Clip.GetHrgn(g); IntPtr hdc = g.GetHdc(); try { int saved = SaveDC(hdc); try { // Copy the clip region from the Graphics object to the DC. SelectClipRgn(hdc, rgn); // Draw the unselected ink! // (Ink is not a published property of the InkSheetModel, so no need to obtain a lock.) this.m_Renderer.Draw(hdc, strokes); if (selection != null) { // Draw each stroke individually, adjusting its DrawingAttributes. // TODO: This is very inefficient compared to drawing them all as a group (make a selection of several hundred strokes to see -- a big slow-down). foreach (Stroke stroke in selection) { // It's possible to erase ink while it's selected, // either with the inverted end of the stylus or via the Undo service. // But even though the deleted ink won't be part of the main Ink.Strokes collection, // it won't have been removed from the selection Strokes collection. // TODO: Being able to delete strokes while they are selected might break more than this. // Evaluate what needs to change in the eraser and undo service to make this less hacky. if (stroke.Deleted) { continue; } // First draw a highlighted background for all the strokes. DrawingAttributes atts = stroke.DrawingAttributes.Clone(); float width = atts.Width, height = atts.Height; atts.RasterOperation = RasterOperation.CopyPen; atts.Color = SystemColors.Highlight; atts.Width += SELECTED_BORDER_WIDTH__HIMETRIC; atts.Height += SELECTED_BORDER_WIDTH__HIMETRIC; this.m_Renderer.Draw(hdc, stroke, atts); } foreach (Stroke stroke in selection) { if (stroke.Deleted) { continue; } // Second, draw the stroke itself, but with a contrastive color. DrawingAttributes atts = stroke.DrawingAttributes.Clone(); atts.RasterOperation = RasterOperation.CopyPen; atts.Color = SystemColors.HighlightText; this.m_Renderer.Draw(hdc, stroke, atts); } } } finally { RestoreDC(hdc, saved); } } finally { g.ReleaseHdc(hdc); if (rgn != IntPtr.Zero) { g.Clip.ReleaseHrgn(rgn); } } } } }