How can i refresh pictureBox by button? - c#

I have a pictureBox and a button on my form. Button is just refreshing pictureBox. When pictureBox is refreshing it’s drawing line at the pictureBox.
private void button_Click(object sender, EventArgs e)
{
pictureBox.Refresh();
}
And i set OnPaint event for my PictureBox, so when my pictureBox is redrawing its call this method:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
//logic for drawing line
//its not so important, cause even if i put messagebox.show, result is the same.
}
I spend whole day to figure out why after pressing the button, line is not appear at the picture box. Turns out that program do like that:
1) button_click -> 2)pictureBox_Paint -> 3) button_click (again!!)
How its even possible? What should i do to just implement logic:
1) button_click -> 2)pictureBox_Paint

Related

MouseMove event prevents the MouseRightButtonUp event in WPF

I have drawn some lines using DrawingVisual. Now I'm trying to implement a simple hit testing.
When the mouse pointer moves over a line I'm redrawing it with twice its thickness to give the user a sense of highlighting (Magenta line in the image below)
This works very well until I also implement a MouseRightButtonUp event. I want to show a messagebox when the user right clicks the line. But somehow while the mouse is over the line and the line is highlighted, the MouseRightButtonUp event does not raise at all. What could be the problem?
MouseMove += OnMouseMove;
MouseRightButtonUp += OnMouseRightButtonUp;
private void OnMouseMove(object sender, MouseEventArgs e)
{
var p = e.GetPosition(Window);
// Check if the mouse hit any lines and redraw
ReDraw();
}
void OnMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
// Check if any line is hit and show the message box
if (lineHit)
{
MessageBox.Show("You hit the line!");
}
}

C# PictureBox and Timer don't work together

so I am trying to make a simple game in C# using PictureBox for painting and timer for update functions, but what I noticed is that when I start painting on my picturebox my timer stops working.. I have no idea why..
Here is the picturebox code:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Console.WriteLine("PicBox running!");
if (this.MyGame.InGame)
{
this.pictureBox1.Refresh();
e.Graphics.Clear(Color.White);
MyGame.CurrentMap.Draw(e.Graphics);
//e.Graphics.Dispose(); <- if I uncomment this, then the whole programm just freezes
}
}
Here is the timer code:
private void timer1_Tick(object sender, EventArgs e)
{
Console.WriteLine("Timer running!");
if (this.MyGame.InGame)
{
MyGame.CurrentMap.Update();
MyGame.UpdateTime();
}
}
Here is a method called by MyGame.CurrentMap.Draw(e.Graphics); :
public void Draw(Graphics g)
{
foreach(Planet item in Entities){
item.Draw(g);
}
}
Any help would be greately appreciated. I come from javascript, so I don't really know if I am doing something terribly wrong here.
When a timer tick occurs, you want to repaint your PictureBox. To do this, you should make it so that the PictureBox receives a Paint event. This is what Refresh() does, so the call to this.pictureBox1.Refresh(); goes in the end of timer1_Tick.
It doesn't make sense for the Paint event to contain a call to Refresh, because this, in turn, generates a Paint event.

change cursor over a pictureBox

i was trying to implemet an image button in winforms application as i can ...easy when using asp.net
the problem seem to be(i suspect) that when the mouse is over the image inside the picturebox
it is not responding or not triggering the mouseEnter event
it looks like if i had a picture that is smaller than the pictureBox Size it will accept the reason to trigger the event but over the image within the pictureBox it would Not ?
the trick was to set pictureBox to sizeMode=zoom. then do 2 things when the mouse is over the "imageButton" : change the size of PictureBox a little larger + change cursor to hand
so i will get a kind of mouse over effect as i could with asp.net
did anyone have that problem ?
at first i tried mouseHover, then i thought enter would do better as it only requiers the mouse to pass the borders of the picture box... both enter and hover events did not work for me ...
Edit :
the event does trigger , i can see that if i initially set sizemode to CenterImage and inside the event
i ask for sizemode=zoom, so the effect dose occur ..but cursor.current=Cursors.Hand will not change.
This should work
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Cursor = Cursors.Hand;
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.Cursor = Cursors.Default;
}
seem like i should have known better how to use Cursors class .
cursor=Cursors.hand;
rather than
cursor.current=Cursors.hand;
that was embarrassing ..
only add MouseMove event on pictureBox and set a Cursor for this
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Cursor = Cursors.Hand;
}

