I have some user controls in a windows form. I wonder
if i set the Font property of the main form, will its child get a) a copy of the new Font, or b) a reference to the new Font, or c) nothing?
Does a font need to be disposed? For example, can I do the following code safely?
form.Font = new Font(...);
Will a font get disposed automatically when the parent (Form or UserControl) is disposed?
Thanks,
Gilbert
Both. The Font property is its own .NET object. Winforms however caches the native Windows font, they are fairly expensive to create. The .NET wrapper object is quite small.
Yes. The code is fine, the Font property setter already disposes the previously assigned font.
Yes, it is disposed by the UserControl. Which in turn is automatically disposed by its parent.
When Font property of the main form is set, its child controls get neither deep copy of System.Drawing.Font object nor the reference to it. On assignment, parent form creates unmanaged font object handle. All child controls are subscribed to parent’s FontChanged event so they have a chance to grab this handle and use it later for text rendering. Font property getter of a control returns parent’s Font if control’s Font property has not been set explicitly (or default font).
Windows Forms does what is logically expected with any other property: When you assign a System.Drawing.Font object to Font property of a control, a previously assigned System.Drawing.Font object gets finalized and garbage-collected if no more references to it remain in your application. So yes, you can do this safely.
System.Drawing.Font object assigned to Font property of a control is NOT getting disposed when the control is disposed, or another System.Drawing.Font is assigned to Font property. So you are safe to create a single System.Drawing.Font object and assign it to multiple controls, which are created and disposed dynamically. You are also free to create multiple fonts and assign them to a control periodically to create some visual effects. Internal unmanaged font handles are managed by Windows Forms.
If the child form is already open, no it won't get a copy.
To expand a little on this if the child form does inherit the parents font. I don't think that changing the parents font would effect the child font after the window is already open.
The garbage collector should take care of it.
yes.
From what I can tell, the Font property of a control is used to determine the font settings to use when drawing the control, but the GDI Font associated with that property isn't used to do the drawing. A control won't care if the Font that's assigned to its Font property is disposed after it's assigned, or even before it's assigned. The control is clearly capable of using some hidden aspects of the Font object which are available even after it is Disposed to determine the appropriate attributes of the font, but I don't know whether it
Uses the supplied Font object, if not disposed, or else creates its own temporary font object each time it has to draw something and disposes the temporary object immediately thereafter.
Uses the supplied Font object, if not disposed, or else creates its own private font object which it will dispose of when either the Font property is reassigned or the control is disposed.
Copies the font family, size, etc. from the Font object when the Font property is assigned, and does everything with its private temporary or persistent Font objects it creates itself.
Copies the font family, size, etc. from the assigned Font object whenever it's necessary to draw something.
The control certainly keeps a reference to the passed-in font object, if for no other reason than to supply it to the Font property getter. I have no idea, though, whether it's better to dispose the Font after assigning it, or whether it's better to keep a copy of the Font in the form and dispose it when the Form itself is disposed.
Related
I am writing a program that overlay's a toolbar onto another applications window. I am able to iterate through the MDI child windows and even access all the controls via PInvoke. The one thing I am trying to figure out is how to get the controls actual Name property.
I am able to see the name of the field using Hawkeye but I cannot figure out how it is getting the control name.
One thought is that it may be injecting something into the target application and running something like Control.FromHandle but I am not 100% sure.
Thanks for any help.
Unfortunately, the Name property of a control is a property of the .Net object that creates the window not of the control window itself. There is no way to get this value using the window handle - PInvoke or otherwise - from outside of the process.
You would need to do some variation on what Hawkeye appears to do. Attach to the process, examine the object hierarchy and/or inject code dynamically using the CLR Debugging API.
I have a list of objects which among other properties contain a Brush (property name "Color").
In a Backgroundworker I want to write the contents of these objects to a file.
Everything works fine until I try to read the color of the brush property.
//this works fine
var brush = myObject.Color;
//this fails with InvalidOperationException
var c= ((SolidColorBrush)myObject.Color).Color;
It seems as if my code is somehow modifying the color but I don't see where/how.
Is there a way to read-only access the color of the brush?
Regards,
tabina
Do i sense that you're accessing UI objects on a thread that didn't create them. You cannot access UI objects from a BGW thread. That's the golden rule not to forget using BGW class
If there is no need to modify the objects after they have been added to that list, you might try to Freeze them before they get accessed from a different thread.
Make sure that the Freeze call happens in the UI thread, where you created those objects. You might also check if freezing is possible at all by calling CanFreeze beforehand.
I want to save form position. I have successfully set Form.Location property in ApplicationSettings->PropertyBinding but Form.Size is not listed in property binding list. Why? Do I need to add this property to save properties list using code?
The Form class overrides the Size property to prevent it from getting saved. This is by design, it uses the ClientSize instead so that the size doesn't depend on the border width chosen by the user. You'll find ClientSize in the property binding list.
This is still not a good idea, you don't want to save the size if the window is minimized or maximized. It will not restore properly. Instead, override the OnResizeEnd() method and only save the size if the WindowState is Normal.
EDIT: I was able to reproduce this in a very stripped-down version of the application. Here is a link to the .zip file
http://www.mediafire.com/?cn918gi15uph1xe
I have the module add the view to two different regions - the status bar region along the top is where the issue occurs. The weird part is, when the same view type is added to the main region, there are no problems. The status bar region is an ItemsControl and the main region is a ContentPresenter. That is the only difference.
Please let me know if you have any insight! Thanks.
-----Original Post-----
Hello all,
I am seeing some weird behavior with WPF. I'm using .NET 4 and PRISM v4. The way we have our application structured is that the skin resource dictionaries exist in their own assembly. The modules do not reference this assembly - instead we have a skin manager class that reads from a config file which skin we want and loads the appropriate components into a merged dictionary. The merged dictionary is set in the Application resources (we clear out the Application.Resources.MergedDictionaries before we add it). The idea is that we can later switch skins at runtime if needed, and the modules don't need to know about the skins until runtime.
Then in our xaml we are referencing styles using DynamicResource. The problem has to do with a TextBlock style defined in the skin and referenced by key, such as
<TextBlock Style="{DynamicResource someKey}" ... />
The style defines the font family, font size, and foreground. The font family and size are applied correctly (I verified this). The foreground, however, is always black. I used Snoop and WPF Inspector to see that the foreground value is "inherited" instead of coming from the style.
I also have a control that inherits from TextBlock and all it does is add some properties that determine what the text value should be (it doesn't affect the style at all). I was able to add a property changed override for the Foreground property and found out that the style's foreground value gets applied, and then the inherited value gets applied after that. I wasn't able to get the .NET source debugging to work so I couldn't figure out why/where it was being called from the second time...
Here is a link to an old, old post from a guy with the exact same problem - he did not find the answer, but instead a workaround. Unfortunately the workaround only works on the inherited control (I can't set InheritanceBehavior for TextBlocks).
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3501ed19-ab40-4064-81b5-e9b7b9d35b56
My guess is that for TextBlock the foreground property is inherited from its parent unless you explicitly set it on your TextBlock instane. For example if you change the Window or UserControl that this Textblock is in to have a Foreground of blue does it work? One thing you can try doing is in the style instead of setting just Foreground to a color, set TextElement.Foreground. See if that works.
It doesn't explain why the problem exists, but a fix was found here:
http://compositewpf.codeplex.com/discussions/257596
The fix is to load the skins before creating/adding views to the shell.
I need to extend a button control to add some additional, bindable, visual states.
What I would like to create is an additional boolean property, to bind to, that will create a simple visual state change on the button. For this example, it could just be an additional border which changes colour according to the boolean value.
All the existing button behaviour should be entirely seperate from this new set of states.
Can this be done?
This can certainly be done. Here's a post that walks you through the steps you'll need to take, and includes additional information for extending the control with properties (besides just those to hold state) that show up in the final control. The pieces you'll need are:
A class that derives from Button (your custom control class)
A default style for this control (which goes in /themes/generic.xaml). You can start off with Button's generic style and add your states to it.
A dependency property that holds your boolean value
A new VisualStateGroup that holds your two new states
Some code in your class that glues together changing states with the boolean value you've defined, presumably resulting from user interaction, etc.
You may find it's easier to edit the visual state in Blend, depending on how sophisticated your transitions will be, etc.