Laggy snipping tool - c#

I'm trying to create snipping tool like this one https://app.prntscr.com/en/index.html. I'm able to modify some codes and managed to show resize handles with selected rectangle(snip), handles work fine and i can move the selected rectangle and resize it. But when I compare it with tool mentioned above it is very slow, can someone point some problems in my code to make it fast?
The tool i'm making look like this:
/*
* Credit for this portion of Imgur Snipping Tool goes to Hans Passant from stackoverflow.com
* http://stackoverflow.com/questions/3123776/net-equivalent-of-snipping-tool
*
* Modified to work with multiple monitors.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Free_Snipping_Tool.Classes;
namespace Free_Snipping_Tool
{
public partial class SnippingTool2 : Form
{
public enum ScreenshotType
{
FULL, ACTIVE, DEFINED
}
private int oldX;
private int oldY;
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
Rectangle topLeft = new Rectangle();
Rectangle topMiddle = new Rectangle();
Rectangle topRight = new Rectangle();
Rectangle bottomLeft = new Rectangle();
Rectangle bottomMiddle = new Rectangle();
Rectangle bottomRight = new Rectangle();
Rectangle leftMiddle = new Rectangle();
Rectangle rightMiddle = new Rectangle();
bool topLeftSelected = false;
bool topMiddleSelected = false;
bool topRightSelected = false;
bool bottomLeftSelected = false;
bool bottomMiddleSelected = false;
bool bottomRightSelected = false;
bool leftMiddleSelected = false;
bool rightMiddleSelected = false;
bool rectangleSelected = false;
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
private static extern int GetForegroundWindow();
SnipSizeControl lbl = new SnipSizeControl();
floatingControlRight fcR = new floatingControlRight();
floatingControlBottom fcB = new floatingControlBottom();
public static Image Snip(ScreenshotType type)
{
switch (type)
{
case ScreenshotType.FULL:
return CreateScreenshot(0, 0, SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
case ScreenshotType.DEFINED:
SnippingTool2 snipper = new SnippingTool2(CreateScreenshot(0, 0, SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height), new Point(SystemInformation.VirtualScreen.Left, SystemInformation.VirtualScreen.Top));
if (snipper.ShowDialog() == DialogResult.OK)
{
return snipper.Image;
}
break;
case ScreenshotType.ACTIVE:
RECT windowRectangle;
GetWindowRect((System.IntPtr)GetForegroundWindow(), out windowRectangle);
return CreateScreenshot(windowRectangle.Left, windowRectangle.Top, windowRectangle.Right - windowRectangle.Left, windowRectangle.Bottom - windowRectangle.Top);
}
return null;
}
private static Bitmap CreateScreenshot(int left, int top, int width, int height)
{
Bitmap bmp = new Bitmap(width, height);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(left, top, 0, 0, new Size(width, height));
g.Dispose();
return bmp;
}
public SnippingTool2(Image screenShot, Point startPos)
{
InitializeComponent();
lbl.Text = "0x0";
lbl.Visible = true;
lbl.BackColor = Color.Black;
lbl.ForeColor = Color.White;
lbl.Visible = false;
this.Controls.Add(lbl);
this.BackgroundImage = screenShot;
Size s = screenShot.Size;
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.None;
this.StartPosition = FormStartPosition.Manual;
this.Size = s;
this.Location = startPos;
this.DoubleBuffered = true;
}
public Image Image { get; set; }
private Rectangle rcSelect = new Rectangle();
private Point pntStart;
bool handleSelected = false;
protected override void OnMouseDown(MouseEventArgs e)
{
if ((e.X > topLeft.X) && (e.X < topLeft.X + topLeft.Width) && (e.Y > topLeft.Y) && (e.Y < topLeft.Y + topLeft.Height))
{
this.Cursor = Cursors.SizeNWSE;
topLeftSelected = true;
handleSelected = true;
}
else if ((e.X > topMiddle.X) && (e.X < topMiddle.X + topMiddle.Width) && (e.Y > topMiddle.Y) && (e.Y < topMiddle.Y + topMiddle.Height))
{
this.Cursor = Cursors.SizeNS;
topMiddleSelected = true;
handleSelected = true;
}
else if ((e.X > topRight.X) && (e.X < topRight.X + topRight.Width) && (e.Y > topRight.Y) && (e.Y < topRight.Y + topRight.Height))
{
this.Cursor = Cursors.SizeNESW;
topRightSelected = true;
handleSelected = true;
}
else if ((e.X > bottomLeft.X) && (e.X < bottomLeft.X + bottomLeft.Width) && (e.Y > bottomLeft.Y) && (e.Y < bottomLeft.Y + bottomLeft.Height))
{
this.Cursor = Cursors.SizeNESW;
bottomLeftSelected = true;
handleSelected = true;
}
else if ((e.X > bottomMiddle.X) && (e.X < bottomMiddle.X + bottomMiddle.Width) && (e.Y > bottomMiddle.Y) && (e.Y < bottomMiddle.Y + bottomMiddle.Height))
{
this.Cursor = Cursors.SizeNS;
bottomMiddleSelected = true;
handleSelected = true;
}
else if ((e.X > bottomRight.X) && (e.X < bottomRight.X + bottomRight.Width) && (e.Y > bottomRight.Y) && (e.Y < bottomRight.Y + bottomRight.Height))
{
this.Cursor = Cursors.SizeNWSE;
bottomRightSelected = true;
handleSelected = true;
}
else if ((e.X > leftMiddle.X) && (e.X < leftMiddle.X + leftMiddle.Width) && (e.Y > leftMiddle.Y) && (e.Y < leftMiddle.Y + leftMiddle.Height))
{
this.Cursor = Cursors.SizeWE;
leftMiddleSelected = true;
handleSelected = true;
}
else if ((e.X > rightMiddle.X) && (e.X < rightMiddle.X + rightMiddle.Width) && (e.Y > rightMiddle.Y) && (e.Y < rightMiddle.Y + rightMiddle.Height))
{
this.Cursor = Cursors.SizeWE;
rightMiddleSelected = true;
handleSelected = true;
}
else if ((e.X > rcSelect.X) && (e.X < rcSelect.X + rcSelect.Width) && (e.Y > rcSelect.Y) && (e.Y < rcSelect.Y + rcSelect.Height))
{
this.Cursor = Cursors.SizeAll;
rectangleSelected = true;
handleSelected = true;
}
else
{
this.Cursor = Cursors.Cross;
topLeftSelected = false;
topMiddleSelected = false;
topRightSelected = false;
bottomLeftSelected = false;
bottomMiddleSelected = false;
bottomRightSelected = false;
leftMiddleSelected = false;
rightMiddleSelected = false;
rectangleSelected = false;
handleSelected = false;
}
// Start the snip on mouse down
if (e.Button != MouseButtons.Left) return;
if (handleSelected == true) return;
pntStart = e.Location;
rcSelect = new Rectangle(e.Location, new Size(0, 0));
lbl.Visible = true;
lbl.Location = new Point(e.X + 10, e.Y + 10); ;
lbl.Value = string.Format("0x0");
lbl.Refresh();
fcR.Visible = false;
oldX = e.X;
oldY = e.Y;
this.Refresh();
}
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
// Modify the selection on mouse move
if ((e.X > topLeft.X) && (e.X < topLeft.X + topLeft.Width) && (e.Y > topLeft.Y) && (e.Y < topLeft.Y + topLeft.Height))
{
this.Cursor = Cursors.SizeNWSE;
}
else if ((e.X > topMiddle.X) && (e.X < topMiddle.X + topMiddle.Width) && (e.Y > topMiddle.Y) && (e.Y < topMiddle.Y + topMiddle.Height))
{
this.Cursor = Cursors.SizeNS;
}
else if ((e.X > topRight.X) && (e.X < topRight.X + topRight.Width) && (e.Y > topRight.Y) && (e.Y < topRight.Y + topRight.Height))
{
this.Cursor = Cursors.SizeNESW;
}
else if ((e.X > bottomLeft.X) && (e.X < bottomLeft.X + bottomLeft.Width) && (e.Y > bottomLeft.Y) && (e.Y < bottomLeft.Y + bottomLeft.Height))
{
this.Cursor = Cursors.SizeNESW;
}
else if ((e.X > bottomMiddle.X) && (e.X < bottomMiddle.X + bottomMiddle.Width) && (e.Y > bottomMiddle.Y) && (e.Y < bottomMiddle.Y + bottomMiddle.Height))
{
this.Cursor = Cursors.SizeNS;
}
else if ((e.X > bottomRight.X) && (e.X < bottomRight.X + bottomRight.Width) && (e.Y > bottomRight.Y) && (e.Y < bottomRight.Y + bottomRight.Height))
{
this.Cursor = Cursors.SizeNWSE;
}
else if ((e.X > leftMiddle.X) && (e.X < leftMiddle.X + leftMiddle.Width) && (e.Y > leftMiddle.Y) && (e.Y < leftMiddle.Y + leftMiddle.Height))
{
this.Cursor = Cursors.SizeWE;
}
else if ((e.X > rightMiddle.X) && (e.X < rightMiddle.X + rightMiddle.Width) && (e.Y > rightMiddle.Y) && (e.Y < rightMiddle.Y + rightMiddle.Height))
{
this.Cursor = Cursors.SizeWE;
}
else if ((e.X > rcSelect.X) && (e.X < rcSelect.X + rcSelect.Width) && (e.Y > rcSelect.Y) && (e.Y < rcSelect.Y + rcSelect.Height))
{
this.Cursor = Cursors.SizeAll;
}
else
{
this.Cursor = Cursors.Cross;
}
if (e.Button == MouseButtons.Left && handleSelected == true)
{
Rectangle backupRect = rcSelect;
if (topLeftSelected == true)
{
rcSelect.X += e.X - oldX;
rcSelect.Width -= e.X - oldX;
rcSelect.Y += e.Y - oldY;
rcSelect.Height -= e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (topRightSelected == true)
{
rcSelect.Width += e.X - oldX;
rcSelect.Y += e.Y - oldY;
rcSelect.Height -= e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (topMiddleSelected == true)
{
rcSelect.Y += e.Y - oldY;
rcSelect.Height -= e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (bottomLeftSelected == true)
{
rcSelect.Width -= e.X - oldX;
rcSelect.X += e.X - oldX;
rcSelect.Height += e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (bottomMiddleSelected == true)
{
rcSelect.Height += e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (bottomRightSelected == true)
{
rcSelect.Width += e.X - oldX;
rcSelect.Height += e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (rightMiddleSelected == true)
{
rcSelect.Width += e.X - oldX;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (leftMiddleSelected == true)
{
rcSelect.X += e.X - oldX;
rcSelect.Width -= e.X - oldX;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
else if (rectangleSelected == true)
{
rcSelect.X = rcSelect.X + e.X - oldX;
rcSelect.Y = rcSelect.Y + e.Y - oldY;
lbl.Location = new Point(rcSelect.X, rcSelect.Y - 25);
lbl.Value = string.Format("{0}x{1}", rcSelect.Width, rcSelect.Height);
this.Refresh();
}
}
else if (e.Button == MouseButtons.Left)
{
int x1 = Math.Min(e.X, pntStart.X);
int y1 = Math.Min(e.Y, pntStart.Y);
int x2 = Math.Max(e.X, pntStart.X);
int y2 = Math.Max(e.Y, pntStart.Y);
rcSelect = new Rectangle(x1, y1, x2 - x1, y2 - y1);
this.Refresh();
lbl.Location = new Point(x1, y1 - 25);
lbl.Value = string.Format("{0}x{1}", x2 - x1, y2 - y1);
lbl.Refresh();
}
oldX = e.X;
oldY = e.Y;
}
protected override void OnMouseUp(MouseEventArgs e)
{
// Complete the snip on mouse-up
if (rcSelect.Width <= 0 || rcSelect.Height <= 0) return;
Image = new Bitmap(rcSelect.Width, rcSelect.Height);
using (Graphics gr = Graphics.FromImage(Image))
{
gr.DrawImage(this.BackgroundImage, new Rectangle(0, 0, Image.Width, Image.Height),
rcSelect, GraphicsUnit.Pixel);
}
topLeftSelected = false;
topMiddleSelected = false;
topRightSelected = false;
bottomLeftSelected = false;
bottomMiddleSelected = false;
bottomRightSelected = false;
leftMiddleSelected = false;
rightMiddleSelected = false;
rectangleSelected = false;
handleSelected = false;
//DialogResult = DialogResult.OK;
}
protected override void OnPaint(PaintEventArgs e)
{
// Draw the current selection
using (Brush br = new SolidBrush(Color.FromArgb(30, Color.Black)))
{
int x1 = rcSelect.X; int x2 = rcSelect.X + rcSelect.Width;
int y1 = rcSelect.Y; int y2 = rcSelect.Y + rcSelect.Height;
e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, this.Height));
e.Graphics.FillRectangle(br, new Rectangle(x2, 0, this.Width - x2, this.Height));
e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1));
e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, this.Height - y2));
}
using (Pen pen = new Pen(Color.Red, 1))
{
e.Graphics.DrawRectangle(pen, rcSelect);
}
//Resize Controls
//Top left
topLeft = new Rectangle(rcSelect.X - 3, rcSelect.Y - 3, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, topLeft);
}
//Top middle
topMiddle = new Rectangle((rcSelect.X - 3) + (rcSelect.Width) / 2, rcSelect.Y - 3, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, topMiddle);
}
//Top right
topRight = new Rectangle((rcSelect.X - 3) + rcSelect.Width, rcSelect.Y - 3, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, topRight);
}
//Bottom left
bottomLeft = new Rectangle(rcSelect.X - 3, (rcSelect.Y - 3) + rcSelect.Height, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, bottomLeft);
}
//Bottom middle
bottomMiddle = new Rectangle((rcSelect.X - 3) + (rcSelect.Width) / 2, (rcSelect.Y - 3) + rcSelect.Height, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, bottomMiddle);
}
//Bottom right
bottomRight = new Rectangle((rcSelect.X - 3) + rcSelect.Width, (rcSelect.Y - 3) + rcSelect.Height, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, bottomRight);
}
//Left middle
leftMiddle = new Rectangle(rcSelect.X - 3, (rcSelect.Y - 3) + (rcSelect.Height) / 2, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, leftMiddle);
}
//Right middle
rightMiddle = new Rectangle((rcSelect.X - 3) + rcSelect.Width, (rcSelect.Y - 3) + (rcSelect.Height) / 2, 6, 6);
using (Brush br = new SolidBrush(Color.FromArgb(200, Color.Red)))
{
e.Graphics.FillRectangle(br, rightMiddle);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// Allow canceling the snip with the Escape key
if (keyData == Keys.Escape) this.DialogResult = DialogResult.Cancel;
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
Edit:
Project file: https://www.dropbox.com/s/k1afggj6inye4kp/Free%20Snipipng%20Tool-project.rar?dl=0

I will cite the official Windows documentation. Although the doc is about Native API, Winforms uses the same underlying technology:
An application invalidates a portion of a window and sets the update
region by using the InvalidateRect or InvalidateRgn function. These
functions add the specified rectangle or region to the update region,
combining the rectangle or region with anything the system or the
application may have previously added to the update region.
The InvalidateRect and InvalidateRgn functions do not generate
WM_PAINT messages. Instead, the system accumulates the changes made by
these functions and its own changes. By accumulating changes, a window
processes all changes at once instead of updating bits and pieces one
step at a time.
Calling .NET Refresh() is equivalent of calling InvalidateAll() + Update(). InvalidateAll marks the whole screen as invalid, and Update() forces the process of redrawing what's invalid, so the whole screen.
You can optimize your program if you just invalidate "manually" what you know has changed.
That's what I did in my modified sample. Instead of calling Refresh(), I added a new oldRcRect variable to be able to invalidate old state and new state, and a RefreshOnMove() method like this (and I replaced most Refresh calls by a RefreshOnMove call) :
private void RefreshOnMove()
{
// invalidate the old rect (+ size of red box)
var rc = oldRcSelect;
rc.Inflate(3, 3);
Invalidate(rc);
// invalidate the new rect (+ size of red box)
// note you can almost omit this second one, but if you move the mouse really fast, you'll see some red box not fully displayed
// but the benefit is small, something like a 3 x width/height rectangle
rc = rcSelect;
rc.Inflate(3, 3);
Invalidate(rc);
// each time you call invalidate, you just accumulate a change
// to the change region, nothing actually changes on the screen
// now, ask Windows to process the combination of changes
Update();
}
PS: about my comment about inner region, I just mean it may be possible to avoid invalidating the content of the white box each time as well, but it's more complex.

Related

RadioButtonGroup in Winforms

I'm trying to create UX that is familiar to Bootstrap 4 Radio Button Group.
I know I can change Appearance=Button but this wont give me desired effect.
This is what I get:
and this is what I want:
I found similar question, but it uses WPF and I need WinForms.
Second one suggest using list view, but in that question list is vertical, but I need horizontal align.
I'm looking for a control that has first button rounded on left and last on right (just like on second image)
My question is: Does anyone know is such control exists? If yes I'll be grateful for anu links, if no then any tips regarding how to create such control are welcome (I know how to create custom controls and paint them so links on how to get started with user controls aren't needed)
EDIT
Because my question got down voted I'm adding code that I've written to create such control.
This is result I got:
and here is code:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace UserControls
{
public sealed class RadioGroupBox: UserControl
{
public RadioGroupBox()
{
DoubleBuffered = true;
ResizeRedraw = true;
Padding = new Padding(2);
CalculateItemWidth();
}
public event EventHandler SelectedIndexChanged;
protected override Size DefaultSize => new Size(200, 30);
private int _cornerRadius = 2;
public int CornerRadius
{
get => _cornerRadius;
set
{
if(value==_cornerRadius) return;
_cornerRadius = value;
Invalidate();
}
}
private string[] _items = {"A", "B", "C"};
[Category("Data")]
//[DefaultValue(null)]
[Description("Items")]
public string[] Items
{
get => _items;
set
{
if(value==_items) return;
_items = value;
CalculateItemWidth();
Invalidate();
}
}
private int _itemWidth;
private void CalculateItemWidth()
{
if (_items == null || _items.Length == 0)
{
_itemWidth = 0;
return;
}
var width = ClientRectangle.Width - Padding.Horizontal;
_itemWidth = width / _items.Length;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
CalculateItemWidth();
//Debug.WriteLine(_itemWidth);
CalculateSelectedItem(e.Location);
}
private int _selectedIndex = -1;
public int SelectedIndex
{
get => _selectedIndex;
set
{
if(value==_selectedIndex) return;
_selectedIndex = value;
Invalidate();
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
_click = true;
if (_hoverPos > -1)
{
if (_selectedIndex != _hoverPos)
{
_selectedIndex = _hoverPos;
SelectedIndexChanged?.Invoke(this, e);
}
}
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
_click = false;
Invalidate();
}
private int _hoverPos = -1;
private bool _click;
private void CalculateSelectedItem(Point mouseLocation)
{
var clientRect = GetPaddedRectangle();
int pos;
if (!clientRect.Contains(mouseLocation))
{
pos = -1;
}
else
{
pos = mouseLocation.X / _itemWidth;
if (pos > _items.Length - 1)
{
pos = -1;
}
}
if (pos != _hoverPos)
{
_hoverPos = pos;
Invalidate();
}
//Debug.WriteLine(_hoverPos);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
CalculateItemWidth();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
var rect = GetPaddedRectangle();
LinearGradientBrush normalBrush = new LinearGradientBrush(rect,
Color.White,
Color.LightBlue,
LinearGradientMode.Vertical);
LinearGradientBrush hoverBlush = new LinearGradientBrush(rect,
Color.RoyalBlue,
Color.MediumBlue,
LinearGradientMode.Vertical);
LinearGradientBrush selectedBrush = new LinearGradientBrush(rect,
Color.DodgerBlue,
Color.Blue,
LinearGradientMode.Vertical);
//e.Graphics.FillRectangle(Brushes.Aqua, this.ClientRectangle);
using (GraphicsPath path = RoundedRect(rect, _cornerRadius))
{
e.Graphics.FillPath(normalBrush, path);
e.Graphics.DrawPath(Pens.DodgerBlue, path);
}
if (_items == null || _items.Length == 0) return;
if (_hoverPos > -1 || _selectedIndex>-1)
{
var flags = RectangleCorners.None;
if (_hoverPos == 0) flags = RectangleCorners.TopLeft | RectangleCorners.BottomLeft;
if(_hoverPos==_items.Length-1) flags = RectangleCorners.TopRight | RectangleCorners.BottomRight;
var rect2 = new Rectangle(rect.X + _hoverPos * _itemWidth, rect.Y, _itemWidth, rect.Height);
if (_hoverPos == _items.Length - 1)
{
rect2 = new Rectangle(rect.X + _hoverPos * _itemWidth, rect.Y, rect.Width-_hoverPos*_itemWidth, rect.Height);
}
if (_hoverPos > -1 && _selectedIndex != _hoverPos)
{
using (GraphicsPath path = RoundedRect(rect2, _cornerRadius, flags))
{
e.Graphics.FillPath(_click ? Brushes.SteelBlue : hoverBlush, path);
}
}
if (_selectedIndex > -1)
{
rect2 = new Rectangle(rect.X + _selectedIndex * _itemWidth, rect.Y, _itemWidth, rect.Height);
if (_selectedIndex == _items.Length - 1)
{
rect2 = new Rectangle(rect.X + _selectedIndex * _itemWidth, rect.Y, rect.Width - _selectedIndex * _itemWidth, rect.Height);
}
flags = RectangleCorners.None;
if (_selectedIndex == 0) flags = RectangleCorners.TopLeft | RectangleCorners.BottomLeft;
if (_selectedIndex == _items.Length - 1) flags = RectangleCorners.TopRight | RectangleCorners.BottomRight;
using (GraphicsPath path = RoundedRect(rect2, _cornerRadius, flags))
{
e.Graphics.FillPath(selectedBrush, path);
}
}
}
//pionowe linie
for (int i = 1; i <= _items.Length-1; i++)
{
e.Graphics.DrawLine(Pens.DodgerBlue,rect.X+i*_itemWidth,rect.Y, rect.X + i * _itemWidth, rect.Y+rect.Height);
}
StringFormat sf = new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
};
for (var i = 0; i < _items.Length; i++)
{
string item = _items[i];
e.Graphics.DrawString(item, Font, i==_hoverPos?Brushes.White:Brushes.DodgerBlue, new Rectangle(rect.X+i* _itemWidth, rect.Y, _itemWidth, rect.Height), sf);
}
//Debug.WriteLine(MousePosition);
}
private Rectangle GetPaddedRectangle()
{
var rect = ClientRectangle;
var pad = Padding;
return new Rectangle(rect.X + pad.Left,
rect.Y + pad.Top,
rect.Width - pad.Horizontal,
rect.Height - pad.Vertical);
}
[Flags]
public enum RectangleCorners
{
None = 0, TopLeft = 1, TopRight = 2, BottomLeft = 4, BottomRight = 8,
All = TopLeft | TopRight | BottomLeft | BottomRight
}
public static GraphicsPath RoundedRect(Rectangle bounds, int radius, RectangleCorners corners = RectangleCorners.All)
{
int diameter = radius * 2;
GraphicsPath path = new GraphicsPath();
if (radius == 0)
{
path.AddRectangle(bounds);
return path;
}
// Make a GraphicsPath to draw the rectangle.
PointF point1, point2;
// Upper left corner.
if ((RectangleCorners.TopLeft & corners) == RectangleCorners.TopLeft)
{
RectangleF corner = new RectangleF(bounds.X, bounds.Y,diameter, diameter);
path.AddArc(corner, 180, 90);
point1 = new PointF(bounds.X + radius, bounds.Y);
}
else point1 = new PointF(bounds.X, bounds.Y);
// Top side.
if ((RectangleCorners.TopRight & corners) == RectangleCorners.TopRight)
point2 = new PointF(bounds.Right - radius, bounds.Y);
else
point2 = new PointF(bounds.Right, bounds.Y);
path.AddLine(point1, point2);
// Upper right corner.
if ((RectangleCorners.TopRight & corners) == RectangleCorners.TopRight)
{
RectangleF corner = new RectangleF(bounds.Right - diameter, bounds.Y,diameter, diameter);
path.AddArc(corner, 270, 90);
point1 = new PointF(bounds.Right, bounds.Y + radius);
}
else point1 = new PointF(bounds.Right, bounds.Y);
// Right side.
if ((RectangleCorners.BottomRight & corners) == RectangleCorners.BottomRight)
point2 = new PointF(bounds.Right, bounds.Bottom - radius);
else
point2 = new PointF(bounds.Right, bounds.Bottom);
path.AddLine(point1, point2);
// Lower right corner.
if ((RectangleCorners.BottomRight & corners) == RectangleCorners.BottomRight)
{
RectangleF corner = new RectangleF(bounds.Right - diameter,bounds.Bottom - diameter,diameter, diameter);
path.AddArc(corner, 0, 90);
point1 = new PointF(bounds.Right - radius, bounds.Bottom);
}
else point1 = new PointF(bounds.Right, bounds.Bottom);
// Bottom side.
if ((RectangleCorners.BottomLeft & corners) == RectangleCorners.BottomLeft)
point2 = new PointF(bounds.X + radius, bounds.Bottom);
else
point2 = new PointF(bounds.X, bounds.Bottom);
path.AddLine(point1, point2);
// Lower left corner.
if ((RectangleCorners.BottomLeft & corners) == RectangleCorners.BottomLeft)
{
RectangleF corner = new RectangleF(bounds.X, bounds.Bottom - diameter,diameter, diameter);
path.AddArc(corner, 90, 90);
point1 = new PointF(bounds.X, bounds.Bottom - radius);
}
else point1 = new PointF(bounds.X, bounds.Bottom);
// Left side.
if ((RectangleCorners.TopLeft & corners) == RectangleCorners.TopLeft)
point2 = new PointF(bounds.X, bounds.Y + radius);
else
point2 = new PointF(bounds.X, bounds.Y);
path.AddLine(point1, point2);
// Join with the start point.
path.CloseFigure();
return path;
}
}
}
it isn't optimized, it's just prove of concept.
Whole point of this question is to find existing control without need to reinvent the wheel.
If I won't be able to find such control I'll create one and share it.

My highscore doesn't match my points at sometimes

When I get my points(poang) to highscore when I hit the blocks with 5 points. They will not update the same, sometimes points(poang) will be 18 and highscore will be 20.
(Sorry about my bad english)
poang = points
linje = line
liv = lives
boll = ball
poang = points
blockröd = blockred
blockgrön = blockgreen
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont spritefont;
Texture2D linje_texture;
Texture2D linjeliten_texture;
Texture2D boll_texture;
Texture2D blockröd_texture;
Texture2D blockgrön_texture;
Texture2D gameover_texture;
Rectangle linje_rect;
Rectangle linjeliten_rect;
Rectangle boll_rect;
Rectangle blockröd_rect;
Rectangle blockgrön_rect;
Rectangle gameover_rect;
Vector2 linje_speed;
Vector2 linjeliten_speed;
Vector2 boll_speed;
Random random;
StreamReader sr;
StreamWriter sw;
int liv = 3;
int poang = 0;
int highscore;
List<Rectangle> block = new List<Rectangle>();
List<Rectangle> block2 = new List<Rectangle>();
bool Start = false;
bool holdingleft = false;
bool holdingright = false;
bool resetballspeed = false;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 760;
graphics.PreferredBackBufferHeight = 620;
}
protected override void Initialize()
{
random = new Random();
linje_speed.X = 6f;
linjeliten_speed.X = 6f;
boll_speed.X = random.Next(-1, 1);
boll_speed.Y = 7f;
sr = new StreamReader("highscore.txt");
highscore = int.Parse(sr.ReadLine());
sr.Close();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spritefont = Content.Load<SpriteFont>("Fonts/Myfont");
linje_texture = Content.Load<Texture2D>("Pics/linje-lång");
linjeliten_texture = Content.Load<Texture2D>("Pics/linje");
boll_texture = Content.Load<Texture2D>("Pics/boll");
blockgrön_texture = Content.Load<Texture2D>("Pics/block-grön");
blockröd_texture = Content.Load<Texture2D>("Pics/block-röd");
gameover_texture = Content.Load<Texture2D>("Pics/GameOver");
linje_rect = new Rectangle((Window.ClientBounds.Width - linje_texture.Width) / 2, 580, linje_texture.Width, linje_texture.Height);
linjeliten_rect = new Rectangle((Window.ClientBounds.Width - linjeliten_texture.Width) / 2, 580, linjeliten_texture.Width, linjeliten_texture.Height);
boll_rect = new Rectangle((Window.ClientBounds.Width - boll_texture.Width) / 2, 556, boll_texture.Width, boll_texture.Height);
gameover_rect = new Rectangle((Window.ClientBounds.Width / 2) - (gameover_texture.Width / 2), (Window.ClientBounds.Height / 2) - gameover_texture.Height / 2, gameover_texture.Width, gameover_texture.Height);
block.Add(blockgrön_rect);
block2.Add(blockröd_rect);
for (int i = 1; i < 2; i++)
{
for (int g = 1; g < 13; g++)
{
block2.Add(new Rectangle((g * 63) - 60, (i * 20), blockröd_texture.Width, blockröd_texture.Height));
}
}
for (int i = 1; i < 4; i++)
{
for (int g = 1; g < 13; g++)
{
block.Add(new Rectangle((g * 63) - 60, (i * 20) + 20, blockgrön_texture.Width, blockgrön_texture.Height));
}
}
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
{
if (poang == highscore)
{
sw = new StreamWriter("highscore.txt");
sw.WriteLine(poang);
sw.Close();
}
Exit();
}
if (Start == true)
{
boll_rect.X += (int)boll_speed.X;
boll_rect.Y += (int)boll_speed.Y;
}
if (Start == false)
{
boll_rect.X = linje_rect.X + ((linje_texture.Width / 2) - (boll_texture.Width / 2)); //how the ball condition is to the long line
boll_rect.X = linjeliten_rect.X + ((linjeliten_texture.Width / 2) - (boll_texture.Width / 2)); //the same but ball condition to small line
}
if (boll_rect.X > Window.ClientBounds.Width - boll_texture.Width || boll_rect.X < 0)
boll_speed.X *= -1;
if (boll_rect.Y > Window.ClientBounds.Height - boll_texture.Height || boll_rect.Y < 0)
boll_speed.Y *= -1;
if (boll_rect.Y > Window.ClientBounds.Height - boll_texture.Height)
{
liv -= 1;
Start = false;
boll_rect.X = (Window.ClientBounds.Width - boll_texture.Width) / 2;
boll_rect.Y = 556;
linje_rect.X = (Window.ClientBounds.Width - linje_texture.Width) / 2;
linje_rect.Y = 580;
linjeliten_rect.X = (Window.ClientBounds.Width - linjeliten_texture.Width) / 2;
linjeliten_rect.Y = 580;
}
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
linje_rect.X -= (int)linje_speed.X;
linjeliten_rect.X -= (int)linjeliten_speed.X;
holdingleft = true;
}
else if (ks.IsKeyDown(Keys.Right))
{
linje_rect.X += (int)linje_speed.X;
linjeliten_rect.X += (int)linjeliten_speed.X;
holdingright = true;
}
else if (ks.IsKeyDown(Keys.Space))
{
Start = true;
}
if (ks.Equals(new KeyboardState()))
{
resetballspeed = true;
}
if (linje_rect.X > Window.ClientBounds.Width - linje_texture.Width)
linje_rect.X = (Window.ClientBounds.Width - linje_texture.Width);
if (linjeliten_rect.X > Window.ClientBounds.Width - linjeliten_texture.Width)
linjeliten_rect.X = (Window.ClientBounds.Width - linjeliten_texture.Width);
if (linje_rect.X < 0)
linje_rect.X = 0;
if (linjeliten_rect.X < 0)
linjeliten_rect.X = 0;
if (linje_rect.Intersects(boll_rect))
{
boll_speed.Y *= -1;
boll_rect.Y += (int)boll_speed.Y;
if (holdingleft == true)
{
boll_speed.X -= 2;
}
else if (holdingright == true)
{
boll_speed.X += 2;
}
else if (resetballspeed == true)
{
boll_speed.X = 1;
}
}
if (linjeliten_rect.Intersects(boll_rect))
{
boll_speed.Y *= -1;
boll_rect.Y += (int)boll_speed.Y;
if (holdingleft == true)
{
boll_speed.X -= 1;
}
else if (holdingright == true)
{
boll_speed.X += 1;
}
else if (resetballspeed == true)
{
boll_speed.X = 1;
}
}
for (int j = 1; j < block.Count; j++)
{
if (boll_rect.Intersects(block[j]))
{
boll_speed.Y *= -1;
poang += 1;
block.RemoveAt(j);
if (poang > highscore)
{
highscore++;
}
}
}
for (int k = 1; k < block2.Count; k++)
{
if (boll_rect.Intersects(block2[k]))
{
boll_speed.Y *= -1;
poang += 5;
block2.RemoveAt(k);
if (poang > highscore)
{
highscore += 5;
}
}
}
holdingleft = false;
holdingright = false;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
if (liv > 0)
{
if (poang < 10)
{
spriteBatch.Draw(linje_texture, linje_rect, Color.White);
}
else if (poang > 9)
{
spriteBatch.Draw(linjeliten_texture, linjeliten_rect, Color.White);
}
spriteBatch.Draw(boll_texture, boll_rect, Color.White);
spriteBatch.DrawString(spritefont, "Lives left: " + liv, Vector2.Zero, Color.White);
spriteBatch.DrawString(spritefont, "Points: " + poang, new Vector2(350, 0), Color.White);
spriteBatch.DrawString(spritefont, "Highscore: " + highscore, new Vector2(660, 0), Color.White);
foreach (Rectangle g in block)
{
spriteBatch.Draw(blockgrön_texture, g, Color.White);
}
foreach (Rectangle t in block2)
{
spriteBatch.Draw(blockröd_texture, t, Color.White);
}
}
else if (liv == 0)
{
spriteBatch.Draw(gameover_texture, gameover_rect, Color.White);
if (poang == highscore)
{
sw = new StreamWriter("highscore.txt");
sw.WriteLine(poang);
sw.Close();
}
}
spriteBatch.End();
base.Draw(gameTime);
}
}
Having trouble with these parts:
for (int j = 1; j < block.Count; j++) //loopar igenom alla block
{
if (boll_rect.Intersects(block[j])) //om bollen träffar rutorna
{
boll_speed.Y *= -1;
poang += 1;
block.RemoveAt(j); //tar bort gröna blocket man träffar
if (poang > 9)
{
linje_rect.Width = 60;
}
if (poang > highscore)
{
highscore++;
}
}
}
for (int k = 1; k < block2.Count; k++)
{
if (boll_rect.Intersects(block2[k]))
{
boll_speed.Y *= -1;
poang += 5;
block2.RemoveAt(k);
if (poang > highscore)
{
highscore += 5;
}
block2.RemoveAt(k);
}
}
Replace highscore++; with highscore = poang;
and highscore += 5; with highscore = poang;
to avoid mismatches between highscore and current score.

Trying to add new levels to my Breakout game

I have a problem with my code, check the code down below, so you understand which section i'm talking about!
I'm trying to add new block levels when "block.Count == 1", you know when all my blocks are destroyed by the ball. I want it to start a new level with a different block path. When I have:
else if (block.Count == 1 && block2.Count == 1)
{
spriteBatch.Draw(gameover_texture, gameover_rect, Color.White);
}
It doesn't draw out my gameover_texture, when are blocks are gone?
(Sorry about my bad english)
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont spritefont;
Texture2D paddle_texture;
Texture2D ball_texture;
Texture2D blockred_texture;
Texture2D blockgreen_texture;
Texture2D gameover_texture;
Rectangle paddle_rect;
Rectangle ball_rect;
Rectangle blockred_rect;
Rectangle blockgreen_rect;
Rectangle gameover_rect;
Vector2 paddle_speed;
Vector2 ball_speed;
Random random;
StreamReader sr;
StreamWriter sw;
int lives = 3;
int points = 0;
int highscore;
int counter = 0;
int seconds = 0;
List<Rectangle> block = new List<Rectangle>();
List<Rectangle> block2 = new List<Rectangle>();
bool Start = false;
bool holdingleft = false;
bool holdingright = false;
bool resetballspeed = false;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 760;
graphics.PreferredBackBufferHeight = 620;
}
protected override void Initialize()
{
random = new Random();
paddle_speed.X = 6f;
ball_speed.X = random.Next(-1, 1);
ball_speed.Y = 7f;
sr = new StreamReader("highscore.txt");
highscore = int.Parse(sr.ReadLine());
sr.Close();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spritefont = Content.Load<SpriteFont>("Fonts/Myfont");
paddle_texture = Content.Load<Texture2D>("Pics/linje");
ball_texture = Content.Load<Texture2D>("Pics/boll");
blockgreen_texture = Content.Load<Texture2D>("Pics/block-grön");
blockred_texture = Content.Load<Texture2D>("Pics/block-röd");
gameover_texture = Content.Load<Texture2D>("Pics/GameOver");
paddle_rect = new Rectangle((Window.ClientBounds.Width - paddle_texture.Width) / 2, 580, paddle_texture.Width, paddle_texture.Height);
ball_rect = new Rectangle((Window.ClientBounds.Width - ball_texture.Width) / 2, 556, ball_texture.Width, ball_texture.Height);
gameover_rect = new Rectangle((Window.ClientBounds.Width / 2) - (gameover_texture.Width / 2), (Window.ClientBounds.Height / 2) - gameover_texture.Height / 2, gameover_texture.Width, gameover_texture.Height);
block.Add(blockgreen_rect);
block2.Add(blockred_rect);
for (int i = 1; i < 2; i++)
{
for (int g = 1; g < 3; g++)
{
block2.Add(new Rectangle((g * 63) - 60, (i * 40), blockred_texture.Width, blockred_texture.Height));
}
}
for (int i = 1; i < 2; i++)
{
for (int g = 1; g < 3; g++)
{
block.Add(new Rectangle((g * 63) - 60, (i * 20) + 40, blockgreen_texture.Width, blockgreen_texture.Height));
}
}
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (Start == true) //kolla om "Start == true",
{
ball_rect.X += (int)ball_speed.X;
ball_rect.Y += (int)ball_speed.Y;
}
if (Start == false)
{
ball_rect.X = paddle_rect.X + ((paddle_rect.Width / 2) - (ball_texture.Width / 2));
}
if (ball_rect.X > Window.ClientBounds.Width - ball_texture.Width || ball_rect.X < 0)
ball_speed.X *= -1;
if (ball_rect.Y > Window.ClientBounds.Height - ball_texture.Height || ball_rect.Y < 0)
ball_speed.Y *= -1;
if (ball_rect.Y > Window.ClientBounds.Height - ball_texture.Height)
{
lives -= 1;
Start = false;
ball_rect.X = (Window.ClientBounds.Width - ball_texture.Width) / 2;
ball_rect.Y = 556;
paddle_rect.X = (Window.ClientBounds.Width - paddle_texture.Width) / 2;
paddle_rect.Y = 580;
}
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
paddle_rect.X -= (int)paddle_speed.X;
holdingleft = true;
}
else if (ks.IsKeyDown(Keys.Right))
{
paddle_rect.X += (int)paddle_speed.X;
holdingright = true;
}
else if (ks.IsKeyDown(Keys.Space))
{
Start = true;
}
else if (ks.Equals(new KeyboardState()))
{
resetballspeed = true;
}
if (paddle_rect.X > Window.ClientBounds.Width - paddle_rect.Width)
paddle_rect.X = (Window.ClientBounds.Width - paddle_rect.Width);
if (paddle_rect.X < 0)
paddle_rect.X = 0;
if (paddle_rect.Intersects(ball_rect))
{
ball_speed.Y *= -1;
ball_rect.Y += (int)ball_speed.Y;
if (holdingleft == true)
{
ball_speed.X -= 3;
}
else if (holdingright == true)
{
ball_speed.X += 3;
}
else if (resetballspeed == true)
{
ball_speed.X = 1;
}
}
if (points == highscore)
{
sw = new StreamWriter("highscore.txt");
sw.WriteLine(points);
sw.Close();
}
for (int j = 1; j < block.Count; j++)
{
if (ball_rect.Intersects(block[j]))
{
ball_speed.Y *= -1;
points += 1;
block.RemoveAt(j);
if (points > 9)
{
paddle_rect.Width = 60;
}
if (points > highscore)
{
highscore = points;
}
}
}
for (int k = 1; k < block2.Count; k++)
{
if (ball_rect.Intersects(block2[k]))
{
ball_speed.Y *= -1;
points += 5;
block2.RemoveAt(k);
if (points > 9)
{
paddle_rect.Width = 60;
}
if (points > highscore)
{
highscore = points;
}
}
}
holdingleft = false;
holdingright = false;
counter++;
if (counter == 60)
{
seconds++;
counter = 0;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
// TODO: Add your drawing code here
spriteBatch.Begin();
if (lives > 0)
{
spriteBatch.Draw(ball_texture, ball_rect, Color.White);
spriteBatch.Draw(paddle_texture, paddle_rect, Color.White);
spriteBatch.DrawString(spritefont, "Lives left: " + lives, Vector2.Zero, Color.White);
spriteBatch.DrawString(spritefont, "Points: " + points, new Vector2(350, 0), Color.White);
spriteBatch.DrawString(spritefont, "Timer: " + seconds, new Vector2(350, 600), Color.White);
spriteBatch.DrawString(spritefont, "Highscore: " + highscore, new Vector2(660, 0), Color.White);
foreach (Rectangle g in block)
{
spriteBatch.Draw(blockgreen_texture, g, Color.White);
}
foreach (Rectangle t in block2)
{
spriteBatch.Draw(blockred_texture, t, Color.White);
}
}
else if (block.Count == 1 && block2.Count == 1)
{
spriteBatch.Draw(gameover_texture, gameover_rect, Color.White);
}
else if (lives == 0)
{
spriteBatch.Draw(gameover_texture, gameover_rect, Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
Fixed the problem now, by putting the else if-statement inside "if (lives > 0)"

Free-form selection crop C#

How can I make a free-form selection (like in paint or photoshop) in a picture box and then crop that selection and save it to a folder?
I already did a rectangle crop but I want that free-form selection..
Here is my rectangle crop:
Image img;
bool mouseClicked;
Point startPoint = new Point();
Point endPoint = new Point();
Rectangle rectCropArea;
private void Button1_Click(System.Object sender, System.EventArgs e)
{
}
private void OnLoad(System.Object sender, System.EventArgs e)
{
loadPrimaryImage();
}
private void loadPrimaryImage()
{
img = Image.FromFile("..\\..\\images.jpg");
PictureBox1.Image = img;
}
private void PicBox_MouseUp(System.Object sender, System.Windows.Forms.MouseEventArgs e)
{
mouseClicked = false;
if ((endPoint.X != -1)) {
Point currentPoint = new Point(e.X, e.Y);
Y1.Text = e.X.ToString();
Y2.Text = e.Y.ToString();
}
endPoint.X = -1;
endPoint.Y = -1;
startPoint.X = -1;
startPoint.Y = -1;
}
private void PicBox_MouseDown(System.Object sender, System.Windows.Forms.MouseEventArgs e)
{
mouseClicked = true;
startPoint.X = e.X;
startPoint.Y = e.Y;
//Display coordinates
X1.Text = startPoint.X.ToString();
Y1.Text = startPoint.Y.ToString();
endPoint.X = -1;
endPoint.Y = -1;
rectCropArea = new Rectangle(new Point(e.X, e.Y), new Size());
}
private void PicBox_MouseMove(System.Object sender, System.Windows.Forms.MouseEventArgs e)
{
Point ptCurrent = new Point(e.X, e.Y);
if ((mouseClicked)) {
if ((endPoint.X != -1)) {
//Display Coordinates
X1.Text = startPoint.X.ToString();
Y1.Text = startPoint.Y.ToString();
X2.Text = e.X.ToString();
Y2.Text = e.Y.ToString();
}
endPoint = ptCurrent;
if ((e.X > startPoint.X & e.Y > startPoint.Y)) {
rectCropArea.Width = e.X - startPoint.X;
rectCropArea.Height = e.Y - startPoint.Y;
} else if ((e.X < startPoint.X & e.Y > startPoint.Y)) {
rectCropArea.Width = startPoint.X - e.X;
rectCropArea.Height = e.Y - startPoint.Y;
rectCropArea.X = e.X;
rectCropArea.Y = startPoint.Y;
} else if ((e.X > startPoint.X & e.Y < startPoint.Y)) {
rectCropArea.Width = e.X - startPoint.X;
rectCropArea.Height = startPoint.Y - e.Y;
rectCropArea.X = startPoint.X;
rectCropArea.Y = e.Y;
} else {
rectCropArea.Width = startPoint.X - e.X;
rectCropArea.Height = startPoint.Y - e.Y;
rectCropArea.X = e.X;
rectCropArea.Y = e.Y;
}
PictureBox1.Refresh();
}
}
private void PicBox_Paint(System.Object sender, System.Windows.Forms.PaintEventArgs e)
{
Pen drawLine = new Pen(Color.Red);
drawLine.DashStyle = DashStyle.Dash;
e.Graphics.DrawRectangle(drawLine, rectCropArea);
}
private void btnCrop_Click(System.Object sender, System.EventArgs e)
{
PictureBox2.Refresh();
Bitmap sourceBitmap = new Bitmap(PictureBox1.Image, PictureBox1.Width, PictureBox1.Height);
Graphics g = PictureBox2.CreateGraphics();
if (!(CheckBox1.Checked)) {
g.DrawImage(sourceBitmap, new Rectangle(0, 0, PictureBox2.Width, PictureBox2.Height), rectCropArea, GraphicsUnit.Pixel);
sourceBitmap.Dispose();
} else {
int x1 = 0;
int x2 = 0;
int y1 = 0;
int y2 = 0;
try {
x1 = Convert.ToInt32(CX1.Text);
x2 = Convert.ToInt32(CX2.Text);
y1 = Convert.ToInt32(CY1.Text);
y2 = Convert.ToInt32(CY2.Text);
} catch (Exception ex) {
MessageBox.Show("Enter valid Coordinates (only Integer values)");
}
if (((x1 < x2 & y1 < y2))) {
rectCropArea = new Rectangle(x1, y1, x2 - x1, y2 - y1);
} else if ((x2 < x1 & y2 > y1)) {
rectCropArea = new Rectangle(x2, y1, x1 - x2, y2 - y1);
} else if ((x2 > x1 & y2 < y1)) {
rectCropArea = new Rectangle(x1, y2, x2 - x1, y1 - y2);
} else {
rectCropArea = new Rectangle(x2, y2, x1 - x2, y1 - y2);
}
PictureBox1.Refresh();
//This repositions the dashed box to new location as per coordinates entered.
g.DrawImage(sourceBitmap, new Rectangle(0, 0, PictureBox2.Width, PictureBox2.Height), rectCropArea, GraphicsUnit.Pixel);
sourceBitmap.Dispose();
}
}
private void pictureBox1_MouseClick(System.Object sender, System.Windows.Forms.MouseEventArgs e)
{
PictureBox1.Refresh();
}
private void CheckBox1_CheckedChanged(System.Object sender, System.EventArgs e)
{
if ((CheckBox1.Checked)) {
CX1.Visible = true;
Label10.Visible = true;
CY1.Visible = true;
Label9.Visible = true;
CX2.Visible = true;
Label8.Visible = true;
CY2.Visible = true;
Label7.Visible = true;
X1.Text = "0";
X2.Text = "0";
Y1.Text = "0";
Y2.Text = "0";
} else {
CX1.Visible = false;
Label10.Visible = false;
CY1.Visible = false;
Label9.Visible = false;
CX2.Visible = false;
Label8.Visible = false;
CY2.Visible = false;
Label7.Visible = false;
}
}
public Form1()
{
Load += OnLoad;
}
}
To copy a free-form selection you need to work with polygons.
Here is a complete example. Just paste this into a new solution and try it out (just change the path to the images).
It will create 2 pictureboxes and load an image into the first one and also create an image. Then you can click on the first image and when you have clicked 2 times it will start to show a selection, when you are finished just press the button and it will copy the selection to the other pictureBox and then save it as an png image.
What it does is to create a brush from the first image and then paint the polygon onto another image and set the other pixels in the rectangle to a background color of your choice, in this case the color: Color.Transparent.
Example:
public partial class Form1 : Form {
private List<Point> _points = new List<Point>();
private PictureBox _pictureBox1;
private PictureBox _pictureBox2;
private Button _button1;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
Size = new Size(1366, 675);
_pictureBox1 = new PictureBox {
Location = new Point(12, 51),
Size = new Size(651, 474),
BorderStyle = BorderStyle.FixedSingle
};
_pictureBox2 = new PictureBox
{
Location = new Point(669, 51),
Size = new Size(651, 474),
BorderStyle = BorderStyle.FixedSingle
};
_button1 = new Button {
Text = #"Copy selected area",
Location = new Point(13, 13),
Size = new Size(175, 23)
};
Controls.AddRange(new Control[] { _pictureBox1, _pictureBox2, _button1 });
_pictureBox1.Image = Image.FromFile(#"d:\temp\Hopetoun_falls.jpg");
_points = new List<Point>();
_pictureBox1.MouseDown += delegate(object o, MouseEventArgs args) { _points.Add(args.Location); _pictureBox1.Refresh(); };
_pictureBox1.Paint += pictureBox1_Paint;
_button1.Click += button_Click;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
if (_points.Count < 2) {
return;
}
var max = _points.Count;
for (int i = 1; i < max; i++) {
e.Graphics.DrawLine(Pens.Red, _points[i-1].X, _points[i-1].Y, _points[i].X, _points[i].Y);
}
e.Graphics.DrawLine(Pens.Red, _points[max - 1].X, _points[max - 1].Y, _points[0].X, _points[0].Y);
}
private static Bitmap GetSelectedArea(Image source, Color bgColor, List<Point> points) {
var bigBm = new Bitmap(source);
using (var gr = Graphics.FromImage(bigBm)) {
// Set the background color.
gr.Clear(bgColor);
// Make a brush out of the original image.
using (var br = new TextureBrush(source)) {
// Fill the selected area with the brush.
gr.FillPolygon(br, points.ToArray());
// Find the bounds of the selected area.
var sourceRect = GetPointListBounds(points);
// Make a bitmap that only holds the selected area.
var result = new Bitmap(sourceRect.Width, sourceRect.Height);
// Copy the selected area to the result bitmap.
using (var resultGr = Graphics.FromImage(result)) {
var destRect = new Rectangle(0, 0, sourceRect.Width, sourceRect.Height);
resultGr.DrawImage(bigBm, destRect, sourceRect, GraphicsUnit.Pixel);
}
// Return the result.
return result;
}
}
}
private static Rectangle GetPointListBounds(List<Point> points) {
int xmin = points[0].X;
int xmax = xmin;
int ymin = points[0].Y;
int ymax = ymin;
for (int i = 1; i < points.Count; i++) {
if (xmin > points[i].X) xmin = points[i].X;
if (xmax < points[i].X) xmax = points[i].X;
if (ymin > points[i].Y) ymin = points[i].Y;
if (ymax < points[i].Y) ymax = points[i].Y;
}
return new Rectangle(xmin, ymin, xmax - xmin, ymax - ymin);
}
private void button_Click(object sender, EventArgs e) {
if (_points.Count < 3) {
return;
}
var img = GetSelectedArea(_pictureBox1.Image, Color.Transparent, _points);
_pictureBox2.Image = img;
_pictureBox2.Image.Save(#"d:\temp\sample.png", ImageFormat.Png);
}
}

Getting exception "Parameter is not valid" when minimizing the form to the taskbar

It happen only when I resize the form when the program is running.
I click the "-" and the program is minimised to the taskbar, then I see the error/exception message.
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (!_addingLines)
SplitText(this.Text);
if (_backBmpBU != null)
this._backBmp = MakeBackBmp(_backBmpBU);
if (this.BitmapModus)
{
UpdateBitmap();
}
}
private void UpdateBitmap()
{
if (_lines != null && _lines.Length > 0)
{
SizeF sz = new SizeF(0, 0);
float lineOrigHeight = sz.Height;
using (Graphics g = this.CreateGraphics())
{
sz = g.MeasureString("Teststring", this.Font);
if (this._additionalSpaceBetweenLines > 0)
sz = new SizeF(sz.Width, sz.Height + this._additionalSpaceBetweenLines);
}
this._textHeight = sz.Height * _lines.Length;
if (_bmp != null)
{
_bmp.Dispose();
_bmp = null;
}
try
{
if (this._textHeight > MAXHEIGHT)
throw new Exception("Text too long, for BitmapMode.");
_bmp = new Bitmap(this.ClientSize.Width, (int)Math.Ceiling(this._textHeight));
using (Graphics g = Graphics.FromImage(_bmp))
{
//set it to value you like...
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
using (SolidBrush b = new SolidBrush(this.ForeColor))
{
for (int i = 0; i < _lines.Length; i++)
{
SolidBrush bb = b;
if (TrimText)
_lines[i] = _lines[i].Trim();
sz = g.MeasureString(_lines[i], this.Font);
lineOrigHeight = sz.Height;
if (this._additionalSpaceBetweenLines > 0)
sz = new SizeF(sz.Width, sz.Height + this._additionalSpaceBetweenLines);
_posX = 0;
if (this.TextLayoutCentered)
_posX = (this.ClientSize.Width - sz.Width) / 2.0F;
bool drect = false;
bool colw = false;
int indx = -1;
int length = 0;
string textToFind = "";
Color fc = this.ForeColor;
Color bc = Color.Transparent;
Color rc = Color.Transparent;
if (Words != null && Words.Count > 0)
{
for (int ii = 0; ii < Words.Count; ii++)
{
if (_lines[i].Contains(Words[ii].WordOrText))
{
bb = new SolidBrush(Words[ii].ForeColor);
if (Words[ii].DrawRect)
drect = true;
if (Words[ii].ColorOnlyThisWord)
colw = true;
indx = _lines[i].IndexOf(Words[ii].WordOrText);
length = Words[ii].WordOrText.Length;
textToFind = Words[ii].WordOrText;
fc = Words[ii].ForeColor;
bc = Words[ii].BackColor;
rc = Words[ii].RectColor;
drect = Words[ii].DrawRect;
}
}
}
if (colw)
{
//reset b and create a new color brush
if (bb.Equals(b) == false)
bb.Dispose();
bb = b;
string ftext = _lines[i];
float cPosX = _posX;
using (SolidBrush bbb = new SolidBrush(fc))
{
while (indx > -1)
{
if (indx > 0)
g.DrawString(ftext.Substring(0, indx), this.Font, bb, new PointF(cPosX, sz.Height * i + _additionalSpaceBetweenLines / 2F));
cPosX += g.MeasureString(ftext.Substring(0, indx), this.Font).Width;
SizeF sfWord = g.MeasureString(ftext.Substring(indx, length), this.Font);
if (bc.ToArgb().Equals(Color.Transparent.ToArgb()) == false)
{
using (SolidBrush bbbb = new SolidBrush(bc))
g.FillRectangle(bbbb, cPosX, sz.Height * i + _additionalSpaceBetweenLines / 2F, sfWord.Width, sfWord.Height);
}
g.DrawString(ftext.Substring(indx, length), this.Font, bbb, new PointF(cPosX, sz.Height * i + _additionalSpaceBetweenLines / 2F));
cPosX += sfWord.Width;
ftext = ftext.Substring(indx + length);
if (textToFind.Length > 0)
indx = ftext.IndexOf(textToFind);
else
indx = -1;
}
if (ftext.Length > 0)
g.DrawString(ftext, this.Font, bb, new PointF(cPosX, sz.Height * i + _additionalSpaceBetweenLines / 2F));
}
}
else
{
if (bc.ToArgb().Equals(Color.Transparent.ToArgb()) == false)
{
using (SolidBrush bbbb = new SolidBrush(bc))
g.FillRectangle(bbbb, _posX, sz.Height * i + _additionalSpaceBetweenLines / 2F, sz.Width, lineOrigHeight);
}
g.DrawString(_lines[i], this.Font, bb, new PointF(_posX, sz.Height * i + _additionalSpaceBetweenLines / 2F));
}
if (drect)
{
if (rc.ToArgb().Equals(Color.Transparent.ToArgb()) == false)
using (Pen p = new Pen(rc))
g.DrawRectangle(p, _posX, sz.Height * i + _additionalSpaceBetweenLines / 2F, sz.Width, lineOrigHeight);
}
if (bb.Equals(b) == false)
bb.Dispose();
if (DrawRect)
{
using (Pen p = new Pen(this.ForeColor))
{
if (DrawRectAroundText)
g.DrawRectangle(p, _posX, sz.Height * i + _additionalSpaceBetweenLines / 2F, sz.Width, lineOrigHeight);
else
g.DrawRectangle(p, 0, sz.Height * i + _additionalSpaceBetweenLines / 2F, this.ClientSize.Width - 1, lineOrigHeight);
}
}
}
}
}
}
catch (Exception ex)
{
if (_bmp != null)
{
_bmp.Dispose();
_bmp = null;
}
this.BitmapModus = false;
//MessageBox.Show(ex.Message + " switching to Dynamic-Draw-Mode.");
OnSwitchModeOnError();
}
}
}
When the program is running and i minimize the form to the taskbar im getting exception:
Parameter is not valid
The full exception message:
System.ArgumentException was caught
HResult=-2147024809
Message=Parameter is not valid.
Source=System.Drawing
StackTrace:
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
at ScrollLabelTest.ScrollLabel.UpdateBitmap() in e:\scrolllabel\ScrollLabel\ScrollLabel\ScrollLabel.cs:line 601
InnerException:
I had the same problem, with a huge list of errors in the Just-In-Time-Debugger. After several hours of searching I found my own way. Try this, no more exceptions!!
private void picMinimize_Click(object sender, EventArgs e)
{
try
{
panelUC.Visible = false; //change visible status of your form, etc.
this.WindowState = FormWindowState.Minimized; //minimize
minimizedFlag = true; //set a global flag
}
catch (Exception)
{
}
}
private void mainForm_Resize(object sender, EventArgs e)
{
//check if form is minimized, and you know that this method is only called if and only if the form get a change in size, meaning somebody clicked in the taskbar on your application
if (minimizedFlag == true)
{
panelUC.Visible = true; //make your panel visible again! thats it
minimizedFlag = false; //set flag back
}
}
Thumb up!

Categories