I made a class Schalter (eng. switch) and now I want to drag and drop this to an other position. The Schalter is a just an object with 0 or 1 as output and it has some drawing in it. I tried something but it just worked half. When I move it it moves much too fast.
Here the code I tried:
namespace Schaltungszeichner {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
s = new Schalter(this);
this.DoubleBuffered = true;
}
private bool myMouseDown = false;
private int myMouseX, myMouseY;
Schalter s;
private void Form1_Paint(object sender, PaintEventArgs e) {
s.zeichnen(e.Graphics);
}
private void Form1_MouseMove(object sender, MouseEventArgs e) {
if (myMouseDown) {
s.X += e.X - myMouseX;
s.Y += e.Y - myMouseY;
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e) {
myMouseDown = false;
}
private void Form1_MouseDown(object sender, MouseEventArgs e) {
if (s.isClicked(e.X, e.Y)) {
s.Out = !s.Out;
myMouseDown = true;
myMouseX = e.X;
myMouseY = e.Y;
}
}
}
}
The problem is that MouseEventArgs holds the mouse position relative to the object which owns the event and not the object being moved. You need to account for this by subtracting the starting position of the moving object.
In Form1_MouseDown change:
myMouseX = e.X;
myMouseY = e.Y;
to:
myMouseX = e.X - s.X;
myMouseY = e.Y - s.Y;
And in Form1_MouseMove change:
s.X += e.X - myMouseX;
s.Y += e.Y - myMouseY;
to:
s.X = e.X - myMouseX;
s.Y = e.Y - myMouseY;
I would also consider renaming myMouseX and myMouseY to something that reflects the values that they now hold, like differenceX and differenceY.
Related
This is more of a question of methodology. I know how to create a control that scales from all sides, but I don't understand why this code doesn't work fluidly without redraw issues (jittering). It scales the panel from the top only, but jitters in the process. What am I missing?
public partial class Form1 : Form
{
Point MousePoint = new Point();
public Form1()
{
InitializeComponent();
panel1.MouseMove += Panel1_MouseMove;
panel1.MouseDown += Panel1_MouseDown;
panel1.Width = 100;
panel1.Height = 100;
}
private void Panel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MousePoint = e.Location;
}
}
private void Panel1_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
panel1.Top = e.Location.Y + panel1.Location.Y - MousePoint.Y;
panel1.Height = panel1.Height - e.Y + MousePoint.Y;
}
}
}
You are changing two different properties: the top, then the height. That could cause the "jittering" you are seeing.
Try using the SetBounds call instead:
panel1.SetBounds(panel1.Left,
e.Location.Y + panel1.Location.Y - mousePoint.Y,
panel1.Width,
panel1.Height - e.Y + mousePoint.Y);
If there are contained controls inside the panel that are anchored, etc, that could affect that smoothness of the resizing, too.
I am a beginner programmer and I feel like I am repeating code unnecessarily. I want to make a picture puzzle game consisting of 16 pictureboxes. The problem is that I feel like I have to repeat code for each picturebox's events as in the below example:
Point move;
bool isDragging = false;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if(isDragging == true)
{
pictureBox1.Left += e.X - move.X;
pictureBox1.Top += e.Y - move.Y;
pictureBox1.BringToFront();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
Just create one method for each of your 3 events:
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if(isDragging == true)
{
// Luckily the sender parameter will tell us which PictureBox we are dealing with
PictureBox pb = (PictureBox)sender;
pb.Left += e.X - move.X;
pb.Top += e.Y - move.Y;
pb.BringToFront();
}
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
Then go to each of your 16 picture boxes in the designer and set the MouseUp event handler to point to pictureBox_MouseUp and the MouseMove event handler to point to pictureBox_MouseMove and the MouseDown event handler to point to pictureBox_MouseMove. Do this for each of the 16 picture boxes.
Try to trigger same events for all PictureBox Controls
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
PictureBox pictureBox = sender as PictureBox;
if(isDragging == true)
{
pictureBox .Left += e.X - move.X;
pictureBox .Top += e.Y - move.Y;
pictureBox .BringToFront();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
Create a new component contained Image component and set dock parent container. Write your drag drop codes into the new component.
For example,
public partial class DraggablePictureBox : UserControl
{
public DraggablePictureBox()
{
InitializeComponent();
}
/// <summary>
/// Sets image of inner picture
/// </summary>
public Image Image
{
get {
return InnerPictureBox.Image;
}
set
{
InnerPictureBox.Image = value;
}
}
private void InnerPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging == true)
{
this.Left += e.X - move.X;
this.Top += e.Y - move.Y;
this.BringToFront();
}
}
private void InnerPictureBox_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
private void InnerPictureBox_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
move = e.Location;
}
private Point move;
private bool isDragging = false;
}
Now you have a one drag drop code for images.
One way to combat this would be to put these in methods, for example
MovePicturePox(Point move, Point newPos, PictureBox pb)
{
pb.Left += newPos.X - move.X;
pb.Top += newPos.Y - move.Y;
pb.BringToFront();
}
These methods can then be called like so
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if(isDragging == true)
{
MovePictureBox(move, new Point(e.X, y.Y), pictureBox1);
}
}
I am having trouble with painting usercontrol on form while moving the control.
The background of the control is shortened if moved to the right or downwards.
My control
public class DotPanel : Control
{
public DotPanel()
{
this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.Yellow),new Rectangle(this.Location,this.Size));
}
}
The main form just places the usercontrol on specified location and supplies the mouse down/move/up events to do the moving
Basicaly this>>
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mouseX = e.X;
mouseY = e.Y;
panelX = dp1.Left;
panelY = dp1.Top;
moving = true;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (moving)
{
dp1.Left = panelX + e.X - mouseX;
dp1.Top = panelY + e.Y - mouseY;
this.Invalidate(true);
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
moving = false;
this.Invalidate(true);
}
Thanks in advance for any clues...
the overriden paint was the problem.
exchanging this.Size and this.Location for ClientRectangle.Size and ClientRectangle.Location worked...
I made a script for 1 form with 2 pictureboxes, until here everything is fine.
If you execute the code below, than you can see you can move the picturebox1 and also drop it inside picturebox2. Now i would like that the dropped picturebox1 can be resized, rotated and moved around inside picturebox2 (once executed by client).
I have looked around but can not find the answers to this problem. Any help i would appreciate, Thank you
Here is the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int x = 0;
int y = 0;
bool drag = false;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
pictureBox1.DoDragDrop(pictureBox1.Image, DragDropEffects.Copy);
x = e.X;
y = e.Y;
drag = true;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
//position new get
pictureBox1.Top += e.Y - y;
pictureBox1.Left += e.X - x;
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
drag = false;
}
private void pictureBox2_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.All;
}
private void pictureBox2_DragDrop(object sender, DragEventArgs e)
{
pictureBox2.Image = (Image)e.Data.GetData(DataFormats.Bitmap);
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox2.AllowDrop = true;
}
}
}
In order to resize the pictureboxes you can define the following methods:
private void IncreaseSize(PictureBox p,int dt)
{
Size size = p.Size;
size.Height = size.Height + dt;
size.Width=size.Width + dt;
p.Size = size;
}
private void DecreaseSize(PictureBox p, int dt)
{
Size size = p.Size;
size.Height = size.Height - dt;
size.Width = size.Width - dt;
p.Size = size;
}
These methods can be called to events that you decide in your main form e.g:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
IncreaseSize(pictureBox1,5);
}
private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
{
DecreaseSize(pictureBox2, 10);
}
I need to make a graph of lines from a csv file and draw it with GDI got a Windows form but now I want to change the scale and move.
I started with something more simple as moving a rectangle with the mouse but to start drawing the rectangle always from the origin.
Can anyone help?
My code is:
public partial class Form1 : Form {
int origenX;
int origenY;
bool transformar = false;
public Form1() {
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e) {
dibujar(e.Graphics);
}
private void Form1_MouseMove(object sender, MouseEventArgs e) {
int deltaX = e.X - origenX;
int deltaY = e.Y - origenY;
if (transformar) {
System.Drawing.Graphics g = this.CreateGraphics();
Matrix mAux = new Matrix();
mAux.Translate(deltaX, deltaY);
g.Transform = mAux;
dibujar(g);
g.Dispose();
}
this.Text = "x=" + deltaX.ToString() + ", y=" + deltaY.ToString();
}
private void Form1_MouseDown(object sender, MouseEventArgs e) {
transformar = true;
origenX = e.X;
origenY = e.Y;
}
private void Form1_MouseUp(object sender, MouseEventArgs e) {
transformar = false;
}
private void dibujar(System.Drawing.Graphics g) {
g.Clear(Color.White);
g.DrawEllipse(new Pen(Color.Blue, 2), new Rectangle(50, 50, 50, 50));
}
}
Already solved, thanks anyway, the code was as follows:
public partial class Form2 : Form {
private float dx=0;
private float dy=0;
private float X0=1;
private float Y0=1;
private bool trasladar = false;
public Form2() {
InitializeComponent();
}
private void Form2_Paint(object sender, PaintEventArgs e) {
e.Graphics.TranslateTransform(dx, dy, MatrixOrder.Append);
e.Graphics.Clear(Color.White);
e.Graphics.DrawEllipse(new Pen(Color.Blue), new Rectangle(50, 50, 50, 50));
}
private void Form2_MouseDown(object sender, MouseEventArgs e) {
Cursor = Cursors.SizeAll;
trasladar = true;
X0 = e.X;
Y0 = e.Y;
}
private void Form2_MouseUp(object sender, MouseEventArgs e) {
Cursor = Cursors.Default;
trasladar = false;
}
private void Form2_MouseMove(object sender, MouseEventArgs e) {
if (trasladar) {
dx += (e.X - X0);
dy += (e.Y - Y0);
X0 = e.X;
Y0 = e.Y;
Invalidate();
}
}
}
Use this.Invalidate(); when the form should redraw.
It will declare the form as invalid, so it will be forced to redraw. Only then the Form1_Paint will be called.
Test this behaivour by doing an Debug output in the Paint-Event.
Then you can start further debugging to get what you want.