How to inherit events between objects - c#

I need inherit events and properties. For example, I need to move a picture around a form.
I have this code to move one picture but I need to create multiple images with the same behavior.
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
x = e.X;
y = e.Y;
}
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pictureBox.Left += (e.X -x);
pictureBox.Top += (e.Y - y);
}
}

Create custom control:
public class MovablePictureBox : PictureBox
{
private int x;
private int y;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
x = e.X;
y = e.Y;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
Left += (e.X - x);
Top += (e.Y - y);
}
}
}
UPDATE:
Instead of attaching a delegates, you should override inherited event functionality, as Microsoft recommends here.
After creating this control just compile program and drag your MovablePictureBoxes from Toolbox to form. They all will be draggable (or movable, if you wish).

What you really want to do is have your multiple PictureBoxes share the same event handlers:
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// the "sender" of this event will be the picture box who fired this event
PictureBox thisBox = sender as PictureBox;
thisBox.Left += (e.X -x);
thisBox.Top += (e.Y - y);
}
}
Each PictureBox you create on your form keep hooking them up to the same, already created, event. If you look at the above code you'll notice that it determines which PictureBox called it and affects just that picture box.

Related

MouseEnter with hook

I'm hooking my form with middle click. And for now i middle click to hook my form then middle click again to trigger my method to draw on my picturebox (which is on my form).
I'd like to middle click once and instantly draw on my picturebox instead of two middle click. I tried MouseHover and MouseEnter with this code :
private void PbxDrawing_MouseEnter(object sender, EventArgs e)
{
bMoving = true;
Point pos = PbxDrawing.PointToClient(Cursor.Position);
x = pos.X;
y = pos.Y;
}
Mouse move :
private void PbxDrawing_MouseMove(object sender, MouseEventArgs e)
{
if(bMoving && x!=-2 && y != -2)
{
g.DrawLine(pen,new Point(x,y), e.Location);
x = e.X;
y = e.Y;
}
}
It allows me to know the position of the cursor and draw but to draw i've to release middle click .
How can i draw from 1 middle click if my middle click was made outside of my form ?
Edit : Clarify question
Just check if the Middle Button is down in the MouseMove event:
private void PbxDrawing_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
x = e.X;
y = e.Y;
}
}
private void PbxDrawing_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
g.DrawLine(pen, new Point(x, y), e.Location);
x = e.X;
y = e.Y;
}
}
Your use of g is a red flag, though. Is g created with PbxDrawing.CreateGraphics()? If yes, this is wrong and should be refactored to use the e.Graphics from the Paint() event of the PictureBox.

Dragging Objects in C#

I am attempting to drag Music Notes vertically, up and down a Music Staff. However, rather than a constant drag, I would like the music notes to only be allowed to be dragged onto particular intervals (only specific y-coordinates). For example, in a vertical line, a music note can be dragged on to coordinates (0,0), (0,5) or (0,10).
Below is my relevant code:
private Point MouseDownLocation;
private void Note_MouseDown(object sender, MouseEventArgs e)
{
foreach (MusicNote mn in panel2.Controls.OfType<MusicNote>())
{
if (sender == mn)
{
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
}
}
private void Note_MouseMove(object sender, MouseEventArgs e)
{
foreach(MusicNote mn in panel2.Controls.OfType<MusicNote>())
{
if (sender == mn)
{
if (e.Button == MouseButtons.Left)
{
mn.Top = e.Y + mn.Top - MouseDownLocation.Y;
}
}
}
}
Any help is appreciated. Thank you!
Basically, you need to check if you drag up or drag down
You should want to check the MouseDown.X and compare it to the MouseUp.X (or Y if you want to check vertical direction as well). It is important to note that (0, 0) is the upper left of your screen. So you need to compare the X position from mouse down event to the mouse up event.
here's an example with one label that moves up and down in steps of 10
private void label1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (label1.Location.Y > 0 && label1.Location.Y < panel1.Size.Height) // not the most accurate way, but you get the idea
{
mPointDown = new Point(e.X, e.Y);
}
}
}
private void label1_MouseUp(object sender, MouseEventArgs e)
{
bool movedUp, movedDown;
if (e.Y == mPointDown.Y)
{
movedUp = movedDown = false;
}
else
{
movedUp = e.Y < mPointDown.Y;
movedDown = !movedUp;
}
if (movedDown)
{
label1.Location = new Point(label1.Location.X, label1.Location.Y + 10);
}
else if (movedUp)
{
label1.Location = new Point(label1.Location.X, label1.Location.Y - 10);
}
}
private void label1_MouseMove(object sender, MouseEventArgs e)
{
mouseDownPoint = e.Location;
}