Drawing in C# winform is fairly slow

I'm creating a custom DataGridView, in which the CheckBox Shows a border when MouseHover is raised.
Here is what I've done so far.
void checkBox_MouseLeave(object sender, EventArgs e)
{
//showBorder defines whether the border is drawn.
this.showBorder = false;
this.DataGridView.InvalidateCell(this);
}
void CheckBoxMouseHover(object sender, EventArgs e)
{
this.showBorder = true;
this.CheckBox.BringToFront();
this.DataGridView.InvalidateCell(this);
}
protected override void Paint(...........)
{
..........
if (showBorder)
{
GraphicsPath border=new GraphicsPath();
border.AddRectangle(new Rectangle(checkBoxPosition.X-1,checkBoxPosition.Y-1,checkBoxSize.Width+1,checkBoxSize.Height+1));
graphics.DrawPath(new Pen(borderColor,1),border);
}
}
But is comes so slow that I have to wait for about half a second to see do border show.
Anyway, MouseLeave works fine.
So how can I improve the performance here?
In addition, how can I customize the checkbox? for example, the background color, etc.
You're using MouseHover event for the Mouse going over the control. Try MouseEnter instead. MouseHover is triggered after the mouse stays over the control for a little bit of time. MouseEnter is instant

How do I associate a button with a control?

OR - How To Shave A Koala To Stop It Looking Squashed. (But I didn't think that would make a suitably techy title)
The Problem: You have three preview images derived from a main image. The preview images are resized for standardised picture spaces on a company website, the main image can be any size image from anywhere.
Example: The main image is a hi-res image of a koala bear measuring 2000x2250. Your previews want to render the koala at 200x200, 200x50 and 250x150.
Your utility program resizes and stretches the original image to the size of your three "actual size" previews but obviously each preview looks a bit squashy and you know everyone hates to see a squashed koala.
To resolve this you add a little cropping method to your program which shaves five pixels from the preview on the desired side. This means you should be able to resize your image and unsquash your koala by shaving off the unnecessary parts of the image.
You add four buttons to each preview image picture box and create four generic methods for sending the correct shaving instructions to the crop method. You want to associate each specific button with a specific picturebox on the form, but you want to send all the click events to four generic functions.
How do you tell the generic function which of the three preview picturebox images you want it to shave in an elegant and wonderful way?
Example Code:
//cropPict=method for cropping the picture in the relevant picturebox.
//CropSide=a little enum which tells the method which side to crop.
private void btnT_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Top);
}
private void btnB_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Bottom);
}
private void btnR_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Right);
}
private void btnL_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Left);
}
EDIT: As it happens, inspired by Hans below, rather than just stuffing the PictureBox into the tag. Which was a great idea I actually put a KeyValuePair into the tag for each button like so:
btnCCB.Tag = new KeyValuePair<CropSide,PictureBox>(CropSide.Bottom,pbxKoala);
btnCCL.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Left, pbxKoala);
btnCCR.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Right, pbxKoala);
btnCCT.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Top, pbxKoala);
Then I could just wire all the buttons up to a single event handler like so:
private void btnC_Click(object sender, EventArgs e)
{
Button btnSend = (Button)sender;
KeyValuePair<CropSide, PictureBox> kvCrop = (KeyValuePair<CropSide, PictureBox>)btnSend.Tag;
cropPict(kvCrop.Value,kvCrop.Key);
}
Of course, there's still plenty more to do but that pretty much sorted out my problem. Thanks Hans!
Use the Button.Tag property to store a reference to its associated PictureBox. Cast sender to Button:
public Form1()
{
InitializeComponent();
button1.Tag = pictureBox1;
button1.Click += btnT_Click;
// etc..
}
private void btnT_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
cropPict((PictureBox)btn.Tag, CropSide.Top);
}

Categories