Texthint delphi что это
Как в TMemo сделать вертикальное выравнивание, отступы и TextHint
Пролог
Итак, из-за чего все собственно и стряслось. Я пишу плагины для LedearTask. Также, в 2017 году, написал векторный редактор для турецкой фирмы станков по производству печатей MATUYA. Что LeaderTask, что MATUYA, выставили интересные требования – вертикальное выравнивание в многострочном редакторе, отступы и TextHint. TextHint имеется ввиду — такое серое приглашение ввести хоть что-нибудь, когда элемент ввода пуст.
LeaderTask: плагин «Лестница Целей» (ввод и хинт по центру в многострочном редакторе)
Matuya Stamp Systems (ввод текста выровнен по правому и нижнему краю)
Как известно, вертикального выравнивания, в отличии от горизонтального, в стандартном Windows API для контролов не существует.
Также, приглашения для ввода какой-то информации в многострочных контролах Windows не поддерживаются.
Таким образом, возникает дилемма – а как? Хочется использовать стандартные компоненты, но при этом иметь расширенные возможности ввода текстовой информации.
Небольшое отступление
С некоторых, достаточно отдаленных, пор, я не пишу компоненты и не использую сторонние. В условиях вечного дедлайна намного выгодней, быстрее и экономичней все писать самому. То, что будет создано в real-time. Т.е. использовать богатые возможности дизайнера Delphi, но подменять классы «на лету» в real-time. Как это все выглядит, надеюсь описать подробнее чуть позже. Что это значит в текущем конкретном случае, опишу сейчас.
Что требуется
По сути, от меня требуется TMemo, в котором есть вертикальное выравнивание, скажем, свойство Layout, свойство TextHint — «приглашение» ввести какой-нибудь текст. Также, требуется сделать отступы сверху-снизу-слева-справа для ввода и отображения текста, чтоб он не «прилипал» к граням контрола.
Теория
Необходим TMemo с дополнительными возможностями. Очевидно, придется писать наследника от TMemo. Не от TCustomMemo, и уж тем более не от TCustomEdit. Нам нужен именно TMemo, потому что мы не собираемся писать библиотеку компонентов, а хотим сделать проект быстро и в срок.
Вертикальное выравнивание нам недоступно. Ну что ж, зато мы можем установить для контролов прямоугольник ввода текста. Это осуществляется следующим образом.
В нашем случае, это будет выглядеть так:
Где ARect –искомый прямоугольник для ввода текста. Очевидно, его верхняя грань должна зависеть от значения свойства Layout. Также, этот прямоугольник может определить и границы отступа от краев для ввода текста.
Далее, немного поковыряв исходники, находим виртуальный метод:
Он вызывается в любом случае, что для DoubleBuffered, что без него. Его вызов будет осуществлен при наличии csCustomPaint в ControlState компонента, после всех значимых отрисовок компонента. Его мы будем использовать для отрисовки TextHint.
Практика
Не буду останавливаться на некоторых, думаю, не особо интересных деталях реализации.
Для начала, у нас появляются следующие дополнительные свойства:
И основные моменты.
1. Объявление класса безусловно таково:
2. В конструкторе пишем строку:
3. Назначение прямоугольник ввода:
4. Расчет прямоугольника ввода:
5. Что такое TrueWordWrap в вызове функции CalcHeight выше. Это метод, которые возвращает истинное значение переноса строк для TMemo, которое зависит на самом деле от ряда параметров:
6. Где происходит вызов перерасчета и назначения прямоугольника ввода:
7. Назначение свойства TextHint чрезвычайно просто, но с учетом того, если кому-то вдруг захочется регистрировать компонент:
9. Чтобы облегчить «подмену» стандартного TMemo на наш, есть следующий метод. Он забирает все основные события и свойства у переданного указателя на TCustomMemo. При выставленном флаге AWithFree, уничтожает экземпляр старого и становится на его место. Т.е., если в коде все завязано на «старый» TCustomMemo, ничего страшного не произойдет. Все будет работать с новым экземпляром, как со старым, за исключением тех моментов, когда будут использованы свойства, про которые вы и так в курсе, и обращаться к ним все равно придется как к TxIPMemo:
Как использовать
Предположим, что уже есть компонент TMemo на форме, которое Вы либо используете в динамике, подобно как выше-вкратце-описанные редакторы, либо статический компонент, созданный в дизайне. Это все не важно.
1. Объявляем где-то следующим образом:
2. В событии OnCreate формы, либо в её конструкторе, пишем следующее:
За уничтожение экземпляра класса не волнуемся – он будет гарантированно уничтожен в деструкторе.
3. Возможно, в том же обработчике FormCreate пишем:
Тем самым забирая свойства и события у Memo1, и уничтожая его, становясь на его место.
4. Собственно, и все. Назначаете необходимые свойства нашему компоненту. И пользуем TMemo с возможностями вертикального выравнивания, отступов (которые могут быть и отрицательными), приглашения для пользователя при пустом Text.
Окно демо-приложения
Эпилог
В исходниках, ссылка на которые ниже, все используемые в тексте вспомогательные функции представлены.
Версия компилятора определяется <$I>подключаемым файлом pro_param.inc.
Т.к., в силу специфики работы, придерживаюсь концепции один модуль – разные версии, представленные исходники компилируются в Delphi 7, Delphi XE 7 и Delphi 10.1 Berlin. По той простой причине, что Delphi 7 у меня куплен, а Delphi 10.1 Berlin – бесплатная лицензия для коммерческих продуктов. А заказчик в последнее время хочет быть абсолютно «белым». Поэтому не использую никаких платных библиотек.
Надеюсь, материал поможет в ситуациях разной степени тяжести.
Как в TMemo сделать вертикальное выравнивание, отступы и TextHint
Пролог
Итак, из-за чего все собственно и стряслось. Я пишу плагины для LedearTask. Также, в 2017 году, написал векторный редактор для турецкой фирмы станков по производству печатей MATUYA. Что LeaderTask, что MATUYA, выставили интересные требования – вертикальное выравнивание в многострочном редакторе, отступы и TextHint. TextHint имеется ввиду — такое серое приглашение ввести хоть что-нибудь, когда элемент ввода пуст.
LeaderTask: плагин «Лестница Целей» (ввод и хинт по центру в многострочном редакторе)
Matuya Stamp Systems (ввод текста выровнен по правому и нижнему краю)
Как известно, вертикального выравнивания, в отличии от горизонтального, в стандартном Windows API для контролов не существует.
Также, приглашения для ввода какой-то информации в многострочных контролах Windows не поддерживаются.
Таким образом, возникает дилемма – а как? Хочется использовать стандартные компоненты, но при этом иметь расширенные возможности ввода текстовой информации.
Небольшое отступление
С некоторых, достаточно отдаленных, пор, я не пишу компоненты и не использую сторонние. В условиях вечного дедлайна намного выгодней, быстрее и экономичней все писать самому. То, что будет создано в real-time. Т.е. использовать богатые возможности дизайнера Delphi, но подменять классы «на лету» в real-time. Как это все выглядит, надеюсь описать подробнее чуть позже. Что это значит в текущем конкретном случае, опишу сейчас.
Что требуется
По сути, от меня требуется TMemo, в котором есть вертикальное выравнивание, скажем, свойство Layout, свойство TextHint — «приглашение» ввести какой-нибудь текст. Также, требуется сделать отступы сверху-снизу-слева-справа для ввода и отображения текста, чтоб он не «прилипал» к граням контрола.
Теория
Необходим TMemo с дополнительными возможностями. Очевидно, придется писать наследника от TMemo. Не от TCustomMemo, и уж тем более не от TCustomEdit. Нам нужен именно TMemo, потому что мы не собираемся писать библиотеку компонентов, а хотим сделать проект быстро и в срок.
Вертикальное выравнивание нам недоступно. Ну что ж, зато мы можем установить для контролов прямоугольник ввода текста. Это осуществляется следующим образом.
В нашем случае, это будет выглядеть так:
Где ARect –искомый прямоугольник для ввода текста. Очевидно, его верхняя грань должна зависеть от значения свойства Layout. Также, этот прямоугольник может определить и границы отступа от краев для ввода текста.
Далее, немного поковыряв исходники, находим виртуальный метод:
Он вызывается в любом случае, что для DoubleBuffered, что без него. Его вызов будет осуществлен при наличии csCustomPaint в ControlState компонента, после всех значимых отрисовок компонента. Его мы будем использовать для отрисовки TextHint.
Практика
Не буду останавливаться на некоторых, думаю, не особо интересных деталях реализации.
Для начала, у нас появляются следующие дополнительные свойства:
И основные моменты.
1. Объявление класса безусловно таково:
2. В конструкторе пишем строку:
3. Назначение прямоугольник ввода:
4. Расчет прямоугольника ввода:
5. Что такое TrueWordWrap в вызове функции CalcHeight выше. Это метод, которые возвращает истинное значение переноса строк для TMemo, которое зависит на самом деле от ряда параметров:
6. Где происходит вызов перерасчета и назначения прямоугольника ввода:
7. Назначение свойства TextHint чрезвычайно просто, но с учетом того, если кому-то вдруг захочется регистрировать компонент:
9. Чтобы облегчить «подмену» стандартного TMemo на наш, есть следующий метод. Он забирает все основные события и свойства у переданного указателя на TCustomMemo. При выставленном флаге AWithFree, уничтожает экземпляр старого и становится на его место. Т.е., если в коде все завязано на «старый» TCustomMemo, ничего страшного не произойдет. Все будет работать с новым экземпляром, как со старым, за исключением тех моментов, когда будут использованы свойства, про которые вы и так в курсе, и обращаться к ним все равно придется как к TxIPMemo:
Как использовать
Предположим, что уже есть компонент TMemo на форме, которое Вы либо используете в динамике, подобно как выше-вкратце-описанные редакторы, либо статический компонент, созданный в дизайне. Это все не важно.
1. Объявляем где-то следующим образом:
2. В событии OnCreate формы, либо в её конструкторе, пишем следующее:
За уничтожение экземпляра класса не волнуемся – он будет гарантированно уничтожен в деструкторе.
3. Возможно, в том же обработчике FormCreate пишем:
Тем самым забирая свойства и события у Memo1, и уничтожая его, становясь на его место.
4. Собственно, и все. Назначаете необходимые свойства нашему компоненту. И пользуем TMemo с возможностями вертикального выравнивания, отступов (которые могут быть и отрицательными), приглашения для пользователя при пустом Text.
Окно демо-приложения
Эпилог
В исходниках, ссылка на которые ниже, все используемые в тексте вспомогательные функции представлены.
Версия компилятора определяется <$I>подключаемым файлом pro_param.inc.
Т.к., в силу специфики работы, придерживаюсь концепции один модуль – разные версии, представленные исходники компилируются в Delphi 7, Delphi XE 7 и Delphi 10.1 Berlin. По той простой причине, что Delphi 7 у меня куплен, а Delphi 10.1 Berlin – бесплатная лицензия для коммерческих продуктов. А заказчик в последнее время хочет быть абсолютно «белым». Поэтому не использую никаких платных библиотек.
Надеюсь, материал поможет в ситуациях разной степени тяжести.
Инструменты пользователя
Инструменты сайта
Боковая панель
Навигация
Загрузки всякие
Связь
Содержание
Нововведения по версиям Delphi
TCustomHint
Все контролы могут использовать свойство CustomHint, которое ссылается на потомка TCustomHint.
В этой статье даны скриншоты новых компонент под XP и Вистой.
Padding and Margin Properties
All VCL controls now have Padding and Margin Properties. These two properties work much like they do in HTML, with Padding describing the length in pixels that a container will place controls within itself. The Margin property describes the number of pixels outside of a control that will be given space.
См. также свойство AlignWithMargins
TDockTabSet
TTaskDialog
The Hello World of a Task Dialog:
Можно вставить проверку на предыдущие версии Windows (XP), которые не поддерживали API TaskDialog:
В противном случае показывать MessageBox.
Custom Buttons Можно добавлять свои кнопки:
Command Links
Нужно выставить флаг tfUseCommandLinks. Также можно покнопочно установить свойство CommandLinkHint
Скрытие технических деталей от пользователя
Свойства ExpandedText и ExpandedButtonCaption позволяют добавить свернутый текст в нижнюю панель диалога:
Если установить флаг tfExpandFooterArea, то текст будет показан в футере. Если установить флаг tfExpandedByDefault, то текст сразу будет показан в развернутом виде.
Custom Icons
Hyperlinks
Можно писать гиперссылки в Text, Footer и ExpandedText
Обработчик клика по ссылке следует написать в событии OnHyperlinkClicked.
Footer
Или использовать флаг tfUseHiconFooter и свойство CustomFooterIcon для кастомной иконки
Checkbox
Radio Buttons
Прогрессбар и callback
Установить флаг tfCallbackTimer и описать событие OnTimer (срабатывает 5 раз в секунду)
TButtonedEdit
TLabeledEdit
TLinkLabel
TCategoryPanelGroup
Появилась в delphi 2009
Как убрать рамку?
Для TCategoryPanel установить protected property BevelOuter в bvNone.
Для TCategoryPanelGroup можно убрать бордюр в процедуре CreateParams следующим образом:
Params.Style := Params.Style and (not WS_BORDER);
TGridPanel
Появилась в Delphi 2006.
TGridPanel implements a grid panel control in which each component is placed within a cell on a grid. With a grid panel, a developer can specify the number of rows and columns on the panel, then each component is placed into the next available cell in the grid, regardless of where it is placed with the mouse.
В зависимости от свойства ExpandStyle будут добавляться новые строки (AddRows) или новые столбцы.
Это могут быть кнопки калькулятора, например.
Можно одну панель вставить в другую (TGridPanel в TGridPanel или TFlowPanel в TGridPanel). Свойства Align, Anchor и Constraint тоже никто не отменял.
The tricky part is setting the percentages. If you have a grid with two columns which are currently set to 50% each, and then set the first column to 25%, you’ll find that the widths for the two columns are actually set to 33.33% and 66.67%, rather than 25% and 75% which is probably what you wanted.
Here’s the problem. When you set the width of the first column to 25%, the TColumnItem object notifies the collection that the item has changed, and the collection then notifies the grid panel that the collection (not a particular item) has changed. At this point the grid panel can see that one column is set to 25% and the other is set to 50% but it doesn’t know which one changed. So how does it arrive at 33.33%? It divides a column’s width by the sum of the percentage for all columns. So for column one this would be 25 / (25+50) = 33.33, and for column two this is 50 / (25+50) = 66.67.
If you keep entering 25% over and over again the end result will eventually approach 25%. This is rather awkward but it does work.
Есть способ попроще:
Аналогично бороться с высотой строк в коллекции RowCollection.
Чтобы отменить центрирование и масштабирование контролов, надо использовать свойство Anchor. Причем свойства контролов Top и Left в инспекторе исчезают.
— все контролы будут масштабироваться при ресайзе:
TFlowPanel
Появилась в Delphi 2006.
TFlowPanel is a TPanel descendent that allows controls placed within it to «flow» together depending on the FlowStyle property. The default value is fsLeftRightTopBottom, meaning controls in the TFlowPanel flow from the upper left to the lower right.
В дизайн-тайм перестаскивание контролов мышкой не работает, можно только вырезать контрол и вставить в самый конец, что довольно муторно, если надо переставить много контролов. Но если присмотреться, то можно увидеть в Инспекторе свойств появлением нового магического свойства ControlIndex у любого контрола, внедрившегося в TFlowPanel. Вот его и надо править для переупорядочивания контролов на панели.
Свойство AutWrap, установленное в false, запрещает многострочное размещение контролов на панели.
TButtonGroup
TCategoryButtons
The control can contain any number of categories, and each category can contain any number of buttons. The categories can be moved at runtime if desired, and individual buttons can be moved or copied between categories as well.
TTabSet
TEdit
Delphi 2005
Wildcard in uses statement allowed
Delphi 2006
FastMM is the default memory manager
final keyword for virtual methods
static methods and properties
strict private/protected visibility keyword
Delphi 2010 и ранее
Константы, переменные и типы внутри класса
Вложенные классы: теперь классы можно объявлять внутри классов, цель избежать конфликта имен.
Exit с параметром
значение должно быть того же типа, что и возвращаемое значение функции.
Class and Record Helpers
Предназначены для добавления новой функциональности в существующий класс (или запись) введением новых методов в класс (запись) без наследования.
Перегрузка операторов
Дженерики
Параметрический полиморфизм. Явление, когда компилятор сам вырабатывает соответствующие варианты кода на основании обобщенного алгоритма
Конкретные реализации алгоритмов можно посмотреть в модуле Generics.Collections, где есть TArray, TList, TStack, TQueue, TDictionary, TObjectList, TObjectQueue, TObjectStack, TObjectDictionary и TEnumerator, способные работать с разными типами данных.
Обобщенные алгоритмы экономят время программиста, сокращая только его код, но для каждого типа (для каждой комбинации типов) всегда генерируется новая версия алгоритма (поэтому размер скомпилированных программ увеличивается).
Записи стали объектами
И теперь имеют свои методы, свойства и конструкторы.
Сравнить две записи на равенство с помощью оператора:
Абстрактные классы
Разрешены полностью абстрактные классы (раньше допускались только конкретные методы), содержащие объявления методов для дальнейшего их перекрытия в потомках.
strict private и strict protected
Строгое private — метод или свойство для класса и невидимое никому, вне класса даже в рамках текущего юнита.
Строгое protected — методы в этой секции будут видимы самому классу и его наследникам.
Пример. Некоторым классам необходимо иметь доступ к закрытым элементам друг друга (например, TCollection — коллекция, TCollectionItem — элемент коллекции).
По этой причине во многих языках существует понятие класса, дружественного (friend) к другому классу (в некоторых языках дружественными могут быть и функции). Дружественный класс будет иметь полный доступ к членам другого класса, даже если они закрыты для прочего стороннего кода.
В Delphi нет специальных языковых конструкций для выделения дружественных классов. Вместо этого здесь используется иной механизм. А именно: любые классы в одном модуле (unit) автоматически считаются дружественными друг к другу и могут обращаться к закрытым элементам друг друга.
Поэтому в примере выше TCollection и TCollectionItem являются дружественными, поскольку расположены в одном модуле
Однако на практике критерий дружественности крайне редко выступает в качестве основного критерия для распределения классов по юнитам. Чаще модуль объединяет логические связанные классы. При этом может получаться, как много не связанных друг с другом (в плане дружественности) классов в одном модуле, так и дружественные классы, разнесённые по разным модулям (если такие классы принадлежат разным логическим компонентам).
Сужение дружественности: strict
Понимая, что не всякий класс в модуле должен быть дружественным к другим классам этого же модуля, разработчики Delphi ввели новое ключевое слово strict, которое в комбинации с private и protected позволяют ограничивать доступ к членам класса для других классов в этом же модуле. Так, к примеру, к элементам класса в strict private не может получить доступа ни один код вне этого же класса, даже если этот код находится в том же модуле. Аналогично, доступ к элементам strict protected будут иметь только наследники этого класса, но не другие классы, даже если они будут находится в том же модуле.
Расширение дружественности: хак
Со второй проблемой (дружественные классы в разных модулях) несколько сложнее. В настоящее время Delphi не предоставляет никаких специальных языковых конструкций для разрешения этого конфликта. Вы не можете объявить классы дружественными друг другу, если они находятся в разных модулях. Поэтому программисту придётся использовать обходные пути.
Первый путь — самый простой и прямолинейный. Он заключается в объявлении пустого класса-наследника в том же модуле, где нужно сделать дружественный класс.
Объявляя класс-наследник (TDummySomeClass), мы делаем доступными ему все protected члены (и не важно, в каком модуле они расположены). А то, что этот класс-заглушка объявлен именно в модуле второго класса (TAnotherClass), сделает эти два класса дружественными, что и даст доступ к закрытому полю protected FItem.
Разумеется, если у вас нет контроля над TSomeClass, то вы не сможете изменить область видимости FItem (изменить private на protected).
Второй вариант разрешения конфликта — использование интерфейсов. Интерфейс (interface) — это набор методов, которые можно произвести с объектом. Иными словами, это как бы «копия» public секции объекта. Интерфейсов может быть много поддержано у одного объекта. Любой внешний код может запросить у объекта любой его сервис, если он знает его «имя» (= GUID).
Таким образом, класс TSomeClass может реализовывать один или несколько интерфейсов, предназначенных для его дружественных классов, расположенных в других модулях. Чтобы подчеркнуть внутреннюю направленность интерфейсов, их можно вынести в отдельный недокументированный модуль. [при чем тут дружественность? методы доступны всем, не только дружественным классам]
Как снять выделение с компонента Tedit при создании формы?
События для формы при создании нового компонента
Здравсвуйте. Создал новый компонент на основе Tbutton. TnewButton = class(TButton). Для него.
Как снять выделение при Edit1.SetFocus?
как снять выделение при Edit1.SetFocuse. procedure TForm1.Button1Click(Sender: TObject); begin.
Как оставить нетронутым выделение текста в Tedit при нажатии курсорных клавиш?
Всем здравствуйте. В окне с именем Edit1 по умолчанию находится текст «Edit1». Делаем так.
Снять выделение при клике на jRadioButton
нужен метод который снимает выделение с jRadioButton при клике на другой jRadioButton
Подсказки внутри поля не реализовывались в стандартных Windows-контролах, поэтому и в VCL их нет
Решение
Подсказки внутри поля не реализовывались в стандартных Windows-контролах, поэтому и в VCL их нет
Ошибаетесь, внутри поля тоже можно подсказки делать.
Добавлено через 8 минут
Вернее вы правы. Чтобы подсказка была внутри поля надо написать в свойство TextHint
а если просто Hint то это и есть наша всплывающая подсказка
Добавлено через 2 минуты
Решение
Добавлено через 1 минуту
Снять выделение с элемента ListView при потере фокуса
Доброго времени суток! На форме есть элемент listView. Допустим, я выбираю в нем некий элемент, а.
ListBox: снять выделение с элемента при повторном нажатии на него
Подскажите как можно снять выделение с ListBox, если я нажимаю на этот же индекс?
Как снять выделение QToolButton?
Есть QToolButton с выпадающим списком. 1) При получении фокуса указателя мыши она становится.
Как снять выделение с DBLookupListBox?
Как снять выделение с DBLookupListBox? Не нашел в инете ответа на свой вопрос..только просто на.
Как очистить DBEdit при создании формы?
DBEdit при создании формы показывает содержимое поля базы (*.mdb). Как очистить DBEdit при создании.
Ошибка при создании компонента TIBTransaction
Сегодя весь день сражаюсь с ibx, lazarus, ibexpert. После того, как наконец удалось установить ibx.