Add MouseDown and MouseMove event on a class at runtime

I try to add an event handler to a personnal class that inherit from the .NET class "Panel".
I tried some several ways to do it but it's not working anymore...
I have a Principal Panel that contains other Panel. It's to design Grafcet.
So I have my class "Etape" that inherit from Panel :
class Etape : Panel
{
private Point MouseDownLocation;
private void Etape_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
this.BackColor = CouleurSelect;
MessageBox.Show("Bonjour");
}
}
private void Etape_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Left = e.X + this.Left - MouseDownLocation.X;
this.Top = e.Y + this.Top - MouseDownLocation.Y;
}
}
}
And I declare it like that :
toto = new Etape();
toto.BackColor = Color.White;
toto.BorderStyle = BorderStyle.FixedSingle;
toto.Width = 40;
toto.Height = 40;
"toto" is add to my "principal" Panel just after that.
I would like to add an Eventhandler to move my panels at runtime. I tried the code you can see above, but I think C# doesn't detect that I'm clicking on the Etape.
Do you have an idea or something to help me ?
Julien
You should override the OnMouseXXX methods:
class Etape : Panel
{
private Point MouseDownLocation;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
this.BackColor = CouleurSelect;
MessageBox.Show("Bonjour");
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
this.Left = e.X + this.Left - MouseDownLocation.X;
this.Top = e.Y + this.Top - MouseDownLocation.Y;
}
}
}
Just declaring a method called Etape_MouseMove() doesn't hook anything up to it.
You need to hook the functions to an event
class Etape : Panel
{
public Etape()
{
MouseDown += Etape_MouseDown;
MouseMove += Etape_MouseMove;
}
private Point MouseDownLocation;
private void Etape_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
this.BackColor = CouleurSelect;
MessageBox.Show("Bonjour");
}
}
private void Etape_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Left = e.X + this.Left - MouseDownLocation.X;
this.Top = e.Y + this.Top - MouseDownLocation.Y;
}
}
}

Drag string on picturebox - C#

I have a picture box and I draw a string on it by DrawString(). I change position of the string by scrolling a TrackBar. But I want to move the string by directly clicking on the string and then dragging. It'll be easier for any user. Can anybody help me achieve this?
Edit: I already move my pictureBox1 my mouse click:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(img, 0, 0);
e.Graphics.DrawString(str, font, new SolidBrush(color), new PointF(NinjaClass.NINJA.pointX, NinjaClass.NINJA.pointY));
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
x = e.X;
y = e.Y;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pictureBox1.Left += (e.X - x);
pictureBox1.Top += (e.Y - y);
}
}
Using DrawString is not very convenient for such a task, you have to save a Rectangle around the string, update that rectangle according to the mouse movement ... If we need to click exactly on the string curve to move the string, using DrawString can't help. In such a case we have to use a GraphicsPath which supports a little hittesting. However in this case we just allow user to click on the string bounds, because clicking on the string curve with small font or even normal font is not easy and very annoying indeed. Try the following code:
//your form constructor
public Form1(){
InitializeComponent();
//add string to the GraphicsPath, the string location is initialized with (10,10)
gp.AddString("Your string goes here", Font.FontFamily,
(int)Font.Style, 20, new Point(10, 10), StringFormat.GenericDefault);
}
GraphicsPath gp = new GraphicsPath();
float dx, dy;
//the Paint event handler for your pictureBox1
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
gp.Transform(new Matrix(1, 0, 0, 1, dx, dy));//Translate and paint
e.Graphics.FillPath(Brushes.Red, gp);
gp.Transform(new Matrix(1,0,0,1,-dx,-dy));//translate back (reset to old location)
}
Point downPoint;
bool hitOn;
//MouseDown event handler for your pictureBox1
private void pictureBox1_MouseDown(object sender, MouseEventArgs e){
if(e.Button == MouseButtons.Left){
downPoint = e.Location;
if (gp.GetBounds(new Matrix(1,0,0,1,dx,dy)).Contains(e.Location)) {
gp.Transform(new Matrix(1, 0, 0, 1, dx, dy));
hitOn = true;
}
}
}
//MouseMove event handler for your pictureBox1
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if(hitOn){
dx = e.X - downPoint.X;
dy = e.Y - downPoint.Y;
pictureBox1.Invalidate();
} else {
pictureBox1.Left += e.X - downPoint.X;
pictureBox1.Top += e.Y - downPoint.Y;
}
}
}
//MouseUp event handler for your pictureBox1
private void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
hitOn = false;
}
Update: For using a transparent backColor Label: There is a note that when you drag and drop a label on a pictureBox at design time, the Parent of the label will be the pictureBox container not the PictureBox, that's by design, because PictureBox is not intended to contain any control. So you have to set the Parent using code, for the code moving the label, you do similarly to what you do with your PictureBox, the difference is the parent of PictureBox is your form while the parent of the label is your pictureBox:
public Form1(){
InitializeComponent();
label1.BackColor = Color.Transparent;
label1.Parent = pictureBox1;
//try this to prevent a little flicker, but looks like it does not help much
typeof(Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance)
.SetValue(pictureBox1, true, null);
}
Point lblDownPoint;
//MouseDown event handler for your label1
private void label1_MouseDown(object sender, MouseEventArgs e){
if(e.Button == MouseButtons.Left) lblDownPoint = e.Location;
}
//MouseMove event handler for your label1
private void label1_MouseMove(object sender, MouseEventArgs e){
if(e.Button == MouseButtons.Left) {
label1.Left += e.X - lblDownPoint.X;
label2.Top += e.Y - lblDownPoint.Y;
}
}
However after trying using a transparent BackColor label instead, I can see that it's fairly worse (caused by flicker) than draw directly on the pictureBox as the previous code does. You should consider to choose between them yourself, the previous code seems a little complicated (but not really if you understand it).

