Если можно присвоить, значит и "отсвоить" как-то...

Тема в разделе "Delphi - FAQ", создана пользователем DblM, 27 июл 2006.

Статус темы:
Закрыта.
  1. DblM

    DblM Гость

    в проДЖекте есть функция:

    procedure TForm1.BitBtn1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
    //всякая всячина
    end;

    создаю кнопку:

    ... var b:TBitBtn;
    begin b:=TBitBtn.Create(form1);
    b.OnMouseUp:=BitBtn1MouseUp; //присваиваю ей ту функцию...

    а как теперь удалить её? програмно...

    пробовал:
    там при создании -> i:=b.ComponentIndex;
    а где надо -> (Components as TBitBtn).Action.Free;
    функция всё равно остаётся...

    подмагните кто моГёт)
     
  2. Kmet

    Kmet Well-Known Member

    Регистрация:
    25 май 2006
    Сообщения:
    1.017
    Симпатии:
    1
    хм, не уверен, но если по аналогии с Си, то b.OnMouseUp:=nil
     
  3. DblM

    DblM Гость

    это было первое что я попробовал... nil и null... ))
    он мне туеву кучу ошибок панавыдавал...
    а ща чёто сработал))
    наверно компиллер делфи связан с этим форумом и выдаёт ошибки пока на эту тему не будет задан вопрос..))
     
  4. garrymax

    garrymax Гость

    Ставить нулевой адрес функции на обработку зарегистрированого события нельзя - потому и ругался.
    Если можно убить саму кнопку (умрет и реакция на событие), то проще:
    Код (Text):
    b.Free;
    Если только реакцию мышки (кнопка еще нужна), то проще подставить функцию-заглушку:
    Код (Text):
    procedure TForm1.NotOnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin {ничего не делать}end;
    ......
    b.OnMouseUp:=NotOnMouseUp;
    Более цивилизованые способы (например ActionList) менее эффективены по размеру кода, а удалить функцию, как машинный код, можно только затиранием самой программы :ph34r:

    Да, еще забыл
    Код (Text):
    b.OnMouseUp:=nil;
    если компелятором не проверяется, то по логике не правильный. По крайне мере. в старых версиях у меня такое не работало.
     
  5. Kmet

    Kmet Well-Known Member

    Регистрация:
    25 май 2006
    Сообщения:
    1.017
    Симпатии:
    1
    Интересно почему? Как раз по логике (скорее по аналогии с Си) nil может быть приведен к любому типу указателя.
     
  6. garrymax

    garrymax Гость

    Не путай Сишную ссылку на функцию и что-то вроде hook's - у дельфи свои способы, просто давно об этом читал и до конца не помню, но смысл приблезительно такой (попробую своими словами и сразу извиняй, что коряво):
    Форма и остальное (кнопка, это тоже окно) не чисто APIшная и события OnMouseUp и другие, это не отдельный код, который вставляется в функцию окна, а хук, который обрабатывется отдельно. Если этот событие как-бы объявлено, то все равно будет вызов.
    Что-то в этом роде.
    Кстати, попробуй в Си приписать какой нибуть функции нулевой адрес - что, она сразу перестанет вызываться? Скорее: "Приложение выполнило недопустимую оппера....... - и все такое на счет недопустимой адресации...
    По этому и неправильный. Скорее всего компилятор при виде такого присваивания убирает событие.
     
  7. DblM

    DblM Гость

    да всё получилоссь))

    а функция была объявлена никому.. а потом уже присвоена кнопке..[после запуска программы] так что nil вполне прокатит...
    скорее это не хук а какая-нибудь адресация и всё..)
     
  8. zubr

    zubr Гость

    Мда... откровение, однако, насчет хука.
    В общето OnMouseUp - это сообщение Windows - WM_LBUTTONUP, которое обрабатываются процедурой окна, которое в данном случае является кнопкой. А OnMouseUp - это часть кода (если он есть <>nil), VCL вставляет в процедуру окна.
     
  9. Kmet

    Kmet Well-Known Member

    Регистрация:
    25 май 2006
    Сообщения:
    1.017
    Симпатии:
    1
    Функции можно присвоить? Покрайней мере не С\С++. Да имя функции может автоматически разыменовываться компиляторомк указателю на первую инструкцию функции, но присвоить функции что либо это вряд ли).

    Я коненчно не утверждаю, но почему то не очень себе представлю как имеено ВЦЛ вставяет эту часть кода. Обджект поскаль не поддерживает ни шаблонов ни каго либо другого средства метапрограммирования.


    Как мне кажется OnMouseUp, как и любое другое событие в конечном итоге представляет собой указатель на функцию(если более точно указатель на функцию-член), просто в обджект паскале такие указатели определяет достаточно хитро, что вроде type ONMOUSE:procedure (.....) of Object. За синтакс не уверен. И оконная процедура на соответсвующие сообщение, по указателю вызывают функцию отвечающую за обработку события.
     
  10. garrymax

    garrymax Гость

    Читай внимательнее: что-то вроде hook's


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


    OnMouseUp - это отдельная функция (ассамблерное CALL и RET) - она и в теле программы на паскале вызывается как процедура - имеет параметры, которые в стек загоняются. Даже по логике, эти параметры будут мешать вкалачиванию кода в функцию окна, а если их описывать, как глобальные переменные, то конечный код был бы тогда ну очень большим.
     
  11. Kmet

    Kmet Well-Known Member

    Регистрация:
    25 май 2006
    Сообщения:
    1.017
    Симпатии:
    1
    Для: garrymax

    Куда что подставить?!

    Сюда что ли?!

     
  12. zubr

    zubr Гость

    Вроде Володи. Ты хоть знаешь что такое хук. Нахрена окну устанавливать хук на сообщения, когда у него есть своя процедура обработки сообщений. Представь, если каждое окно Windows (кнопки, Editы, Memo и т. п.) будет устанавливать хук - система даже загрузится не сможет.

    Опять откровение. Да возьми и открой Controls.pas, да посмотри где вызывается OnMouseUp. В банальном обработчике сообщения WM_LBUTTONUP:
    Код (Text):
    procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;

    procedure TControl.MouseUp(Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y);
    end;

    procedure TControl.DoMouseUp(var Message: TWMMouse; Button: TMouseButton);
    begin
    if not (csNoStdEvents in ControlStyle) then
    with Message do MouseUp(Button, KeysToShiftState(Keys), XPos, YPos);
    end;

    procedure TControl.WMLButtonUp(var Message: TWMLButtonUp);
    begin
    inherited;
    if csCaptureMouse in ControlStyle then MouseCapture := False;
    if csClicked in ControlState then
    begin
    Exclude(FControlState, csClicked);
    if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
    end;
    DoMouseUp(Message, mbLeft);
    end;
    То что у тебя в голове каша, твои проблемы, но зачем молодежи х**ню впаривать.
     
  13. garrymax

    garrymax Гость

    Zubr, заметь - без мата, возможно тебе это тоже будет откровением, но
    является описание функций (процедур с возвратом), а не вставляемым кодом. Если не доходит, то возьми любую книгу по структурированному программированию и почитай разницу.
    А на счет "вроде Володи": Я уже боюсь упоминать о назначении WndProc - может так статься, что это будет СТРАШНЫМ ОТКРОВЕНИЕМ ДЛЯ ТЕБЯ, но если ты найдешь более подходящее описание подобным ответвлениям, то мне останится снять шляпу перед таким полиглотом. А пока будешь изучать основы Windows API и вообще логику построения программ Windows-приложений на Дельфи, то каша будет в твоих ответах.
    Если не достаточно, хотя вопросивший уже закрыл тему, то могу еще много довыдов привести - у меня еще два дня без работы есть.
     
  14. zubr

    zubr Гость

    Для: garrymax
    Это ты 2 дня думал, чтобы опять нести бред.
    Вообще то выше приведенные процедуры - это процедуры без возврата значения. Учи паскаль.
    Я тебе ничего доказывать не буду, имхо это бесполезное занятие.
    Все, хватит флеймить. Тема закрыта.
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей