That is not true. On Windows, any thread can have its own UI and its own message loop, Microsoft puts no restriction on that at all. And any thread can send messages to a window in another thread.
But even with that you are extremely limited in what is possible, as when you want to for example create any control (like a Window, Button, etc.) this control is restricted to the message queue of the thread that called CreateWindow. Meaning sure you can create a button in another thread, when that thread has a message queue, but as soon as that thread stops serving that queue, that control seizes to function. So you can't create (or destroy for that matter) controls of other threads.
So you aren't modifying the GUI of the main thread, as much as building a parallel GUI (which may just consist of a few controls living on other controls from another thread or even process) in your worker thread that lives and dies with that thread.
And this can be a major problem for the VCL or LCL, because not all LCL controls are even a single winapi window class, but may consist of multiple windows that are dynamically created (e.g. TDirectoryEdit consists of an Edit and a Button). So while updating of certain properties of a winapi element may be possible with a PostThreadMessage or SendMessage call, if a higher level control requires to create or destroy any subcontrols for an operation it can't be made cross platform on the Windows API.
So I still stick to my point, the WinAPI GUI api is not build for cross platform applications. So while some things may be possible, it is not intended to be used accross threads, and things like creating or destroying controls/windows simply does not work because it was never intended to be used that way.