I have added a listBox containing a list and a toolStrip in my application. These are used to select control to added runtime in a panel. (I have added an image. The toolStrip and listBox are on the left and right side respectively.) Now what I do with these controls is,
1 - I select an item from toolStrip or listBox
2 - A runtime control is made and shown on the form
3 - On Mouse_Up event, the control is set on the Panel (If it is in the panel.)
Now the question is, as shown in the image, the runtime control is not at the tip of the cursor. I want these runtime controls on the tip of the cursor.
Below is the Image.
EDIT: Below is the code.:
private void listBox_MouseDown(object sender, MouseEventArgs e)
{
this.globalLabel1 = new Label();
this.globalLabel1.Text = this.listBox.SelectedItem.ToString() + " : ";
//other label properties like, tag, name, events, font etc.
}
private void listBox_MouseMove(object sender, MouseEventArgs e)
{
if (this.globalLabel1 != null)
{
this.globalLabel1.Left = System.Windows.Forms.Cursor.Position.X
- this.Location.X;
this.globalLabel1.Top = System.Windows.Forms.Cursor.Position.Y
- this.Location.Y;
this.globalLabel1.Show();
this.lPanel.SendToBack();
}
}
private void listBox_MouseUp(object sender, MouseEventArgs e)
{
this.globalLabel1.Parent = this.lPanel;
this.globalLabel1.Anchor = AnchorStyles.Top | AnchorStyles.Left;
this.globalLabel1.Left = Cursor.Position.X
- /*Cursor.Size.Height -*/ this.lPanel.Location.X
- this.Location.X;
this.globalLabel1.Top = Cursor.Position.Y
- /*Cursor.Size.Width -*/ this.lPanel.Location.Y
- this.Location.Y;
}
Thanks.
You have to set the Location of your runtime added control relatively to the parent, you can use the method PointToClient like this:
private void listBox_MouseUp(object sender, MouseEventArgs e) {
globalLabel1.Parent = lPanel;
globalLabel1.Anchor = AnchorStyles.Top | AnchorStyles.Left;
globalLabel1.Location = lPanel.PointToClient(Cursor.Position);
}
i). I don't know why are you not using Panel_MoveUP event, Because you wan to place it on panel.
ii). At Panel_moveUp you have to make little bit position change to cursor position by Hit and trail method, I not sure about this why is this difference coming so.
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
this.globalLabel1 = new Label();
this.globalLabel1.Text = this.listBox1.SelectedItem.ToString() + " : ";
//other label properties like, tag, name, events, font etc.
}
//////////////////////////USE PANEL_MOVEUP EVENT//////////////
private void lPanel_MouseMove(object sender, MouseEventArgs e)
{
if (this.globalLabel1 != null)
{
this.globalLabel1.Left = System.Windows.Forms.Cursor.Position.X-50 // Change
- this.Location.X;
this.globalLabel1.Top = System.Windows.Forms.Cursor.Position.Y-100 //Change
- this.Location.Y;
this.globalLabel1.Show();
this.lPanel.SendToBack();
this.lPanel.Controls.Add(globalLabel1);
}
}
Related
I have a tableLayoutPanel with 16 cells. 15 of the cells have controls. I want to be able to move the controls from one cell to another at runtime.
I have used
private void button15_Click(object sender, EventArgs e)
{
tableLayoutPanel1.Controls.Remove(button15);
tableLayoutPanel1.Controls.Add(button15, 3, 3);
}
This works well but i want to know if there is any better way to do this???
In Winforms, you can only move a control inside its parent (of course there are some exceptions to some controls which in fact don't have any Parent). So the idea here is if you want to move a control of your TableLayoutPanel, you have to set its Parent to your Form of another container when mouse is held down, when moving, the position of the control is in the new parent, after mouse is released, we have to set the Parent of the control to the TableLayoutPanel back, of course we have to find the drop-down cell position and use SetCellPosition method to position the control on the TableLayoutPanel, here is the demo code for you (works great), I use 2 Buttons in this demo, you can replace them with any control you want:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
//This will prevent flicker
typeof(TableLayoutPanel).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(tableLayoutPanel1, true, null);
}
Point downPoint;
bool moved;
//This is used to store the CellBounds together with the Cell position
//so that we can find the Cell position later (after releasing mouse).
Dictionary<TableLayoutPanelCellPosition, Rectangle> dict = new Dictionary<TableLayoutPanelCellPosition, Rectangle>();
//MouseDown event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseDown(object sender, MouseEventArgs e) {
Control button = sender as Control;
button.Parent = this;
button.BringToFront();
downPoint = e.Location;
}
//MouseMove event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseMove(object sender, MouseEventArgs e) {
Control button = sender as Control;
if (e.Button == MouseButtons.Left) {
button.Left += e.X - downPoint.X;
button.Top += e.Y - downPoint.Y;
moved = true;
tableLayoutPanel1.Invalidate();
}
}
//MouseUp event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseUp(object sender, MouseEventArgs e) {
Control button = sender as Control;
if (moved) {
SetControl(button, e.Location);
button.Parent = tableLayoutPanel1;
moved = false;
}
}
//This is used to set the control on the tableLayoutPanel after releasing mouse
private void SetControl(Control c, Point position) {
Point localPoint = tableLayoutPanel1.PointToClient(c.PointToScreen(position));
var keyValue = dict.FirstOrDefault(e => e.Value.Contains(localPoint));
if (!keyValue.Equals(default(KeyValuePair<TableLayoutPanelCellPosition, Rectangle>))) {
tableLayoutPanel1.SetCellPosition(c, keyValue.Key);
}
}
//CellPaint event handler for your tableLayoutPanel1
private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e) {
dict[new TableLayoutPanelCellPosition(e.Column, e.Row)] = e.CellBounds;
if (moved) {
if (e.CellBounds.Contains(tableLayoutPanel1.PointToClient(MousePosition))) {
e.Graphics.FillRectangle(Brushes.Yellow, e.CellBounds);
}
}
}
}
Remove Lock & set dock to none and move!
So I am trying to make a drag and drop application that drags something on a panel. I did it before and I have forgot the code that I used for it. I would also like it to have an event too. Here is an example that failed to work:
private void pictureBox1_Click(object sender, EventArgs e)
{
PictureBox flower1 = new PictureBox();
flower1.Image = pictureBox1.Image;
flower1.Location = new Point(panel1.Location.X, panel1.Location.Y);
flower1.Width = 100;
this.Controls.Add(flower1);
flower1.MouseDown += new MouseEventHandler(flower1_MouseDown);
}
void flower1_MouseDown(object sender, MouseEventArgs e)
{
//flower1.Location = new Point(MousePosition.X, MousePosition.Y);
}
I wanted me to click on a flower, then it would be placed onto the panel then, if the mouse is clicked over that control duplicated onto the panel, then make the location the mouse cursors location. How would I go about doing any of this? It does not even appear to duplicate.
EDIT: Just realised that the image is underneath the panel making it not able to be seen. That's one issue, now how do I get it to drag and drop?
private void pictureBox1_Click(object sender, EventArgs e)
{
PictureBox flower1 = new PictureBox();
flower1.Image = pictureBox1.Image;
flower1.Location = Point.Empty;
flower1.Width = 100;
flower1.Parent = panel1;
flower1.MouseDown += new MouseEventHandler(flower1_MouseDown);
}
I have a PictureBox that is inside a TabPage, and of course this TabPage is part of a TabView and this TabView is inside a Form. I want users be able to move this picture box within the tab page. For this I am using the MouseDown, MouseMove and MouseUp events of the picture box:
private void pictureBoxPackageView_MouseDown(object sender, MouseEventArgs e)
{
if (!_mapPackageIsMoving)
{
_mapPackageIsMoving = true;
}
}
private void pictureBoxPackageView_MouseMove(object sender, MouseEventArgs e)
{
if(_mapPackageIsMoving)
{
pictureBoxPackageView.Location = MousePosition; //This is not exact at all!
return;
}
//Some other code for some other stuff when picturebox is not moving...
}
private void pictureBoxPackageView_MouseUp(object sender, MouseEventArgs e)
{
if (_mapPackageIsMoving)
{
_mapPackageIsMoving = false; //Mouse button is up, end moving!
return;
}
}
But my problem lies in the MouseMove event. As soon as I move mouse after button down, the picture box jumps out of tab page's visible area.
I need to know how to handle the move only within the rectangle of the tab page, and if picture box is being dragged out of tab view's visible area, it shouldn't move anymore unless user brings the mouse inside the tab view's visible rectangle.
Any helps/tips will be appriciated!
You need a variable to hold the original position of the PictureBox:
Modified from a HansPassant answer:
private Point start = Point.Empty;
void pictureBoxPackageView_MouseUp(object sender, MouseEventArgs e) {
_mapPackageIsMoving = false;
}
void pictureBoxPackageView_MouseMove(object sender, MouseEventArgs e) {
if (_mapPackageIsMoving) {
pictureBoxPackageView.Location = new Point(
pictureBoxPackageView.Left + (e.X - start.X),
pictureBoxPackageView.Top + (e.Y - start.Y));
}
}
void pictureBoxPackageView_MouseDown(object sender, MouseEventArgs e) {
start = e.Location;
_mapPackageIsMoving = true;
}
I want to get the mouse position with respect to the control in which mouse pointer is present. That means when I place the cursor to the starting point (Top-Left corner) of control it should give (0,0). I am using the following code:
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
this.Text = Convert.ToString(Cursor.Position.X + ":" + Cursor.Position.Y);
}
But this gives the position with respect to the screen not to the control.
Code sample will be appreciated.
Use Control.PointToClient to convert a point from screen-relative coords to control-relative coords. If you need to go the other way, use PointToScreen.
You can directly use the Location property of the MouseEventArgs argument passed to your event-handler.
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
Text = e.Location.X + ":" + e.Location.Y;
}
The following will give you mouse coordinates relative to your control. For example, this results in (0,0) if mouse is over top left corner of the control:
var coordinates = yourControl.PointToClient(Cursor.Position);
One can use following methods for getting the relative from absolute and absolute from relative coordinates:
Point Control.PointToClient(Point point);
Point Control.PointToScreen(Point point);
Cursor.Position return Point on Screen, but Control.PointToClient(Cursor.Position) returns point on control (e.g. control -> panel). In your case, you have e.Locate which return point on control.
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
Text = panel1.PointToClient(Cursor.Position).ToString();
}
Simply subtract from the cursor position the Left and Top coordinates of the control:
this.Text = Convert.ToString(
Cursor.Position.X - this.Left + ":" +
Cursor.Position.Y - this.Top);
I use MouseLocation and PointToClient to check. And then use it in a timer!
bool IsMouseHover(Control c, Control container)
{
Point p = Control.MousePosition;
Point p1 = c.PointToClient(p);
Point p2 = container.PointToClient(p);
if (c.DisplayRectangle.Contains(p1) && container.DisplayRectangle.Contains(p2))
{
return true;
}
return false;
}
private void lienzo_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
{
Point coordenadas = new Point();
coordenadas = Mouse.GetPosition(lienzo);
string msg = "Coordenadas mouse :" + coordenadas.X + "," + coordenadas.Y;
MessageBoxResult resultado;
string titulo = "Informacion";
MessageBoxButton botones = MessageBoxButton.OK;
MessageBoxImage icono = MessageBoxImage.Information;
resultado = MessageBox.Show(msg, titulo, botones, icono);
}
Where "lienzo" is my canvas panel
Snippet code as following:
private void Control_MouseMove(object sender, MouseEventArgs e)
{
var btn = sender as Button;
var point = e.Location;
point.X += btn.Location.X;
point.Y += btn.Location.Y;
Control findTarget = btn.Parent.GetChildAtPoint(point, GetChildAtPointSkip.Invisible) as Button;
if (findTarget != null)
{
// TO DO
}
}
Where the button is one of many buttons in a hosting panel.
Create af standard Project C# WinForms
Place 2 Textboxes named X and Y, and a Timer object from the toolbox to the Design page
Press [F7] and replace all code with below.
using System;
using System.Windows.Forms;
namespace MousePos
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Start();
}
private void Form1_MouseCaptureChanged(object sender, EventArgs e)
{
X.Text = MousePosition.X.ToString();
Y.Text = MousePosition.Y.ToString();
}
}
}
Set Timer.Tick action to "Form1_MouseCaptureChanged"
[F5] Run - and now you have an MosusePos app.
How do you edit items and subitems in a listview? Let's say I have a listview with 3 columns,and subitems,
Car Brand | Car Name | Car Year
Ford | Mustang | 2000
Dodge | Charger | 2007
How would I Add items like that to listview and how would I edit let's say the Car Name on which ever row by index[] if I needed to edit at runtime at firing of an event?
If you're looking for "in-place" editing of a ListView's contents (specifically the subitems of a ListView in details view mode), you'll need to implement this yourself, or use a third-party control.
By default, the best you can achieve with a "standard" ListView is to set it's LabelEdit property to true to allow the user to edit the text of the first column of the ListView (assuming you want to allow a free-format text edit).
Some examples (including full source-code) of customized ListView's that allow "in-place" editing of sub-items are:
C# Editable ListView
In-place editing of ListView subitems
I use a hidden textbox to edit all the listview items/subitems. The only problem is that the textbox needs to disappear as soon as any event takes place outside the textbox and the listview doesn't trigger the scroll event so if you scroll the listview the textbox will still be visible.
To bypass this problem I created the Scroll event with this overrided listview.
Here is my code, I constantly reuse it so it might be help for someone:
ListViewItem.ListViewSubItem SelectedLSI;
private void listView2_MouseUp(object sender, MouseEventArgs e)
{
ListViewHitTestInfo i = listView2.HitTest(e.X, e.Y);
SelectedLSI = i.SubItem;
if (SelectedLSI == null)
return;
int border = 0;
switch (listView2.BorderStyle)
{
case BorderStyle.FixedSingle:
border = 1;
break;
case BorderStyle.Fixed3D:
border = 2;
break;
}
int CellWidth = SelectedLSI.Bounds.Width;
int CellHeight = SelectedLSI.Bounds.Height;
int CellLeft = border + listView2.Left + i.SubItem.Bounds.Left;
int CellTop =listView2.Top + i.SubItem.Bounds.Top;
// First Column
if (i.SubItem == i.Item.SubItems[0])
CellWidth = listView2.Columns[0].Width;
TxtEdit.Location = new Point(CellLeft, CellTop);
TxtEdit.Size = new Size(CellWidth, CellHeight);
TxtEdit.Visible = true;
TxtEdit.BringToFront();
TxtEdit.Text = i.SubItem.Text;
TxtEdit.Select();
TxtEdit.SelectAll();
}
private void listView2_MouseDown(object sender, MouseEventArgs e)
{
HideTextEditor();
}
private void listView2_Scroll(object sender, EventArgs e)
{
HideTextEditor();
}
private void TxtEdit_Leave(object sender, EventArgs e)
{
HideTextEditor();
}
private void TxtEdit_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
HideTextEditor();
}
private void HideTextEditor()
{
TxtEdit.Visible = false;
if (SelectedLSI != null)
SelectedLSI.Text = TxtEdit.Text;
SelectedLSI = null;
TxtEdit.Text = "";
}
Click the items in the list view.
Add a button that will edit the selected items.
Add the code
try
{
LSTDEDUCTION.SelectedItems[0].SubItems[1].Text = txtcarName.Text;
LSTDEDUCTION.SelectedItems[0].SubItems[0].Text = txtcarBrand.Text;
LSTDEDUCTION.SelectedItems[0].SubItems[2].Text = txtCarName.Text;
}
catch{}
Sorry, don't have enough rep, or would have commented on CraigTP's answer.
I found the solution from the 1st link - C# Editable ListView, quite easy to use. The general idea is to:
identify the SubItem that was selected and overlay a TextBox with the SubItem's text over the SubItem
give this TextBox focus
change SubItem's text to that of TextBox's when TextBox loses focus
What a workaround for a seemingly simple operation :-|
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
li = listView1.GetItemAt(e.X, e.Y);
X = e.X;
Y = e.Y;
}
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
int nStart = X;
int spos = 0;
int epos = listView1.Columns[1].Width;
for (int i = 0; i < listView1.Columns.Count; i++)
{
if (nStart > spos && nStart < epos)
{
subItemSelected = i;
break;
}
spos = epos;
epos += listView1.Columns[i].Width;
}
li.SubItems[subItemSelected].Text = "9";
}