WPF: Calculating window size based on content - wpf

I need to fit the window's width and height to its content. I'm aware of existance of SizeToClient property of Window, however, if one chooses WidthAndHeight as the value of SizeToClient, window events are fired in invalid way, such that several components raise an exception during Loaded event: "Hwnd of zero is not valid" (for example GlassWindow's SetAeroGlassTransparency from Windows API CodePack).
Is there a workaround? I may calculate the window size manually, but I do not know, how to retrieve the window's chrome sizes (in other words, the real window's content margin sizes).
Details of WPF bug
Best regards -- Spook.

You could use SystemParameters to determine the size of the chrome. For example, SystemParameters.CaptionHeight.

Related

Sizing WPF windows automatically

When designing WPF dialog windows in the XAML designer (that are not manually resizeable by the user), the windows automatically resize to fit their content, and everything is fine. But when I run my app, the windows become huge and there's a lot of empty space.
I know this is a "feature" of WPF that can be "fixed" by setting the SizeToContent tag, but another issue arises when I do this: If the window contains a textbox, for instance, and the user enters data that overflows the visible area, the window will stretch to accommodate it. This happens with listboxes, treeviews, you name it.
All I want is for Visual Studio to figure out the ideal window size that it shows me at design time, then set the window to be that size at runtime, and don't change the size after that. It seems like this should be an easy thing to do.
Edit: Figured out part of the problem: I have controls set up in a grid, and the column's width is set to "Auto" which is why everything is resizing.
Use View Box
The ViewBox is a very useful control in WPF. If does nothing more than scale to fit the content to the available size. It does not resize the content, but it transforms it. This means that also all text sizes and line widths were scaled. Its about the same behavior as if you set the Stretch property on an Image or Path to Uniform.
Although it can be used to fit any type of control, it's often used for 2D graphics, or to fit a scalable part of a user interface into an screen area.
<Viewbox>
<Enter your code/>
</Viewbox>
Try setting the window's height and width to Auto. Also, remove the SizeToContent attribute. This should fix it.
I do not think that this is this is something which is commonly requested so it's probably not easy to do, one method i can think of would be starting with automatic SizeToContent and handling the Loaded event and setting:
Height = ActualHeight;
Width = ActualWidth;
SizeToContent = System.Windows.SizeToContent.Manual;

How to resize multiple WPF controls when the text size changes?

What's the correct pattern to resize controls when a font size changes?
For example, I used the WPF designer to make a form, and placed UI elements from the toolbox. Late in the game I got the requirement that the font size of every UI element needs to be configurable, so now I'm thinking there has to be a better way to resize controls when the font size changes. Right now I'm doing alot of code behind calculations on Margin properties.
For such cases I usually place my control inside Grids and StackPanels, this way font size won't affect the layout, everything will be stretchable.
Never place controls on the Window using absolute coordinates.
Make sure your Height and Width on the controls are set to Auto.
When you use the designer/toolbox to add controls it usually provides a static height/width. If you type the tag in the XAML editor you get the control default which is usually Auto.
You'll notice the black diamond in the property window next to the attributes that are changed from their default value. You can right click and choose reset value to clear the attribute from your XAML and see what the default value is.

Form height problem when FormBorderStyle is NONE

I have a borderless form (FormBorderStyle = None) with the height of 23 pixels (set in the designer)
When .NET draws my form at runtime - it draws it 38 pixels high (it adds the height of a title-bar for some reason).
MessageBox.Show(this.Height.ToString()); //this shows 38!! why?
To work it around I have to set "Height = 23;" in the Form_Load event.
private void MyForm_Load(object sender, EventArgs e)
{
this.Height = 23; //workaround. wtf??
}
You can try this yourself in Visual Studio 2010 (Winforms App, target Framework - 2.0).
Wtf?
Yeah, it is a bug, of sorts. Note how in the designer you set the size of the form with the Width and Height properties. Those properties include the size of the borders and the title bar. That's a problem however, your form may run on a machine where the user has increased, say, the title bar font size. That then would reduce the size of the window's client area. Or in other words, the form's ClientSize property would change on that machine. Leaving less room for the controls and messing up the design of your form pretty badly.
There's code inside the Form class that runs after the Handle is created, right before the Load event runs. It recalculates the Size of the form, using the same ClientSize you had on your machine. Now everything is good, the Height of the form won't match the one you set in the designer but the form otherwise looks the same and the layout of the controls is identical.
That same code also ensures that the window doesn't get too small. And that's where it falls over, it doesn't pay enough attention to the FormBorderStyle property. Clipping the height to the title bar size plus the client area height, as you found out. It also prevents the form getting too narrow, trying to make sure that the icon and min/max/close buttons are always visible. Even if you don't have any.
The workaround is to change the ClientSize after this code runs, the OnLoad override or Load event handler is the right place for that. Beware that if you hard-code the form size like this then you should also set the AutoScaleMode property to None. Make sure that this doesn't cause trouble on a machine that has a different DPI setting.

How to detect that WPF window has been snapped in Windows 7

Windows 7 has the snapping feature which 'snaps' a window to the edges, and changes the one dimension of the window size to match the same dimension of the screen, and then choses another size for the other dimension.
I want to detect that it has happened so that in my WindowStyle.None window with custom chrome, I can implement the proper behavior for double clicking the titlebar.
The snapping does not alter the WindowState, so I cannot detect that it has happened. Since only one dimension of window is set to match the the screen, I can not distinquish between a snapped window and a user resized window. Does Win7 send out a specific message, or include a flag in the WM_xxxx messages when it causes a resize? Is the formula to the other dimension (not the one matching the screen) defined anywhere so that I can check if both dimensions match that of a snapped window?
have you tried using spy++ to watch window messages to see what gets sent in what order? maybe there's an extra mesage in there that windows is using.

How to determine width of a windows forms controls whose width was increased because it is Anchored?

I currently have a Textbox on a Windows Forms, and I need to dynamically add a PictureBox box control at the right of the Textbox.
I create the PictureBox programmatically and I when setting the location of the PictureBox, i'm setting like this:
pBox.Location = new Point(tbControl.Location.X + ctrl.Width, ctrl.Location.Y);
So i'm setting the picture box to be located at the X location of the textbox PLUS the width of the textbox. However, since the textbox has an anchor property set to right, its width increases to fill the space between itself and the form border.
Problem is, that even though the textbox's width is visually bigger than the actual value of Textbox.Width. the Width property is not taking into account the extra width of being anchored.
I already tried properties like Textbox.Bounds.Width, Textbox.ClientSize.Width, Textbox.DisplayRectangle.Width, etc. with no luck. All of those properties return the original Width of the control without taking into account the resized width due to the Anchor property.
Does anyone know how I can determine the real size of the textbox? Thank you
The Width property always tracks the current width of a control, whether it is anchored or not. However, the TextBox is going to grow when you make the container larger and that will make it overlap the PictureBox. You have to anchor the PB to the right as well.
These should be returning the adjusted size. Either you are referring to the wrong textbox, or you are doing the query before the size has actually changed.

Resources