Picturebox change location on mouseenter without white borders appearing - c#

Hello I'm trying to do the effect that the button is pressed, so when mousenter moving 2px the picturebox, I'm using picturebox as button because It allows me to set transparent backgrounds.
I tried forcing the background to transparent in various events(paint,pevious change location,after change location),but without success.
I think that is caused for the re-drawing when changing an element, because the white part of the background that whas "hidden" by the picturebox appears.
Any idea how to solve that?
Thanks in advance
private void buttonX2_MouseLeave(object sender, EventArgs e)
{
((PictureBox) sender).Location = new Point(
((PictureBox) sender).Location.X, ((PictureBox) sender).Location.Y - 2);
}
private void buttonX2_MouseEnter(object sender, EventArgs e)
{
((PictureBox)sender).Location = new Point(
((PictureBox)sender).Location.X, ((PictureBox)sender).Location.Y + 2);
}

The problem seems to come from moving in or out too slowly. If you do that you will say enter from below, but the PB is moving up so you're out of it again, so it moves down and therefore you're in it again etc..The correct repainting of the Background can't keep up with these 'Jittering ButtBoxes'..
First, as Hans noted, make things less obtrusive: make the Form's BackColor dark, maybe even black!
Second to avoid the problem of jittering, move the Mouse Cursor itself a few pixels with the Pictureboxes, like this:
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
PictureBox PB = (PictureBox)sender;
Point MP = Cursor.Position;
this.SuspendLayout();
PB.Location = new Point( PB.Location.X, PB.Location.Y - 2);
Cursor.Position = new Point(MP.X, MP.Y - 2);
this.ResumeLayout();
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
PictureBox PB = (PictureBox)sender;
Point MP = Cursor.Position;
this.SuspendLayout();
PB.Location = new Point( PB.Location.X, PB.Location.Y + 2);
Cursor.Position = new Point(MP.X, MP.Y + 2);
this.ResumeLayout();
}

Related

Why isn't my application drawing anything?

