Delphi: как использовать элементы управления без окон?

я знаю, что безоконные элементы управления — это не волшебство. Безоконный элемент управления может иметь фокус ввода (например, Internet Explorer). Фокус ввода — это не что иное, как рисование:

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

В случае с моим окном (Windows) мне нужно знать, что мой безоконный дочерний элемент управления (давайте притворимся, что он является потомком TGraphicControl) получает события клавиатуры. Поэтому во время OnKeyDown, OnChar, OnKeyUp моей формы мне нужно было бы притвориться, что они переходят к моему дочернему элементу управления без окон.

Что я могу сделать, но это боль.

Но тогда пользователь, вероятно, захочет использовать навигацию Tab, и мне придется каким-то образом перехватить обычную обработку порядка элементов управления вкладками Delphi и зацепиться за себя, чтобы сказать, что эта штука является следующим (и предыдущим) в порядке табуляции.

Что я могу сделать, но это боль.

А еще есть ActiveControl, который ничего не понимает, кроме TWinControl. Так что, если Delphi когда-нибудь попытается выяснить, у кого есть фокус, она сойдет с ума. Так что мне пришлось бы иметь альтернативную реализацию ActiveControl.

Что я могу сделать, но это боль.

Другими словами: это слишком много работы? я борюсь со всем, чем является Delphi, и все это для того, чтобы иметь несколько десятков безоконных элементов управления, доступных через ввод с клавиатуры? Дизайнеры Delphi никогда не думали об использовании интерактивных безоконных элементов управления, и если я попытаюсь сделать это сейчас, я просто застряну в хартлокер?

Delphi дала мне возможность добровольно помочь мне, но я выбрал путь боли.


Требуется некоторое дополнительное объяснение безоконных элементов управления.

Не каждый элемент управления, с которым вы взаимодействуете, должен быть элементом управления Windows. Вполне возможно сфокусироваться и отправить ввод с клавиатуры на элемент управления, который не является окном Windows.

Например, почти каждый элемент управления, который вы видите в окне браузера Internet Explorer, является элементом управления без окон. На следующем снимке экрана вы можете увидеть элемент управления edit, который вы можете ввести, и кнопку, которая (на этом снимке экрана) имеет фокус:

альтернативный текст

Вы можете видеть пунктирный прямоугольник фокуса, а кнопка имеет голубоватый оттенок (что в Windows указывает на наличие фокуса).

Если бы я нажал Пробел, когда кнопка Google Search была в фокусе, я бы нажал кнопку. Причина, по которой это работает, заключается в том, что Microsoft написала целую библиотеку элементов управления для виджетов. Эти элементы управления выглядят и работают (почти) точно так же, как обычные общие элементы управления — они являются почти точными клонами общих элементов управления Windows, вплоть до применяемых тем.

Mozilla Firefox и Google Chrome также используют библиотеку элементов управления виджетов. Они не используют встроенные оконные элементы управления Microsoft, а вместо этого используют библиотеку графических интерактивных безоконных виджетов.

И если у вас есть подходящая среда разработки, то виджеты без окон работают точно так же, как «обычные» оконные элементы управления. GTK+ — это библиотека виджетов, а Glade — это IDE, которая позволяет размещать элементы управления в этой библиотеке виджетов.

я не знаю, в какой среде разработки были созданы Firefox, Chrome или Blender, но их виджеты поддерживают элементы управления без окон.


Итак, теперь на мой вопрос.

Если я не ошибаюсь, мне кажется, что хотя Delphi поддерживает базу TControl (которая имеет ширину, высоту и может рисовать сама), она не может получать фокус клавиатуры. Мне кажется, что Borland никогда не проектировала Delphi VCL как общую библиотеку виджетов. Единственное доказательство, которое я должен поддержать, это то, что ActiveControl формы является TWinControl:

property ActiveControl: TWinControl;

Это не означает, что Delphi может или должна быть ограничена оконными элементами управления. Библиотека виджетов VCL может быть расширена для поддержки выделения элементов управления без окон.

