This is one of the few Windows objects I'm really proud of: odcstream.

I almost always use odcstream instead of TextOut.

If you like streams (some of you hate 'em I know) and you like Windows (yeah, that too)
then you'll like this....

Its very easy to use - I recommend using it inside of you Paint() function of an OWL 2.0
TWindow derived class.

If you have any questions - drop me a line...

here is a code fragment example (look for dc).  Note that dcbuf is a member of TMyWindow,
and is instantiated using the default size of 512 bytes.



void TMyWindow::Paint( TDC &tdc, BOOL /*erase*/, TRect &rc )
{
	int
		nCols = ( rect.right - rect.left ) / TxtWide,
		ColBeg = ( rc.left  / TxtWide ), // + (int)Scroller->XPos,
		ColEnd = ( rc.right / TxtWide ), // + (int)Scroller->XPos /*+ 1*/,
		RowBeg = ( rc.top    / tm.tmHeight ),
		RowEnd = ( rc.bottom / tm.tmHeight ) /*+ 1*/,
		Row = 0,
		Col = 0;

	TColor
		ColorHilite( GetSysColor( COLOR_HIGHLIGHT ) ),	// highlight color when an item is selected
		ColorText( GetSysColor( COLOR_WINDOWTEXT ) ),	// ColorText color inside a window
		ColorBkGnd( GetSysColor( COLOR_WINDOW ) );		// window background color

	TBrush
		BrushSelected( ColorHilite ),							// brush for painting behind selected item
		BrushUnselect( ColorBkGnd );							// brush for painting behind unselected item

	TPen
		PenCurPos( ColorText, 1, PS_DOT ),					// highlights the current "cursor" position
		PenBkGnd( ColorBkGnd, 1, PS_SOLID );				// unselected item pen color

	TFont
		font( &logFont );											// get window font

	tdc.SelectObject( font );                          // set the font
	tdc.SetBkMode( TRANSPARENT );								// Text BkGnd does not overwrite Rectangles

	odcstream
		dc( tdc, dcbuf );
	dc.hardtab();													// use hard tab stops
	dc.tab( tabStop );

	if( !pContainer )
	{
		dc << "No Container..." << endl;
		return;
	}

	ITERATOR
		iter( *pContainer );

	for( int i = 0; iter; i++, iter++ )
	{
		const OBJ
			*o = GetCurrentObject( iter );

		if( o )														// ignore non-allocated Objects
		{
			if( Row >= RowBeg && Row <= RowEnd &&
				 Col >= ColBeg && Col <= ColEnd )
			{
				int
					xTxt = Col*TxtWide,
					yTxt = Row*tm.tmHeight;

				tdc.SelectObject( ( i == CurPos )? PenCurPos: PenBkGnd );	// select pen
				if( isSelected[i] )														// select brush
				{
					tdc.SetTextColor( GetSysColor( COLOR_HIGHLIGHTTEXT ) );
					tdc.SelectObject( BrushSelected );
				}
				else
				{
					tdc.SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
					tdc.SelectObject( BrushUnselect );
				}

				tdc.Rectangle( xTxt, yTxt, xTxt+TxtWide, yTxt+tm.tmHeight );
				dc << gotoxy( xTxt+tm.tmAveCharWidth, yTxt ) << *o << flush;
			}
			Row++;
			if( Row == nRows )
			{
				Row = 0;
				Col++;
			}
		}
	}
	tdc.RestoreObjects();
	if( Row == 0 )														// an empty Column was started
		Col--;															// kill it so scrolling is nicer
	Col -= nCols - 1;													// subtract the displayable cols
	Scroller->SetRange( ( Col < 0 )? 0: Col, 0 );			// base scroller range on # cols
}





Nat