I'm very new(read 3 weeks exp) to C#(programming in general),started with html/css and javascript and now on my way with C#.
I'm trying to make my own simple 'Paint' application in windows form. But i've encountered an issue and just cant wrap my head around it, doesnt matter how much i read or follow other mans code, i'm stuck. The following code works fine but when resizing the application window the drawing dissappears.
As a solution ive read that declaring the Graphics method within the panel1_Paint event this should be resolved And here is my issue. See last code sample, ive come up with this(yes like i said, im new to this)and its not drawing anything.
ive simply tried to recreate the first example under the panel1_Paint event but i guess something went wrong during the mouseMove event and i cant figure out what it is.
Could someone explain to me what i am missing here, that would be very appreciated. thanks in advance.
[Old code]
namespace Painter
{
public partial class Form1 : Form
{
Graphics graphics;
Pen pen = new Pen(Color.Black, 1);
Point startingPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
bool mousePaint = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
startingPoint = e.Location;
if (e.Button == MouseButtons.Left)
{
mousePaint = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(mousePaint == true)
{
endPoint = e.Location;
graphics = panel1.CreateGraphics();
graphics.DrawLine(pen, startingPoint, endPoint);
}
startingPoint = endPoint;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mousePaint = false;
}
}
}
[New Code]
namespace Painter
{
public partial class Form1 : Form
{
Pen pen = new Pen(Color.Black, 1);
Point startingPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
bool mousePaint = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = panel1.CreateGraphics();
if (mousePaint == true)
{
graphics.DrawLine(pen, startingPoint, endPoint);
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
startingPoint = e.Location;
if (e.Button == MouseButtons.Left)
{
mousePaint = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(mousePaint == true)
{
endPoint = e.Location;
}
startingPoint = endPoint;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mousePaint = false;
}
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = panel1.CreateGraphics();
This is nonsense! Always and only use the e.Graphics object from the Paint param!!
Also: To trigger the Paint event do a panel1.Invalidate(); whenever your drawing data have changed!
Also: Make sure you understand just what your mousePaint flag is supposed to control: the mouse painting (i.e. adding new shapes to draw) or the regular painting (i. all shape previously drawn)!? Note that all drawing, current and previous needs to be done from the Paint event, whenever necessary i.e. over and over again!
To be able to do so: Collect all the shpes' data in a List<T>..
To Doublebuffer a Panel you need to subclass it. Your code turns on DoubleBuffering for the Form, which fine but won't help the Panel..
Instead simply use a PictureBox, which is control meant for drawing on!
A DoubleBuffered Panel subclass is as simple as this:
class DrawPanel : Panel
{
public DrawPanel()
{
DoubleBuffered = true;
}
}
Update: Instead you can also use a Label (with Autosize=false); it also has the DoubleBuffered property turned on out of the box and supports drawing better than Panels do.
The following code works fine but when resizing the application window the drawing dissappears.
This happens because resizing the application window invalidates portion of your panel which causes the portion to be redrawn.
Reason why your second approach is not working (the one labelled as [NEW CODE]) is because the Paint event is called only when relevant component is redrawn. You could partially solve this by forcing redraw of the panel in your MouseDown/MouseMove event handlers but you would still lose your previously painted stuff.
Possible solution is to create instance of Bitmap and paint there. Then just set this Bitmap as BackgroundImage of the panel. You can find more information on that here. Of course you would need to think about stuff like resizing and what should happen to the bitmap if application window gets shrunk or enlarged.
Here is some code that I quickly put together to get you started:
namespace WinForms_PaintTest
{
public partial class Form1 : Form
{
private Pen pen;
private Bitmap bitmap;
public Form1()
{
InitializeComponent();
this.pen = new Pen(Color.Black, 1);
this.bitmap = new Bitmap(this.panel1.Width, this.panel1.Height);
this.panel1.BackgroundImage = this.bitmap;
}
private void panel1_MouseMove(Object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
using (Graphics g = Graphics.FromImage(this.bitmap))
{
g.DrawRectangle(this.pen, e.Location.X, e.Location.Y, 1, 1);
}
this.panel1.Refresh();
}
}
private void Form1_FormClosed(Object sender, FormClosedEventArgs e)
{
this.pen.Dispose();
this.bitmap.Dispose();
}
}
}
Also regarding this:
this.DoubleBuffered = true;
I believe your intention was to prevent the flickering when relevant control is being redrawn? If that is case you need to set this property against the panel and not against the form itself. It is little bit tricky though because DoubleBuffered property of the panel is protected so you will need to either inherit from the panel or resort to reflection. You can find more information here .

how to change the drawstring position when the user changes the coordinates values

i am planning to write something on a picture box.in the page load event i am able to do that.
Graphics g = Graphics.FromImage(pictureBox1.Image);
Font font = new Font("Courier New", 6);
payagainst = "PARADISE TRADING, CONT & REAL ESTATE";
g.DrawString(payagainst, font, new SolidBrush(Color.Black), pagainstX, pagainstY);
My requirement is there is two textbox in the form ie to mention the the X and Y coordinates of the newly drawn label. If the user changes the values in the textbox position of the label has to be changed according to the values given in the text box. in the text box leave event i have written the code as follows. but its not working. whats the correct method to achieve this.
private void txtpaX_Leave(object sender, EventArgs e)
{
if (flag != 0)
{
Graphics gs = Graphics.FromImage(pictureBox1.Image);
Font font = new Font("Courier New", 6);
payagainst = "PARADISE TRADING, CONT & REAL ESTATE";
amount = 3300;
gs.DrawString(payagainst, font, new SolidBrush(Color.Black), float.Parse(txtpaX.Text), float.Parse(txtpaY.Text));
flag = 1;
}
}
any help will be appreciated
What is supposed to happen after the string is printed over the image?
Do you need to save the image or pass it on or is the display in the PictureBox the only aim?
For the latter case this is the way to do it:
You place the drawing code only in the Paint event and call it, by invalidating the PictureBox, either whenever the TextBoxes have a change or when you leave them..:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString(yourText, yourFont, yourBrush,
float.Parse(textBox1.Text), float.Parse(textBox2.Text));
}
// this will show up only after leaving the textbox:
private void textBox_Leave(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
// this will provide a live change:
private void textBox_TextChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
Note that you should hook this code to both TextBoxes!
This code will persist the drawing but it will not change the actual Bitmap. Which I guess wouldn't make sense until you know exactly where the text should go..
If you want to change the actual Image you can do it like this:
private void stampButton_Click(object sender, EventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
G.DrawString(yourText, yourFont, yourBrush,
float.Parse(textBox1.Text), float.Parse(textBox2.Text));
}
..and then maybe save it like this:
private void saveButton_Click(object sender, EventArgs e)
{
pictureBox1.Image.Save("yourfilename", System.Drawing.Imaging.ImageFormat.yourfileformat);
}

C# - Drag and Drop & Keep Control

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

Text under mouse cursor on PictureBox

I have a problem with displaying the text under the mouse cursor on Picture Box.
I want to dynamically display the mouse coordinates under the cursor.
I'm trying to display text by label and change the label's position when a "MouseMove" event happens.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
label1.Location = new Point(e.X + 10, e.Y + 10);
}
But, I think, it is a bad solution...
And although it works it hides other output when we move the cursor
Thanks a lot!
Thanks for Thomas's advice, here code to display mouse coordinate under cursor:
ToolTip tt = new ToolTip();
tt.SetToolTip(pic, " ");
tt.ShowAlways = true;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
tt.ToolTipTitle = e.X + " " + e.Y;
}