Но, возможно, Delphi уже поддерживает элементы управления без окон, а я просто этого не понимаю? Есть ли в Delphi уже установленный механизм для поддержки выделения фокуса TControl? Но я достаточно умный парень, и я почти уверен, что Delphi VCL не может делать то, что могут другие библиотеки виджетов.

Что затем приводит к другому вопросу: сколько работы потребуется для подкласса форм и тому подобного для его поддержки? Есть ли кто-то еще, возможно, кто-то из TeamB, кто намного умнее меня, кто уже попробовали и пришли к выводу, что это невозможно?

я спрашиваю сейчас, заранее, если попытка добавить поддержку управления без окон почти невозможна (то есть бесполезна) - так что я не трачу недели на это впустую. я пытаюсь использовать знания сообщества разработчиков Delphi.

я задаю вопрос.


person Ian Boyd    schedule 23.02.2010    source источник
comment
Голосование закрыть как не реальный вопрос. И на самом деле его нет, как только вы сняли украшения. @Ian, SO - это сайт вопросов и ответов, который пытается помочь вам (и, в идеале, другим людям с аналогичным вопросом позже) получить хороший ответ на настоящий вопрос. Если вы не знаете, зачем вам все это, то как это может сделать кто-то другой?   -  person mghie    schedule 23.02.2010
comment
Существует ли библиотека виджетов (будь то Borland VCL или какая-либо другая библиотека) для Delphi, которая поддерживает элементы управления без окон? Или понятие оконного элемента управления настолько глубоко укоренилось в Delphi, что а) его не только не существует, но и б) было бы почти невозможно создать его, не отбрасывая почти все, что может предложить IDE Delphi?   -  person Ian Boyd    schedule 23.02.2010


Ответы (7)


Бесполезно создавать безоконные элементы управления и встраивать их в среду Delphi VCL.

Вы приводите Internet Explorer в качестве примера. Но в этом случае он полностью отвечает за все, что на нем находится. У него есть свое внутреннее представление о том, что такое активный элемент управления, но подумайте о том, как он выглядит снаружи: это всего лишь один гигантский элемент управления. Когда вы спрашиваете ОС, что имеет фокус, единственный элемент управления браузера имеет его, независимо от того, какой из подэлементов управления браузера появляется, имеет фокус.

Когда вы нажимаете Tab, для ОС это выглядит так, как будто браузер просто использовал символ табуляции, как это делают элементы управления редактированием. Элементы управления Edit перемещают курсор на несколько пробелов и добавляют символы табуляции в свои внутренние буферы; элементы управления браузера перемещают курсор в другую область дисплея.

Вы думаете сделать все это на Delphi TForm. Формы Delphi уже имеют структуру для управления активным элементом управления и обработки нажатий клавиш, и вам придется бороться со всем этим. Если вам нужны элементы управления без окон, воспользуйтесь маршрутом Internet Explorer и создайте собственный элемент управления-контейнер, чтобы хранить его, чтобы вы могли контролировать все, что происходит внутри него.

Ваш контейнер может быть элементом управления VCL, но вещи, которые вы в него помещаете, вероятно, не могут — они все равно будут ожидать использования правил VCL для фокусировки и обработки клавиатуры. Обратите внимание, что вы также не можете поместить обычные элементы управления Windows в Internet Explorer. Все, что вы туда помещаете, должно проходить через определенные интерфейсы ActiveX. Возможно, вам также понадобятся интерфейсы, или, может быть, вы можете просто создать свой собственный набор управляющих классов, которые происходят от какого-то специального класса-предка, который вы разрабатываете для работы с вашим контейнером. Не начинайте с TGraphicControl; он слишком укоренился в VCL, чтобы его можно было использовать в качестве основы для вашей ответвленной библиотеки управления.

Это будет много работы, но опять же, как и Internet Explorer.

