ContextManuStripTool.show() position is wrong - c#

I'm trying to learn how to use the ContextMenuStrip
when using this code :
private void DG_dataGridView_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
var hitTest = DG_dataGridView.HitTest(e.X, e.Y);
if (hitTest.Type == DataGridViewHitTestType.ColumnHeader)//currentMouseOverRow >= 0)
{
string colName = DG_dataGridView.Columns[hitTest.ColumnIndex].Name;
GlobalParam.Insatance.ClickData = new RightClickData(hitTest, colName);
RightClickToolStrip.Show(DG_dataGridView, new Point(e.X, e.Y));
}
}
}
I see the menu pop up in the right position
but when instead I use this code :
private void DG_dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
var hitTest = DG_dataGridView.HitTest(e.Location.X, e.Location.Y);
string colName = DG_dataGridView.Columns[e.ColumnIndex].Name;
GlobalParam.Insatance.CustomMouseGridClickData = new CustomMouseOnGridClickData(e, hitTest.Type, colName);
RightClickToolStrip.Show(DG_dataGridView, new Point(e.X, e.Y));
}
}
I see the menu pop on the top left corner of my DataGridView
I know this is due to the operation of DataGridViewCellMouseEventArgs
I have tried to set other control in the toolStrip.Show method without success
what is the proper way to get my click position

With the ColumnHeaderMouseClick event, you don't have to test for the column getting clicked or not using that HitTest method. Also, I think the coordinates are relative to the column being clicked, so you can try using the GetColumnDisplayRectangle function to offset it property:
void DG_dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
if (e.ColumnIndex > -1) {
Rectangle r = DG_dataGridView.GetColumnDisplayRectangle(e.ColumnIndex, true);
RightClickToolStrip.Show(DG_dataGridView, r.Left + e.X, r.Top + e.Y);
}
}
}

Related

Save 4 mouse positions

