Тема: Фокус введення для форми без компонентів які підтримують фокус

Windows forms. MDI. Створюється вікно з Autoscroll = True для якого задається властивість MDIParent. В новоствореному вікні з компонентів лише TableLayout і Label. Вони не забирають фокус введення через що при натисненні клавіш активується поперднє вікно в якому є компоненти (ListView, Textbox, Button) з фокусом введення. Потрібно прокручувати вміст вікна за доп. курсорних клавіш, Page up, Page down і т.д. Пробував перенести фокус на автоматично додану смужку прокрутки але її немає в списку компонентів форми (властивість Controls) та й коли натискаєш на неї мишкою вона не стає активною.

2

Re: Фокус введення для форми без компонентів які підтримують фокус

javascriptIsLife написав:

Потрібно прокручувати вміст вікна за доп. курсорних клавіш, Page up, Page down

Так, це відома проблема основних компонентів .NET. Коли появиться можливість (десь в кінці тижня), гляну як можна обійти проблему. За той час кинь код в топік.

javascriptIsLife написав:

коли натискаєш на неї мишкою вона не стає активною.

Тут поправлю, вона активна (як мінімум Enabled), мабуть вона не хапайе фокус (!Focused && !ContainsFocus && !CanFocus).

В Paint.Net така ж проблема.

3

Re: Фокус введення для форми без компонентів які підтримують фокус

Ці скроли взагалі малюються системою, і не є окремими контролами з точки зору фреймворка. Спробуйте перенести фокус на саму форму, можливо не методами фреймворка, а функціями WinAPI.

4

Re: Фокус введення для форми без компонентів які підтримують фокус

Так, це відома проблема основних компонентів .NET. Коли появиться можливість (десь в кінці тижня), гляну як можна обійти проблему. За той час кинь код в топік.

Я знайшов що треба перехоплювати події натиснення на клавіші прокрутки і слати формі повідомлення WM_VSCROLL та інші через функцію SendMessage.

Виклик функції SetFocus, методу Focus самої форми, задавання WS_TABSTOP (The window is a control that can receive the keyboard focus when the user presses the TAB key.) через SetWindowLongPtr не допомагає. Якщо вікно є дочірнім вікном в MDI (через властивість MdiParent форми задано батьківську форму) і не містить компонентів на кшталт Button що перехоплюють фокус або просто порожнє, то натиснення клавіш призводить до активації попереднього вікна. В Windows forms навіть не вдається перехопити відповідні події. Я проглянув код Windows forms проте все що я зрозумів що така якось повʼязана з оцим шматком з файлу Form.cs:

    /// <summary>
    ///  Retrieves true if this form is currently active.
    /// </summary>
    internal bool Active
    {
        get
        {
            Form? parentForm = ParentForm;
            if (parentForm is null)
            {
                return _formState[s_formStateIsActive] != 0;
            }

            return parentForm.ActiveControl == this && parentForm.Active;
        }
        set
        {
            if (_formState[s_formStateIsActive] != 0 == value)
            {
                return;
            }

            if (value && !CanRecreateHandle())
            {
                return;
            }

            _formState[s_formStateIsActive] = value ? 1 : 0;

            if (value)
            {
                _formState[s_formStateIsWindowActivated] = 1;

                // Check if validation has been canceled to avoid raising Validation event multiple times.
                if (!ValidationCancelled)
                {
                    if (ActiveControl is null)
                    {
                        // If no control is selected focus will go to form
                        SelectNextControl(null, true, true, true, false);
                    }
                    InnerMostActiveContainerControl.FocusActiveControlInternal();
                }

                OnActivated(EventArgs.Empty);
            }
            else
            {
                _formState[s_formStateIsWindowActivated] = 0;
                OnDeactivate(EventArgs.Empty);
            }
        }
    }

І функцією SelectNextControl з файлу Control.cs:

    /// <summary>
    ///  Selects the next control following ctl.
    /// </summary>
    public bool SelectNextControl(Control? ctl, bool forward, bool tabStopOnly, bool nested, bool wrap)
    {
        Control? nextSelectableControl = GetNextSelectableControl(ctl, forward, tabStopOnly, nested, wrap);
        if (nextSelectableControl is not null)
        {
            nextSelectableControl.Select(true, forward);
            return true;
        }
        else
        {
            return false;
        }
    }

5

Re: Фокус введення для форми без компонентів які підтримують фокус

Придумав таке: KeyPreview для форми в True, на форму додавати ListView (просто Me.Controls.Add(New ListView)) який не видно за рештою компонентів, реагувати на події KeyDown форми і слати потрібні сигнали через SendMessage у відповідь на натиснення певних клавіш. ListView тому що якщо наприклад, додати Button, то в події KeyDown форми не відловлюються настинення клавіш Home, Down, Page up, Page down.