Changing the Input Language to default when form deactivates - c#

So I have a form, it uses a certain Input Language , when i switch to another window like a browser I want to change back to the computers default Input Language , seems simple. Just use the form deactivate event and put
InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;
Doesn't work. The deactivate event only triggers after the form has been deactivated but the system Input Language cannot be changed unless your form has focus.
I need an event that triggers right before a form deactivates to run that line of code. Anyone have any ideas?

Related

How to set focus back to form, after button is pressed

I am making a game, and to open up and close the store, you press S. While in the store, you have six different choices to buy from, but they are all buttons.
However, once you buy something, the focus is no longer on the form, but on the button, and the key down event is part of the form, therefore, because the focus gets switched from the form to the button, the key down event no longer works, and disables you from closing the store and continuing on with the game.
My question is how to set the focus back to a form once a button is press? I started out with visual basic, and the code would be something along the lines of form1.setfocus, but its totally different in c#.
I have tried Activating the form, .focus, a lot, and nothing seems to be setting the focus back to the form. Help would be greatly appreciated.
Form1.focus();
But I think, to get keyboard events on Form itself, you need KeyPreview set to true for the Form so that Form gets Keys first and then other controls.
Try:
form.Focus();
MSDN:
The Focus method returns true if the control successfully received input focus. The control can have the input focus while not displaying any visual cues of having the focus. This behavior is primarily observed by the nonselectable controls listed below, or any controls derived from them.
Tell me more
You can add the key down event to the buttons too.

Close Modal Form when mouse click outside form area

I would like to close a modal form when the user clicks outside (anywhere on the computer desktop) the modal form. How can we do this as a modal form is not meant to lose focus.
You need to hook mouse (and keyboard if required) and capture their events. Then check if the click happened outside the form (and area). If yes, flag a sign which can be read by the model form that it can close down.
Algo:
Hook mouse click event.
When callback function is called, check for the click position - if it's inside your form or not (you might need to translate the locations to Desktop locations - I hope you know how to!)
If the point is outside the form, set a flag (boolean or anything that makes you happy). Make sure the form can read the flag somehow.
Trigger an event for form to capture. In it's handler read the flag status. If true, close/unload the form.
This page will tell you technical details and functions.
I don't think you need to make it modal... then you can take siride's option of closing it on the Deactivate event.
The reason you don't need to make it modal: The first time you display it, it will have the focus and be topmost. Modal prevents you from clicking somewhere else, but you want to be able to click somewhere else... and when you do, the form goes away, so there are no modal needs.

Interacting with a form without it activating

I'm trying to implement code-completion popup window in my project. The window is derived from Form. It contains two controls: custom list derived from UserControl (it shows completion possibilities with icons) and a VScrollBar.
When the popup appears, it doesn't steal focus from the editor (form's ShowWithoutActivation is overriden to return true) and the editor sends certain keystrokes to the popup so the user can interact with it using keyboard. So far it works like a charm.
The problem is, I want to allow the user to use mouse as well. But, when the user clicks into the popup window, its form activates and steals focus from the editor. I can react to this by giving the focus back to the editor, I have even set up a Timer to do this regularly, but apart from being a poor solution, the title bar of the editor always flickers when this happens (when the popup is clicked).
Is there any way to interact with the popup form (using mouse) that doesn't make the form activate?
The ShowWithoutActivation's documentation reads: "If your non-activated window needs to use UI controls, you should consider using the ToolStrip controls, such as ToolStripDropDown. These controls are windowless, and will not cause a window to activate when they are selected." This seems exactly like the thing I need, but I want to use a custom control and a scroll bar.
The same problem would be with a tooltip that shows these two arrows to switch method overloads (known from VS) - the whole form would use no controls at all (only render the text and the arrows), but when clicked, it should not activate. The problem could be summarized up to "How to create a form that would never activate, but allow the user to interact with certail controls inside?".
Thanks.
Just override the onFocus event...
public partial class myListBox:ListBox
{
protected override void OnGotFocus(EventArgs e)
{
}
}
The issue is that you're using a Form for this rather than building some custom control that doesn't run in its' own UI thread like a Form does.
The flashing and highlighting is handled by windows whenever a Form activates/focuses. The only thing I cay think of is to make your Form borderless and create/draw/handle your own title bar that doesn't flash when focused.
OK, I may have found a solution. The key seems to be WM_MOUSEACTIVATE message, which the popup form must intercept and respond with MA_NOACTIVATE. But there's a catch - the control derived from UserControl still grabs focus when clicked (the scrollbar luckily doesn't anymore). The problem seems to be in the UserControl.OnMouseDown method, which internally puts focus on the control. There are some ways to fix this:
derive the control from Control instead of UserControl
override the OnMouseDown method and not call base.OnMouseDown there
make the control's CanFocus property return false, but this seems not possible, because that means to make the control either not visible or not enabled, which is both undesirable
The last case when the popup form steals focus seems to be when its resizing (using mouse) ends. But it is safe here to call Owner.Activate() as a result to Activated event...

