TECHNOLOGIES
FORUMS
JOBS
BOOKS
EVENTS
INTERVIEWS
Live
MORE
LEARN
Training
CAREER
MEMBERS
VIDEOS
NEWS
BLOGS
Sign Up
Login
No unread comment.
View All Comments
No unread message.
View All Messages
No unread notification.
View All Notifications
Answers
Post
An Article
A Blog
A News
A Video
An EBook
An Interview Question
Ask Question
Forums
Monthly Leaders
Forum guidelines
Aus Guy
NA
1
4.1k
MultiThreading PictureBox- Loses image after time?
May 12 2013 2:18 PM
First off let me state that I put this in multi-threading because it is indeed a threaded process that's producing this problem.
Alright, I have a basic StretchBlt function, running in a separate thread, that's ripping a screen image to Bitmap() and throwing it in a PictureBox. (Delegated, of course)
This is working fine at 60+fps for anywhere from about 2-5 minutes at which point the PictureBox 'loses' its image (white square with red X through it). Nothing changes internally, it just seems after several hundred updates, the PictureBox simply gives up.
I'm wondering if I'm running into an overflow problem with the Control or if there's some bizarre way I'm running 'out of sync' with my thread vs GUI thread?
I'll pastebin a shortened sample below.. Threading a function to StretchBlt and inlining the delegate to update the PictureBox.
(Sorry in advance for any foul coding practices, this is merely my proof of concept code, it'll be rewritten and cleaned later.)
private void manualScreenCap(Stopwatch sw)
{
GetWindowRect(wndLiveHWND, ref gRect);
IntPtr bufferHdc;
Bitmap _bmpBuffer = new Bitmap(400, 300);
Graphics g = Graphics.FromImage(_bmpBuffer);
IntPtr tgtHdc = GDI32.GetWindowDC(wndLiveHWND);
int tgtWidth = gRect.Right - gRect.Left;
int tgtHeight = gRect.Bottom - gRect.Top;
// centering and sizing our maximum bounding box based on a 4:3 ratio
Size aspectedSize = new Size(4, 3);
Size tgtFormSize = new Size(tgtWidth, tgtHeight);
Size maxFitSize = CalculateResizeToFit(aspectedSize, tgtFormSize);
int leftOffset, topOffset;
leftOffset = (tgtWidth - maxFitSize.Width) / 2;
topOffset = (tgtHeight - maxFitSize.Height) / 2;
// again for selection window, but only if it's currently active
if (_f_SelectionIndicator)
{
tgtWinLeft = gRect.Left + leftOffset - 4;
tgtWinTop = gRect.Top + topOffset - 4;
tgtWinWidth = maxFitSize.Width + 8;
tgtWinHeight = maxFitSize.Height + 8;
}
// rip tgt's image, inserting into a buffer, resized properly. :)
bufferHdc = g.GetHdc();
GDI32.SetStretchBltMode(bufferHdc, 3); // don't know why 3's best.. and FAST, wow.
GDI32.StretchBlt(bufferHdc, 0, 0, 400, 300, tgtHdc, leftOffset, topOffset, maxFitSize.Width, maxFitSize.Height, GDI32.TernaryRasterOperations.SRCCOPY);
// release the bufferBitmap so we can draw on it internally
g.ReleaseHdc(bufferHdc);
if (opts._f_ApplyTimeStamp)
{
// create our brush shit up here so it's ready for a fast-write to avoid flickering (I hope);
SolidBrush sb = new SolidBrush(Color.FromArgb(127, 127, 127, 127));
String dtString = DateTime.Now.ToString(@"ddd, MMM dd, yyyy - HH\:mm\:ss");
dtString += " " + (captures + 1).ToString().PadLeft(2, '0') + " [" + Global.sTitle + "]";
Font font = new Font("Lucida Console", 9f, FontStyle.Regular);
SizeF sf = g.MeasureString(dtString, font);
int lOffset = 400 - (int)sf.Width;
// draw our rectangle and timestmap (including current frame 1-30)
g.FillRectangle(sb, lOffset, 0, sf.Width, sf.Height);
g.DrawString(dtString, font, Brushes.White, lOffset + 1, 1);
sb.Dispose();
dtString = null;
font.Dispose();
}
#region setPicture;
if (pictureBox1.InvokeRequired)
{
pictureBox1.Invoke(new MethodInvoker(
delegate()
{
if (pictureBox1.Image != null)
{
Image oldImg = pictureBox1.Image;
pictureBox1.Image = null;
oldImg.Dispose();
}
pictureBox1.Image = (Bitmap)_bmpBuffer.Clone();
pictureBox1.Update();
}));
}
else
{
if (pictureBox1.Image != null)
{
Image oldImg = pictureBox1.Image;
pictureBox1.Image = null;
oldImg.Dispose();
}
pictureBox1.Image = (Bitmap)_bmpBuffer.Clone();
pictureBox1.Update();
}
#endregion setPicture;
#region DISPOSE GDI Objects;
{
_bmpBuffer.Dispose();
GDI32.DeleteDC((int)tgtHdc);
GDI32.ReleaseDC(IntPtr.Zero, tgtHdc);
g.Dispose();
GDI32.DeleteObject((int)bufferHdc);
}
#endregion DISPOSE GDI Objects;
}
Reply
Answers (
0
)
how to display the rid view records using chart
Silverlight 5 Certification??