Paint Draw Image from another Thread? - c#

I read that you can increase the drawing speed/time by drawing with the paint event, and with that you can also draw unscaled.
So i would very much like to try it on my panel.
The problem is though, the image is recieved in another Thread then the GUI, and i don´t know how to give it to the paint event.
I really don´t want to invoke and stuff (as that is incredibly slow, at least when i have used it).
The code will look, something like this.
protected override void panel1_Paint(object sender, PaintEventArgs e, Image u)
{
e.Graphics.DrawImageUnscaled(u, Point.Empty);
}
Though there i tried using override to add to add an image in the field, ald i wanted to make it static, so i could call it from a Thread. Sadly i t didn´t work.
But well, i tried.
private void panel1_Paint(object sender, PaintEventArgs e)
{
// e.Graphics.DrawImageUnscaled(u, Point.Empty);
}
There is the "working" one, except i can´t get the image to it.
I tried making an image variable, then save the image in that variable, and paint it.
but paint does never see the image in it, it can´t access the Image, guess cause it´s written from another thread.
//initialize
private Image Im;
////////
my Thread
Im = Image.FromStream(....);
////////////7
void panel1_Paint(object sender, PaintEventArgs e)
{
if(Im !=null)
e.Graphics.DrawImageUnscaled(Im, Point.Empty);
}
This is how i tried, and failed.

Related

Run opengl in c# backgroudWorker

Recently, I was learning OpenGL for C#. The basic structure I need is:
Computation in UI
=> Draw OpenGL in a separate window
=> More computation in a UI.
So far, the program always freeze up in the second step (make a window, draw some stuff, and that's it). I have tried:
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
//Draw the image on the window
Glut.glutIdleFunc(OnRenderFrame);
Glut.glutDisplayFunc(OnDisplay);
Glut.glutCloseFunc(OnClose);
Glut.glutMainLoop();
}
and call
public Form1()
{
InitializeComponent();
//initialize the window, the shapes, shader, and some other stuff
backgroundWorker1.RunWorkerAsync();
}
but it does not work. I have also tried to put the code for drawing in a button_Click and some other, but none works so far. Can anyone please help me with that?
PS: I learn OpenGL from GiawaVideos, in which I have also tried to ask this question, but consider their last video is 2 years ago, I don't have much hope.
It seem that BackgroundWorker can not be used to affect anything in the UI (which incidentally also include the OpenGL window). So I only have to find a way for the to drawing code to run separately while "technically" still in the same thread via Timer.Tick. The code now is:
public Form1()
{
InitializeComponent();
//initialize the window, the shapes, shader, and some other stuff
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
//Draw stuff, not affecting the main UI thread flow
}

Creating a form with transparent PNG as background in c#

i want to create a transparent form with png as background... which looks verymuch similar to this.
http://cdn.lo4d.com/t/screenshot/800/lili-usb-creator-3.jpg
so far i've used this code
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.DrawImage(this.BackgroundImage, e.ClipRectangle);
}
but the problem is when moving the part below doesnt update!!
i tried to use
invalidate();
but it keeps on drawing the image over and over making the dropshadow part denser and denser.
is there anything i can do??
this one works great.not very neat but it works upto the mark.
http://www.codeproject.com/Articles/19213/An-Alpha-Channel-Composited-Windows-Form-with-Desi

How do I know when an Image is loaded in Picturebox

I've some huge images (7000*5000) to load simultaneously in my program, which I'm displaying in picturebox one by one. These images take some time to load in the PictureBox. At first I'm loading all the images in an Image array as Bitmap, then I'm just showing the first image in picturebox picturebox.Image = imageArray[0]. So I want to show wait cursor until first image is shown in Picturebox. Is there any way to know when the first image is shown on Picturebox?
You can use the PictureBox events : LoadProgressChanged to show the loading progress and LoadCompleted to do something when it is finished.
private void pictureBox1_LoadProgressChanged(object sender, ProgressChangedEventArgs e)
{
// animate a progressbar...
}
private void pictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e)
{
// done !
}
To make this work, you have to keep the .WaitOnLoad value property to False, and you have to use one of the LoadAsync method.

What might cause an ArgumentException when updating a PictureBox?

Having decided to try AForge for video and imaging stuff, I tried to implement this simple demo:
private void Main_Load(object sender, EventArgs e)
{
// enumerate video devices
FilterInfoCollection videoDevices = new FilterInfoCollection(
FilterCategory.VideoInputDevice);
// create video source
VideoCaptureDevice videoSource = new VideoCaptureDevice(
videoDevices[0].MonikerString);
// set NewFrame event handler
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
// start the video source
videoSource.Start();
}
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
this.pictureBox1.Image = eventArgs.Frame;
}
The problem is that I always get an ArgumentException, though doesn't always happen right away. It pops up on Application.Run(new Main());, but the top of the stacktrace looks like this:
at System.Drawing.Image.get_Width() at System.Drawing.Image.get_Size()
at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
Not sure if this is relevant, but the ParamName attribute of the exception is null. I've tried wrapping the image assignment in a try...catch block, but this didn't help. I've also checked to make sure that the image is not null before assignment. I've also checked for non-null, but 0x0 sized images.
What have I done wrong? Can anyone suggest a workaround?
I think the problem is that you do not make a copy
of the passed bitmap (frame) in your event handler.
The AForge documentation says:
Since video source may have multiple clients, each client is responsible
for making a copy (cloning) of the passed video frame, because the video source
disposes its own original copy after notifying of clients.
So, if you directly assign the frame to the picture box
the bitmap could be disposed by the AForge framework while the PictureBox
is trying to draw the bitmap.

Issue when Applying Region to a Form

I am facing a strange behavior when I apply a non-rectangular region to a Windows Form (lets say an ellipse). The issue is that the form seems to disappear for a moment (as if the region is empty) when initially resized. It looks like a slight flicker whereas the contents of the desktop behind the form become visible for a fraction of the second. After the first resize this flicker is no longer observable.
This can be reproduced by simply creating a Windows Forms project and applying an ellipse region to the form by using the size of the form as a bounds rectangle for the ellipse (in this way you will be able to resize the form hence its borders will not be completely "eaten" by the region).
Note: I am updating the region of the Form in the OnResize event.
The code that I am using looks the following way:
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
GraphicsPath path = new GraphicsPath();
path.AddEllipse(new Rectangle(Point.Empty, this.Size));
this.Region = new Region(path);
}
Any ideas what might be causing this?
Quick follow-up:
I noticed that when I put the same code snippet in the OnSizeChanged event the flicker disappears or seems to happen rarely.
Thanks!
Handles Paint event
private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(new Rectangle(Point.Empty, this.Size));
this.Region = new Region(path);
}
You've fixed a massive problem for me in the same area.
I'm using this:
private void BorderedPanel_SizeChanged(object sender, EventArgs e)
{
this.Region = new Region(RoundedRectangle.CreatePlusOne(this.ClientRectangle, this.cornerRadius, this.RectangleCorners));
Refresh();
}
and it works without flickering. So it's worth giving a shot!

Categories