Custom Control Design Mode Problem

G

Guest

I have developed a custom control to be used in my application. My
application includes a form designer, so the control can be hosted while
designmode for the control is either true or false, depending on whether they
are using the form designer, or in "run mode". The custom control includes a
slider control that is supposed to be active in our form designer
(designmode=true) and inactive in our run mode (designmode=false). The
problem is that I'm getting the reverse.

I've put this code into an Intialize method that fires when the custom
control is instantiated.

Private Sub Initialize()
If Me.DesignMode = True Then
Splitter1.Enabled = True
Else
Splitter1.Enabled = False
End If
End Sub

This works in order to disable the splitter if the controls
designmode=False, but does not enable the splitter if the reverse is true.

I am working in VB.Net 2003.
 
J

Jeffrey Tan[MSFT]

Hi,

Thanks for your post.

Based on my understanding, your application implemented the IDesignHost and
other interfaces to introduce design-time support for hosting custom
controls.

Currently, I am not sure I understand your problem very well. It seems that
your program logic below is correct:

Private Sub Initialize()
If Me.DesignMode = True Then
Splitter1.Enabled = True
Else
Splitter1.Enabled = False
End If
End Sub

Do you mean that Me.DesignMode sometimes reports the wrong state? More
specificly, sometimes Me.DesignMode reports false in design-time, yes?

If we use Reflector to view Component.DesignMode, we will see:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Browsable(false)]
protected bool DesignMode
{
get
{
ISite site1 = this.site;
if (site1 != null)
{
return site1.DesignMode;
}
return false;
}
}

So, Component.DesignMode just query the internal ISite and return its
DesignMode property. However, if site is not created, it will just report
false. For more information, please refer to the link below:
"Bug Details: DesignMode variable does not appear to work as expected"
http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackid=d
6ad5162-9693-49cc-abc0-659111823582

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
M

Matt Fielder

Jeffrey,

Thank you for your reply. I'm sorry for the ambiguity of the first post,
but all of your assumptions were exactly correct. I did some checking, and
as you suspected, my control was not yet sited. I moved the code to the
method below, which is by both the resize and paint events of the control
(I'll figure which is best after it's working). I've monitored the output
windows during runtime, so I know the splitter is enabled, however I just
can't get it to activate when designmode=true. Is it possible that the
control while in design mode is not allowing focus to pass through, and if
so, do you have any suggestions for how to handle the problem?
Private Sub RedrawControls()
Dim ControlHeight As Integer = txtField.Height

If Me.ClientRectangle.Height <> txtField.Height Then
Me.SetClientSizeCore(Me.ClientRectangle.Width, txtField.Height)
Exit Sub
End If

If lblPrompt.Visible = True Then
txtField.SetBounds(lblPrompt.Width, 0, Me.ClientRectangle.Width -
lblPrompt.Width, lblPrompt.Height)
Else
txtField.SetBounds(0, 0, Me.ClientRectangle.Width,
lblPrompt.Height)
End If

If Me.DesignMode = True Then
Splitter1.Enabled = True
Debug.WriteLine(Splitter1.Enabled)
Else
Splitter1.Enabled = False
End If

End Sub
 
J

Jeffrey Tan[MSFT]

Hi Matt,

Thanks for your feedback.
I've monitored the output windows during runtime, so I know the splitter
is enabled,
Do you mean that you see the below Debug.WriteLine line outputs "true"
value?

If Me.DesignMode = True Then
Splitter1.Enabled = True
Debug.WriteLine(Splitter1.Enabled)
Else
Splitter1.Enabled = False
End If
however I just can't get it to activate when designmode=true
I assume you mean that, although the Debug.WriteLine outputs
Splitter1.Enabled to be true, it still can not get any focus. This is your
concern, yes?

In the above statement, does the "designmode=true" mean DesignMode in
VS.net designer, or mean the DesignMode in your application design-time
support implementation? I suspect the latter.

Currently, because I did not have your runtime designer implementation
code, I can not understand what going wrong and can not give very useful
suggestion. But in design-time, the control's behavior is hooked by the
ControlDesigner associated with it. More specificly, Winform applied
System.Windows.Forms.Design.SplitterDesigner to Splitter control. I think
you can use Reflector to view the source code of
System.Windows.Forms.Design.SplitterDesigner to get more information of its
design-time behavior.

Normally, Splitter control shows focus through a design-time border
rectangle, which is drawn by SplitterDesigner.DrawBorder method.
SplitterDesigner.DrawBorder is called in SplitterDesigner.OnPaintAdornments
like this:
protected override void OnPaintAdornments(PaintEventArgs pe)
{
Splitter splitter1 = (Splitter) base.Component;
base.OnPaintAdornments(pe);
if (splitter1.BorderStyle == BorderStyle.None)
{
this.DrawBorder(pe.Graphics);
}
}

Its parent class method is: ControlDesigner.OnPaintAdornments, which is
finally called in ControlDesigner.WndProc with message: 15, that is
WM_PAINT for the control.

So you can follow this call stack to analysis why the focus border does not
appear in your application at "DesignMode".

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Matt,

Does my reply make sense to you? Is your problem resolved? Please feel free
to tell me, thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
M

Matt F.

Jeffrey,

I am still unable to resolve the issue.

In answer to your question of::

