Como eu acho que o controle está focada?
Pergunta
Eu tenho um aplicativo MDI .net escrito em vb.net. Estou tentando programar uma forma que permitirá que o usuário selecione um caractere especial, como °, µ, ², ³, ? e assim por diante e ter esse caráter inserido em qualquer controle foi focada antes da sua lançando a forma através de um hot-chave ou o menu principal do pai MDI.
A maneira fácil de fazer isso seria a de descobrir qual o controle foi focada no que formulário filho MDI quando o formulário de seleção de personagens é invocado, mas não consigo encontrar qualquer informação sobre como fazer isso.
Todas as idéias?
Solução 3
Encontrada uma maneira mais fácil -
[Parent Form].ActiveMdiChild.ActiveControl
Outras dicas
Parece que a mensagem WM_SETFOCUS não estão vindo através .... My bad. Tenho certeza de que eles viriam através do método Control.WndProc . Como em torno do trabalho, tive de p / invoke GetFocus evertime chegou uma mensagem e armazenar o identificador do controle que tem foco.
A seção 1 ° código é a classe de filtro e a seção 2 código é o código de teste.
public class LastFocusedControlFilter : IMessageFilter
{
[DllImport("user32")]
private static extern IntPtr GetFocus();
private IntPtr? _lastCtrl;
private readonly Control _ctrlToIgnore;
public LastFocusedControlFilter(Control controlToIgnore)
{
_ctrlToIgnore = controlToIgnore;
}
public bool PreFilterMessage(ref Message m)
{
if (!_ctrlToIgnore.IsHandleCreated || _ctrlToIgnore.Disposing || _ctrlToIgnore.IsDisposed)
{
return false;
}
IntPtr handle = GetFocus();
if (handle != _ctrlToIgnore.Handle)
{
_lastCtrl = handle;
}
return false;
}
public Control GetLastFocusedControl()
{
return _lastCtrl.HasValue ? Control.FromHandle(_lastCtrl.Value) : null;
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Form form = new Form())
{
Action resetBackColor = null;
for (int i = 0; i < 10; i++)
{
TextBox textBox = new TextBox();
resetBackColor += delegate { textBox.BackColor = Color.White; };
textBox.Text = ((char)('a' + i)).ToString();
textBox.Location = new Point(0, textBox.Height * i);
form.Controls.Add(textBox);
}
Button showTextButton = new Button();
LastFocusedControlFilter msgFilter = new LastFocusedControlFilter(showTextButton);
showTextButton.Dock = DockStyle.Bottom;
showTextButton.Text = "Show text of last selected control";
showTextButton.Click += delegate(object sender, EventArgs e)
{
resetBackColor();
Control lastControl = msgFilter.GetLastFocusedControl();
if (lastControl == null)
{
MessageBox.Show("No control previous had focus.");
}
else
{
lastControl.BackColor = Color.Red;
MessageBox.Show(string.Format("Control of type {0} had focus with text '{1}'.", lastControl.GetType(), lastControl.Text));
}
};
form.Controls.Add(showTextButton);
Application.AddMessageFilter(msgFilter);
Application.Run(form);
}
}
}
Adicionar um IMessageFilter eo monitor para mensagens do Windows, como WM_SETFOCUS ou < a href = "http://msdn.microsoft.com/en-us/library/ms646274%28VS.85%29.aspx" rel = "nofollow noreferrer"> WM_ACTIVATE . Você pode usar Control.FromHandle para IntPtrs converter para Controles NET.
Você pode adicionar uma classe como este para seu projeto:
public class FocusWatcher
{
private static System.Windows.Forms.Control _focusedControl;
public static System.Windows.Forms.Control FocusedControl
{
get
{
return _focusedControl;
}
}
public static void GotFocus(object sender, EventArgs e)
{
_focusedControl = (System.Windows.Forms.Control)sender;
}
}
Então, para qualquer controle sobre qualquer forma que você quer ser um candidato para "mais controle recentemente focado", você faria isso:
textBox1.GotFocus += FocusWatcher.GotFocus;
e, em seguida, FocusWatcher.FocusedControl
acesso para obter o controle mais recentemente focado. as mensagens de Monitoramento irá funcionar, mas você tem que ignorar as mensagens que você não quer (como WM_ACTIVATE do formulário MDI).
Você pode iterar por todos os controles em cada formulário e adicionar esse manipulador para o evento GotFocus, mas certamente há controles que você não quero isso para (como botões, por exemplo). Você poderia, em vez iterate e só adicionar o manipulador para TextBoxes.