ToolStrip with custom ToolStripControlHost makes tab order focus act weird - c#

I'm experiencing some strange behavior. Let me try to explain, I stripped my code down to the bare minimum and I'm still having the problem. So first of all, I'm using VS2013 with .NET 4.0 and I'm on Windows 8.1.
So I have a custom UserControl with a TextBox that's being used through a ToolStripControlHost, if I focus on this textbox and hit TAB, it only cycles through the controls to the LEFT of this textbox. If I have it focused and hit SHIFT+TAB, it cycles through the buttons to the right of it.
So this is an example of my form. The textbox in the middle is a custom control. My code (as simplified as possible) looks like:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
public class ToolStripTestControl : ToolStripControlHost
{
public ToolStripTestControl() : this(new TestControl()) { }
public ToolStripTestControl(Control c) : base(c) { }
}
public class TestControl : UserControl
{
private TextBox _textBox = new TextBox();
public TestControl()
{
_textBox.Dock = DockStyle.Fill;
this.Controls.Add(_textBox);
}
protected override Size DefaultMinimumSize { get { return new Size(100, 22); } }
}
Simply creating a new WinForms (.NET4) project and following these steps will allow you to replicate the problem:
Add new class file and paste the code above.
Build
Add a ToolStrip to your form
On the ToolStrip add a Button, my custom control, and another Button (through the designer is how I've been doing it)
Run
Once running...
Focus in the custom control
Hit TAB a few times, it should only focus on controls to the left.
Hit SHIFT+TAB a few times and it will only focus to the right.
Does anyone know what the problem is - or how I can fix this? I've been tearing my hair out all day trying to fix this. I finally stripped my code down and I can't seem to get it to work. I even tried overriding much of the OnEnter/OnGotFocus functionality and doing it myself, but that became a nightmare.
Thanks!
Update1: So a few extra tid-bits.
If I change the custom control to inherit from TextBox instead of UserControl, tabbing/focus works as expected.
If I change it to be a Control instead of a UserControl the tabbing works fine, as well, however the focus never gets inside my inner TextBox - the focus seems to be lost (or presumably on the outer parent control but not being passed down to the inner TextBox).
I do see a MS Connect item added that describes this problem from 2009, but this link only seems to work if I'm NOT logged in to Microsoft Connect. Which means, I can't vote on it or comment... http://connect.microsoft.com/VisualStudio/feedback/details/472592/tab-cycling-through-controls-with-usercontrol-on-toolstrip-doesnt-perform-as-expected

The .NET 2.0 ToolStripItem classes have been a major bug factory. They are window-less controls, but reproducing the exact behavior of a Windows window isn't that easy. There is an enormous amount of code underneath, most of it internal so you can't tinker with it. And with quirks when they don't emulate the behavior of a window perfectly. You could call them "airspace" issues, pretty similar to the kind of problems that WPF has.
The airspace issue here is focus, entirely unambiguous for a true window but it needs to be faked for a ToolStripItem. It is actually the item's parent that has the focus, it needs to be emulated for the item. It is the transition that bytes, ToolStrip expects a window-based control to have a reliable Focus property.
Trouble is, your custom host doesn't. It is the inner control that has the focus. This could arguably be blamed on an omission in the ToolStripControlHost class. Probably. The trouble with emulating a window, there's never enough code :)
Anyhoo, fix your problem by adding this sliver of code to your host:
public override bool Focused {
get { return _textBox.Focused; }
}

Related

C# Excessive Repainting of WebView2 Control after Applying NativeWinAPI Styles