How to do two things with one click in Windows Form

On my main form, there is another (floatable) window. This floatable window works sort of like a popupwindow in that it will close when the user clicks somewhere else outside of this window. This is handled by the Deactivate event. But what I want to do is, if the user clicks on a different control (say a button), I want to both close this float window and then activate that button with just one click. Currently, the user has to click twice (one to deactivate the window and once more to activate the desired button). Is there a way to do this with just one click?
foreach(Control c in parentForm.Controls)
{
c.Click += delegate(object sender, EventArgs e)
{
if(floatyWindow != null && floatyWindow.IsFloating)
{
floatyWindow.Close();
}
};
}
And then add your handlers as normal. This additional handler can close the floaty window.
Make sure you floaty window isn't a dialog too as this will not allow your parent form's controls to be clicked.
I had a slightly hacky solution. In your Deactivate event, fire another custom event to your main form. Then when you main form is handling the custom event, enumerate through your control(this.Controls) and locate the control under the mouse by checking all their bound then call Focus(). You might need to sort by the one with the smallest surface area, or you can have a separate list of "focus-able" control like button just for this purpose.
Another way might be to switch focus to your main form immediately after OnMouseLeave of the floatable window, or OnMouseHover of your main window, but keep the floatable windows on top, just no focus. Handle the global mouse down of your main form, and close the floatable window by then.
These are just theories, not tested.
I had an issue like this once too, when a customer wanted "floaty" windows all over there application. I used used an approach similar to the one described in this article:
http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/article.asp
Code sample available here:
http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/Popup_Form_Demonstration.asp
By extending this a bit we created "floaty" windows similar to the ones VS uses when you get a runtime error while debugging code.
At the very least reading the code may give you some insight, however, quarrelsome's response may be the more simple solution.

Control.Enter event doesn't fire when switching tasks. Is there an alternative that does?

