I have a custom PictureBox which can zoom in using MouseWheel event. Now I want to add a panning feature to it. I mean when PictureBox is in zoomed state, if user left clicks and holds the click then move the mouse, the image would pan within the picturebox.
Here is my code but unfortunately it does not work! I don't know where to look anymore...
private Point _panStartingPoint = Point.Empty;
private bool _panIsActive;
private void CurveBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Focus();
_panIsActive = true;
_panStartingPoint = e.Location;
}
}
private void CurveBox_MouseUp(object sender, MouseEventArgs e)
{
_panIsActive = false;
}
private void CurveBox_MouseLeave(object sender, EventArgs e)
{
_panIsActive = false;
}
private void CurveBox_MouseMove(object sender, MouseEventArgs e)
{
if(_panIsActive && IsZoomed)
{
var g = CreateGraphics(); //Create graphics from PictureBox
var nx = _panStartingPoint.X + e.X;
var ny = _panStartingPoint.Y + e.Y;
var sourceRectangle = new Rectangle(nx, ny, Image.Width, Image.Height);
g.DrawImage(Image, nx, ny, sourceRectangle, GraphicsUnit.Pixel);
}
}
I am suspecting the MouseMove event...I am not sure if anything happens in this event and/or nx and ny does contain correct point.
Any helps/tips is really appriciated!
I think the math is backwards. Try it like this:
private Point startingPoint = Point.Empty;
private Point movingPoint = Point.Empty;
private bool panning = false;
void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
panning = true;
startingPoint = new Point(e.Location.X - movingPoint.X,
e.Location.Y - movingPoint.Y);
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
panning = false;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
if (panning) {
movingPoint = new Point(e.Location.X - startingPoint.X,
e.Location.Y - startingPoint.Y);
pictureBox1.Invalidate();
}
}
void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(Color.White);
e.Graphics.DrawImage(Image, movingPoint);
}
You aren't disposing your graphic object, and CreateGraphics is just a temporary drawing anyway (minimizing would erase it) so I moved the drawing code to the Paint event and am just invalidating as the user is panning.
Related
While dragging rectangle object fast, dragging stops and cursor only moves. Without releasing button click button, moving the cursor on the rectangle object starts the dragging again. It is dragging fine when i drag on a constant speed.
My code is,
private void ConnectorMethod()
{
_draggedLine = new Rectangle();
_draggedLine.Width = 100;
_draggedLine.Height = 12;
_controlModel.PlayerCanvas.Children.Add(_draggedLine);
_draggedLine.PreviewMouseLeftButtonDown += copy_Connector;
_draggedLine.PreviewMouseLeftButtonUp += connector_leftUp;
}
private void copy_Connector(object sender, MouseButtonEventArgs e)
{
_connecting_Connector = (Rectangle)sender;
_Connector_position = e.GetPosition(_connecting_Connector);
_connecting_Connector.PreviewMouseMove += ConnectorMouseMove;
}
private void connector_leftUp(object sender, MouseButtonEventArgs e)
{
_connecting_Connector.PreviewMouseMove -= ConnectorMouseMove;
}
private void ConnectorMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point canvasRelativePosition = e.GetPosition(_controlModel.PlayerCanvas);
Canvas.SetTop(_connecting_Connector, canvasRelativePosition.Y - _Connector_position.Y);
Canvas.SetLeft(_connecting_Connector, canvasRelativePosition.X - _Connector_position.X);
e.Handled = true;
}
}
Thanks in Advance.
I have fixed it with implementation canvas rectangle object in
private void Brick_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true;
}
private void Brick_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
Brick1.Left = e.X;
Brick1.Top = e.Y;
}
}
public void Brick_MouseUp(object sender, MouseEventArgs m)
{
isDragging = false;
}
It kinda works but it glitches out when you move it (The picturebox teleports around the screen rapidly). https://www.youtube.com/watch?v=hWazyAnGNBE
You need to use the PointToClient method of the Form
var relativePoint = this.PointToClient(new Point(X, Y));
// Or
var relativePoint = this.PointToClient(Cursor.Position);
Control.PointToClient Method (Point)
Computes the location of the specified screen point into client
coordinates.
Update
private void Brick_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
var relativePoint = this.PointToClient(Cursor.Position);
Brick1.Left = relativePoint.X;
Brick1.Top = relativePoint.Y;
}
}
I tried to make drag and drop application . I drawn rectangle in run time and I want to detect if user try to move this rectangle or not
this is my code
private bool Mouse_Down = false;
Rectangle re = new Rectangle(100, 100, 60, 60);
private void DrawRegion_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.RoyalBlue), re);
}
private void DrawRegion_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse_Down == true)
{
re.Location = e.Location;
if (re.Right > DrawRegion.Width)
{
re.X = DrawRegion.Width - re.Width;
}
if (re.Top < 0)
{
re.Y = 0;
}
if (re.Left < 0)
{
re.X = 0;
}
if (re.Bottom > DrawRegion.Height)
{
re.Y = DrawRegion.Height - re.Height;
}
Refresh();
}
}
private void DrawRegion_MouseUp(object sender, MouseEventArgs e)
{
Mouse_Down = false;
}
private void DrawRegion_MouseDown(object sender, MouseEventArgs e)
{
Mouse_Down = true;
}
For more details now this rectangle move either user click on this rectangle or in any empty space so I want to detect if clicked location color pixel is rectangle color pixel or not before moving rectangle how to do that ?
Note:DrawRegion is a picturebox
Sorry for bad English
You can use Rect.Contains() to detect if your Rectaingle contain your current location
private void DrawRegion_MouseClick(object sender,MouseEventArgs e)
{
if (re.Contains(e.Location))
Mouse_Down = true;
else
Mouse_Down = false;
}
check this https://msdn.microsoft.com/en-us/library/ms557979(v=vs.110).aspx
When mouse move over a panel2, I need to draw lines. So far I have done following
public Form1()
{
InitializeComponent();
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
if (isDragging)
{
letsPaint(sender, e);
}
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
mouseMoveX = e.X;
mouseMoveY = e.Y;
this.Paint += new PaintEventHandler(panel2_Paint);
}
}
private void letsPaint(object sender, PaintEventArgs e)
{
Pen blackpen = new Pen(Color.Black, 3);
Graphics g = e.Graphics;
g.DrawLine(blackpen, mouseClickedX, mouseClickedY, mouseMoveX, mouseMoveY);
g.Dispose();
}
But nothing happens when I move mouse. I think I did something wrong PaintEventHandler() here. Please tell me how to do this and also if there is any better way for this.
Also I think my method will drawline on the form but I need to draw line on the panel2. How to do? Thanks in advance.
You invalidate:
public Form1()
{
InitializeComponent();
panel2.Paint += new letsPaint;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging) {
mouseMoveX = e.X;
mouseMoveY = e.Y;
panel2.Invalidate();
}
}
and you don't dispose the graphic object (you didn't create it), but you do the pen:
private void letsPaint(object sender, PaintEventArgs e) {
using (Pen blackpen = new Pen(Color.Black, 3)) {
e.Graphics.DrawLine(blackpen,
mouseClickedX, mouseClickedY, mouseMoveX, mouseMoveY);
}
}
Here is a quick little method that works with a bitmap:
Bitmap bmp;
Point lastPoint;
public Form1() {
InitializeComponent();
bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
panel1.MouseDown += panel1_MouseDown;
panel1.MouseMove += panel1_MouseMove;
panel1.Paint += panel1_Paint;
}
void panel1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(bmp, Point.Empty);
}
void panel1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
using (Graphics g = Graphics.FromImage(bmp)) {
g.DrawLine(Pens.Black, lastPoint, e.Location);
}
lastPoint = e.Location;
panel1.Invalidate();
}
}
void panel1_MouseDown(object sender, MouseEventArgs e) {
lastPoint = e.Location;
}
This will flicker, so you would want to replace your panel with a double-buffered panel. Something like this:
public class PanelEx : Panel {
public PanelEx() {
this.DoubleBuffered = true;
}
}
My current code allows me to draw rectangles from a user defined spot but not in the way in whihc i desire. I need it to be like you would do it in paint, here is my current code:
namespace SimpleDraw2
{
///
/// Description of MainForm.
///
public partial class MainForm : Form
{
bool IsMouseDown = false;
Point MousePosition;
int DrawShape = 0;
Bitmap StoredImage;
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
pictureBox1.Image = new Bitmap (pictureBox1.Width,pictureBox1.Height);
StoredImage = new Bitmap(pictureBox1.Width,pictureBox1.Height);
}
void PictureBox1MouseDown(object sender, MouseEventArgs e)
{
IsMouseDown = true;
MousePosition = e.Location;
Graphics gStored = Graphics.FromImage(StoredImage);
gStored.Clear(Color.Transparent);
gStored.DrawImage(pictureBox1.Image, 0, 0);
}
void PictureBox1MouseUp(object sender, MouseEventArgs e)
{
IsMouseDown = false;
}
void PictureBox1MouseMove(object sender, MouseEventArgs e)
{
Graphics g = Graphics.FromImage(pictureBox1.Image);
if (DrawShape == 0)
{
Pen p = new Pen(Color.Red, 10);
if (IsMouseDown)
{
g.DrawLine(p,MousePosition,e.Location);
MousePosition = e.Location;
}
}
if (DrawShape == 1)
{
g.Clear(Color.Transparent);
g.DrawImage(StoredImage,0,0);
g.DrawRectangle(Pens.Green,MousePosition.X,MousePosition.Y,e.X,e.Y);
}
if (DrawShape == 2)
{
g.Clear(Color.Transparent);
g.DrawImage(StoredImage, 0, 0);
g.DrawEllipse(Pens.HotPink, MousePosition.X, MousePosition.Y, e.X, e.Y);
}
if (DrawShape == 3)
{
g.Clear(Color.Transparent);
g.DrawImage(StoredImage, 0, 0);
g.DrawArc(Pens.Indigo,pictureBox1.Bounds, e.Y, e.X);
}
//if (DrawShape == 4)
//{
// g.Clear(Color.Transparent);
// g.DrawImage(StoredImage, 0, 0);
// g.DrawPolygon(Pens.Indigo, Point[] e.X);
//}
this.Refresh();
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
axWindowsMediaPlayer1.URL = ofd.FileName;
}
}
private void button1_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.Ctlcontrols.pause();
Bitmap bmp = new Bitmap(axWindowsMediaPlayer1.Width, axWindowsMediaPlayer1.Height);
Graphics gfx = Graphics.FromImage(bmp);
gfx.CopyFromScreen(PointToScreen(axWindowsMediaPlayer1.Location), new Point(0, 0), axWindowsMediaPlayer1.Bounds.Size, CopyPixelOperation.SourceCopy);
pictureBox1.BackgroundImage = bmp;
//axWindowsMediaPlayer1.Visible = false;
//pictureBox1.Visible = true;
}
private void button3_Click(object sender, EventArgs e)
{
Graphics gg = Graphics.FromImage(pictureBox1.BackgroundImage);
gg.Clear(Color.Transparent);
Graphics gStored = Graphics.FromImage(StoredImage);
gStored.Clear(Color.Transparent);
Graphics g = Graphics.FromImage(pictureBox1.Image);
g.Clear(Color.Transparent);
}
private void button4_Click(object sender, EventArgs e)
{
DrawShape = 1;
}
private void button6_Click(object sender, EventArgs e)
{
DrawShape = 2;
}
private void button8_Click(object sender, EventArgs e)
{
DrawShape = 3;
}
private void button7_Click(object sender, EventArgs e)
{
DrawShape = 0;
}
}
}
If someone could help me edit my code to iron out the issue to make it easy drag and draw system it would me much appreciate.
Thanks in Advance
Chris
From msdn:
Draws a rectangle specified by a
coordinate pair, a width, and a
height.
So your code won't work:
g.DrawRectangle(Pens.Green,MousePosition.X,MousePosition.Y,e.X,e.Y);
Should be something like
g.DrawRectangle(Pens.Green, MousePosition.X, MousePosition.Y, Math.Abs(e.X - MousePosition.X), Math.Abs(e.Y - MousePosition.Y));
The biggest problem I see is that you're trying to draw in the mouse events. This means your drawing will be wiped away the instant you get a refresh event.
Only draw in Paint events, never in mouse events. If you want your app to draw as a result of mouse events, set a point, rectangle, or whatever in the mouse events (like you start to do with IsMouseDown), invalidate the area you want to change in your MouseMoved event, then draw your rectangle or whatever in your Paint event.