Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  06:28[Войти] | [Зарегистрироваться]
Ответ на вопрос № 72459

Вопросы с аналогичными сообщениями об ошибках:
  • Incompatible types (104)

    24-08-2009 12:40
    Коллеги!
    Извините за тупой вопрос...
    Пробую назначать обработчик событий какому-либо компоненту. В случае нотации


    Button.OnClick:= Control_OnClick;
    ...
    procedure Control_OnClick(Sender: TObject);
    begin
        //код процедуры
    end;


    выводится сообщение компилятора "Incompatible types: method pointer and regular procedure"

    Если же процедура описана как метод формы


    Button.OnClick:= Control_OnClick;
    ...
    procedure TForm1.Control_OnClick(Sender: TObject);
    begin
        //код процедуры
    end;


    то все получается. Как можно назначить событию произвольный обработчик, в т.ч. из другого Unit'а?
    Почему спрашиваю: хочу перенести часть кода обработчиков в отдельный модуль, чтобы не мозолил глаза.
    Спасибо за ответы.

    [+] Добавить в избранные вопросы

    Отслеживать ответы на этот вопрос по RSS

    Ответы:


    Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
    Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

    26-08-2009 06:37 | Сообщение от автора вопроса
    Коллеги, всем спасибо за ответы, особенно 777, Александру Алексееву и, конечно, неподражаемому Geo, весьма терпеливо пытавшемуся прочитать мои мысли.
    Сделал, в общем, так, как советовал 777: создал класс, а его методами сделал те самые обработчики событий, после чего все начало присваиваться, как положено.
    Для чего это нужно: делаю проект, в котором реализованы скрипты, реагирующие на события. При этом события назначаются так:


    Events:= TEvents.Create(Self, memoScript.Lines);
    ...
    Button.OnClick:= Events.OnClick;
    ...
    procedure TEvents.OnClick (Sender: TObject);
    begin
        UpdateScript;
        FActiveScript.Run(TComponent(Sender).Name + '_OnClick', [Sender]);
    end;


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

    25-08-2009 01:55
    Ну, я (как обычно) вылезу с перпендикулярным поворотом темы обсуждения. А зачем, собственно, нужно так делать?

    Вот автор говорит, что "хочу перенести часть кода обработчиков в отдельный модуль, чтобы не мозолил глаза". А почему они мозолят глаза?

    Первое, что мне приходит в голову (из опыта общения на Круглом Столе), автор пытается реализовать сложное поведение какого-то контрола. Ну, что-то вроде, на PaintBox что-то сложное рисуется, каким-то образом реагирует на нажатия мышки и т.п. В результате, модуль с формой оказывается загажен обработчиками событий, реализующих специфику поведения отдельного контрола, а не самой формы (как это должно быть). В этом случае имеет смысл подумать не о переносе обработчиков в другой юнит, а о включении этих обработчиков в сам класс. То есть, взять имеющийся контрол, вывести из него потомка, а вэтот потомок включить реализацию того самог специфического поведения. Звучит для человека неподготовленного страшновато, но на деле не так страшен черт, как его малюют ;-)

    Второй вариант, который ямогу домыслить, заключается не то, чтобы в мозолинии глаз, а в том, что разные формы одинаково выполняют обработку каких-либо событий (например, куча диалогов со сходными принципами обработки). Как это ни странно, но тут тоже можно подумать о том, чтобы вывести свой базовый класс, от которого будут наследоваться однотипные окна, включив общую логику обработки внутрь класса. А можно пойти по пути разработчиков VCL, которые создали специальную функцию, создающую и показывающую диалоговое окно (см. юнит Dialogs). Можно поступить так же, но сохранив возможности визуального проектирования: создать визуально базовую форму для диалогового окна, а классу этой формы дописать методы, которые по переданным значениям будут видоизменять эту форму (типа, тексты заполнять, кэпшно подписывать, иконку менять и т.п.).

    Если все эти обработчики связаны некоторым общим содержательным смыслом, красиво выглядит решение с созданием специально класса, где все обработчики являются классовыми методами (в стиле классов Exception).

    Ну, и последнее. Может так оказаться, что требуемые обработчики действительно реализуют логику работы формы (как это и должно быть), но они слишком громоздкие, плюс возможны какие-то пересечения (какие-то обработчики могут использоваться в разных формах). В этом случае считаю более правильным вариант, предложенный Сергеем Дупликом: процедуры выносите в отдельный юнит и вызывайте их из стандартных обработчиков событий. Это поможет Вам легче читать логику работы формы: вы по бработчикам сразу видите, что обрабатывается, а заглянув в реализацию понимаете, какая внешняя функция для обработки используется.

    P.S. Во всех случаях нестоятельно рекомендуется грамотно продумывать имена (то есть никаких TDummy). Это существенно повысит читаемость кода.

    P.P.S. Если уточните, что именно Вы хотите сделать, то можете получить более короткий и конкретный вариант ответа, вместо расплывчатого эссе обо всем на свете ;-)

    24-08-2009 22:55
    хочу перенести часть кода обработчиков в отдельный модуль
    переносите в процедуры и вызывайте их из обычных обработчиков.

    24-08-2009 17:45
    777:
    >>> Сделайте их методами прямого потомка TObject, описанного в том отдельном модуле.

    Присоединяюсь...

    >>> Если не ошибаюсь, то их даже можно описать как классовые методы (class procedure), и тогда не понадобится создавать экземпляр этого класса (если обращения к его полям не требуется).

    А вот в этом нет никакой необходимости. См. мой комментарий от 23-07-2009 18:27 по ссылке: http://www.delphikingdom.com/asp/articles_forum.asp?ArticleID=1406

    Exelord:
    В этом случае класс создавать не придётся:
    procedure TForm1.FormCreate(Sender: TObject);
    var m:TMyMethod;
    begin
    form1.OnClick:=m.Click;
    end;


    Я обычно поступаю так:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      OnClick := TКлассОбработчика(nil).Click;
    end;

    В этом случае в качестве Self просто будет передан nil. Это хорошо ещё тем, что при попытке обращения к Self в том обработчике сразу же получим исключение (и т.о. обнаружим ошибку в коде).

    Советую автору прочитать мой комментарий по приведённой ссылке (а также другие комментарии и саму статью, но очень критически). Я там привёл пример назначения всем TEdit, расположенным непосредственно на форме, обработчиков, благодаря которым каждый TEdit подсвечивается при входе в него и восстанавливает обычный цвет при выходе. Рекомендую также посмотреть ссылки:
    »вопрос КС №62879«
    »вопрос КС №55213«

    P.S. Все приводимые мной примеры - рабочие.

    24-08-2009 13:29 | Комментарий к предыдущим ответам
    Александр Алексеев
    Так ещё лучше :).

    24-08-2009 13:28
    В этом случае класс создавать не придётся:


    procedure TForm1.FormCreate(Sender: TObject);
    var m:TMyMethod;
    begin
    form1.OnClick:=m.Click;
    end;


    24-08-2009 13:26
    Например:

    unit Unit2;

    interface

    type
      TDummy = class
        class procedure Button1Click(Sender: TObject);
      end;

    implementation

    class procedure TDummy.Button1Click(Sender: TObject);
    begin
      // do your work here
    end;

    end.



    unit Unit1;

    interface

    ...

    type
      TForm1 = class(TForm)
      ...
      end;

    ...

    implementation

    uses
      Unit2;

    ...

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Button1.OnClick := TDummy.Button1Click;
    end;

    ...

    end.


    24-08-2009 13:24 | Комментарий к предыдущим ответам
    Простите, вышла ошибка:


    TMyMethod = class
      procedure Click(Sender:TObject);
      end;



    24-08-2009 13:24 | Комментарий к предыдущим ответам
    To Exelord:

    TMyMethod = class
      Click: procedure(Sender:TObject);
    end;

    наверно все же имелось в виду

    TMyMethod = class
      procedure Click(Sender:TObject);
    end;

    24-08-2009 13:22
    Как можно назначить событию произвольный обработчик, в т.ч. из другого Unit'а?
    Почему спрашиваю: хочу перенести часть кода обработчиков в отдельный модуль, чтобы не мозолил глаза.


    Сделайте их методами прямого потомка TObject, описанного в том отдельном модуле. Если не ошибаюсь, то их даже можно описать как классовые методы (class procedure), и тогда не понадобится создавать экземпляр этого класса (если обращения к его полям не требуется).

    24-08-2009 13:20
    Button.OnClick - TNotifyEvent, а
    TNotifyEvent = procedure(Sender: TObject) of object;
    Т.е. вы можете сделать так:
    TMyMethod = class
      Click: procedure(Sender:TObject);
    end;

    Добавьте свое cообщение

    Вашe имя:  [Войти]
    Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
    контрольный вопрос:
    Однажды, в студеную зимнюю пору я из лесу вышел, был сильный ЧТО?
    в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
    Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
    Тип сообщения:
    Текст:
    Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Вопросы с аналогичными сообщениями об ошибках:
  • Incompatible types (104)


    Страница избранных вопросов Круглого стола.
  •   
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования