The rendering is handled by a separate object called a CEGUI::WindowRenderer (the defaults for these are in the FalagardWRBase module). The idea is that the core functionality of any given widget type should totally independent of it's visual aspect, so in CEGUI we have these two items separate (with varying degrees of success; but hey, it's a work in progress
The default approach we use in the library is for the WindowRenderer for a given widget type to get most of it's basic form via a falagard looknfeel WidgetLook specification. WindowRenderer types are mapped to Window types along with a LookNFeel within the scheme file.
Having said this, the use of the WindowRenderer is not a requrement; certainly not for user project widgets where customisation is less of an issue than it is for us as library providers
You can just as easily dispense with WindowRenderer objects and override that populateRenderCache function.
One key thing to understand is that when you 'draw' things in that function (or via the WindowRenderer), you're not actually drawing it immediately; rather you're queueing things to be drawn at a later time. You do this by using the Window objects RenderCache, and add images and text strings to that, which will be drawn later at an appropriate time.
Anyway, take a look in the FalagardWRBase files, since that's where the rendering 'action' takes place.