Search code examples
delphiinno-setuponchange

What does it mean WizardForm.TypesCombo.OnChange(WizardForm.TypesCombo) in Inno Setup?


In documentation for TComboBox = class(TCustomComboBox) there's this:

property OnChange: TNotifyEvent; read write;, where TNotifyEvent = procedure(Sender: TObject);.

Judging from that OnChange has no parameters, only the returned value. In Delphi OnChange event has the Sender: TObject parameter. Why is that allowed to type the following then and what does it mean if it's not the same as Sender: TObject?

WizardForm.TypesCombo.OnChange(WizardForm.TypesCombo)

(taken from Inno Setup Remember selected setup type when Uninstallable=no)


Solution

  • WizardForm.TypesCombo.OnChange is an event handler that is called by VCL (Delphi GUI library used to build Inno Setup), when user changes the selected item in TypesCombo. In Inno Setup source code that event handler is assigned to TWizardForm.TypesComboChange method. That implementation updates the selected setup components based on the newly selected setup type.

    But if you change the selected setup type by assigning WizardForm.TypesCombo.ItemIndex in Pascal Script code in your Inno Setup script, the TWizardForm.TypesComboChange won't get called. So the setup components won't get updated and the installer wizard GUI will get into an inconsistent state. To force the setup component selection update, you have to trigger the call to the TWizardForm.TypesComboChange manually in your Pascal Script code. You cannot call the method directly, as its a private method, not exposed in Inno Setup Pascal Script. But as the WizardForm.TypesCombo.OnChange holds a pointer to the method, you can (and should) call it via the pointer.


    WizardForm.TypesCombo.OnChange is of type TNotifyEvent so, it has the same amount of parameters. The TNotifyEvent event handler type declaration specifies that the handler takes one TObject argument. That argument will contain pointer to the component for which the event handler is called, when it is triggered by VCL in a response to a user action. That's for the case, the event handler is shared by multiple components. What is not the case here, and the TWizardForm.TypesComboChange actually does not use the argument value at all. But for consistency and future compatibility, it's good to call it the way VCL would – so with TWizardForm.TypesCombo.

    And that what that code does:

    WizardForm.TypesCombo.OnChange(WizardForm.TypesCombo);
    

    As the WizardForm.TypesCombo.OnChange equals to WizardForm.TypesComboChange, the above code is the same as calling:

    WizardForm.TypesComboChange(WizardForm.TypesCombo);