Limit resizable dimensions of a custom control (c# .net) - c#

I am making a user control in MS Visual C#, and there is one thing that I just can't find an answer to:
How do I limit which dimensions a control can be resized in during design view?
For a clear example of what I'm asking, the built in TrackBar control can only only be made wider, not taller, and only displays the resizing squares on the left and right in design mode. Is there a way to replicate this for a user control?
I have tried setting MinimumSize and MaximumSize values in the designer for my control, but this doesn't give ideal results.

To get the full behavior you're talking about (no adorners on top/bottom or left/right) and custom functionality inside the design time environment, you'll probably have to resort to building a custom control designer for your control.
This is a huge topic, as there are a lot of things you can do. Effectively what you'd do is create a class that inherits from ControlDesigner, override whatever functionality you need, then register it on your user control with the DesignerAttribute, specifying typeof(IDesigner) for the 2nd parameter (and your custom ControlDesigner-derived type for the first).
Enhancing Design-time Support
Custom Designers
ControlDesigner class example
Custom Design-time Control Features in Visual Studio .NET
Now, in the case of TrackBar, it has its own designer that overrides the ControlDesigner.SelectionRules property. This property simply lets you return an enumeration value (it's a Flags enum, so you can OR them together) indicating how your design-time selection adorners appear (or not appear). Once you've restricted design-time resizing via a designer, it's simply up to your control itself to constrain its own size vai SetBoundsCore.

I'm fairly sure you can do this with Control.SetBoundsCore, as described here.link text

I am not sure for the resizing square but MaximunSize and MinimumSize are the right values for you.
But it's not enough to set them in the constructor of your class because everytime you drop an instance of your control from the designer to a form these values get set after the constructor.
You should:
override MinumumSize and MaximumSize, and do net set the base value from your value but your value.
private Size maxSize = new Size(100, 5);
public override Size MaximumSize
{
get { return base.MaximumSize; }
set { base.MaximumSize = maxSize; }
}
create a public method in your class:
public bool ShouldSerializeMaximumSize()
{
return false;
}
and
private void ResetMaximumSize()
{
me.MaximumSize = maxSize;
}
These methods are a convention from the Windows Forms Desinger: http://msdn.microsoft.com/en-us/library/53b8022e.aspx

Related

TabControl ItemSize with TabPage ImageKey

I have a TabControl where I want to keep the tabs to a fixed size and I want icons in the tabs. I have set TabControl.SizeMode = Fixed and TabControl.ItemSize = 100, 18. I have also set TabControl.ImageList and am assigning images to the tabs via TabPage.ImageKey.
Here is what it looks like if I comment-out assigning the ImageKey:
And here is what it looks like if I am assigning the ImageKey:
Is there some sort of "alignment" for the icons? I want them to be on the far left in the blank space, but instead they are starting where the text starts. Any suggestions?
(BTW - if I set TabControl.SizeMode = Normal, I get the tab content the way I want it, but the tabs aren't a fixed size):
I can verify the issue that you are seeing with TabControl.SizeMode = Fixed (on Windows 10). I initially seen it in the designer when configuring a TabPage with an icon. However the irritating thing is that the issue corrected itself if the designer is closed and reopened. This suggests a window style setting of some sort and there are some Tab Control Styles set in the CreateParams Property based on the SizeMode Property. However, I found no solution in attempting to apply the TCS_FORCEICONLEFT style. If the ImageIndex property is set prior to the control being shown, then the alignment is as desired. So I figured that there must be something being configured on handle creation.
If you call the form's RecreateHandle method after setting the TabPage.ImageIndex property, the form redraws and all looks good. However this cause the form to blink. Calling the Control.RecreateHandle method on the TabControl also works. This is a protected method and would necessitate using a derived TabControl to expose the method or you could use Reflection to invoke the method.
public class MyTC : TabControl
{
public void FixIcon()
{
RecreateHandle();
}
}

How to refresh a winform custom control at design time after changing a property

Let's say I create a custom control which embed a trackbar. I also create an orientation property for my custom control.
When I drop the custom control on a form by default it will be horizontal. Then I set it to vertical, the trackbar should refresh to be vertical at design time.
How to do so ?
I think you should call Refresh() after changing the value:
public OrientationProperty Direction
{
get
{
return _direction;
}
set
{
_direction = value;
if (DesignMode)
{
Parent.Refresh(); // Refreshes the client area of the parent control
}
}
}
private OrientationProperty _direction;
Here's my solution to this issue:
1. Whenever you set something property, call Invalidate() in the setter.
2. After correspondent properties and refreshing method (for eg. overridden OnPaint) are implemented, rebuild!!! then you'll see the modifications taken effect in design time
3. During design, always check whether compilation errors are present, as this might stop VS performing all his tasks.
With this, when I put my control on a form, and adjust its own properties, refreshing happens immediately as expected.
PS.: old post, but at least verified the behavior in VS2015 too :)

How can I write a BringToFront method for a WPF UserControl?

I am developing a UserControl, call it CoolControl, that is meant to act somewhat like a window, with a few special features. So far, it can be resized and dragged all around the screen. If I add multiple CoolControl objects to my application window using XAML, the last one that was declared is always in front. This is fine, but I want to make it so that if I click on one of my CoolControl objects during run-time, that control will put itself in front of all the other controls.
I've tried using Canvas.SetZIndex, but unless I'm simply unable to come up with a clever enough solution, I don't see how that can help me. Because once I set one control's Z-Index to 9999, over time every other control I click will have the same value of 9999. And then, once again, the control declared last ends up in front.
If you were given the task of writing a BringToFront() method for someone's UserControl, how would you do it in the simplest way possible? I'd prefer a better solution than getting the parent window, looping through all the controls, finding the maximum Z-Index, and then setting the Z-Index of the CoolControl accordingly, if THAT is even a valid solution.
I'm not familiar with the Canvas.SetZIndex method. It looks like some sort of attached property or behaviour.
If you can provide the logic to set the z-index, I've outlined a way to keep track of the instances and manage the z-indexes, keeping them in the order in which they have been selected/created.
public class CoolControl : UserControl
{
public CoolControl()
{
InitializeComponent();
Instances.Add(this);
}
static IList<CoolControl> Instances = new List<CoolControl>();
void SelectThisInstance()
{
foreach(var instance in Instances)
{
// decrement z-index instance
}
// set z-index of this instance to show at top
}
}

Setting custom control properties

I though it would be very simple but I can not get it today.
I have a user control, with a grid control contained in it.
public Unit Width
{
get
{
return CustomerGrid.Width;
}
set
{
CustomerGrid.Width = value;
}
}
I expose the width property and when I set it in the designer it works at run-time but not design time.
What class do I inherit from or method to override to get my controls to function at design time.
Note I tried to inherit from WebControl but got the message
Make sure that the class defined in this code file matches the 'inherits' attribute, and that it extends the correct base class
I understand you're talking about user controls (ascx) and not about custom controls (no ascx). If this is the case, you should inherits from UserControl and you would have the property available on design time without any other addition.
In case you're talink about custom controls, here you have a good article about adding design time support to custom controls
http://msdn.microsoft.com/en-us/library/aa478960.aspx

Make user control display outside of form boundry

I've decided to reimplement the datetime picker, as a standard datetime picker isn't nullable. The user wants to start with a blank field and type (not select) the date.
I've created a user control to do just that, but if the user control is near the edge of the form, it will be cut off on the form boundry. The standard datetime picker doesn't suffer from this problem.
Here is a picture showing the problem. My user control is on the left, the standard datetimepicker is on the right:
alt text http://img50.imageshack.us/img50/9104/datetimepickervu6.jpg
As you can see, the standard control will display over the form AND application boundry. How do I get the month picker in my control to do the same thing?
Thanks!
The ToolStripDropDown control has this functionallity so by inheriting from it we can make a simple PopupWindow.
/// <summary>
/// A simple popup window that can host any System.Windows.Forms.Control
/// </summary>
public class PopupWindow : System.Windows.Forms.ToolStripDropDown
{
private System.Windows.Forms.Control _content;
private System.Windows.Forms.ToolStripControlHost _host;
public PopupWindow(System.Windows.Forms.Control content)
{
//Basic setup...
this.AutoSize = false;
this.DoubleBuffered = true;
this.ResizeRedraw = true;
this._content = content;
this._host = new System.Windows.Forms.ToolStripControlHost(content);
//Positioning and Sizing
this.MinimumSize = content.MinimumSize;
this.MaximumSize = content.Size;
this.Size = content.Size;
content.Location = Point.Empty;
//Add the host to the list
this.Items.Add(this._host);
}
}
Usage:
PopupWindow popup = new PopupWindow(MyControlToHost);
popup.Show(new Point(100,100));
...
popup.Close();
The screenshots looks like a Windows Forms applications, so my answer is for winforms.
I guess the best solution would be to create a customcontrol that itself uses the datetime picker that already has the behavior.
Show a empty textbox until it gets clicked, then display the datetimepicker.
That would save you a bunch of code..
I ran into this when trying to implement a custom control and discovered that it's a remarkably hard problem. There's no built-in functionality within the Windows.Forms model to support controls whose display area extends outside the client area of their container.
You basically have to either use the Windows API or draw your controls inside a Form with AlwaysOnTop set. Both approaches are harder than they should be. I ended up redesigning my control so that instead of displaying its expanded contents in a dropdown it used a modal dialog. This was a pretty unsatisfying solution, but I spent a couple of weeks trying other approaches and could never get anything that worked consistently across all use cases (like disappearing when the application loses focus).
I'm not 100% sure, but a quick look at the DateTimePicker class on Reflector takes me to the SafeNativeMethods.SetWindowPos internal class.
You can override the SetBoundsCore from the base Control class or, like Tigraine stated, create a custom control based on the DateTimePicker.
Hope it helps,
Bruno Figueiredo
The reason that your control gets chopped off is because it is a child control of the form that you reside on. Any control on the form must be contained by the form, hence it gets chopped off.
I haven't done this in .Net, but had a similar problem in VB6. The solution then was to set the parent of the popup window (the calendar in your case) to be the desktop. This will allow it to extend beyond the boundaries of your form. You'll have to do some P/Invoke magic to find the hWnd of the popup, and another P/Invoke to set the parent.

Categories