Rep steps:
create example .NET form application
put a TextBox on the form
wire a function up to the TextBox's Enter event
When you run this application, the Control.Enter event fires when focus first goes to the TextBox. However, if you click away into another application and then click back into the test application, the event will not fire again.
So moving between applications does not trigger Enter/Leave.
Is there another alternative Control-level event that I can use, which will fire in this scenario?
Ordinarily, I would use Form.Activated. Unfortunately, that is troublesome here because my component is hosted by a docking system that can undock my component into a new Form without notifying me.
What are you trying to do in the Enter event?
I can't find another control-level event that fires in your example program but when my test app does regain focus, the control that last had focus still has it.
Interesting question but it needs a little more context.
If I try your example and click outside the control on another window, desktop, etc, I can get the Got and Lost Focus events to fire, but if you're only trying to click within a form or a control with only 1 control, these event will never be fired because it is the only thing to focus on. Neither will Entered or left, unless you change the dynamics or overload the controls, you cannot get this to happen
In your example, I think you need another control. The reason being is that the first control (tabIndex 0) is the one with focus. With no other control to switch focus to, this control will always be focused, and therefore can never be entered. Switching to another application or form will not change the focus or active control in this form so when you return you will still not get the event fired.
With added controls control.entered should work fine. If this is your only control, why not call the event on formLoad, or TextChanged, when the form gets focus?
Thanks, I'll give some background.
My control is a UserControl that contains a grid and a toolbar. A user will typically launch several of these controls to view different slices of the system's data.
There are several keyboards shortcuts that can launch actions from the selected row in the current grid. However, it is a requirement that these keyboard shortcuts should apply not only to the currently focused grid. If the user is currently focused on one of the many other areas of the application, then this keyboard shortcut should still work, and it should be routed to the last focused grid.
So I wired a function to the Control.Enter event of my UserControl to basically say LastFocusedGrid = this.
And it would work, except for the docking and undocking...
See, these controls are hosted inside an application with docking features, somewhat similar to visual studio.
By default, the control launches as a tab within the main working area of the application, similar to the way a source file opens in visual studio.
However, the user can "rip out" a tab by grabbing the tab header and dragging it out of the main application. At this point, the application creates a new "float form" to host the control. Switching between the main application and this float form is the same as switching between apps, for the purposes of the Control.Enter and Form.Activated events.
At that point we have the "one control within a form" scenario simulated with the example application described in the original post.
Now, there are some ways around this. I could leverage the Form.Activated event, which DOES fire when switching between forms. If you add an event in the test application to the Form's Activated event, you will see that it works great.
The problem is that my UserControl's relationship with its parent Form is fluid, making the solution somewhat complicated. I tried wiring up to "this.ParentForm.Activated" which worked okay. The problem is when do you call this? What happens when you are undocked/redocked? I ended up with a nasty bunch of code with things like "previousParentForm" so that I could unhook from the old form, and then I was still facing the problem that the docking system doesn't notify me when my parent Form is being changed, so I was going to have to make a bunch of changes there, too.
These problems are not unsolvable, but if there is a simpler control-level "parent form was activated" event, then that would be a lot more elegant.
That's rather long, but I hope it clarifies the situation.
So when creating your grid, can you not set the KeyPressed, or KeyUp, etc. event? If so, all the grids can make use of the same event handler. Just make sure that when you get into the event handler to do something like:
Grid currentGrid = (Grid)sender;
Then you should be able to apply that block of code to any grid that gets sent in without having to worry about keeping track.
Since all the event handler really is, it's location is a mute point really as long as everything you need to execute it is accessible.
Frye, the problem is that the keyboard shortcuts should work no matter where the user is in the application. They are gloabl commands, handled at the top level, and then routed to the "last focused grid."
So handling the keystrokes at the grid level will not help.
To be more specific, assume user launches grids A, B, and C. But he also launches other controls X, Y, and Z that have nothing to do with my code.
User clicks on A, then on C. Then he clicks on Y, then on Z. With focus on Z, he hits my keyboard shortcut. In this case, grid C should respond since it was the last grid the user was focused in.
It sounds like the issue that you're having is not directly related to the Enter event and more to the point, if you have controls "that have nothing to do with your code" then you really aren't looking at a control level event.
Guess I wasn't clear.
My control lives in a container application. So do other unrelated controls by other teams. Think of it like visual studio -- my control is the code editing tab, but there is also the pending changes list and the properties window, which cohabitate with the source files but aren't directly related.
The keyboard shortcut is handled by the container application. Then it should be routed to the last one of my controls that the user was focused on.
Maintaing this "LastFocusedGrid" reference is what I do in the Enter event.
If you want to see similar functionality at work in visual studio, try this:
open a few source files
navigate to the "Start Page" tab.
Hit Ctrl-F and search "current document" for some string
Notice that the serach feature auto-navigates to the LAST FOCUSED source file to perform the search.
So even though you weren't focused in the source file, the ctrl-F command was processed by visual studio and routed to the last focused source file tab.
Now try the same thing with Ctrl-G. It doesn't work unless you are focused directly in the source file.
My keyboard commands need to work like Ctrl-F here, not like Ctrl-G. That is why I don't just capture the keyboard events directly in my control.
Does that clarify or make things worse?
Have you tried just a simple Control.GotFocus?
in this example if you toggle between clicking the textboxes neither the enter or got focus will do as expected, however if you click the child forms instead both will behave as expected.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace EnterBrokenExample
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form Form1 = new Form();
Form c1 = new Form();
Form c2 = new Form();
Form1.IsMdiContainer = true;
c1.MdiParent = Form1;
c2.MdiParent = Form1;
c1.Show();
c2.Show();
TextBox tb1 = new TextBox();
c1.Controls.Add(tb1);
tb1.Enter += ontbenter;
tb1.Text = "Some Text";
tb1.GotFocus += ongotfocus;
TextBox tb2 = new TextBox();
c2.Controls.Add(tb2);
tb2.Enter += ontbenter;
tb2.Text = "some other text";
tb2.GotFocus += ongotfocus;
Application.Run(Form1);
}
static void ontbenter(object sender, EventArgs args)
{
if (!(sender is TextBox))
return;
TextBox s = (TextBox)sender;
s.SelectAll();
}
static void ongotfocus(object sender, EventArgs args)
{
if (!(sender is TextBox))
return;
TextBox s = (TextBox)sender;
s.SelectAll();
}
}
}

Categories