c++firemonkeyc++builder-xe8

How to override on click event of custom Firemonkey control


I am attempting to create a custom Firemonkey control which inheirts from the TListView control. I want to add some functionality to the control which is automatically executed when a user clicks on the control. Therefore, my goal is NOT to specify an OnItemClick method on my control's form, but rather add functionality directly into the control itself.

I am struggling to comprehend what I need to do in order to tap into the on click handler for TListView. In my head, I imagine my solution would look something similar to this pseudo code:

//somewhere in the base TListView code
void __fastcall TListView::ClickHandler()
{
    //logic for handling a click on the list view
}

//somewhere in my custom list view control
void __fastcall TMyListView::ClickHandler()
{ 
    TListView::ClickHandler(); //call base click handler so all the normal stuff happens

    //my additional logic goes here
}

However, I cant seem to find anything in the documentation about what method I should attempt to override, or how I should be going about this at all.

I did find this information about calling the 'Click-event' handler. I set up a simple example like so:

void __fastcall TFmListView::Click()
{
    ShowMessage("This is the control's click");
}

This works fine, however according to the documentation:

If the user has assigned a handler to a control's OnClick event, clicking the control results in that method being called.

Therefore, any additional logic I placed in the Click() method of the control would be lost if one of the control's on click event properties was set.

What is the proper way to go about extending the functionality of what happens when a custom control is clicked?


Solution

  • Here is a C++Builder solution for you.

    Here is the class interface and implementation:

    class TMyListView : public TListView
    {
    protected:
        virtual void __fastcall DoItemClick(const TListViewItem *AItem);
    };
    
    ...
    
    /* TMyListView */
    
    void __fastcall TMyListView::DoItemClick(const TListViewItem *AItem)
    {
        // write here the logic that will be  executed
        // even if the OnItemClick handler is not assigned
        ShowMessage("Internal itemclick");
    
        // call the OnItemClick handler, if assigned
        TListView::DoItemClick(AItem);
    }
    

    Then you declare an instance of the TMyListView class and the necessary event handler in the form declaration:

    TMyListView *LV;
    void __fastcall MyOnItemClick(const TObject *Sender, const TListViewItem *AItem);
    

    And here is the implementation of the event handler and LV creation:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        LV = new TMyListView(this);
        LV->Parent = this;
        LV->Position->X = 1;
        LV->Position->Y = 1;
        LV->Width = 100;
        LV->Height = 100;
    
        LV->Items->Add()->Text = "111";
    
        LV->OnItemClick = &MyOnItemClick;
    }
    
    void __fastcall TForm1::MyOnItemClick(const TObject *Sender, const TListViewItem *AItem)
    {
        ShowMessage("Assigned itemclick"); //or any other event handler action
    }
    

    Both messages will be shown.