Обнаружение переключения между 2 экземплярами UserControl - PullRequest
0 голосов
/ 11 марта 2019

У меня есть класс, производный от UserControl (ниже).Пользователь может одновременно открыть несколько экземпляров этого элемента управления.Я хочу быть в состоянии определить, когда пользователь переключается с одного на другой, т.е. нажимает на одно, а затем нажимает на другое.

OnEnter и OnLoad вызываются только при первом отображении элемента управления
OnLeave никогда не вызывается.
OnGotFocus и OnLostFocus никогда не вызываются, но, очевидно, их использование не рекомендуется.
Что мне нужно сделать?

 public partial class MyView : System.Windows.Forms.UserControl
 {
         // Before `OnLoad`
         // WM_NCCREATE, WM_NCCALCSIZE WM_CREATE, WM_SIZE, WM_MOVE,WM_REFLECT, WM_SHOWWINDOW, WM_PARENTNOTIFY
         // After `OnLoad`, Before `OnEnter`
         // WM_WINDOWPOSCHANGING, WM_NCCALCSIZE, WM_WINDOWPOSCHANGED, WM_SIZE, WM_GETTEXTLENGTH, WM_GETTEXT, (WM_WINDOWPOSCHANGING, WM_NCCALCSIZE, WM_WINDOWPOSCHANGED, WM_SIZE, WM_CHILDACTIVATE, WM_MOVE, WM_SHOWWINDOW
        private const int WM_ACTIVATE = 0x006;
        protected override void WndProc(ref Message message)
        {
            if (message.Msg == WM_ACTIVATE)
            {
                System.Diagnostics.Trace.WriteLine("MyView.WndProc(): message: " + message);
            }
            base.WndProc(ref message);
        }

        // called before OnEnter
        protected override void OnLoad(System.EventArgs eventArgs)
        {
            base.OnLoad(eventArgs);

            Form form1 = this.FindForm();      // null
            Form parentForm = this.ParentForm; // null
        }

        // called only on first display, not when the user switches between the 2 controls
        protected override void OnEnter(EventArgs eventArgs)
        {
            base.OnEnter(eventArgs);
        }

        protected override void OnLeave(EventArgs eventArgs)
        {
            base.OnLeave(eventArgs);
        }

        // Never called
        protected override void OnGotFocus(EventArgs eventArgs)
        {
            base.OnGotFocus(eventArgs);
        }

        // Never called
        protected override void OnLostFocus(EventArgs eventArgs)
        {
            base.OnGotFocus(eventArgs);
        }
 }

Ответы [ 2 ]

1 голос
/ 12 марта 2019

Требование: «Я хочу быть в состоянии определить, когда оператор ... нажал на одну, а затем нажал на другую».

По-видимому, вы хотите получать уведомления, если щелкает элемент управления или какой-либо из его дочерних элементов управления. Для этого вам нужно подписаться на события Click всех ваших дочерних элементов управления.

protected override void OnControlAdded(ControlEventArgs e)
{
     // subscribe to click event of e.Control
     e.Control.Click += OnChildClicked;
}
// TODO: de-subscribe in OnControlRemoved

public void OnChildClicked(object Sender, EventArgs e)
{
    // Clicked on child control, act as if Clicked on me
    this.OnClick(e);
}

Событие click вызывается любым событием, похожим на щелчок, даже если оно выполняется клавиатурой, например, нажатием клавиши ввода.

Вы написали, что хотели щелкнуть мышью. Если вы действительно хотите только щелчки мыши, используйте событие MouseClick. Если оператор использует TAB для выбора одного из ваших дочерних элементов управления и нажимает ENTER, чтобы щелкнуть по нему, вы не будете получать уведомления.

1 голос
/ 11 марта 2019

Это полный исходный код для пользовательского элемента управления.Он работает как есть.

В форме я создал два экземпляра элемента управления и могу нажать на них.Как и я, квадраты переключаются с красного на синий.

Вы должны иметь возможность устанавливать точки останова в методах OnGotFocus и OnLostFocus.Недействительные есть для перерисовки.

Волшебство в том, что есть два элемента управления (как и у вас), но кроме того, переопределение OnButtonclicked устанавливает фокус.Я полагаю, что это часть, которая отсутствует в вашем примере.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace DesktopApp1
{
    public partial class MyView : System.Windows.Forms.UserControl
    {

        protected Color SelectedColor { get; set; } = Color.Red;
        protected Color NormalColor { get; set; } = Color.Blue;
        protected override void OnPaint(PaintEventArgs e)
        {
            using (SolidBrush blueBrush = new SolidBrush(this.Focused?SelectedColor:NormalColor))
            using (Pen blackPen = new Pen(Color.Black, 3))
            {
                e.Graphics.FillRectangle(blueBrush, ClientRectangle);

                Rectangle inset = new Rectangle(this.ClientRectangle.X + 1, this.ClientRectangle.Y + 1, this.ClientRectangle.Width -3 , this.ClientRectangle.Height - 3);
                e.Graphics.DrawRectangle(blackPen, inset);
            }
            base.OnPaint(e);
        }

        private void OnButton1Clicked(object sender, EventArgs e)
        {
            this.Select();
        }

        protected override void OnGotFocus(EventArgs e)
        {
            Invalidate();
            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            Invalidate();
        }
    }
}

Чтобы завершить ответ, вот форма 1.Designer.cs

namespace DesktopApp1
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.myView2 = new DesktopApp1.MyView();
            this.myView1 = new DesktopApp1.MyView();
            this.SuspendLayout();
            // 
            // myView2
            // 
            this.myView2.Location = new System.Drawing.Point(189, 12);
            this.myView2.Name = "myView2";
            this.myView2.Size = new System.Drawing.Size(150, 150);
            this.myView2.TabIndex = 1;
            // 
            // myView1
            // 
            this.myView1.Location = new System.Drawing.Point(9, 12);
            this.myView1.Name = "myView1";
            this.myView1.Size = new System.Drawing.Size(150, 150);
            this.myView1.TabIndex = 0;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(355, 175);
            this.Controls.Add(this.myView2);
            this.Controls.Add(this.myView1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private MyView myView1;
        private MyView myView2;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...