person Rob Kennedy    schedule 23.02.2010
comment
Формы Delphi уже имеют структуру для управления активным элементом управления и обработки нажатий клавиш, и вам придется бороться со всем этим. Спасибо. Это было действительно то, на что я надеялся. Delphi был написан с нуля, чтобы не иметь элементов управления без окон. И если бы я попытался программировать, чтобы создать элемент управления без окон: я бы боролся с Delphi на каждом этапе пути. - person Ian Boyd; 23.02.2010
comment
Кроме того, есть один элемент управления, который Microsoft не преобразовала в версию без окон — поле со списком. Вы заметите, что поля со списком всегда появляются поверх любого другого содержимого html — независимо от того, как много вы играете с z-порядками. Это потому, что это все еще оконный элемент управления Windows. - person Ian Boyd; 23.02.2010
comment
я создал некоторые элементы управления. я хотел, чтобы они были без окон, чтобы они были легкими, а также потому, что это позволяло им быть частично прозрачными. Но когда пришло время перейти к ним с помощью TAB, я понял, что TControls не интерактивны. И хотя они реагировали на посылаемые им события клавиатуры, мне пришлось убедить Delphi, что они являются элементами управления, достойными ее внимания. - person Ian Boyd; 23.02.2010
comment
Чтобы делать то, что вы хотите, вам нужно предоставить оконный контейнер для ваших элементов управления. Это не мешает вам помещать в контейнер другие оконные элементы управления; им просто нужно знать, как взаимодействовать с вашим контейнером. Поле со списком Internet Explorer не является исключением. У него есть дескриптор окна, но он по-прежнему специально приспособлен для работы внутри IE. Это не стандартное поле со списком Windows. IE предоставляет интерфейсы ActiveX, поэтому вы можете адаптировать другие элементы управления, чтобы они соответствовали IE. - person Rob Kennedy; 23.02.2010
comment
Последний вопрос, я думаю, будет таким: возможно ли вообще использовать Delphi для управления без окон? Предполагая, что я написал (или импортировал) безоконную версию каждого элемента управления (кнопка, поле редактирования, флажок, древовидное представление, список, строка состояния и т. д.). Далее предположим, что я создал потомка TForm, который понимает дочерние TControl: не слишком ли TApplication привык к идее TForm? я заметил, что TScreen также имеет ActiveControl: TWinControl, должен ли я создавать новые версии TApplication и TScreen, и все остальное? Другими словами... бесполезно? - person Ian Boyd; 23.02.2010
comment
Конечно, вы можете использовать Delphi. Вы можете писать все, что хотите. Но VCL, как и сама ОС, ожидает, что вещи, которые могут получить фокус, будут иметь оконные дескрипторы. Как далеко вы хотите зайти в этом? Если вы собираетесь заменить Screen.ActiveControl, вы также собираетесь заменить GetActiveWindow? Какая разница? Никто не знает о содержимом вашего контейнера. - person Rob Kennedy; 23.02.2010
comment
На самом фундаментальном уровне я думаю, что мне нужно сохранить TApplication. я считаю (возможно, ошибочно), что IDE зависит от наличия объекта TApplication. Среда IDE анализирует исходный файл проекта и знает, как добавлять/удалять формы на основе Application.Create. Мне кажется, что я мог бы многое выбросить, но я должен сохранить TApplication. В приложении .NET есть объект Application, который настраивает насос сообщений, аналогичный Delphi. Но когда вы создаете приложение WPF, есть объект System.Windows.Application. я боюсь, что мне придется переписать приложение для поддержки без окон. - person Ian Boyd; 24.02.2010

Да, это бесполезно.
И это не вина Delphi, вы просто боретесь с самой Windows.
Если вам нужен элемент управления, который ведет себя как оконный элемент управления, используйте оконный.
И вы верно, попытка воссоздать весь стек оконных элементов управления API с нуля - это боль.

