Actually, it's not the only way, it's -as you've mentioned- the hardcoded way: sorry about that.
You can also skin your TitleWindow component to accept background images. 
To create the appropriate skin with all the necessary states, you can copy the base skin: spark.skins.spark.TitleWindowSkin as MyTitleWindowSkin, and add some customization to it:
In the MetaData tag you should enter the name of your custom TitleWindow class:
<fx:Metadata>
    <![CDATA[ 
        [HostComponent("my.package.CustomTitleWindow")]
    ]]>
</fx:Metadata> 
To accept backgroundImage, 
- you should declare a variable:
[Bindable] private var
backgroundImage:*;
 
- override the
updateDisplayList(unscaledWidth,
unscaledHeight) method, and inside
of it initialize this member:
backgroundImage =
getStyle("backgroundImage"); 
in the <!-- layer 2: background fill
--> section, after the solid-color-fill (<s:Rect
id="background"...), you should put
the following snippet:
<s:Rect id="backgroundImg" 
    left="1" right="1" 
    top="{topGroup ? topGroup.height : 0}" 
    bottom="{bottomGroup ? bottomGroup.height : 0}">
    <s:fill>
        <!-- BackgroundImage -->
        <s:BitmapFill id="img" source="{backgroundImage}"
            smooth="true" fillMode="scale" />
    </s:fill>
</s:Rect>
 
Next you need to create a new class (my.package.CustomTitleWindow), that extends TitleWindow, set its skin, and bind the backgroundImage style: 
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    skinClass="my.package.MyTitleWindowSkin">
    <fx:Metadata>
        [Style(name="backgroundImage", type="*")]
    </fx:Metadata>
    <mx:VBox width="100%" height="100%">
        <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
        <s:Button label="Do something" />
    </mx:VBox>
</s:TitleWindow>
at the end a small test (which worked fine at my side, and i hope it's closer to what you're looking for):
<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
    <my:CustomTitleWindow title="Window without background image"
        width="100%" height="50%" />
    <my:CustomTitleWindow title="Window with background image"
        width="100%" height="50%" backgroundImage="{IMyConstants.MYLOGO}" />
</s:VGroup>
Update
For setting the skin and the background image from a css file, you only need some minor modifications: 
Create a CSS file with content: 
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
@namespace my "your.package.*";
my|CustomTitleWindow {
    skin-class: ClassReference("your.package.MyTitleWindowSkin");
}
.twWithBgImage {
    background-image: Embed("icons/logo.png");
}
The test would look like: 
<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
    <my:CustomTitleWindow title="Window without background image"
        width="100%" height="50%" />
    <my:CustomTitleWindow title="Window with background image"
        width="100%" height="50%" styleName="twWithBgImage" />
</s:VGroup>
and you need to remove the skin declaration from the CustomTitleWindow class: skinClass="your.package.MyTitleWindowSkin".
Of course you don't need to apply the skin to the my|CustomTitleWindow class, you could use it just for a css class, this way you surely don't need to modify your existing component.
Update -- without custom component
Forget the CustomTitleWindow class.
skinnedtw.css
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
.twWithBgImage {
    skin-class: ClassReference("your.package.MyTitleWindowSkin");
    background-image: Embed("icons/logo.png");
}
TestApp.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx">
    <fx:Style source="assets/skinnedtw.css" />
    <s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
        <s:TitleWindow title="Window without background image"
            width="100%" height="50%">
            <mx:VBox width="100%" height="100%">
                <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
                <s:Button label="Do something" />
            </mx:VBox>
        </s:TitleWindow>
        <s:TitleWindow title="Window with background image"
            width="100%" height="50%" styleName="twWithBgImage">
            <mx:VBox width="100%" height="100%">
                <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
                <s:Button label="Do something" />
            </mx:VBox>
        </s:TitleWindow>
    </s:VGroup>
</s:WindowedApplication>
My output still looks like this:
