C# WndProc event handler - c#

I added a form control to my form in a designer. But I need to override that control's WndProc. Can I do that without creating a new control extending the old one? Because when I extend the old one like this my designer won't work anymore:
partial class ThatControlWithWndProc : TheControlIActuallyWant {}
Or how can I get my designer to work with this new control that I created and not throw me an error?

If you just edit the .Designer.cs file directly to refer to your overridden control, and ensure that it follows the rules for controls to be designer-compatible (like having a default constructor, and not relying on any other initialisation) you should be fine.

Related

Visual Studio Form Designer Showing List of Controls

I know that getting the Form Designer to work is a ticklish business. Generics, x64, subtle problems with the project's XML... But perhaps someone can offer advice about my current problem, which is that a component I created that inherits from TabPage, when I try to view it in the designer shows up as a list of its controls, like this:
Thanks in advance.
You cannot make a TabPage as root of the designer, while you can do the same for a Panel or other container controls. The limitation is because, TabPage can only be hosted in TabControl, not even in the overlay control of the designer:
TabPage cannot be added to a
'System.Windows.Forms.Design.DesignerFrame+OverlayControl'. TabPages
can only be added to TabControls.
A control can be shown as root of the designer when the base class of the control has designer of type of DocumentDesigner. Form and UserControl are such controls which means when you create a new Form1:Form or new UserControl1:UserControl, since the base class derived from a designable control, then the class can be edited in the designer as root.
I believe you can handle your requirement by using UserControl, but for learning purpose (or as a workaround) if you want to make a control deriving from Panel designable, you can copy the following code in a code file:
public class MyControl: MyDesignableControl
{
}
[Designer(typeof(DocumentDesigner), typeof(IRootDesigner))]
public class MyDesignableControl : Panel
{
}
Then save it and then double click on it and you can see you can design it like a root control.
Then after you done with the design, change the Panel to TabPage.
Remarks on
DocumentDesigner
This designer is a root designer, meaning that it provides the
root-level design mode view for the associated document when it is
viewed in design mode.
You can associate a designer with a type using a
DesignerAttribute.
For an overview of customizing design time behavior, see Extending
Design-Time
Support.

Winforms Designer: How to disable my usercontrol from being a container?

I have a relatively simple setup. I have a custom usercontrol that has a bunch of components on it, some text boxes, and a listview.
In the designer, I can drag and drop other controls into my usercontrol, and it adds them to the usercontrol instance. I don't want this.
How can I explicitly say "Don't allow additional controls to be added to this usercontrol?"
That's not the way it works. When you drop your user control on a form then adding controls to it isn't supported. That requires a special designer, this answer shows what is required. Maybe it looks like the controls get added but they merely overlap your user control. Their parent is still the form.
If a programmer opens your user control class itself in the designer then, sure, he can add controls as he pleases. The only way to stop that is to not ship the source code and use the sealed keyword to prevent deriving from it.
You could create a boolean property MyContainer.DisableAddControls or something.
If your MyContainer.Controls.Add(..) is overridden, then you can throw some custom exception in that Add() method as follows:
if(DisableAddControls)
{
throw new DisableAddControlsException();
}
If you are inheriting that method straight from ContainerControl, then you can handle the ControlAdded event and throw the exception there.
myContainer.ControlAdded += myContainerControlAdded;
private void Control_Added(object sender, System.Windows.Forms.ControlEventArgs e)
{
if(DisableAddControls)
{
throw new DisableAddControlsException();
}
}
On second thought, this won't throw out your designer at design time... nevermind.

How to set the defaul event for a user control?

I created a user control with an event. I do not want to add the following code every time I add a new instance of the control to a form.
Control1.Operate += new MyControl.OperateEventHandler(Control1_Operate)
Instead I would like to simply double-click the control and have the above code added by the IDE to the Designer file. By default the Control1_Load event is assigned in the Designer file. Is it possible to change this?
For C# use:
[DefaultEvent("Click")]
public class MyClass : BaseClass
{
//code
}
MS Code:
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaulteventattribute.aspx
It seems you want to set a DefaultEvent for your control.
Use DefaultEventAttribute on your Control class.
A similar question exists:
How can I set the default event to be edited for my custom control in Visual Studio?
Hope it helps!
The behavior you are looking for is more like what you have for buttons. You double click on it and you have the event handler method generated for you. But in here, the event handler code is generated on the fly. In your cae, you want to attach, a pre-defined method with the event of the User Control. Try defining some custom properties or event for your usercontrol and then set the default value. For e.g. : http://msdn.microsoft.com/en-us/library/yhzc935f.aspx .

ParentForm is null (in a Button inside a UserControl inside a Form)!

I got this code working!
I have a button inside a my UserControl dropped at design time in a my Form. All worked well and when in a button's event I called this.ParentForm it correctly returned to me the (only) parent Form.
After a refactoring, I moved the UserControl with the button to another NameSpace and the same piece of code no longer works. this.ParentForm now is NULL!
I read the MSDN site and it says that only when the control is hosted in IE or another context this.ParentForm returns null. But I moved only the namespace!
Anyone has an idea?
I cannot use a different constructor to pass it the parent form because at design time Visual Studio wouldn't render the Form.
See if you're accessing the control's parent form before the control has been added to the form.
Your code my be triggering upon the user control class initialization, but the control hasn't been added to the Parent form.
Try putting this code in the Control Load event.
Look at the code-behind file that contains the designer-generated code. During the renaming, you may have confused the Visual Studio designer and it may have "orphaned" an instance of your control in the Form.designer.cs file.
In particular, look at the code in the InitializeComponent method and see if you can spot any code that creates an instance of your UserControl but does not add it to a container, or adds it to a container that is not added to the form.

IExtenderProvider and WinForms designer file

C# 3.5 Winforms...
So I’ve recently discovered the IExtenderProvider and how it can be used to extend controls with additional properties.
In a prototype project that I setup i put a break point on the ‘set’ method for my extendee property and as the form loads I could see the ‘set’ method executing for every control on the form; which is exactly what I wanted. Following the successful prototype I implemented the extender component into my main project. All the forms in my project inherit from a base form which I’ve added my extender component to. On the base form I set the modifier of the extender component to public so that its accessible by the form inheriting this base form.
Doing the same thing before i added a break point on the ‘set’ method for my extendee property but the method doesn’t execute for the controls in the form (but only for the controls in the base form). HELP!
I should probably add at this point that i’ve source controlled my forms and so most of them are checked-in (ie lock from modification). For the forms that I’ve checked out and modified the provider property; I’ve noticed in the designer file that all controls have an additional statement which calls the ‘set’ method of the provider property.
this.MyProvider1.SetMyProperty(this.txtTextBox1, false);
Am I right in thinking that for the extender component to work it has to physically modify the designer file or should it be able to cope with locked files and therefore call the set method dynamically? I guess if it does have to modify the designer file then this isn’t a problem for new forms or forms that get modified after the extender component was added to the project – but it would be problem when you have 101 forms all locked by source-safe...
I’d appreciate any thoughts...
At what point does the extender provider (IExtenderProvider) extend the 'type' (in my case a winforms control) that the extender was intended for; at design time or at run time?
The designer is responsible for showing you the properties of the extender in the property editor
Method bool CanExtend(object) from the IExtenderProvider interface
Am I right in thinking that for the extender component to work it has to physically modify the designer file or should it be able to cope with locked files and therefore call the set method dynamically?
It has to physically modify the designer file, and write the extended properties there
I guess if it does have to modify the designer file then this isn’t a problem for new forms or forms that get modified after the extender component was added to the project – but it would be problem when you have 101 forms all locked by source-safe...
This is is not a problem for new forms, and not for old forms.
If you want to set some extended properties, open the old form and set the extended properties (a check out of the file is necessary)
This really does confirm my suspicions, many thanks. But this does leave a problem in that the components are only extended if some physical change is made to the old form.
I was trying to hijack the Set property method to also add and remove an event handler to the component (if the component was a control). Image the property is a Boolean and when set to false it adds the event handle and therefore the default behaviour (setting to true doesn’t add and event handler)
To cut a long story short the controls which were part of newly added forms automatically have an event handler added even without me explicitly setting the property to false but the designer file of the old forms never modifier so the event handler wasn’t added.
As some background, I was trying to add a global event handler for all controls
Global event handler for all controls for User Help
The theme here is to add context help to my forms here’s example of the extender ( the event handler is added as part of the end initialiser)
public partial class HelpProvider : Component, IExtenderProvider, ISupportInitialize
... other code of the extender omitted ...
#region ISupportInitialize Members
public void BeginInit()
{
// do nothing
}
public void EndInit()
{
if (DesignMode)
return;
foreach (Component item in _disableOnlineHelp)
{
if (item == null)
continue;
if (GetDisableOnlineHelp(item)) // developer has decide to set property to TRUE
continue;
Control control = item as Control;
if (control != null)
continue;
control.HelpRequested += new HelpEventHandler(HelpProvider_HelpRequested);
_toolTip.SetToolTip(control, GetHelpText(control));
}
}
#endregion
#region DisableOnlineHelp Provider Property
public virtual bool GetDisableOnlineHelp(Component component)
{
object flag = _disableOnlineHelp[component];
if (flag == null)
return false;
return (bool)flag;
}
public virtual void SetDisableOnlineHelp(Component component, bool value)
{
_disableOnlineHelp[component] = value;
}
#endregion
One issue might be the foreach loop in the EndInit method:
Control control = item as Control;
if (control != null)
continue;
If the item is, in fact, a Control, you get out of the loop before executing this code:
control.HelpRequested += new HelpEventHandle(HelpProvider_HelpRequested);
_toolTip.SetToolTip(control, GetHelpText(control));
so you never add the Event Handler or the ToolTip, to any Control. Oops :)
Thanks,
John

Categories