vb.net で記述された .net MDI アプリケーションがあります。ユーザーが °、µ、²、³、ɑ などの特殊文字を選択できるようにするフォームをプログラムしようとしています。ホットキーまたは MDI 親のメイン メニュー。
これを行う簡単な方法は、文字選択フォームが呼び出されたときに、どのコントロールがどの MDI 子フォームにフォーカスされていたかを把握することですが、これを行う方法に関する情報が見つかりません。
何か案は?
どうやら WM_SETFOCUS メッセージが届いていないようです....残念です。それらはControl.WndProcメソッドで実現されると確信しています。回避策として、メッセージが来るたびにGetFocusを p/invoke し、フォーカスのあるコントロールのハンドルを保存する必要がありました。
1 番目のコード セクションはフィルタ クラスで、2 番目のコード セクションはテスト コードです。
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);
}
}
}
IMessageFilterを追加し、WM_SETFOCUSやWM_ACTIVATEなどの Windows メッセージを監視します。Control.FromHandleを使用して、IntPtrs を .NET コントロールに変換できます。