Gif image looping only once - c#

I was trying to figure out how to make sure that a GIF image what I put to my WindowsForm project through picturebox going to loop only once and still without finding an answer even after going through as many sites with this problem as I could find.
I know that with using of picturebox programmer lossing control of looping (in case that you set looping only once when creating the gif animation in editor) and I somehow have to get a code which will basically say when gif animation gets to some certain frame...in my case to last one which is number 7 and gets there in 430 milliseconds (190,40,40,40,40,40,40) the gif animation going to be Disposed.
So the whole idea was to make a simple game with balloons which will have an animation with flying and animation with exploding after pressing of the mouse on the ballon_grey picture box.
It would look like that:
private void timer1_Tick(object sender, EventArgs e)
{
//makes balloon going up
balloon_grey.Location = new Point(balloon_grey.Location.X, balloon_grey.Location.Y - 3);
}
private void balloon_grey_Click(object sender, EventArgs e)
{
//forces balloon_grey picturebox to change animation to balloon_grey_explosion.gif
balloon_grey.Image = Image.FromFile("balloon_grey_explosion.gif");
//gets the amount of frames from the gif animation...don't know if this is needed to reach the goal
int frames = Properties.Resources.balloon_grey_explosion.GetFrameCount(FrameDimension.Time);
}
Thank you for your time and any advice about the problem.

Related

How to know whether it is increasing or decreasing when the size of a Window changes

I have a form and I would like to have different logic when its size increases and decreases.
My only idea is to compare the new size with previous size in the function private void MainWindow_SizeChanged(object sender, EventArgs e) and implement the logic accordingly if size increased or decreased.
I am creating this thread because I have suspecision that there is a much more easier also more common with the API way to check whether it increased or decreased.
Edit: comments asked for the logic I am trying to implement.
I have picturebox inside my window
and when windows size increases picturebox adapts however when it decreases it shows scrollbars.
Thanks
It seems that question is left hanging so I better explain my solution.
My intuition was not so off the path, What I simply did is I put the PictureBox in some Panel in my case SplitContainer.Panel1.
PictureBox was already a class global for my Main Window and PictureBox properties Dock set to none and Anchor to Top, Left also mentioned Panel's AutoScroll should be set to True.
Also I rewrote the event Panel.SizeChanged() in such a way where I compare Panel.ClientSize dimensions with PictureBox dimensions if ever PictureBox dimensions are smaller just update them with Panel.ClientSize dimensions.
private void splitContainer1_Panel1_SizeChanged(object sender, EventArgs e)
{
if (pictureBox.Height < splitContainer1.Panel1.ClientSize.Height || pictureBox.Width < splitContainer1.Panel1.ClientSize.Width)
{
pictureBox.Height = splitContainer1.Panel1.ClientSize.Height;
pictureBox.Width = splitContainer1.Panel1.ClientSize.Width;
}
}

Failed to take photo with the webcam using the library AForge

I am making use of the AForge class library.
From this library I am using VideoSourcePlayer to take photos with the webcam.
My purpose is to create a function that allows the user to photograph images to establish them as company logo.
Not only can you choose images from the computer, but you can also capture images from the outside through the camera, since you may only want to transfer a logo of a physical support (paper) to the program.
As commented earlier in SO, (how to pause a video file played using videosourceplayer), VideoSourcePlayer does not have a Pause method or any function that allows to freeze the image.
Yes, it is true that it has the GetCurrentFrame() method, but that only gets a Bitmap from the current frame that must be passed to a PictureBox.
But I want that when the user clicks the button Capture the image of the VideoSourcePlayer simulate being frozen, and when the user presses the Delete button because he did not like the photo, then the image stops being frozen and recovers its movement.
Logic is like pausing or playing a video.
Well, there's no method for it, so I decided to look for another way to get this, and ...
If a picture is taken, use a PictureBox that contains the last frame and that is displayed on the VideoSourcePlayer, but if it is deleted, then the PictureBox is removed and the VideoSourcePlayer is returned with video.
private readonly Bitmap EmptyBitmap;
private void CaptureBtn_Click(object sender, EventArgs e)
{
Bitmap bitmap = this.VideoSource.GetCurrentVideoFrame();
ShowTakedFrame(bitmap, false);
}
private void ShowTakedFrame(Bitmap Frame, bool remove)
{
var picture = new System.Windows.Forms.PictureBox();
picture.Size = this.VideoSource.Size;
picture.Location = this.VideoSource.Location;
if (!remove)
{
this.VideoSource.Stop();
picture.Image = Frame;
this.Controls.Remove(VideoSource);
this.Controls.Add(picture);
}
else
{
this.Controls.Remove(picture);
this.Controls.Add(VideoSource);
this.VideoSource.VideoSource = this.CaptureDevice;
this.VideoSource.Start();
}
}
private void DeleteBtn_Click(object sender, EventArgs e)
{
ShowTakedFrame(EmptyBitmap, true);
}
My problem is that when capturing the photo, the image is a few seconds after the moment when you press the Capture button and when you delete the captured image, using the Delete button, the video of the VideoSourcePlayer is frozen.
Can someone help me with this?
The problem is that when you remove the PictureBox and add the VideoSourcePlayer, it creates a new object, that is, one that does not have the configuration properties of the previous one. My recommendation is that you create the capture in a different form.