C# - Moving a control to the mouse's position

I am trying to get a control to follow the cursor when the user clicks and drag the control. The problem is that 1.) the control doesn't go to the mouse's position, and 2.) the control flickers and flies all over the place. I've tried a few different methods of doing this, but all so far have failed.
I've tried:
protected override void OnMouseDown(MouseEventArgs e)
{
while (e.Button == System.Windows.Forms.MouseButtons.Left)
{
this.Location = e.Location;
}
}
and
protected override void OnMouseMove(MouseEventArgs e)
{
while (e.Button == System.Windows.Forms.MouseButtons.Left)
{
this.Location = e.Location;
}
}
but neither of these work. Any help is appreciated, and thanks in advance!
Here's how to do it:
private Point _Offset = Point.Empty;
protected override void MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_Offset = new Point(e.X, e.Y);
}
}
protected override void MouseMove(object sender, MouseEventArgs e)
{
if (_Offset != Point.Empty)
{
Point newlocation = this.Location;
newlocation.X += e.X - _Offset.X;
newlocation.Y += e.Y - _Offset.Y;
this.Location = newlocation;
}
}
protected override void MouseUp(object sender, MouseEventArgs e)
{
_Offset = Point.Empty;
}
_Offset is used here for two purposes: keeping track of where the mouse was on the control when you initially clicked it, and also keeping track of whether the mouse button is down or not (so that the control doesn't get dragged when the mouse cursor goes over it and the button isn't down).
You definitely don't want to switch the ifs in this code to whiles, as it will make a difference.
there are mistakes in the answer 1
1.Set mouse handlers to control ,not to form
like button1_MouseMove
2.do not use this vector,but your control instead(Point newlocation = button1.Location;)
3.you do not need to override handlers.
in my test after these changes button(or other control) moves fine.
Chigook
Try this to move the object according to the mouse's position and the code below given is to gather the mouse's move path and the location saved in the arraylist to obtain the path where mouse point is moving. You have to declare the arraylist globally.
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ArrayList inList = new ArrayList();
inList.Add(e.X);
inList.Add(e.Y);
list.Add(inList);
}
}
When the user clicks the button the control has to move in the path that the user dragged in the screen
private void button1_Click_2(object sender, EventArgs e)
{
foreach (ArrayList li in list)
{
pic_trans.Visible = true;
pic_trans.Location = new Point(Convert.ToInt32(li[0]), Convert.ToInt32(li[1]));
pic_trans.Show();
}
}
private Point ptMouseDown=new Point();
protected override void MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ptMouseDown = new Point(e.X, e.Y);
}
}
protected override void MouseMove(object sender, MouseEventArgs e)
{
if (_Offset != Point.Empty)
{
Pointf[] ptArr=new Pointf[]{this.Location};
Point Diff=new Point(e.X-ptMouseDown.X,e.Y-ptMouseDown.Y);
Matrix mat=new Matrix();
mat.Translate(Diff.X,Diff.Y);
mat.TransFromPoints(ptArr);
this.Location=ptArr[0];
}
}
protected override void MouseUp(object sender, MouseEventArgs e)
{
_Offset = Point.Empty;
}

Categories

Resources