person Francesca    schedule 23.02.2010
comment
Другие приложения, которым удалось это сделать; они воюют с самой виндой? Это можно сделать, если используемая библиотека виджетов поддерживает элементы управления без окон. Delphi, кажется, исходит из того, что каждый элемент управления должен быть оконным. я не знаю, на каком языке были написаны Internet Explorer, Chrome, Firefox и Blender, но, очевидно, в среде, библиотека виджетов которой поддерживает элементы управления без окон. Есть ли в Delphi механизм поддержки таких элементов управления без окон (они же виджеты)? - person Ian Boyd; 23.02.2010
comment
Ян, вы ошибаетесь, думая, что эти программы используют готовые библиотеки виджетов. Эти программы имеют собственные библиотеки, специально разработанные для этой задачи. - person Rob Kennedy; 23.02.2010
comment
@Роб. Это может быть, но существующие библиотеки виджетов. GTK+, wxWidgets, Juce, Qt, Swing. Есть и другие библиотеки: WinForms, MFC. Подходит ли VCL к первому (без окон) или второму (с оконным режимом)? - person Ian Boyd; 23.02.2010
comment
Вы уверены, что библиотеки GTK+ и wxWidgets не используют дескрипторы окна? Я подозреваю, что они делают. Однако я не знаю об элементах управления Java. Возможно, нет, потому что они всегда находятся внутри контейнера Java. Итак, мы снова видим, что безоконные элементы управления требуют специального контейнера. - person Rob Kennedy; 23.02.2010
comment
@Ian: wxWidgets в Windows могут использовать дескрипторы окон (скомпилированные как wxMSW), но не должны этого делать (если скомпилированы как wxUniversal). Если это не так, управление фокусом должно быть реализовано фреймворком. Но нативный внешний вид может быть достигнут на 100 % только при использовании нативных, то есть оконных элементов управления, поэтому wxUniversal всегда будет худшим выбором. Таким образом, wxWidgets следует отнести к последней категории. - person mghie; 23.02.2010
comment
@Rob: конечно, для управления без окон требуется специальный контейнер. я просто надеялся, что Borland сделал этот контейнер под названием TForm. - person Ian Boyd; 24.02.2010

Да, вы примерно разобрались. Использование элементов управления без окон означает, что вы теряете все, чем Windows может вам помочь. Наличие более пары на одном фактическом окне — это боль.

person Ignacio Vazquez-Abrams    schedule 23.02.2010
comment
я бы потерял то, что Windows может сделать для меня, но есть фреймворки и библиотеки виджетов, которые могут это сделать. Является ли Delphi одной из этих библиотек виджетов? Можно ли попросить Delphi поддерживать элементы управления, не являющиеся оконными? - person Ian Boyd; 23.02.2010
comment
Все эти библиотеки виджетов либо используют оконные элементы управления, либо сами выполняют всю тяжелую работу с помощью одного оконного элемента управления. - person Ignacio Vazquez-Abrams; 23.02.2010

Большинство этих программ, скорее всего, изначально не были разработаны с использованием инструментов типа RAD, поэтому у них не было другого выбора, кроме как заново изобрести колесо. Одним из самых больших преимуществ Delphi является глубокая поддержка VCL и сторонних компонентов для обеспечения желаемого внешнего вида.

Один метод, который я с большим успехом использовал для уменьшения количества дескрипторов окон, используемых в приложении, основанном на сложной форме (подготовка налогов), заключался в рисовании текста на холсте и перемещении одного потомка TCustomEdit в положение, которое редактировал пользователь. Было тривиально захватить клавиши TAB/Up/Down и переместить редактирование в соответствующую позицию. Проблема, которую мы обнаружили, заключалась в том, чтобы нарисовать горячий прямоугольник вокруг поля, на котором зависла мышь. Мы закончили с массивом сетки TObject, где элемент массива был бы nil (поле отсутствует), TLIst (сетка содержит несколько полей) или класс, который содержал бы наш дескриптор поля. Это уменьшило количество проверок диапазона, которые нам приходилось выполнять, поскольку более вероятно, что поле содержало только одно поле или не более 4 полей.

person skamradt    schedule 23.02.2010
comment
Вау, мы работаем над одним и тем же программным обеспечением или что-то в этом роде...? :-) - person Vegar; 23.02.2010

fpGUI Toolkit — пример того, что вам нужно. Последний код fpGUI в репозитории исходного кода основан на многооконном дизайне. Это просто означает, что каждый виджет/компонент имеет дескриптор окна, но Windows или Linux ничего не делают с этим окном, кроме основных сообщений уведомлений (mouseenter, mouseexit и т. д.). fpGUI по-прежнему имеет полный контроль над тем, куда перемещается каждый компонент, доступны ли они для фокусировки, как они выглядят и т. д. Некоторые виджеты/компоненты в fpGUI также не являются оконными компонентами. например: TfpgScrollbar, TfpgMainMenu, кнопка в ComboBox и т. д.

