Restrict mouse move event inside a row of Grid - wpf c# - c#

I have a button inside a panel like below. I have to move the GLControl inside this panel anywhere. But when tried like below, GLControl goes away from panel when move the button to the border of panel. How can I restrict the movement of button inside the panel only?
<WindowsFormsHost x:Name="windowsFormsHost1" Grid.Row="5" Grid.ColumnSpan="3" Initialized="WindowsFormsHost_Initialized" >
<wf:Panel x:Name="Panel_glcontrol" Dock="None" BackColor="yellow">
<wf:Panel.Controls>
<opentk:GLControl x:Name="glControl" Width="450" Height="299"
Dock="None" MouseMove="GlControl_MouseMove" MouseDown="GlControl_MouseDown" Resize="glControl_Resize" Paint="glControl_Paint" />
</wf:Panel.Controls>
</wf:Panel>
</WindowsFormsHost>
private System.Drawing.Point MouseDownLocation;
private void GlControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
glControl.Left = e.X + glControl.Left - MouseDownLocation.X;
glControl.Top = e.Y + glControl.Top - MouseDownLocation.Y;
}
}
private void GlControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}

It looks like more a WinForms question. Try to set a restriction to the code that is used to update the control position. For example:
glControl.Left = Math.Min(panel.Width - glControl.Width, e.X + glControl.Left - MouseDownLocation.X);
glControl.Top = Math.Min(panel.Height - glControl.Height, e.Y + glControl.Top - MouseDownLocation.Y);

Related

Create a Rectangular Mouse Select area panel with Multiple Pictureboxes over it

I have a panel with multiple pictureboxes over it. I want to create a rectangle over panel and Picturebox when MouseLeft Button is down and Mouse is dragged. I understand Rectangle Mouse select area can be created with the combination of Mousedown on Panel and MouseMove events on Picturebox and Panel.
Now My Implementation is , When i receive Mousedown event on Panel I save Mousedown Location and look for MouseMove events. if mousemove events is on panel i draw a rectangle over panel and if Mouse Move event is on Picturebox i start drwaing Rectangle for that Picturebox.
Now the Problem is , when mouseleft button is down and mouse move is done over panel i am able to receive mousemove events over it and draw rectangle over panel. However i am not receiving any MouseMove Events for Picturebox to create rectangle select area for it.
Is my Implementation Correct and can someone kindly propose the solution for this ?
I am Posting My Code Snippet for reference.
Code:
//Panel Class
public partial class Childwindow : Form
{
//Mouse down event
private void ClickEventOnchildForm(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
RectStartPoint = e.Location;
IsSelecting = true;
Invalidate();
}
}
//Mouse Move event
private void flowLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
Point tempEndPoint = e.Location;
Rect.Location = new Point(
Math.Min(RectStartPoint.X, tempEndPoint.X),
Math.Min(RectStartPoint.Y, tempEndPoint.Y));
Rect.Size = new Size(
Math.Abs(RectStartPoint.X - tempEndPoint.X),
Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
this.flowLayoutPanel1.Invalidate();
}
//Paint event
private void flowLayoutPanel1_Paint_1(object sender, PaintEventArgs e)
{
if (Rect != null && Rect.Width > 0 && Rect.Height > 0)
{
e.Graphics.FillRectangle(selectionBrush, Rect);
}
}
}
Public class Picturebox: UserControl{
private void picbox_MouseMove(object sender, MouseEventArgs e)
{//Higlight particular Picturebox
}
}

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).

Grab, move and drop control in Form by mouse

Hello I have found this code that might help me with following issue, I'm trying to make drag, drop and move label in my Form by mouse.
private Point MouseDownLocation;
private void MyControl_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
private void MyControl_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
this.Left = e.X + this.Left - MouseDownLocation.X;
this.Top = e.Y + this.Top - MouseDownLocation.Y;
}
}
But when I assing mousemove and mousedown as events to label and i try to grab the label and move with mouse it moves with the whole Form.
May I ask where is should the code be improved?
Thank you for your time.
Instead of using this.Left (which is the form), you need to move your control:
private void MyControl_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MyControl.Left = e.X + MyControl.Left - MouseDownLocation.X;
MyControl.Top = e.Y + MyControl.Top - MouseDownLocation.Y;
}
}
In addition, you may want to capture the mouse on button down, and release it on button up. That will prevent very fast movements from "breaking" your logic. For details, see Mouse Capture in Windows Forms.

How to inherit events between objects

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.

Can't set the position of a contextmenustrip?

I'm trying to open a contextmenustrip at the place where I right-clicked the mouse, but it always shows at top left of the screen.
Here is the code I used:
private void dataGridView1_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
contextMenuStrip1.Show(new Point(e.X,e.Y));
doss.getdossier(connection.conn, Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells[0].Value));
}
}
if (e.Button == MouseButtons.Right)
{
contextMenuStrip1.Show(Cursor.Position);
}
the reason it's not appearing is because you are using e.X and e.Y for the values. They are not the actual location on the screen. They are the location of the mouse within the datagrid. So say you clicked on the first cell of the first row, that will be near the top left of that component. e.X and e.Y are the mouse locations within the component.
assuming you are in Windows Forms, try this:
if (e.Button == MouseButtons.Right)
{
Control control = (Control) sender;
// Calculate the startPoint by using the PointToScreen
// method.
var startPoint = control.PointToScreen(new Point(e.X, e.Y));
contextMenuStrip1.Show(startPoint);
...
...

Categories

Resources