My program can draw lines using canvas.Drawline(). How to click line and change this color (select line)?
private List<Point> coordFirst = new List<Point>();
private List<Point> coordLast = new List<Point>();
public Graphics canvas;
private void Form1_Load(object sender, EventArgs e)
{
canvas=panel1.CreateGraphics();
}
Coordinate line stored in coordFirs & coodLast.
Here is a suitable Line class:
class Line
{
public Color LineColor { get; set; }
public float Linewidth { get; set; }
public bool Selected { get; set; }
public Point Start { get; set; }
public Point End { get; set; }
public Line(Color c, float w, Point s, Point e)
{ LineColor = c; Linewidth = w; Start = s; End = e; }
public void Draw(Graphics G)
{ using (Pen pen = new Pen(LineColor, Linewidth)) G.DrawLine(pen, Start, End); }
public bool HitTest(Point Pt)
{
// test if we fall outside of the bounding box:
if ((Pt.X < Start.X && Pt.X < End.X) || (Pt.X > Start.X && Pt.X > End.X) ||
(Pt.Y < Start.Y && Pt.Y < End.Y) || (Pt.Y > Start.Y && Pt.Y > End.Y))
return false;
// now we calculate the distance:
float dy = End.Y - Start.Y;
float dx = End.X - Start.X;
float Z = dy * Pt.X - dx * Pt.Y + Start.Y * End.X - Start.X * End.Y;
float N = dy * dy + dx * dx;
float dist = (float)( Math.Abs(Z) / Math.Sqrt(N));
// done:
return dist < Linewidth / 2f;
}
}
Define a List for the lines, probably at class level:
List<Line> lines = new List<Line>();
Here is how you can initialize it with a few lines:
for (int i = 0; i < 20; i++) lines.Add(new Line(Color.Black, 4f,
new Point(R.Next(panel1.Width), R.Next(panel1.Height)),
new Point(R.Next(panel1.Width), R.Next(panel1.Height))));
Here is the result of clicking on a crossing:
Whenever you add, change or remove a line you need to make the Panel reflect the news by triggering the Paint event:
panel1.Invalidate();
Here is the Paint event of the Panel:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Line L in lines) L.Draw(e.Graphics);
}
In the MouseClick event you do the test:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
foreach(Line L in lines)
L.LineColor = L.HitTest(e.Location) ? Color.Red : Color.Black;
panel1.Invalidate();
}
To avoid flicker don't use the basic Panel class as it isn't doublebuffered. Instead use either a PictureBox or a Label (with AutoSize=false) or a doublebuffered Panel subclass:
class DrawPanel : Panel
{ public DrawPanel () { DoubleBuffered = true; } }
Notes:
There is no such thing as a 'Line' in WinForms, only pixels of various colors. So to select a line you need to store it's two endpoints' coordinates and then find out if you have hit it when clicking.
The above example shows how to do it in math.
Instead one could test each line by drawing it onto a bitmap and test the pixel the mouse has clicked. But drawing those bitmaps would have to do math behind the scenes as well and also allocate space for the bitmaps, so the math will be more efficient..
Yes the Line class looks a little long for such a simple thing a s a line but look how short all the event codes now are! That's because the responsiblities are where they belong!
Also note the the first rule of doing any drawing in WinForms is: Never cache or store a Grahics object. In fact you shouldn't ever use CreateGraphics in the first place, as the Graphics object will never stay in scope and the graphics it produces will not persist (i.e. survive a Minimize-maximize sequence)..
Also note how I pass out the e.Graphics object of the Paint event's parameters to the Line instances so they can draw themselves with a current Graphics object!
To select thinner lines it may help to modify the distance check a little..
The Math was taken directly form Wikipedia.
You can change the color of everything on click. By using click event of particular object.
I give you an example for button. If you click on button then panal’s color will be change. You can modify the code as per your requirement.
private List<Point> coordFirst = new List<Point>();
private List<Point> coordLast = new List<Point>();
public Graphics canvas;
private void Form1_Load(object sender, EventArgs e)
{
canvas = panel1.CreateGraphics();
}
private void panel1_Click(object sender, EventArgs e)
{
panel1.BackColor = Color.Blue;
}
private void nonSelectableButton3_Click(object sender, EventArgs e)
{
panel1.BackColor = Color.BurlyWood;
}
Related
I'm trying to create a custom Canvas by inherit from Canvas with the so famous feature Zoom and Pan.
I succeeded to Pan and Zoom using the mouse events (move and wheel), BUT : all the canvas (in my case black background) moved and not only my few shapes.
it's about the global Pan and Zoom and not drag&Drop one shape
so I added a custom Shape inherited from shape like this :
public class DataShape : Shape, INotifyPropertyChanged
{
public int ID;
public Geometry DataShapeGeometry;
public ScaleTransform ShapeScaleTransfrom;
public TranslateTransform ShapeTranslateTransform;
public TransformGroup ShapeTransformGroup;
protected override Geometry DefiningGeometry { get { return DataShapeGeometry; } }
public DataShape()
{
DataShapeGeometry = new LineGeometry(); // just to not having Null object that prevent creation of " DataShapeGeometry.Transform "
ShapeTransformGroup = new TransformGroup();
ShapeTranslateTransform = new TranslateTransform();
ShapeScaleTransfrom = new ScaleTransform();
ShapeTransformGroup.Children.Add(ShapeTranslateTransform);
ShapeTransformGroup.Children.Add(ShapeScaleTransfrom);
DataShapeGeometry.Transform = ShapeTransformGroup;
}
for the Custom Canvas I have this (part of the code)
first I used the _pan TranslateTransform as a global Transform, as I said it worked but all my Canvas moved, then i wonted to use the shapeTranslateTransform and the shapeScalTransform , no reaction but i confirmed that the values incremente properly (the zoom geting bigger and bigger , same for the offset, i even used a Textbox to show that :))
public class ZoomPanCanvas : Canvas
{
public static int Global_ID = 0;
public MainWindow w1;
public List<DataShape> selectedDataShapes;
public DataShape selectedShape;
private Point? dragStartPoint = null;
private Matrix transform = Matrix.Identity;
private TranslateTransform _pan = new TranslateTransform();
public ZoomPanCanvas()
{
this.RenderTransform = _pan;
this.MouseWheel += ZoomPanCanvas_MouseWheel;
this.MouseLeftButtonDown += ZoomPanCanvas_MouseLeftButtonDown;
this.MouseMove += ZoomPanCanvas_MouseMove;
this.MouseLeftButtonUp += ZoomPanCanvas_MouseLeftButtonUp;
}
public void RedrawAll()
{
this.InvalidateArrange();
}
#region EVENTS_METHOD
private void ZoomPanCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.Cursor = Cursors.Hand;
dragStartPoint = e.GetPosition(this);
}
bool b = false;int j = 0;
private void ZoomPanCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point point = e.GetPosition(this);
/* this was working <--------------------------------------
_pan.X += point.X - dragStartPoint.Value.X;
_pan.Y += point.Y - dragStartPoint.Value.Y;*/
foreach (UIElement datashape in this.Children)
{
// it works we need to pan each shape
selectedShape = datashape as DataShape;
((TranslateTransform) (selectedShape.ShapeTransformGroup.Children[0])).X += point.X - dragStartPoint.Value.X;
((TranslateTransform)(selectedShape.ShapeTransformGroup.Children[0])).Y += point.Y - dragStartPoint.Value.Y;
//((selectedShape.DataShapeGeometry.Transform)as TranslateTransform).X += point.X - dragStartPoint.Value.X;
// ((selectedShape.DataShapeGeometry.Transform) as TranslateTransform).Y += point.Y - dragStartPoint.Value.Y;
}
dragStartPoint = point;
}
}
private void ZoomPanCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.Cursor = Cursors.Arrow;
dragStartPoint = null;
}
private void ZoomPanCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point position = e.GetPosition(this);
// scale get only two values, it does'nt increment !
double scale = e.Delta > 0 ? 1.1 : (1.0 / 1.1);
//this.transform.ScaleAt(scale, scale, position.X, position.Y);
//this.RenderTransform = new MatrixTransform(this.transform);
foreach (UIElement datashape in this.Children)
{
// it works we need to pan each shape
selectedShape = datashape as DataShape;
//selectedShape.DataShapeGeometry.Transform.Value.Scale(scale, scale);
((ScaleTransform)(selectedShape.ShapeTransformGroup.Children[1])).ScaleX = ((ScaleTransform)(selectedShape.ShapeTransformGroup.Children[1])).ScaleX * scale;
((ScaleTransform)(selectedShape.ShapeTransformGroup.Children[1])).ScaleY = ((ScaleTransform)(selectedShape.ShapeTransformGroup.Children[1])).ScaleY * scale;
w1.TXT1.Text = ((ScaleTransform)(selectedShape.ShapeTransformGroup.Children[1])).ScaleX.ToString();
}
}
#endregion
}
I trayed to apply the GroupTransform to initialize all types of transform (Translate for Pan andScale for Zoom) in the Datashape Constructor.
I reached "selectedShape.ShapeTransformGroup.Children[]" from inside my ZoomPanCanvas i confirmed that values change but no impact in the interface.
I dare have a great expectation to create a sort of intelligent Cad Canvas (or like visio ).
I will not use ItemsControl, it's useful but when dealing with Algorithmic Geometry I prefer a straightforward simple canvas.
Many thanks
I want to click on points that I drew.
It would be also cool if a window would popup and I could do something with that. But the general thing i want to do is clicking on a drawn point. I want to make it work, that i can click on the map on points that I drew.
Example image:
public partial class Form1 : Form
{
Graphics g;
Pen p;
Point cursor;
int k = 0;
Point[] points = new Point[50];
public Form1()
{
InitializeComponent();
g = pbxkarte.CreateGraphics();
p = new Pen(Color.DeepSkyBlue, 3);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Pbxkarte_Click(object sender, EventArgs e)
{
if (drawmodecbx.Checked == true)
{
g.DrawEllipse(p, cursor.X - 10, cursor.Y - 10, 20, 20);
points[k++] = new Point(cursor.X, cursor.Y);
lbxDrawnPoints.Items.Add("X:" + cursor.X + "Y:" + cursor.Y);
}
}
private void Pbxkarte_MouseMove(object sender, MouseEventArgs e)
{
cursor = this.PointToClient(Cursor.Position);
xydisplay.Text = "X:" + cursor.X + "Y:" + cursor.Y;
}
}
}
Example code:
Two class level variables and a helper function:
List<Point> dots = new List<Point>();
int dotSize = 12;
Rectangle fromPoint(Point pt, int size)
{
return new Rectangle(pt.X - size/ 2, pt.Y - size / 2, size, size);
}
The mouseclick (as opposed to the click event) contains the location:
private void Pbxkarte_MouseClick(object sender, MouseEventArgs e)
{
if (!dots.Contains(e.Location))
{
dots.Add(e.Location);
Pbxkarte.Invalidate(); // show the dots
}
}
You could add code to remove dots or change the properties, esp. if you create a dot class. - If you want to avoid overlapping dots you can to use code like the one in the mousemove to detect this. But. Don't repeat the code! Instead factor out a boolOrPoint IsDotAt(Point) function you can use both times!!
In the mousemove I only show the hit state. You do your thing..
private void Pbxkarte_MouseMove(object sender, MouseEventArgs e)
{
bool hit = false;
foreach (var dot in dots)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(fromPoint(dot, dotSize));
if (gp.IsVisible(e.Location))
{
hit = true; break;
}
}
}
Cursor = hit ? Cursors.Hand : Cursors.Default;
}
All dot in the list must get shown every time anything changes, both in the list or in the system.:
private void Pbxkarte_Paint(object sender, PaintEventArgs e)
{
foreach (var dot in dots)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(fromPoint(dot, dotSize));
e.Graphics.FillPath(Brushes.Red, gp);
}
}
}
If you want more properties, like texts or colors do create a class dot and use a List<dot> !
How is it possible to draw a line to link treeview node to another treeview node
link should be shown in from
In WinForms TreeViews are special.
For one they don't have a Paint event, so it is not possible to draw on them.
(You can subclass them though, see the update below..!)
Secondly you can't nest a transparent control in them. You can nest it but it won't be transparent..)
So drawing onto the TreeView seems to be imposible. But maybe it is not what you want anyway..?
Let's instead draw a line between two TreeViews, connection two TreeNodes n1 and n2.
Let's place the TVs onto a Panel panel1.
For testing I create two class level Points p1 and p2:
Point p1 = Point.Empty;
Point p2 = Point.Empty;
In the Panel's Paint event we draw the line:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Firebrick, p1, p2);
}
For testing I set the Points in the NodeMouseClick event:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode n1 = e.Node;
// for testing I search for a corresponding node:
TreeNode n2 = treeView2.Nodes.Find(n1.Name, true).First();
// for testing I select the node:
treeView2.SelectedNode = n2;
// top left points in the node:
p1 = n1.Bounds.Location;
p2 = n2.Bounds.Location;
// add the offset of the treviews:
p1.Offset(treeView1.Left, treeView1.Top);
p2.Offset(treeView2.Left, treeView2.Top);
// trigger the paint event;
panel1.Invalidate();
}
Note that the above code connects the upper left points of the nodes.
To connect the outsides of the respective lines you could calculate the points like this:
p1 = new Point(treeView1.Right, n1.Bounds.Top + n1.Bounds.Height / 2 + treeView1.Top);
p2 = new Point(treeView2.Left, n2.Bounds.Top + n2.Bounds.Height / 2 + treeView2.Top);
Update: Big thanks to Larstech for his info about overriding the WndProc method and catching WM_PAINT. I tend to block out WndProc ;-)
Using this technique it is indeed possible to draw onto a TreeView:
This screenshot uses a TreeView subclass and paints three lines: One on each TV and one on the Panel below.
Here is the TreeView class:
class PTreeView : TreeView
{
public bool IsLeft { get; set; }
public int BorderWidth { get; private set; }
private float slope { get; set; }
private Point Pt { get; set; }
public PTreeView() { }
public void markNode(TreeNode node, float slope_)
{
if (this.IsLeft ) Pt =
new Point(node.Bounds.Right, node.Bounds.Top + node.Bounds.Height / 2);
else Pt = new Point(node.Bounds.Left, node.Bounds.Top + node.Bounds.Height / 2);
slope = slope_;
BorderWidth = (this.Width - this.ClientRectangle.Width) / 2;
}
internal const int WM_PAINT = 0xF;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
{
Graphics G = this.CreateGraphics();
G.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
int px = IsLeft ? this.ClientRectangle.Width : 0;
int py = (int)(Pt.Y + slope * (Pt.X - px));
Point p0 = new Point(px, py);
G.DrawLine(Pens.Coral, Pt, p0);
}
}
}
It exposes a bool to set if the TV is left or right of the other one and its BorderWidth, and a method markNode that determines which node should be connected with the lines and what slope the line has.
The NodeMouseClick has been expanded a little:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode n1 = e.Node;
TreeNode n2 = treeView2.Nodes.Find(n1.Name, true).First();
treeView2.SelectedNode = n2;
p1 = new Point(
treeView1.Left + n2.Bounds.Left + n1.Bounds.Width + treeView1.BorderWidth,
treeView1.Top + n1.Bounds.Top + n1.Bounds.Height / 2 + treeView1.BorderWidth);
p2 = new Point(
treeView2.Left + n2.Bounds.Left + treeView2.BorderWidth,
treeView2.Top + n2.Bounds.Top + n2.Bounds.Height / 2 + treeView2.BorderWidth);
float slope = -1f * (p2.Y - p1.Y) / (p2.X - p1.X);
treeView1.markNode(n1, slope);
treeView2.markNode(n2, slope);
panel1.Invalidate();
treeView1.Invalidate();
treeView2.Invalidate();
}
It now calculates the slope and calls both markNode and Invalidate on both treeviews..
No real changes in the Panel Paint:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.DrawLine(Pens.Coral, p1, p2);
}
I'm currently working on a battleships game,but i've ran into an issue.So far i've managed to draw the grid.the purpose of the draw method is to draw an image(don't know how to/if i can color a certain surface) inside a square in the grid,when i left-click.
the problem here is that,even if the image's size is 25x25(the size of a square) it occupies like half the screen,and that's when it works.50% of the times when i run nothing happens,and the other 50% it draws a huge image in the middle of the screen,regardless of where the cursor is located or if i left-click.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Paint += new PaintEventHandler(form1_paint);
}
private void form1_paint(object sender, PaintEventArgs e)
{
draw(e);
}
int x,y;
private void draw(PaintEventArgs e)
{
if (MouseButtons.Left != 0)
{
x = Cursor.Position.X;
y = Cursor.Position.Y;
Image poza = Image.FromFile("D://C//12E//c#//yellow4.jpg");
if (x < 301 && x > 24 && y < 301 && y > 24)
{
PointF coltz = new PointF(x / 25 * 25, y / 25 * 25);
e.Graphics.DrawImage(poza, coltz);
}
}
}
Does anyone know how i can solve this?or if someone has a better idea for a battleships grid, I am open to suggestions.Thanks!
Fisrt of all, this line of code: Cursor.Position.X gives you the global position of the cursor on the screen, not in the game window. I suggest you to handle MouseMove event to get the position relative to the content of your app.
The second thing is that you are loading the image from file on your computer. I think it's better to add the image to your app's resources, so you can load it easier just calling it by name, e.g.: AppName.Properties.Resources.ImageName - it returns Image object you can immediately use.
One more thing. This if (MouseButtons.Left != 0) won't check whether left mouse button is pressed or not. You have to check if MouseButtons property equals System.Windows.Forms.MouseButtons.Left.
Here's the full code that works for me:
public partial class Form1 : Form
{
private int x, y;
public Form1()
{
InitializeComponent();
Paint += Form1_Paint;
MouseMove += Form1_MouseMove;
MouseDown += Form1_MouseMove;
}
void Form1_Paint(object sender, PaintEventArgs e)
{
Draw(e);
}
private void Draw(PaintEventArgs e)
{
if (MouseButtons == System.Windows.Forms.MouseButtons.Left)
{
if (x < 301 && x > 24 && y < 301 && y > 24)
{
PointF coltz = new PointF(x / 25 * 25, y / 25 * 25);
e.Graphics.DrawImage(AppName.Properties.Resources.ImageName, coltz);
}
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
Invalidate();
}
}
And here's the result:
I also subscribed MouseDown event to show yellow rectangle when user clicks the button without moving the cursor.
the thing is,before adding your code,the draw worked fine.now,every time i move the mouse,the grid gets redrawn,and it looks like it's constantly refreshing,bleeping somehow.not sure how to phrase this
public Form1()
{
InitializeComponent();
Paint += Form1_Paint;
MouseMove += Form1_MouseMove;
MouseDown += Form1_MouseMove;
}
private int x,y;
void Form1_Paint(object sender, PaintEventArgs e)
{
Draw(e);
}
private void Draw(PaintEventArgs e)
{
if (MouseButtons == System.Windows.Forms.MouseButtons.Left)
{
if (x < 301 && x > 24 && y < 301 && y > 24)
{
PointF coltz = new PointF(x / 25 * 25, y / 25 * 25);
e.Graphics.DrawImage(battleships.Properties.Resources.yellow4, coltz);
}
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g;
g = e.Graphics;
Pen pen = new Pen(Color.Black);
pen.Width = 1;
for (int i = 25; i <= 300; i = i + 25)
{
g.DrawLine(pen, i, 25, i, 300);
g.DrawLine(pen, 25, i, 300, i);
}
}
}
I have a GroupBox that has multiple controls, specifically 4 PictureBoxes.
These are pieces of an image puzzle. Please note that the number of images can change. I want to allow a drag and drop effect to each of them. To mark the source and the destination I did the following:
foreach (var box in boxes)
{
box.DragEnter += new DragEventHandler(box_DragEnter);
box.MouseDown += new MouseEventHandler(box_MouseDown);
box.DragDrop += new DragEventHandler(box_DragDrop);
box.AllowDrop = true;
}
When a box is clicked it will be marked to a global variable (that will be the source) and when a box raises the DragDrop event that will be the destination.
As I previously mentioned, since the number of the boxes can be changed I do not want to add separate methods as handlers for each event.
My issue here is that I do not know how to "detect" which box has raised what event.
Example:
*If I press on the left-top image I want to know that I pressed on it to mark the source (let's say global picSource = 1) and if I drop on right-bottom image I want to know that as a destination (picDestination = 4). All that must occur in the handlers. *
Tests:
Adding a parent panel (same size as the GroupBox) with a Click event & doing a comparison between a Point issued with the X&Y provided by the event handler and a rectangle designated with the X,Y, width, height of the panel.
Adding handlers to the GroupBox (does not work either)
Notes:
e.X and e.Y refer to the position of the mouse
void box_MouseDown(object sender, MouseEventArgs e)
The purpose of this is to switch boxes (source <--> destination)
You can just detect puzzle element by mouse's coordinates in the controls container's MouseDown and MouseUp event as follows:
public partial class PuzzleForm : Form
{
private readonly Image[,] Images;
private readonly int Nx;
private readonly int Ny;
private int sourceIndexX;
private int sourceIndexY;
private int destinationIndexX;
private int destinationIndexY;
private PuzzleForm()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true);
InitializeComponent();
}
public PuzzleForm(Image[,] images)
: this()
{
Images = images;
Nx = Images.GetLength(0);
Ny = Images.GetLength(1);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Graphics g = e.Graphics)
{
for (int j = 0; j < Ny; j++)
for (int i = 0; i < Nx; i++)
{
Rectangle rect = new Rectangle(ClientSize.Width * i / Nx, ClientSize.Height * j / Ny, ClientSize.Width / Nx - 1, ClientSize.Height / Ny - 1);
g.DrawImage(Images[i, j], rect);
}
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button != MouseButtons.Left)
return;
sourceIndexX = e.X * Nx / ClientSize.Width;
sourceIndexY = e.Y * Ny / ClientSize.Height;
Cursor = Cursors.Hand;
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (e.Button != MouseButtons.Left)
return;
destinationIndexX = e.X * Nx / ClientSize.Width;
destinationIndexY = e.Y * Ny / ClientSize.Height;
Cursor = Cursors.Default;
if (sourceIndexX != destinationIndexX || sourceIndexY != destinationIndexY)
{
swapImages();
MessageBox.Show(String.Format("From [{0}, {1}] to [{2}, {3}]", sourceIndexX, sourceIndexY, destinationIndexX, destinationIndexY));
}
}
private void swapImages()
{
Image tmp = Images[sourceIndexX, sourceIndexY];
Images[sourceIndexX, sourceIndexY] = Images[destinationIndexX, destinationIndexY];
Images[destinationIndexX, destinationIndexY] = tmp;
Invalidate();
}
}
Usage:
Image[,] images = new Image[2, 2];
// Fill array with images:
images[0, 0] = Bitmap.FromFile(#"...");
images[0, 1] = Bitmap.FromFile(#"...");
images[1, 0] = Bitmap.FromFile(#"...");
images[1, 1] = Bitmap.FromFile(#"...");
PuzzleForm puzzleForm = new PuzzleForm(images);
// Show form or whatever you want.
...