Можно ли сфокусировать элемент управления в форме, которая не может быть сфокусирована с помощью стиля WS_CHILD?

#c# #winforms

#c# #winforms

Вопрос:

Я создал раскрывающийся элемент управления, похожий на поле со списком, где при нажатии кнопки под кнопкой появится «выпадающая» форма, и пользователь сможет выбрать опцию из списка. Сама выпадающая форма не может быть сфокусирована, поэтому родительская форма никогда не теряет фокус. Все это отлично работает, как и предполагалось, но моя проблема в том, что я хотел бы использовать любой тип элемента управления в этой раскрывающейся форме. Любой элемент управления, который требует фокусировки для работы (например, текстовое поле), не будет работать, потому что он не сможет получить фокус, поскольку выпадающая форма не может быть сфокусирована.

Я использую этот код здесь для выпадающей формы:

 protected override CreateParams CreateParams
{
    get
    {
        CreateParams ret = base.CreateParams;
        ret.Style = (int)Flags.WindowStyles.WS_CHILD;
        ret.ExStyle |= (int)Flags.WindowStyles.WS_EX_NOACTIVATE | (int)Flags.WindowStyles.WS_EX_TOOLWINDOW;
        ret.X = this.Location.X;
        ret.Y = this.Location.Y;
        return ret;
    }
}
  

Который я получил отсюда:
https://www.codeproject.com/Articles/71808/Creating-a-Form-That-Doesn-t-Take-Focus

Я попытался вручную установить родительский элемент раскрывающегося списка в корневую форму, но это приводит к тому, что он не отображается.

Я хотел бы знать, есть ли какое-то решение, позволяющее выбирать эти элементы управления, содержащиеся в выпадающем списке, несмотря на то, что сама форма не выбирается. Возможно, сообщение Windows, которое я могу обработать, чтобы обойти логику фокусировки?

Комментарии:

1. Возможно, удалите переопределение CreateParams и добавьте это другое protected override bool ShowWithoutActivation => true; . Сделайте форму без границ (чтобы она отображалась как WS_CHILD would , но на самом деле не была дочерней): в этом случае он не будет красть фокус (фокус не перемещается из вызывающей формы), но все элементы управления в psudo-выпадающем списке могут быть выбраны. Вы также можете создать UserControl.

2. @Jimi Да, я пробовал это, когда изначально создавал выпадающий список. По какой-либо причине ShowWithoutActivation, возвращающий true, не имеет никакого эффекта и по-прежнему позволяет активировать форму, даже вызывая OnActivated .

3. Нет, это не так. Возврат true возвращает внутреннее ShowParams свойство return SW_SHOWNOACTIVATE , которое затем используется SetVisibleCore() вызовом для отображения окна. OnActivated() не вызывается, пока вы намеренно не переместите фокус на эту форму. Как уже упоминалось, используйте только это переопределение . Кстати, при работе с внутренними элементами элемента управления вам всегда нужно указывать, какую версию фреймворка вы используете. Если вы не используете 4.8, перейдите на эту версию. Если вы используете .Net Core…

4. @Jimi Хорошо, я TopMost установил true значение, которое, как я считаю, является причиной ShowWithoutActivation игнорирования… Кажется, показывает форму без активации, если TopMost она не установлена. В настоящее время я использую .Net 4.5, я должен иметь возможность перейти на 4.8. Несмотря на это, на этом этапе мне придется немного повозиться, чтобы вернуть функциональность в выпадающий список, чтобы посмотреть, работает ли он, когда он не дочерний.

5. Ну, вы действительно не хотите устанавливать его там самым верхним 🙂 Вы также можете использовать Show(this) в этом контексте, псевдо-выпадающий список будет иметь правильного владельца с самого начала и по-прежнему будет плавающим . Обратите внимание, что некоторые типы элементов управления могут быть родительскими для рабочего стола … (но, да, не так просто управлять). — Не связано: зачем использовать 4.5 в новом проекте? Вам нужно поддерживать древние системы?

Ответ №1:

В итоге я не использовал CreateParams переопределение, а вместо этого просто использовал protected override bool ShowWithoutActivation => true; форму без полей.

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