C# Animation with timer flickers the background

I'm trying to make an animation for my C# program. There's a space rocket that ascends 8 pixels vertically with a timer interval of 25ms. I've managed to make the animation but since the picturebox's background (I've used for the rocket) is set to transparent it flickers the form's background image everytime it moves. What can I do to prevent it?
The code I've used for timer tick :
pictureBox1.Top -= 8;
P.S: I've tried to change the picturebox with panel, slow downed the rocket and timer but nothing seemed to change.
Well i haven't tried it myself now.
There needs to be a render event which you can hook to and make manipulations to your UI which would render smoothly.
Control.Paint
Try something like these :
private void Form1_Load(object sender, System.EventArgs e)
{
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
}
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
pictureBox1.Top -= 8;
}
Again this isn't tested and i haven't developed any thing in winforms for ages.
But that's the direction you should go for to render things smoothly.
That double buffered thing mentioned above is also a factor in some cases.
but this is mainly the way to do it.

How can I get the transparency right when layering pictureboxes?

In my setup i have 5 pictureboxes which I am trying to layer.
My code for this is:
pbCoin1.Parent = pbMap;
pbCoin1.BackColor = Color.Transparent;
pbCoin2.Parent = pbMap;
pbCoin2.BackColor = Color.Transparent;
pbCoin3.Parent = pbMap;
pbCoin3.BackColor = Color.Transparent;
pbFlashlight.Parent = pbMap;
pbFlashlight.BackColor = Color.Transparent;`
All 5 pictureboxes contain images. The method I am using works fine, but the problem is that the PbCoin 1,2,3 are glitching trough my pbFLashlight(see image).
Can someone provide a solution such that the coins are only visible when the transparent part of the black layer is over it?
Don't use multiple picture boxes. Use a single PictureBox to represent the game area and handle the .Paint event. Do all of your drawing using GDI calls on the Graphics reference that .Paint sends you in e. You will want to call PictureBox.Invalidate at the end of the Paint event to cause it to queue up the next frame
For better performance, create a new Bitmap instance that you keep a reference to for the life of the game. Clear and do all your drawing to that bitmap every frame, then draw that bitmap to the PictureBox in .Paint.
For even better performance than that, don't use WinForms.
The basic pattern should look like this:
private void Canvas_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(...);
Canvas.Invalidate();
}

Highlighted squares on a CustomControl chessboard don't persist beyond the initial MouseDown event

I've been coding a Windows app chess game in C# as an exercise in honing my skills, and also because it's fun. I have included functionality that allows a player to select the option to highlight the squares a piece can legally move to when it gets clicked. A CustomControl handles the rendering of the chessboard and it also highlights the squares.
It all works as planned until the player begins to drag the piece to a new square. The moment the mouse moves, the highlights go away. I suspect that a Paint event is raised and the board redraws itself. And since the highlights are not part of the initial board layout, they don't get drawn.
What I would like to happen is for the squares to remain highlighted until the piece is dropped on its destination square. Is it possible to accomplish this? Any suggestions will be appreciated.
Psuedo code:
void piece_MouseDown(object sender, MouseEventArgs e)
{
Piece piece = (Piece)sender;
legalSquares = CalculateLegalSquares(piece.CurrentSquare);
if (legalSquares.Count > 0 && this.showLegalMoves)
{
chessBoard1.HighlightSquares(legalSquares);
}
// I believe a Paint event gets raised either here...
piece.DoDragDrop(piece, DragDropEffects.Move);
}
void piece_DragEnter(object sender, DragEventArgs e)
{
// ...or here, that removes the highlights.
if (e.Data.GetDataPresent("Chess.Piece"))
{
e.Effect = DragDropEffects.Move;
}
else
{
e.Effect = DragDropEffects.None;
}
}
void piece_DragDrop(object sender, DragEventArgs e)
{
Piece piece = (Piece)e.Data.GetData("Chess.Piece");
if (piece.CurrentSquare != dropSquare)
{
if (legalSquares.Contains(dropSquare))
{
// This is where I’d like the highlights to stop
// DoStuff()
}
}
}
It sounds like you are highlighting the valid squares by drawing directly, but this will get erased on any repaint. You will probably lose the highlights if your window is repainted for other reasons also, such as minimizing and restoring it, or dragging another window on top of it.
If this is the case, you probably need to override the OnPaint method and do your highlighting there. When you want to change what is highlighted, set some state in your class to control what is drawn as highlighted in the OnPaint method, and then Invalidate your window.

Categories