sorry to bother again with a similar question. However, I have an issue with my code again in C#. I would like to give you the code I have got so far:
private void pictureBox2_Click(object sender, EventArgs e)
{
PictureBox flower2 = new PictureBox();
flower2.Image = Properties.Resources.Flower3;
flower2.Location = new Point(panel1.Location.X + 10, panel1.Location.Y + 10);
flower2.Size = new System.Drawing.Size(pictureBox2.Size.Width, pictureBox2.Size.Height);
flower2.Parent = panel1;
this.Controls.Add(flower2);
flower2.BringToFront();
flower2.MouseMove += new MouseEventHandler(flower2_MouseMove);
flower2.MouseDown += new MouseEventHandler(flower2_MouseDown);
}
private void flower2_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
private void flower2_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
flower2.Left = e.X + flower2.Left - MouseDownLocation.X;
flower2.Top = e.Y + flower2.Top - MouseDownLocation.Y;
}
}
What I wanted it to do is when an image is clicked, create a new one and be able to drag and drop it. I succeeded only when I put my code at the top of the page. Which is not what I want because I want to be able to add as many images as I would like. I tried alot of different methods. The errors are at:
flower2.Left = e.X + flower2.Left - MouseDownLocation.X;
flower2.Top = e.Y + flower2.Top - MouseDownLocation.Y;
At all the words under the name of flower2. This is because, I have defined flower2 in pictureBox2_Click so everytime it's clicked a new PictureBox will generate. But, I need to make it so I can generate as many images as I want and without putting it at the top of the page, this makes it so it only uses one image at a time.
Each picturebox you make is routed to those events, thus the sender object is the picturebox, you just need to cast it to the right type then move that.
PictureBox pb = (PictureBox)sender;
pb.Left = e.X + pb.Left - MouseDownLocation.X;
Related
I've been trying to make a drag and drop game. I have 4 panels and 4 labels. You have to drag the labels on top of the correct panel.
The problem is checking if a label is on top of the panel. The user can frely drag the labels.
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
button1.Left = e.X + button1.Left - MouseDownLocation.X;
button1.Top = e.Y + button1.Top - MouseDownLocation.Y;
}
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
Here is the code i used to move the control. I have to mention that this is a test project, so I used a button instead of a label, but the idea is the same.
Is there any way if I can check whether a control is on top of another or not ?
After each move, simply get the Rectangle from the Bounds property of your button and panel, then use either Intersect() or Contains():
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
button1.Location = new Point(e.X + button1.Left - MouseDownLocation.X, e.Y + button1.Top - MouseDownLocation.Y);
Rectangle btnRC = button1.Bounds;
Rectangle pnlRC = panel1.Bounds;
// see if the rectangles INTERSECT
if (pnlRC.IntersectsWith(btnRC))
{
panel1.BackColor = Color.Green;
}
else
{
panel1.BackColor = this.BackColor;
}
// see if the panel COMPLETELY CONTAINS the button
if (pnlRC.Contains(btnRC))
{
panel1.BackColor = Color.Green;
}
else
{
panel1.BackColor = this.BackColor;
}
}
}
To check if the mouse is over the control, you can check if the Cursor.Position is in the ClientRectangle of the control, but you first need to call PointToClient method of the control to convert the cursor position relative to the panel's (0,0), for example:
var b = panel1.ClientRectangle.Contains(panel1.PointToClient(Cursor.Position));
The flag can be checked in the same event handler which is used to move the control, for example:
if(b) panel1.BackColor = Color.Red; else panel1.BackColor = Color.Gray;
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 making an application that requires tabs (tab-control) to be added or removed. I have done the add and remove for tabs fine, but I have custom buttons instead of using the tabs. (This button will go the the first tab page when clicked):
//This will make it go to TAB 1
private void button1_Click(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 0;
}
//This will change the MOUSEENTER to the correct image
private void button1_MouseEnter(object sender, EventArgs e)
{
button1.MouseEnter += new EventHandler(button1_MouseEnter);
this.button1.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.Tab_Down));
}
//This will change the MOUSELEAVE to the correct image
private void button1_MouseLeave(object sender, EventArgs e)
{
button1.MouseLeave += new EventHandler(button1_MouseLeave);
this.button1.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.Tab_Norm));
}
However, how will I create it so when you click the "Add Tab" button it creates a new tab but it also creates a new button with tabControl1.SelectedIndex = 1; in it for example.
Edit
I have done this to add a new tab (to tabControl1):
private void button2_Click(object sender, EventArgs e)
{
string title = "TabPage " + (tabControl1.TabCount + 1).ToString();
TabPage myTabPage = new TabPage(title);
tabControl1.TabPages.Add(myTabPage);
}
This adds a new tab on top of the existing ones fine. But I how do I do it so that it also creates a new button with the properties of the button above but makes it so instead of tabControl1.SelectedIndex = 1; it does tabControl1.SelectedIndex = 3; and goes up every time I add a new tab? - Thanks
After a few updates here is a new version of my answer. It shows you how to
Add a Button which adds a new TabPages and selects it
Make the Tab control draw closing 'x' characters to the right of each tab, like Firefox or Visual Studio do it.
Make the add Button like you want it, maybe the Text="+" and the height like the tabs' height. It is automatically positioned on the tab. You may need to reposition it, if your Tab is moved or resized.
In the Form_Load event the Tab is set to OwnerDrawFixed and each page's text is append by a few blanks to make room for the closing x. The code creates a class variable closeX to hold the current x-rectangle and tests it in the MouseClick event.
Make sure to wire up the tabControl1_DrawItem and tabControl1_MouseClick events!
private void cb_addPage_Click(object sender, EventArgs e)
{
string title = "TabPage " + (tabControl1.TabCount + 1).ToString() + " ";
TabPage myTabPage = new TabPage(title);
tabControl1.TabPages.Add(myTabPage);
tabControl1.SelectedTab = myTabPage;
}
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
cb_addPage.Top = tabControl1.Top;
cb_addPage.Left = tabControl1.Right - cb_addPage.Width;
foreach (TabPage tp in tabControl1.TabPages) tp.Text += " ";
}
Rectangle closeX = Rectangle.Empty;
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Size xSize = new Size(13,13);
TabPage tp = tabControl3.TabPages[e.Index];
e.DrawBackground();
using (SolidBrush brush = new SolidBrush(e.ForeColor) )
e.Graphics.DrawString(tp.Text+ " ", e.Font, brush,
e.Bounds.X + 3, e.Bounds.Y + 4 );
if (e.State == DrawItemState.Selected)
{
closeX = new Rectangle(
e.Bounds.Right - xSize.Width, e.Bounds.Top, xSize.Width, xSize.Height);
using (SolidBrush brush = new SolidBrush(Color.LightGray))
e.Graphics.DrawString("x", e.Font, brush,
e.Bounds.Right - xSize.Width, e.Bounds.Y + 4);
}
}
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
if (closeX.Contains(e.Location))
tabControl1.TabPages.Remove(tabControl1.SelectedTab);
}
If you want to use an Image to adorn the tabs, include an ImageList with your form, load it with the Image(s) and if the close button is the 1st image, change the code like this:
if (e.State == DrawItemState.Selected)
{
closeX = new Rectangle(e.Bounds.Right - xSize.Width - 3,
e.Bounds.Top + 5, xSize.Width, xSize.Height);
e.Graphics.DrawImage(imageList1.Images[0], closeX,
new Rectangle(0,0,16,16), GraphicsUnit.Pixel );
}
I append a screenshot of the Tab with a few pages
And one using this close button image:
Update: Note that if your TabPage contains IDisposable objects you should make sure they all get disposed before you remove the page! See here for example code!
I'm with a problem moving a label on a panel. When I move this label, reached the top and left (0.0), the label respects the top and left. To spend half of the screen, the label exceeds the panel as shown in picture.
My codes:
public partial class frmStandard : Form
{
Point startposition;
}
public void MouseDown(object sender, MouseEventArgs e)
{
startposition = e.Location;
}
public void MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
((Label)sender).Left = Math.Max(0, e.X + ((Label)sender).Left - startposition.X);
((Label)sender).Top = Math.Max(0, e.Y + ((Label)sender).Top - startposition.Y);
}
}
I need the label does not exceed the panel size.What should be added in the codes?
You need to check the other Borders.
You will have to use the dimension data of the containing Panel for this.
In the spirit of keeping things dynamic, as your code already is, I use he Label's Parent instead of referring to just the one Panel:
private void MouseMove(object sender, MouseEventArgs e)
{
Label L = (Label)sender;
Rectangle PR = L.Parent.ClientRectangle;
if (e.Button == MouseButtons.Left)
{
L.Left = Math.Min(Math.Max(0, e.X + L.Left - startposition.X), PR.Right - L.Width);
L.Top = Math.Min( Math.Max(0, e.Y + L.Top - startposition.Y), PR.Bottom - L.Height);
}
}
To keep it even more general, one could replace Label with Control and let the user move other Controls around wit the same pieces of code..
I am trying to write a program which will allow a user to drag and drop images into the program and then be able to select the image, move it about, re-size it, crop it etc.
So far I have created a windows form which consists of a panel. A user can drag a picture file onto the panel and a picturebox will be created at the coordinates of the mouse when it is dropped and an image is loaded in the picturebox. I can add several images in this fashion.
Now I want to allow the user to manipulate and move about the images that they have dropped into the panel.
I have tried searching for solutions but cant seem to find an answer which I understand.
Any help is much appreciated..
This is my current code
private void panel1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.All;
}
private void panel1_DragDrop(object sender, DragEventArgs e)
{
String[] imagePaths = (String[])e.Data.GetData(DataFormats.FileDrop);
foreach (string path in imagePaths)
{
Point point = panel1.PointToClient(Cursor.Position);
PictureBox pb = new PictureBox();
pb.ImageLocation = path;
pb.Left = point.X;
pb.Top = point.Y;
panel1.Controls.Add(pb);
//g.DrawImage(Image.FromFile(path), point);
}
}
You can get the mouse position when the user initially clicks and then track the mouse position in the PictureBox's MouseMove event. You can attach these handlers to multiple PictureBoxes.
private int xPos;
private int yPos;
private void pb_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
xPos = e.X;
yPos = e.Y;
}
}
private void pb_MouseMove(object sender, MouseEventArgs e)
{
PictureBox p = sender as PictureBox;
if(p != null)
{
if (e.Button == MouseButtons.Left)
{
p.Top += (e.Y - yPos);
p.Left += (e.X - xPos);
}
}
}
For dynamic PictureBoxes you can attach the handlers like this
PictureBox dpb = new PictureBox();
dpb.MouseDown += pb_MouseDown;
dbp.MouseMove += pb_MouseMove;
//fill the rest of the properties...