I am trying to create a form which contains panels created programmaticaly and controls able to drag drop and resize just like Microsoft Visual Studio IDE.
And I created something like this. there should be so many lines (blue one) and also so many boxes(yellow one) and I can be able to move yellow boxes inside of blue lines. everything works with defined controls on design time.
and the source codes here
public partial class Form1 : Form
{
bool allowResize = false;
public Form1()
{
InitializeComponent();
panel1.AllowDrop = true;
panel2.AllowDrop = true;
panel3.AllowDrop = true;
panel4.AllowDrop = true;
panel1.DragEnter += panel_DragEnter;
panel2.DragEnter += panel_DragEnter;
panel3.DragEnter += panel_DragEnter;
panel4.DragEnter += panel_DragEnter;
panel1.DragDrop += panel_DragDrop;
panel2.DragDrop += panel_DragDrop;
panel3.DragDrop += panel_DragDrop;
panel4.DragDrop += panel_DragDrop;
panelMove.MouseDown += panelMove_MouseDown;
}
void panelMove_MouseDown(object sender, MouseEventArgs e)
{
panelMove.DoDragDrop(panelMove, DragDropEffects.Move);
}
void panel_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
void panel_DragDrop(object sender, DragEventArgs e)
{
((Panel)e.Data.GetData(typeof(Panel))).Parent = (Panel)sender;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
allowResize = true;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
allowResize = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (allowResize)
{
this.panelMove.Height = pictureBox1.Top + e.Y;
this.panelMove.Width = pictureBox1.Left + e.X;
}
}
}
but I dont know how to create thoose controls (blue and yellow boxes ) on runtime.
You should check the Anchor property of Control. Anchor allows the control to automatically re-sized at runtime.
Use the Anchor property to define how a control is automatically
resized as its parent control is resized. Anchoring a control to its
parent control ensures that the anchored edges remain in the same
position relative to the edges of the parent control when the parent
control is resized.
You can anchor a control to one or more edges of its container. For
example, if you have a Form with a Button whose Anchor property value
is set to Top and Bottom, the Button is stretched to maintain the
anchored distance to the top and bottom edges of the Form as the
Height of the Form is increased.
MSDN : Control.Anchor
Related
I'm using c# 3.5 / winforms
On my form, I have 2 picturebox PB1 and PB2 (and lots of others controls), in a panel.
The user can drag PB1 to PB2. But he can also cancel the drop by release the left button anywhere on the form or outside the form.
PB1 can be dragged a fixed number of times. When the drag start, I decrease a variable in PB1 and if it reach 0, the PB became invisible.
But if the user cancel the drag, PB1 must know that to increase the variable and set the visibility of PB1.
My problem is : how PB1 can know when a drag is canceled (or actually, dropped, even on a valid control) ? Remember that the user can release the drag outside of the form, so I can't use the Drop event on the form. I try the GiveFeedback and the QueryContinueDrag events, but they are fired as long as the drag continue, but not when it stop.
Some code :
class COPGOJetonImage
{
private PictureBox PB1;
public COPGOJetonImage()
{
PB1 = new PictureBox();
//here I initialize PB1
((Control)PB1).AllowDrop = true; //in case of
PB1.MouseDown += OnMouseDown;
}
public void OnMouseDown(object sender, MouseEventArgs ev)
{
PB1.DoDragDrop(PB1.Image, DragDropEffects.Copy);
}
}
"there are 1 to 4 valid targets."
In this example we are dragging pictureBox1, and pictureBox2 thru pictureBox5 are the valid drop targets. We create a DataObject with a custom name to encapsulate pictureBox1 during the drag/drop operation. In the drop targets, we only allow a drop if the custom name is present in the thing being dragged. This ensures we only get a DragDrop event from pictureBox1 itself, and we know it's safe to decrement our drop counter. We can retrieve pictureBox1 back from the DataObject and change its state so that it can no longer be dropped:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int DropsLeft = 5;
private string DataFormatName = "YourUniqueDataFormatNameHere";
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.MouseMove += PictureBox1_MouseMove;
PictureBox[] pbs = new PictureBox[] { pictureBox2, pictureBox3, pictureBox4, pictureBox5 };
foreach (PictureBox pb in pbs)
{
pb.AllowDrop = true;
pb.DragEnter += Pb_DragEnter;
pb.DragDrop += Pb_DragDrop;
}
}
private void PictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
DataObject data = new DataObject(DataFormatName, pictureBox1);
pictureBox1.DoDragDrop(data, DragDropEffects.Copy);
}
}
private void Pb_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormatName))
{
e.Effect = DragDropEffects.All;
}
else
{
e.Effect = DragDropEffects.None;
}
}
private void Pb_DragDrop(object sender, DragEventArgs e)
{
DropsLeft--;
// retrieve the data
PictureBox pb = (PictureBox)e.Data.GetData(DataFormatName);
if (DropsLeft == 0)
{
MessageBox.Show("No more drops left!");
pb.Enabled = false;
pb.BackColor = Color.Red; // for visual effect
}
}
}
Using C#.NET 4.5
I'm attempting to change the vScrollbar property of the User Control On when Entering and Off when Leaving the Control.
I used Mouse_Enter and Mouse_Leave, however when leaving across another control or the scroll bar ( that did show ), the scroll bar disappeared.
Question:
How do i check if the mouse is inside the user control field?
Question 2: How do i disable the scrollbar at the bottom of the user control? (Horisontal Scrollbar)
If you need more information or if i am unclear somewhere, then just tell me.
Any help will be appreciated, thanks in advance!
EDIT: This is the code for the user control:
public partial class EnemyStats : UserControl
{
public EnemyStats()
{
InitializeComponent();
label1.Left = (this.Width / 2) - (label1.Width / 2);
hpBar1.Width = this.Width - 8;
// Here i add the event that shows the scrollbar to all controls;
foreach (Control con in this.Controls)
{
con.MouseEnter += new EventHandler(EnemyStats_MouseEnter);
}
}
public double enemyMaxHP
{
get
{
return hpBar1.maxValue;
}
set
{
hpBar1.maxValue = value;
}
}
public double enemyHP
{
get
{
return hpBar1.Value;
}
set
{
hpBar1.Value = value;
}
}
private void EnemyStats_SizeChanged(object sender, EventArgs e)
{
if (this.Width < label1.Width) this.Width = label1.Width;
label1.Left = (this.Width / 2) - (label1.Width / 2);
hpBar1.Width = this.Width - 8;
}
private void EnemyStats_MouseEnter(object sender, EventArgs e)
{
// This scrollbar was added by dragging it from the toolbox onto the user control in the designer
vScrollbar1.Visible = true;
}
private void EnemyStats_MouseLeave(object sender, EventArgs e)
{
// This scrollbar was added by dragging it from the toolbox onto the user control in the designer
vScrollbar1.Visible = false;
}
}
But scrollbars does not work:
public void randomMethodInUserControl()
{
this.ScrollBars = ScrollBars.Vertical;
}
Here is what I've found ( Assuming you are using a Textbox )
with Textbox1 set to multi line ( and no scrollbars from the designer view and prepoulated with text ( long enough to use the Scrollbars ))
private void textBox1_MouseEnter(object sender, EventArgs e)
{
textBox1.ScrollBars = ScrollBars.Vertical;
}
private void textBox1_MouseLeave(object sender, EventArgs e)
{
textBox1.ScrollBars = ScrollBars.None;
}
How ever i did find that though this worked, when i wen't over the Scrollbar Side, it stayed on ( Similar to your going over other controls ). There for my solution to you ( though this is kind of a workaround ) would be to grab yourself a ( background color : Transparent ) label and encase your textbox with it. ( let it show in the designer to have a margin of 2-5px around your Textbox and let the textbox handle Mouse Enter and Mouse Leave events.
private void label1_MouseLeave(object sender, EventArgs e)
{
textBox1.ScrollBars = ScrollBars.None;
}
private void label1_MouseEnter(object sender, EventArgs e)
{
textBox1.ScrollBars = ScrollBars.Vertical;
}
I have a panel, that can be moved left or right (chosen automatically according to its current position, distance is static) by click. Also, the user can drag the panel vertically however he wants by clicking the panel, holding the button and moving his mouse. The problem is, that the panel does the left/right move also, when it is dropped after being moved vertically, so the user has to click it again afterwards, to get to correct side (left/right). Here are the methods I am using:
Adding eventhandlers to panel(called Strip here)
Strip.MouseDown += new MouseEventHandler(button_MouseDown);
Strip.MouseMove += new MouseEventHandler(button_MouseMove);
Strip.MouseUp += new MouseEventHandler(button_MouseUp);
Strip.Click += new EventHandler(strip_Click);
And here all the methods mentioned above:
void button_MouseDown(object sender, MouseEventArgs e)
{
activeControl = sender as Control;
previousLocation = e.Location;
Cursor = Cursors.Hand;
}
void button_MouseMove(object sender, MouseEventArgs e)
{
if (activeControl == null || activeControl != sender)
return;
var location = activeControl.Location;
location.Offset(0, e.Location.Y - previousLocation.Y);
activeControl.Location = location;
}
void button_MouseUp(object sender, MouseEventArgs e)
{
activeControl = null;
Cursor = Cursors.Default;
}
void strip_Click(object sender, EventArgs e) // The one moving strip to left or right
{
activeControl = sender as Control;
if (activeControl.Left != 30)
activeControl.Left = 30;
else
activeControl.Left = 5;
}
How to make the panel not move left or right when it was moved vertically?
You'll need to distinguish between a click and a drag. So add a private field named "dragged".
private bool dragged;
In the MouseDown event handler add:
dragged = false;
In the MouseMove event handler add:
if (Math.Abs(location.Y - previousLocation.Y) >
SystemInformation.DoubleClickSize.Height) dragged = true;
In the Click event handler add:
if (dragged) return;
I spent a few hours searching the internet for ways to take my panel and grab it from the left side and pull it left. I found many sources and I tried to alter it to my needs, but it always goes from left to right. My code I currently have is:
bool allowResize = false;
private void PanelResize_MouseUp(object sender, MouseEventArgs e)
{
allowResize = false;
}
private void PanelResize_MouseMove(object sender, MouseEventArgs e)
{
if (allowResize)
{
FavoritesPanel.Width = PanelResize.Left + e.X;
}
}
private void PanelResize_MouseDown(object sender, MouseEventArgs e)
{
allowResize = true;
}
"PanelResize" is a picturebox pushed to the left side of the panel. "FavoritesPanel" is the panel. Both are anchored to the top, bottom, and right side.
My overall question is, how can I correct my code to drag my panel from right to left?
problem is that default setting of changing Width of some panel means that it makes panel more width in way that right side is shifting to right direction.
You need two things. This what you have (resizing width) and second is that you need to shift whole panel to left side as long as you make it more width.
I have similar code here. I made code which allows you to roll up upper side of panel. So I had to do two things again: make my panel more height and shift whole panel more up. Here is my code:
public partial class Form1 : Form
{
private int actualCursorY;
private int lastCursorY;
private bool isDragged;
public Form1()
{
InitializeComponent();
}
private void barRadPanel_MouseDown(object sender, MouseEventArgs e)
{
lastCursorY = PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y)).Y;
isDragged = true;
}
private void barRadPanel_MouseUp(object sender, MouseEventArgs e)
{
isDragged = false;
}
private void barRadPanel_MouseMove(object sender, MouseEventArgs e)
{
if (isDragged)
{
actualCursorY = PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y)).Y;
mainRadPanel.Location = new Point(mainRadPanel.Location.X, actualCursorY);
if (lastCursorY != actualCursorY)
{
mainRadPanel.Height -= actualCursorY - lastCursorY;
lastCursorY = actualCursorY;
}
}
}
}
I tried to use
e.Y
instead of
PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y)).Y
but it made some errors.
This is what it does:
I have a fom which has one user control docked to fill.
this user control displays different images.each image has Id and I have a list of imageId vs imageDetail object dictionary.
Mouse Move event of this user control is captured and i am displaying current X and Y position of mouse in tool tip.
I also want to display image detail in tool tip when user keeps the mouse over image for some time.
I tried to do this with Mouse Hover event but it only raised when mouse enters in user control bound. after this if i move mouse within user control mouse hover event does not fire...
How can i display current X, Y position along image detail in tool tip.
is there any way to simulate Mouse Hover event within Mouse Move using some timer.
Is there any sample code..
I solved this problem by
public partial class Form1 : Form
{
Timer timer;
bool moveStart;
int count = 0;
Point prev;
public Form1()
{
InitializeComponent();
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
}
void timer_Tick(object sender, EventArgs e)
{
this.timer.Stop();
this.moveStart = false;
this.toolTip1.SetToolTip(this, string.Format("Mouse Hover"));
this.textBox1.Text = (++count).ToString();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (this.prev.X == e.X && this.prev.Y == e.Y)
return;
if (moveStart)
{
this.prev = new Point(e.X, e.Y);
this.timer.Stop();
this.toolTip1.SetToolTip(this, string.Format("Mouse Move\nX : {0}\nY : {1}", e.X, e.Y));
this.timer.Start();
}
else
{
moveStart = true;
}
}
}
The simplest way would be to call the MouseOver subroutine from the MouseMove subroutine as such:
void MouseMove(object sender, MouseEventArgs e)
{
//Call the MouseHover event
MouseHover(sender, e);
}
void MouseHover(object sender, EventArgs e)
{
//MouseHover event code
}
If you want more control over when and how to display your tooltip, however, you'll need to do something similar to the following:
Declare a listening variable at class level.
Hook to the MouseHover event so the listening variable is turned on when the mouse enters.
Hook to the MouseLeave event so the listening variable is turned off when the mouse leaves.
Put your tooltip code in the MouseMove handler so it displays your tooltip if the listening variable is on.
Here's some code to demonstrate what's I outlined above.
class Form1
{
bool showPopup = false;
void MouseHover(object sender, EventArgs e)
{
showPopup = true;
}
void MouseLeave(object sender, EventArgs e)
{
showPopup = false;
toolTip.Hide(this);
}
void MouseMove(object sender, MouseEventArgs e)
{
if (showPopup)
{
toolTip.Show("X: " + e.Location.X + "\r\nY: " + e.Location.Y,
this, e.Location)
}
}
}
Of course, you'll have to add a ToolTip with the name toolTip and associate the various methods (subroutines) with the appropriate events of your control (Form, PictureBox, etc).