Dragging graphics objects on top of bitmaps

I am attempting to drag a shape around a picturebox on the mousemove event but am struggling to get it to move smoothly. The picture box has an image loaded as the background and I would like the graphics object to drag a circle on top of the image when the mouse is clicked and dragged.
I have it working by creating a clone of the original image each time the mouse moves and reloading the picture box but it seems like their must be a better way to achieve this.
Without reloading the original bitmap each time any graphics added remain on the image creating a trail which is more like a paint application.
How do I clear previous drawings without reloading the entire image each time? Any help appreciated.
private void picCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (_drag)
{
picCanvas.Image = (Bitmap)_original.Clone();
Graphics g = Graphics.FromImage((Bitmap)picCanvas.Image);
g.DrawEllipse(_whitePen, e.X, e.Y, 10, 10);
picCanvas.Invalidate();
}
}
private void picCanvas_MouseDown(object sender, MouseEventArgs e)
{
_drag = true;
}
private void picCanvas_MouseUp(object sender, MouseEventArgs e)
{
_drag = false;
}
check this sample it is simpler
//Load Image
Bitmap TestImage = new Bitmap(FileName);
//Create Graphics Object
Graphics g = Graphics.FromImage(TestImage);
g.DrawEllipse(new Pen(Color.Red), i, j,0.5F, 0.5F);
//View Your Results
pictureBox1.Image = TestImage;
To solve the problem in the best way, use picCanvas.Paint event.
Set the positions at mousemove event and use that positions to draw at paint event.
Point pos = Point.Empty;// or your initial position
private void picCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (_drag)
{
pos = e.Location;
}
}
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
if (_drag)
{
Graphics g = e.Graphics;//The event handler sends us the graphics object to use for painting
g.DrawEllipse(_whitePen, pos.X, pos.Y, 10, 10);
}
}
You should add the Paint event to the Control and set the image at formload or some initialization function.
picCanvas.Image = (Bitmap)_original.Clone();
Using the above answer from Honibis I ended up with this.
load in the image and invalidate the picture to cause a refresh
picCanvas.Image = image;
picCanvas.Invalidate()
then in the paint event
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
if (_drag)
{
using (Pen pen = new Pen(Color.White, 2))
{
e.Graphics.DrawEllipse(pen, pos.X, pos.Y, 10, 10);
}
}
}

Categories

Resources