When programming with GDI+, do I need to stick to using pattern to all kinds of objects like Brush, Font, it can make code very cluttered.
Any suggestions?
Yes, you should do that for all (IDisposable) objects that you create.
The exceptions are the stock objects (Brushes.Blue, Pens.Black, e.Graphics, ...) because you don't create them.
it can make code very cluttered.
using is not as cluttered as a full try/finally. Note that you can economize the nesting:
using (Pen p = ...)
using (Brush b = ...)
{
// draw with p and b
}
But if the choice is between cluttered code or the possibility of the program failing, is there really a choice?
Yes, you should. These objects could contain unmanaged resources (e.g., GDI+ handles) that need to be disposed of properly. So, either use a using block or wrap everything thing in a try / finally statement where in the finally block you invoke IDisposable.Dipose.
Please see these previous answers on this topic:
What Happens if I Don't Call Dispose
Wrapping MemoryStream in a using
If you created the brush using new you should dispose of it.
If you got the brush from the Brushes collection, do not dispose of it. See the remarks section of http://msdn.microsoft.com/en-us/library/system.drawing.brushes.aspx for more info.
The same holds true of fonts, if you created it with new, dispose of it. If you got it from something else, look at the documentation to see if you should dispose if it or not.
Yes, you have to.
Alternative is using default brushes and fonts such as Brushes.Black, ...
Related
Today my intstructor, where I'm intern, said I should use
HImage hi = null;
HOperatorSet.GenEmptyObject(out hi);
hi.Dispose();
hi = f.GrabImageAsync(-1.0);
Instead of
HImage hi = null;
hi = f.GrabImageAsync(-1.0);
Prototypes of used functions as follows
void HOperatorSet.GenEmptyObj(out HObject emptyObject);
HImage HFramegrabber.GrabImageAsync(double maxDelay);
I respect my instructor ,but I don't see any meaningful explanation at creating and disposing an object before calling hi = f.GrabImageAsync(-1.0); as that functions returns an instance of that object and therefore no need for Generating and Disposing object first, at least in my opinion.
So anyone can clarify if it is really needed or not. Thank you in advance.
I agree with you. Generally there is no use in creating and immediately disposing a variable.
As far as we can see from the code, HOperatorSet.GenEmptyObject doesn't interact with your f variable, so there would be no meaning in calling that method.
Also, there is no point in setting HImage hi to null, since that is probably the default already and it is set using the out parameter.
So my bet would be on:
HImage hi = f.GrabImageAsync(-1.0);
Most of the time Dispose() is called to release all managed resources that no longer in need. So let's assume that HOperatorSet.GenEmptyObject(out hi) method opens FileStream and saves reference to some field in new HImage instance. Later in code you would like to do other operation with this HImage instance and no longer need this FileStream or any other resources. It's a good moment to call hi.Dispose() that closes it before you proceed with doing anything else. But in any other case your instructor is misleading you.
There are a few classes in WinForms which have multiple purposes, some of which require resources and some of which don't. The one I'm most familiar with is Font. A Font instance encapsulates a combination of font settings as well as a GDI handle to a GDI font resource. The Font property setter of most WinForms controls will cause the controls to copy of the settings from the passed-in font object and store a copy of the passed in Font reference so that it may be returned by a call to the property getter, but will not cause the controls to actually use the passed-in font for drawing. Since the settings can be read from a Font object even after is is disposed, it is in fact possible to create and dispose Font objects when setting controls' Font properties; in some cases it may arguably be a reasonable least-of-evils approach:
If Font objects are created and abandoned without disposal, that will usually not cause too much of a GDI resource drain, but such wishful thinking doesn't represent good design.
A policy of calling Dispose on a control's old value of Font before setting a new value will require that every control own its own separate Font object, which will then encapsulate a resource the control will never use. The one advantage is that code which reads a control's Font property will be able to draw using that Font object directly.
Having controls hold references to font objects that are already disposed will make it possible for multiple controls to safely share the same font object, and will consume fewer GDI resources than either of the other approaches. The one limitation is that any code which reads a control's Font property and wants to draw with that font will have to use it to construct a new Font object for the purpose (and probably dispose of it after use).
IMHO, the fact that disposing Font objects immediately on creation is a useful pattern suggests that the Framework should have included separate types for the purposes of describing fonts (the purpose of a control's Font property) and encapsulating GDI font objects (the purpose of the Font parameter to string-drawing methods). If the latter type had included Dispose and the former type not, there would have been no question about how to use each. Since the Font type exists, however, along with code that uses it for those disjoint purposes, the eager-dispose pattern may be a reasonable least-of-evils approach.
I'm not sure that approach represents what's going on in your instructor's example since I'm not familiar with the types involved. It may be that the object returned by GenEmptyObject doesn't actually allocate any resources and its Dispose method does nothing (and stating that the particular object may be safely abandoned may be better than calling Dispose prematurely) but if the object acquires resources which won't be needed for its intended use, early disposal might possibly be appropriate if commented.
Should I use using block inside a loop or outside of it? Is there any sensible performance difference? Is there any difference in the case of Graphics object? While the second approach may seem better, the while could be a long block and make the code less readable.
while (i < 100)
{
using(Graphics g = Graphics.FromImage(bitmap)
{
g.DrawImage(...);
}
}
vs.
using(Graphics g = Graphics.FromImage(bitmap)
{
while (i < 100) // a long while block
{
// I may use other functions such as g.DrawLine .. or g.DrawText ...
// Moreover while could be a long block
g.DrawImage(...);
}
}
Unless you're using a different Bitmap for each loop, you should put the using block outside of it.
As a rule of thumb, place the using inside the loop if you plan to use the object only once OR the object is not designed to be reused (SQLCommand class comes to mind as an example). Otherwise place it outside the loop.
In your specific case, if your intent is to draw the same image 100 times, then outside the loop is the way to go. On the other hand, if your intent is to draw 100 distinct images inside a loop, then the only way it could work would be to place the using inside the loop, because the Graphics object cannot be reused with another image.
in terms of performance outside of the while loop so you don't have to make 100 objects. It might depend how you want to manage exceptions though.
Given the sample code, I would absolutely go for the second option and put the loop inside the using. Far better performance that way.
If there's additional logic that is changing which bitmap you are using in the middle of the loop, you may need to consider the first option. Just be aware that you will likely suffer a performance hit.
I create a new Pen Object:
Private NewPen As New Pen(New SolidBrush(Color.FromArgb(12,52,220)))
When I now call NewPen.Dispose does it also dispose of the SolidBrush I used to create the pen, or do I have to dispose of it separately?
No. The Private keyword in your snippet is the only real hint that you are making a mistake. That implies that you made the pen a field of a class. That's never the correct thing to do, drawing objects are very cheap to create (about a microsecond) but expensive to keep around. They get allocated on a desktop heap that all programs that run on that desktop need to share. You never want to occupy space in that heap needlessly.
Always create a drawing object at the moment you need it. Which lets you fall in the pit of success with the Using statement:
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Using sbr = New SolidBrush(Color.FromArgb(12, 52, 220))
Using pen = New Pen(sbr)
'' Use the pen
''....
End Using
End Using
End Sub
This tends to be pretty unintuitive to many programmers, they usually learn that keeping objects around and re-using them is a Good Thing. The general rule you'd want to keep in mind is that it is usually the reverse for disposable objects. There are some types of objects that are expensive to create so seem to warrant keeping them around. The .NET Framework however always makes an effort to cache them itself. The Font class is a good example.
Simple answer: no. The Pen class (click to view the .net source code) doesn't store any references to the brush. You are responsible for disposing the brush. That's why this returns False:
Using b As New SolidBrush(Color.Black)
Using p As New Pen(b)
Debug.WriteLine("Is equal: {0}", (b Is p.Brush))
End Using
End Using
I've made a test WindowForm application that takes a snapshot of the window by it's boundaries. But I can't seem to give GetBounds() what it needs. He wants graphics but it already contains the bounds, I just want his point and size:
private void CaptureBtn_Click(object sender, EventArgs e)
{
Region region = GetRegionByHWnd(GetForegroundWindow());
Rectangle rectangle = new Rectangle(
region.GetBounds().Location,
region.GetBounds().Size);
CaptureImage(rectangle.Location, Point.Empty, rectangle.Size);
}
Did that problem occur to anyone before, or knows how to fix it?
For getBound some windows for you can
use ClientRectangle property , This
property returns bound form and this
dll (ScreenCaptureLib.dll) helps you
for getImage in the desktop.
http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=19415
First, Region implements IDisposable, so you should be wrapping it in a using statement or calling Dispose when you done with it.
Other than that we will need to see your code for GetRegionByHWnd and CaptureImage. Do you really even need that code at all? Why won't someWindow.Bounds work for you?
Perhaps that helps: RECTANGLE
I don't know your methods like captureimage. But Perhaps you need the relative position to the control?
Point to Client / Point to Screen
If not, please tell the data you expect to get and what you receive.
Also take a lookt to the RECT MSDN type instead of the Rectangle type.
Some good articles are here:
http://www.codeguru.com/csharp/csharp/cs_graphics/screencaptures/article.php/c6139
http://cid-32fd2eb6551ddb56.office.live.com/self.aspx/.Public/CaptureWindow.rar?sa=170500830
http://winapi.freetechsecrets.com/win32/WIN32Capturing_an_Image.htm
Regards
I want to provide different parts of an application with independent Graphics instances which end up painting on the same base Graphics. Simply cloning the Graphics works, but since both instances refer to the same GDI handle, there are not independent. I can't use Begin and EndContainer as well since I have a method which has to provide the new Graphics instances. -so I cannot determine when to call EndContainer. The use case is quite similar to the Graphics.create() method in Java.
I've found some workarounds, but none of them works for a Graphics provided by the PrintController.
Is there any proxy-Graphics I can use? Or is there a possibility to create another Graphics for the same device for instance?
This sounds bad. Do not store references to a Graphics object, it only ever lives temporarily and is only valid while a Paint or PrintPage event handler is running. Do make sure to pass it as an argument to whatever method does the drawing instead of storing it in a field or a global variable.
If the method is altering the state of the object then use the Save() and Restore() methods to prevent this from causing problems in subsequent methods that use that same object. Cloning it is never necessary with this approach.
Graphics objects are not meant to be persisted. You could use a backbuffer approach by drawing to a Bitmap before your final render.
Perhaps you could raise an event to which listening drawing components could subscribe, and your calling code could chain these together. That way you could use the same Graphics instance without compromising GDI efficiency.
Not sure what exactly you're trying to do but you can use CreateGraphics() on a Control or Graphics.FromImage(xx) to create a new Graphics object for the control and/or image. There's also a few more functions in Graphics.FromXXX
A possibility would be to create multiple graphics objects which are pointing to multiple targets, for example an memory image. Then after done, combine all images into one.
But the thing I don't understand is, if all graphics instances should paint to the same target why do you need multiple graphics objects in the first place?
I was facing same problem, I found the only solution is to duplicate the drawings code line !!
Like the following:
e.Graphics.DrawString(points(i).pointText, myFont, Brushes.Blue, New Point(points(i).crossPointX4, points(i).crossPointY4)) : G.DrawString(points(i).pointText, myFont, Brushes.Blue, New Point(points(i).crossPointX4, points(i).crossPointY4))