Having experiences various forms of flickering and graphical glitches, I searched online for possible solution. The only thing that worked straight away was accepted solution using NativeWinAPI from post just below:
Avoid Flickering in Windows Forms?
Inserting this code in the main form of the application and keeping handle for 'this' practically eliminated every issue I had with graphics.
At least until I included a web browser (WebView2 Control). This control along side with the code from the post causes the control itself to constantly repaint itself. This in turn causes graphical issues within entire User Control that is parent to the WebView2. Other controls flicker in and out, which is super annoying and unpleasant.
Having spent hours(days really) trying to figure out what is wrong and practically rewriting entire project, the issue was located and it disappears straight after disabling function that sets the window style.
I am fairly certain that WebView2 Control is the only control having issues as I created OnPaint functions that write to console every time that the control was repainted, and disabling webview2 stops other controls from being repainted, while when enabled I get 100's of repaints within few seconds.
The problem is that disabling those changes makes the application look even worse with all the flickering and graphical glitches that it was fixing before.
I do not understand what the code from the link exactly does (too advanced/complex for my current knowledge). If anyone could help me figure out how to solve the issue I would really appreciate it.
Update:
I created a small demo project for anyone interested in addressing this.
It is a 7zip of the project placed on google drive:
FlickeringDemo.7z
Microsoft Edge Canary Browser is required for WebView2 to work correctly:
Download Edge Canary Here
Main form has bool flag that control graphical improvements and flickering. Simply set it to true/false to observe the difference.
Debug.WriteLine(); - will output Paint Event counter into console in Visual Studio.
bool FlickerEnabled = false;
public MainForm()
{
InitializeComponent();
if (FlickerEnabled)
{
InitialiseGraphicalFixes();
}
}
I was having the same problem in my project and I've managed to solve it.
In the provided FickeringDemo.zip sample, to stop flickering with that version of WebView2 (1.0.664.37) you should set to true the DoubleBuffered property in all of your .Net Controls; see code below for an example on how to do it.
Another thing that I've found is that this fix stops to working in WebView2 1.0.774.44; in that version the rest of your controls will not flick, but the WebView2 will flick a lot. I didn't find a way to solve it...
public partial class WebViewControl : UserControl
{
...
public WebViewControl()
{
...
//the fix to solve flicker if the WS_EX_COMPOSiTED is set on the top window
SetDoubleBuffered(this, true);
}
private void SetDoubleBuffered(Control control, bool value)
{
try
{
control.GetType().GetProperty("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(control, value, null);
}
catch
{
}
foreach (Control child in control.Controls)
{
SetDoubleBuffered(child, value);
}
}

C#, BindingNavigator, Ugly line at the right end

How do I get rid of this ugly line?
Draw a default bindingnavigator on an empty Form and you will see the problem. RenderMode is ManagerRenderMode. I want this render mode so the mouse over colors is correct. However, If I switch to System as rendermode the ugly line disapears, but then mouse over color/effect gets ugly.
I have been looking around for a solution for some time now, but nothing. Maybe someone here have seen this problem before?
It's not a BindingNavigator specific issue, but the ToolStrip which BindingNavigator inherits.
It's caused by the DrawToolStripBorder method when the ToolStripProfessionalRenderer class RoundedEdges property is true (the default).
In order to turn it off, I can suggest the following helper method:
public static class WindowsFormsExtensions
{
public static void DisableRoundedEdges(this ToolStripRenderer renderer)
{
var professionalRenderer = renderer as ToolStripProfessionalRenderer;
if (professionalRenderer != null)
professionalRenderer.RoundedEdges = false;
}
}
Now you can turn it off for the specific control (it's not available at design time, so it has to be at run time inside your form/control constructor or load event):
this.bindingNavigator1.Renderer.DisableRoundedEdges();
or to disable it globally, add the following in your Main method before calling Application.Run:
ToolStripManager.Renderer.DisableRoundedEdges();

How to set the blinking cursor to WPF Editable ComboBox?

In my WPF program I have a standard ComboBox (Editable). My desired behavior is that upon FormLoad, I would like the user to be able to type into the ComboBox and select from the list. (At FormLoad I've already populated it with some strings.) So I set comboBox.Focus(), and since I have IsTextSearchEnabled="True", which is the default behavior, this works fine.
My problem is, when comboBox.Focus() is set, it does indeed focuses the control, but I do not get the blinking cursor inside it. This is what it looks like:
This in theory gets the job done, but I believe it's not very user-friendly. I would like the ComboBox to be focused, and also have the blinking cursor.
I get the blinking cursor when I click on the editable ComboBox, so I looked up what event gets fired when I do that. Turns out it's PreviewMouseLeftButtonDown, so I tried programmatically firing this event (although this is something I usually try to avoid) to see if that will be an option. This is my code:
comboBox.RaiseEvent
(
new MouseButtonEventArgs
(
Mouse.PrimaryDevice,
Environment.TickCount,
MouseButton.Left
)
{
RoutedEvent = PreviewMouseLeftButtonDownEvent
}
);
I used a Console.WriteLine() to print a simple message to verify in Output Window if the event gets fired, and indeed it does. However, I still do NOT get the blinking cursor in my ComboBox.
Then I looked through SO, and found this question and the OP's edited fix seems to work. However this seems like quite a bit round-about way to get a seemingly simple task done, so I'm wondering if there's a rather straightforward or simpler way that I can achieve the desired result.
Calling the Focus() method once the window has loaded seems to work just fine for me:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
this.Loaded += (s,e) => comboBox.Focus();
}
}
If it doesn't work for you, then please provide a reproducible sample of your issue: https://stackoverflow.com/help/mcve

Is there a way to stop the WinForms designer defaulting to control Load event

This drives me nuts. In the Visual Studio WinForms designer, if you double-click a control it will produce a XXXX_Load handler for that control. This is never, ever, what you want. You want Click event or a Changed event or more likely to go to the existing Click event. You do NOT was a new Load event. It is worse because a double click can happen by accident. You click once, then again - bingo a Load event handler. I use a pen-tablet combo and double clicks are very easy!
Can someone tell me if there is a way to stop this happening. I would like a Click handler. I would settle for nothing happening.
One way to achieve that is inheriting the control and modifying the DefaultEventAttribute.
Specifies the default event for a component.
[DefaultEvent("Click")]
public class MyRadionButton : RadionButton {
}
But some care/extra work may need to be done when you override a control. You need to keep that in mind when using this approach.
In addition to Mehrzad's answer, you can completely disable it by passing an empty string to the DefaultEvent attribute:
[DefaultEvent("")]
public class MyCustomControl : UserControl
{
}
This works because the default control designer uses the ComponentDesigner.DoDefaultAction when the control is double clicked. By default, this uses reflection to look up the method signature of the default event. If it can't find it, it doesn't do anything.

How to remove the focus border of a CheckBox in C# Visual Studio?

Tried most properties and did not manage to completely disable the focus of a checkbox in visual studio. Does anyone know how to do it?
I am using a System.Windows.Forms.CheckBox object. I am using an image as background and when the CheckBox is in focused state a border is drawn, which makes the background image look pretty bad. So I want to get rid of it...
EDIT: Adding a picture to clarify the intention of this question...
The user can tap "TAB" and click on the object to see it displayed as focused.
That was a problem for me since it made the GUI look simply terrible.
The code for the CheckBox control that takes care of the painting is very elaborate, shared with Button and RadioButtion, supporting many styles. It cannot be overridden, the involved classes and methods are all internal.
But luckily you only want to mess with the focus rectangle. All you have to do is convince the control that it should not show it. That's very easy, add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox.
using System.Windows.Forms;
class MyCheckBox : CheckBox {
protected override bool ShowFocusCues {
get { return false; }
}
}

Categories

Resources