The second (and third) messaging option provided by Delphi is to use TThread.Queue or TThread.Synchronize. As they are just variations of the same concept, I'll describe them together.
Unlike Windows messages, which can be sent from the main thread to a background thread if you write the background thread in an appropriate way, Queue and Synchronize don't provide any support for that. You can only use them to send messages to the main thread.
The beauty of Queue and Synchronize is that they are completely platform independent. Delphi's RTL makes sure that you can use them with VCL or FireMonkey on any of their supported platforms.