Если вам нужна настоящая не оконная версия, это означает, что есть только одно окно верхнего уровня с дескриптором окна, все остальные виджеты/компоненты внутри этого окна фактически не существуют для ОС (у них нет дескрипторов окна), тогда fpGUI тоже может помочь. Первоначальный дизайн fpGUI Toolkit был основан на таком дизайне. Опять же, посмотрите в репозитории исходного кода ветку кода v0.4. В этом дизайне fpGUI должен был обрабатывать абсолютно все, создавать события mouseenter/mouseleave, переводить системы координат для компонентов контейнера, обрабатывать (фальшивые) состояния фокуса компонента и т. д. Да, первоначальный дизайн — это МНОГО работы, но потом вы иметь очень переносимую структуру, которую можно легко применить и к другим ОС.

И да, fpGUI полностью реализован на языке Object Pascal с использованием компилятора Free Pascal, что обеспечивает кроссплатформенную поддержку. В настоящее время fpGUI работает на устройствах Windows, Linux (32- и 64-разрядная версия), Windows Mobile и Embedded Linux (ARM).

person Community    schedule 26.02.2010
comment
Я думаю, что наиболее важным для OP является раздел «Введение» на вашей связанной странице, где вы объясняете, почему вы отказались от этого дизайна для одноручного - за дизайн виджета. - person mghie; 27.02.2010
comment
Ссылка кажется битой. Я предполагаю, что wiki.lazarus.freepascal.org/fpGUI является более постоянной ссылкой на такое же программное обеспечение. Существует также fpgui.sourceforge.net. - person tripleee; 20.06.2019

Я понятия не имею, в чем на самом деле твоя проблема, но я думаю, что эта небольшая история может иметь значение...

У нас есть приложение, которое заполняет дюжину форм. Пользователь может заполнять дополнительные формы, а также изменять значения, заполняемые самим приложением.

Теперь, в нашей первой реализации, мы использовали оконные компоненты для каждого отдельного поля ввода, чтобы поля могли получать фокус и ввод. Это оказалось большой проблемой, потому что все эти окна отнимали много ресурсов.

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

Опять же - я понятия не имею, чем вы действительно хотите управлять. TWinControl является TWinControl по какой-то причине, но может быть решение того, что вы хотите, каким бы оно ни было...

person Vegar    schedule 23.02.2010
comment
Посмотрите на текстовое поле, которое вы вводите в браузере. Это текстовое поле не является окном Windows. У него нет собственного дескриптора окна или оконной процедуры. Нажатия клавиш отправляются в окно Windows, но окном, в которое они отправляются, является вся страница. Вам не нужен класс Windows для создания элемента управления, вам просто нужна библиотека элементов управления, которая не основана на классе Windows. Команда ie воссоздала все обычные элементы управления в виде версий без окон (текстовое поле, кнопка, флажок и т. д.). Это не элементы управления Windows, они без окон. - person Ian Boyd; 23.02.2010
comment
ну, вы можете делать в Delphi почти все, что захотите, но отчасти смысл использования Delphi заключается в том, чтобы получить преимущество, данное VCL. Вместе с delphi можно использовать и другие библиотеки виджетов, а некоторые даже позволяют использовать часть функций Delphi ide, таких как палитра и инспектор (например, twinforms.com/products/wxformsdelphi/index.php). - person Vegar; 23.02.2010

Я думаю, что fgGUI может вам помочь.

Сначала проверьте его Вики.

Я думаю, вы можете использовать эту структуру для своего приложения в Delphi, так как она полностью написана на Паскале. На самом деле он основан на FreePascal ;)

ХТН

person Yogi Yang 007    schedule 24.02.2010
comment
С домашней страницы: это означает, что каждый виджет (компонент) имеет собственный дескриптор окна. /фейспалм - person Ian Boyd; 24.02.2010
comment
Re: неработающая ссылка, см. также мой комментарий к другому ответу, ссылающемуся на это - person tripleee; 20.06.2019