1

vb.net で記述された .net MDI アプリケーションがあります。ユーザーが °、µ、²、³、ɑ などの特殊文字を選択できるようにするフォームをプログラムしようとしています。ホットキーまたは MDI 親のメイン メニュー。

これを行う簡単な方法は、文字選択フォームが呼び出されたときに、どのコントロールがどの MDI 子フォームにフォーカスされていたかを把握することですが、これを行う方法に関する情報が見つかりません。

何か案は?

4

4 に答える 4

2

どうやら 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);
        }
    }
}
于 2009-10-27T15:50:38.120 に答える
1

IMessageFilterを追加し、WM_SETFOCUSWM_ACTIVATEなどの Windows メッセージを監視します。Control.FromHandleを使用して、IntPtrs を .NET コントロールに変換できます。

于 2009-10-27T14:37:19.827 に答える