Hi I want to save 4 mouse positions when I click on button.
Smth like this:
ButtonClick -> 1.MouseClick / Save Mouse Position-> 2.MouseClick / Save Mouse Positon .....
private void button2_Click_1(object sender, EventArgs e)
{
if (!int.TryParse(textBox4.Text, out parsedValue))
{
MessageBox.Show("Wpsiz liczbe");
return;
}
else
{
iset = int.Parse(textBox3.Text);
ms = int.Parse(textBox4.Text);
MouseDownFunction();
}
}
private void MouseDownFunction(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
eqhelmetx = MousePosition.X;
eqhelmety = MousePosition.Y;
if (e.Button == MouseButtons.Left)
{
eqchestx = MousePosition.X;
eqchesty = MousePosition.Y;
if (e.Button == MouseButtons.Left)
{
eqleginsx = MousePosition.X;
eqleginsy = MousePosition.Y;
if (e.Button == MouseButtons.Left)
{
eqbootsx = MousePosition.X;
eqbootsy = MousePosition.Y;
}
}
}
}
}```
I tried but it doesn't work. Thanks for any help
List<Point> MousePositions = new List<Point>(); // list for saving mouse positions
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (MousePositions.Count == 4)
MousePositions.RemoveAt(0); // for saving last 4 positions
MousePositions.Add(e.Location); // when clicking form saving mouse location
}
private void button1_Click(object sender, EventArgs e)
{
foreach (var item in MousePositions)
MessageBox.Show(item.ToString()); // showing mouse positions
}

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;
}

Winforms datagridview : drag and drop causes an error

An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code
Additional Information : Rows cannot be programmatically removed unless the DataGridView is data-bound to an IBindingList that supports change notification and allows delete
This is how I bind my data to datagridview :
IEnumerable<myTable> query = from p in db.myTables select p;
testList = query.ToList();
dataGridView1.DataSource = testList;
And this is what I use to drag & drop rows :
private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
{
if (dataGridView1.SelectedRows.Count == 1)
{
if (e.Button == MouseButtons.Left)
{
rw = dataGridView1.SelectedRows[0];
rowIndexFromMouseDown = dataGridView1.SelectedRows[0].Index;
dataGridView1.DoDragDrop(rw, DragDropEffects.Move);
}
}
}
private void dataGridView1_DragEnter(object sender, DragEventArgs e)
{
if (dataGridView1.SelectedRows.Count > 0)
{
e.Effect = DragDropEffects.Move;
}
}
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
int rowIndexOfItemUnderMouseToDrop;
Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
rowIndexOfItemUnderMouseToDrop = dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
if (e.Effect == DragDropEffects.Move)
{
dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown);
dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rw);
}
}
Whenever I tried to drag & drop, dragging is ok but drop causes the error that I mentioned above, and if possible I dont want to use bindinglist because if I use it I will have to make lots of changes.
If you can help I would be greateful.
I fixed the problem. I've made changes on mouse events
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.X, e.Y))
{
DragDropEffects dropEffect = dataGridView1.DoDragDrop(dataGridView1.Rows[rowIndexFromMouseDown], DragDropEffects.Copy);
}
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
if (rowIndexFromMouseDown != -1)
{
Size dragSize = SystemInformation.DragSize;
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
}
else
dragBoxFromMouseDown = Rectangle.Empty;
}
private void dataGridView1_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
try
{
if (e.Data.GetDataPresent(typeof(DataGridViewRow)))
{
Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
if (e.Effect == DragDropEffects.Copy)
{
DataGridViewRow Row = (DataGridViewRow)e.Data.GetData(typeof(DataGridViewRow));
dataGridView1.Rows.Add(Row.Cells[0].Value, Row.Cells[1].Value, Row.Cells[2].Value);
}
}
else
{
//Reflect the exception to screen
MessageBox.Show("Geen data! #01", "Error");
}
}
catch (Exception msg)
{
MessageBox.Show(msg.Message, "Error");
}
}

Drawing lines in a PictureBox

First I need to make some color scribbles (the picture below is taken from M. Yang article's on Still Image Colorization) on an monochrome input image which is loaded into a PictureBox control.
I'm trying to use this to get the effect:
private void PictureBoxOnMouseDown(Object sender, MouseEventArgs e)
{
if((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
this.MouseInitialPosition = e.Location;
}
}
private void PictureBoxOnMouseMove(Object sender, MouseEventArgs e)
{
if((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
this.MouseLastPosition = e.Location;
}
this._PictureBox.Invalidate();
}
private void PictureBoxOnPaint(Object sender, PaintEventArgs e)
{
using(var pen = new Pen(Color.Red, 3.0F))
{
e.Graphics.DrawLine(pen, this.MouseInitialPosition, this.MouseLastPosition);
}
}
But that's giving me not quite I've been waiting for:
I can't put several lines. Lines are not stored;
I'm overwriting line with line;
Second. I need to get all pixels from an image I've been drawing onto and filter them in some way (i.e. extract special ones). How do I store lines/scribbles onto image and then read the image efficiently?
A simple solution would be to store lines when a mouseMove event occurs on a picturebox control and then invalidate to redraw:
public class Lines
{
public Point startPoint = new Point();
public Point endPoint = new Point();
}
Lines l = new Lines();
List<Lines> allLines = new List<Lines>();
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Collect endPoint when mouse moved
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
l.endPoint = e.Location;
//Line completed
allLines.Add(l);
this.pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// Collect startPoint when left mouse clicked
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
l = new Lines();
l.startPoint = e.Location;
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var aLine in allLines)
{
e.Graphics.DrawLine(Pens.Blue, aLine.startPoint, aLine.endPoint);
}
}
Just keep a list of lines. Then when OnPaint is called draw all the lines.
The Line class would be something like:
public class Line
{
public List<Point> Points = new List<Point>();
public DrawLine(Pen pen, Grphics g)
{
for (int i = 0; i < Points.Count - 1; ++i)
g.DrawLine(pen, Points[i], Points[i+1];
}
}
private void PictureBoxOnMouseDown(Object sender, MouseEventArgs e)
{
if((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
var newLine = new Line();
newLine.Points.Add(e.Location);
lines.Add(newLine);
}
}
PictureBoxOnMouseMove(Object sender, MouseEventArgs e)
{
if((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
lines[lines.Count-1].Points.Add(e.Location);
}
}
private void PictureBoxOnPaint(Object sender, PaintEventArgs e)
{
using(var pen = new Pen(Color.Red, 3.0F))
{
foreach (var line in lines)
DrawLine(pen, e.Graphics)
}
}

C# - DatagridView and ContextMenu

I have a datagridview where I show infomation about products. I want to bind a contextmenu when the user selects a cell and then right clicks on that cell. I have another contextmenu and that one is bound to the columns of the datagridview. If a user right clicks on a column the contextmenu shows.
I have tried like this but it does not work. The context menu shows when the user right clicks on a cell, but the contextmenu that is bound to the column header does not work.
private void GridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
productContextMenu.Show(GridView1, e.Location);
}
}
How do I make it so that when the user right clicks on a datagridview shows up?
Many thanx in advance.
EDIT
Thnx for the answers. I solved the problem like this:
private void GridView1_MouseUp(object sender, MouseEventArgs e)
{
DataGridView.HitTestInfo hitTestInfo;
if (e.Button == MouseButtons.Right)
{
hitTestInfo = GridView1.HitTest(e.X, e.Y);
if (hitTestInfo.Type == DataGridViewHitTestType.Cell)
{
productContextMenu.Show(GridView1, e.Location);
}
}
}
Both the contextmenus shows. When I click on the column that context menu shows, and when I click on a cell that contextmenu shows.
Try this
private void dataGridView1_CellMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
contextMenu.Show(datagridview, e.Location);
}
}
or
private void dataGridView_MouseUp(object sender, MouseEventArgs e)
{
// Load context menu on right mouse click
DataGridView.HitTestInfo hitTestInfo;
if (e.Button == MouseButtons.Right)
{
hitTestInfo = dataGridView.HitTest(e.X, e.Y);
// If column is first column
if (hitTestInfo.Type == DataGridViewHitTestType.Cell && hitTestInfo.ColumnIndex == 0)
contextMenuForColumn1.Show(dataGridView, new Point(e.X, e.Y));
// If column is second column
if (hitTestInfo.Type == DataGridViewHitTestType.Cell && hitTestInfo.ColumnIndex == 1)
contextMenuForColumn2.Show(dataGridView, new Point(e.X, e.Y));
}
}
For the problem with the relative position, you can also use this aproach:
DataGridViewColumn dgvC = new DataGridViewColumn();
DataGridViewRow dgvR = new DataGridViewRow();
dgvC = dgv.Columns[e.ColumnIndex];
dgvR = dgv.Rows[e.RowIndex];
Point p = new Point();
p.X = (dgvC.Width * e.ColumnIndex) + e.X;
p.Y = (dgvR.Height * e.RowIndex) + e.Y;
dgv.ContextMenu.Show(dgv, p);

Categories

Resources