Элемент управления, чтобы удалить себя из контейнера управления - PullRequest
4 голосов
/ 29 марта 2011

Существует контейнерный элемент управления, TScrollBox, который является родительским элементом управления для нескольких элементов.

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

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

Я на самом деле знаю пару вариантов:

  • таймер с небольшим интервалом (который запускается нажатием кнопки);
  • скрытая внешняя кнопка (на которую отправляются сообщения о нажатии и отклонении мыши);
  • пользовательский обработчик сообщений формы.

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

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

Ответы [ 2 ]

4 голосов
/ 29 марта 2011

Обычный подход - отправить сообщение в элемент управления, который должен быть освобожден. Посмотрите, как TForm.Release реализован, например. На самом деле я не вижу причин, по которым вы даже не можете повторно использовать сообщение CM_RELEASE.

Смысл публикации сообщения заключается в том, что он отправляется в конец очереди и обрабатывается только после завершения обработки любых синхронных сообщений (т.е. доставленных SendMessage). Это позволяет избежать вызова методов для объекта после его освобождения, что, очевидно, является ошибкой, о которой вы хорошо знаете.

2 голосов
/ 29 марта 2011

Во-первых, я бы посоветовал вам написать собственный элемент управления, который наследуется от TScrollBox, и предоставить экземпляр и удаление суб-элемента управления как функцию внутри этого поля прокрутки, а не что-то сделанное «там, где открыто», в ваша форма. Этот код будет идти в своем собственном модуле, и только открытые его элементы будут видны снаружи. Это просто объектно-ориентированные основы.

Во-вторых, если вы удаляете (удаляете) элементы управления из поля прокрутки, таймер является просто источником хаоса. Возможно, что если вы также вложили в подклассы каждый элемент управления, помещенный в этот контейнер, вы могли бы использовать механизм, используемый TForm.Release (он отправляет им сообщения CM_RELEASE), и реализовать CM_RELEASE таким образом, чтобы элементы управления удаляли себя при отправке этого сообщения. Однако я нахожу это уродливым, за исключением случая редактирования элементов управления, которые разрушаются, когда теряют фокус.

Я бы напрямую удалил эти методы, не прибегая к таймеру, путем создания подкласса как класса TScrolLBox, так и любых других классов, которые я хочу добавить в него, а затем, чтобы удаление элемента управления обрабатывалось родительским объектом ( TScrollBox), а не путем каких-либо внешних манипуляций.

...