In the above statement, does the "designmode=true" mean DesignMode in
VS.net designer, or mean the DesignMode in your application design-time
support implementation? I suspect the latter.

you are correct in assuming that the problem is while in design time support
within my application.

Then I get a bit lost in your suggestions. You suggest following a call
stack, by overridign OnPaintAdornments if I understand correclty, however
the application is in VB.Net and your suggested test code appears in C#.
 
J

Jeffrey Tan[MSFT]

Hi Matt,

Thanks for your feedback.

No, I did not mean to override the OnPaintAdornments method. Actually at
design-time, Splitter control's border is drawn by SplitterDesigner class
which attaches to Splitter control. Internally, SplitterDesigner draws
Splitter control border in SplitterDesigner.OnPaintAdornments method, I
then provide the source code for SplitterDesigner.OnPaintAdornments in C#(I
get this code from Reflector, you can also choose to view the code in
VB.net in Reflector).

Currently, I am not sure the root cause of your problem, so I suggest show
you the design-time Splitter control drawing call stack:
ControlDesigner.WndProc (WM_PAINT
)->ControlDesigner.OnPaintAdornments->SplitterDesigner.OnPaintAdornments
->SplitterDesigner.DrawBorder.

In normal situation, the border should draw well, but in your situation, it
seems that it does not draw, yes? So I suggest you add breakpoint in these
methods to see which method fail to call.

Just as I say in original reply, without reproduce out the problem, it is
hard for us to give a solution to resolve it. Can you narrow down the
problem into a little sample reproduce project? Then with this sample
project, I think I can understand the problem much better. Thanks for your
understanding.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
M

Matt F.

Jeffrey,

Thank you for your patience with me in dealing with this issue. I'm afraid
at this point I must show my ignorance in a couple of areas.

First, I assume that your reference to "reflector" is some sort of add-in?
If so, do you have information on where it is obtainable from?
Secondly, I obviously can see the call stack for my application, however
there is no reference that I'm seeing to the call stack for the splitter
draw --- if you could point me in the right direction to do this, it would
be appreciated.
Thirdly, I agree that this is a problem that would best be solved by
creating a much simpler project that breaks it down to the smallest possible
number of components, etc. However as I'm sure you are aware, the act of
implementing IDesignerHost is in no way a small task, which makes breaking
this out into a smaller set of code impractical.

What I have found that may or may not shed some light on the problem is the
..CanSelect property of the splitter is returning false, even though the
control is enabled, visible and .CanFocus is true. Unfortunately .CanFocus
is a readonly property --- do you have any idea what else might be causing
this property to return false?
 
O

Oliver Sturm

Matt said:
This works in order to disable the splitter if the controls
designmode=False, but does not enable the splitter if the reverse is true.

This is an issue that's been discussed on the web to no end. A nice
explanation is here:
http://weblogs.asp.net/fmarguerie/archive/2005/03/23/395658.aspx

As to the workarounds - test carefully whether things really work for you.
I've seen several of the suggestions fail under specific circumstances,
none seems to be completely reliable in all situations.


Oliver Sturm
 
J

Jeffrey Tan[MSFT]

Hi Matt,

Thanks for your feedback.
First, I assume that your reference to "reflector" is some sort of add-in?
No, Reflector is a .Net decompiler writen by Lutz Roeder, it can be used to
view the souce code of .Net Framework. It is really a must have tool for
.Net developer :), the below is the download link:
http://www.aisto.com/roeder/dotnet/
Secondly...
What I have found that may or may not shed some light on the problem is the
.CanSelect property of the splitter is returning false, even though the
control is enabled, visible and .CanFocus is true.
Yes, this is by design. If you view Control.CanSelect property in MSDN, you
will see the following statement:
"The Windows Forms controls in the following list are not selectable and
will return a value of false for the CanSelect property. Controls derived
from these controls are also not selectable.
...
Splitter
....."

However, I do not think this has anything to do with our problem.
Splitter.CanSelect is a design-time behavior, and it is by design for not
selectable. In our scenario, the problem is that at designtime, when the
Splitter control is enabled, when it has focus, it does not draw a design
time focus rectangle, yes?
If we view Splitter control in VS.net designer, we will see that when it
has focus, a normal design focus rectangle will appear as its border. This
is actually not drawn by Splitter control, it is actually draw by the its
associated SplitterDesigner.(SplitterDesigner is not a public documented
class, we can just see it through the Reflector). So we should move our
focus in this SplitterDesigner class, not the Splitter control(because we
are at design-time, aren't we?) So I suggest you add a breakpoint in
certain method of SplitterDesigner class(Note: we have to setup the
debugging symbols correct, debuggin symbol is critical for the debugging
session, more specificly, we should set a environment variable like this:
_NT_SYMBOL_PATH=srv*C:\Symbols*http://msdn.microsoft.com/download/symbols;
For more informaiton, about how to setup symbol for debugging, please refer
to: http://www.codeproject.com/debug/windbg_part1.asp)

After setting up the symbol, we can add breakpoint for .Net method with
"New BreakPoint" dialog, for example, input the following method:
System.Windows.Forms.Design.SplitterDesigner.OnPaintAdornments

After the breakpoint is hit, we can get the SplitterDesigner invoking call
stack through "Call Stack" debugging window in VS.net.

Hope this information helps.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top