   Buffering problems with child windows.
  Hi, i've been coding an app with basic graphical capabilities (Win32 API) in an attempt to make a networked BlackJack game.  However, i've created a child window that is an EditBox to handle chat input.However, when the EditBox is created it doesn't display unless a call to InvalidateRect() is made.  This call causes the EditBox to flicker terribly.The EditBox displays fine if I removemy buffering code.So can anyone point me in the direction of some articles that could solve my problem, or have a stab at solving this one themselves?Here's my buffer class;Buffer.h#ifndef BUFFER_H_#define BUFFER_H_/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/class CBuffer{public:/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CBuffer( );virtual~CBuffer( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/virtual boolOnEnter( const HWND& wnd );virtual boolOnPreRender( );virtual boolOnPostRender( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/inline HDCGetHDC( );inline HDCGetMemDC( );protected:/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HDCmDC;HDCmMemDC;HDCmBackDC;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HBITMAPmFront;HBITMAPmBack;HBITMAPmOldFront;HBITMAPmOldBack;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HWNDmWndCpy;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/WndRectmRect;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/virtual voidOnExit( );};/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/inline HDC CBuffer::GetHDC( ){return mDC;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/inline HDC CBuffer::GetMemDC( ){return mMemDC;}#endifBuffer.cpp#include "Global.h"#include "Buffer.h"/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CBuffer::CBuffer( ): mDC( NULL ), mMemDC( NULL ), mBackDC( NULL ), mFront( NULL ), mBack( NULL ), mOldFront( NULL ), mOldBack( NULL ), mWndCpy( NULL ), mRect( WndRect( 1024, 768, 0, 0 ) ){}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CBuffer::~CBuffer( ){OnExit( );}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CBuffer::OnEnter( const HWND& wnd ){mWndCpy = wnd;mDC = GetDC( mWndCpy );mMemDC = CreateCompatibleDC( mDC );mBackDC = CreateCompatibleDC( mDC );if( ! mDC || ! mMemDC || ! mBackDC ){CLogger::GetInstance( )-&gt;WriteLog( "Couldn't create DC's" );return false;}RECT rect;GetClientRect( mWndCpy, &rect );mRect.ConvertToVec4( rect );mFront = CreateCompatibleBitmap( mDC, mRect.GetRight( ), mRect.GetBottom( ) );mOldFront = ( HBITMAP )SelectObject( mMemDC, mFront );mBack = CreateCompatibleBitmap( mBackDC, mRect.GetRight( ), mRect.GetBottom( ) );mOldBack = ( HBITMAP )SelectObject( mBackDC, mBack );if( ! mFront || ! mBack ){CLogger::GetInstance( )-&gt;WriteLog( "Couldn't create buffer surfaces." );return false;}FillRect( mBackDC, &rect, ( HBRUSH )GetStockObject( WHITE_BRUSH ) );return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CBuffer::OnPreRender( ){return ( bool )BitBlt( mMemDC, mRect.GetLeft( ), mRect.GetTop( ), mRect.GetRight( ), mRect.GetBottom( ), mBackDC, 0, 0, SRCCOPY );}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CBuffer::OnPostRender( ){return ( bool )BitBlt( mDC, mRect.GetLeft( ), mRect.GetTop( ), mRect.GetRight( ), mRect.GetBottom( ), mMemDC, 0, 0, SRCCOPY );}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/void CBuffer::OnExit( ){if( mDC && mWndCpy ){ReleaseDC( mWndCpy, mDC );mDC = NULL;mWndCpy = NULL;}if( mMemDC && mFront ){SelectObject( mMemDC, mOldFront );DeleteObject( mFront );DeleteDC( mMemDC );mMemDC = NULL;mFront = NULL;}if( mBackDC && mBack ){SelectObject( mBackDC, mOldBack );DeleteObject( mBack );DeleteDC( mBackDC );mBackDC = NULL;mBack = NULL;}}My EditBox classEditBox.h#ifndef EDITBOX_H_#define EDITBOX_H_class CEditBox : public CGameObject{public:/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CEditBox( );CEditBox( const WndRect& pos, const HWND& wnd, const HINSTANCE& inst );virtual~CEditBox( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/virtual boolOnEnter( );virtual boolOnUpdate( );virtual boolOnExit( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/static LRESULT CALLBACKEditBoxProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );protected:/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HWNDmEditBox;HWNDmWndCopy;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HINSTANCEmInstCopy;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/PosVector2DmDim;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CStringmClassName;};#endifEditBox.cpp#include "Global.h"#include "EditStates.h"#include "EditBox.h"/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CEditBox::CEditBox( ): CGameObject( ), mWndCopy( NULL ), mEditBox( NULL ), mInstCopy( NULL ), mClassName( "EDIT" ){}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CEditBox::CEditBox( const WndRect& pos, const HWND& wnd, const HINSTANCE& inst ): CGameObject( ), mWndCopy( wnd ), mEditBox( NULL ), mInstCopy( inst ), mClassName( "EDIT" ){mPosition.SetX( pos.GetX( ) );mPosition.SetY( pos.GetY( ) );mDim.SetX( pos.GetZ( ) );mDim.SetY( pos.GetW( ) );}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CEditBox::~CEditBox( ){}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CEditBox::OnEnter( ){CGameObject::OnEnter( );mEditBox = CreateWindow( mClassName.GetConstChar( ), NULL, WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |ES_AUTOVSCROLL | ES_LEFT | ES_MULTILINE | ES_NOHIDESEL |WS_VSCROLL | WS_HSCROLL | WS_BORDER | ES_WANTRETURN,mPosition.GetX( ), mPosition.GetY( ), mDim.GetX( ), mDim.GetY( ), mWndCopy, NULL,mInstCopy, NULL );ChangeState( CEditIdleState::GetInstance( ) );return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CEditBox::OnUpdate( ){CGameObject::OnUpdate( );RECT redrawRect = { ( long )mPosition.GetX( ), ( long )mPosition.GetY( ), ( long )mDim.GetX( ), ( long )mDim.GetY( ) };InvalidateRect( mEditBox, &redrawRect, FALSE );return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CEditBox::OnExit( ){CGameObject::OnExit( );return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/LRESULT CEditBox::EditBoxProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ){switch( msg ){case WM_ERASEBKGND:return true;break;}return DefWindowProc( wnd, msg, wparam, lparam );}Finally, my windows class where it all gets called.Win32.h#ifndef WIN32_H_#define WIN32_H_class CWin32{public:/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CWin32( );virtual~CWin32( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/virtual boolOnEnter( );virtual boolOnUpdate( );protected:/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HWNDmWnd;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/HINSTANCEmInstance;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/MSGmMsg;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CStringmClassName;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/WndRectmRect;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CBuffer*mBuffer;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/IMAGEIDmID;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CButton*mButton;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CEditBox*mEditBox;/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/enum __ReturnMessages{IDLE,BUSY,EXIT};/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/intMessagePump( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/boolCreateAppWindow( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/virtual voidOnExit( );/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/static LRESULT CALLBACKWndProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );};#endifWin32.cpp#include "Global.h"#include "Win32.h"/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CWin32::CWin32( ): mWnd( NULL ), mInstance( NULL ), mClassName( "Networked BlackJack v0.15a" ), mRect( WndRect( 0, 0, 1024, 768 ) ), mBuffer( NULL ), mButton( NULL ), mEditBox( NULL ){memset( &mMsg, 0, sizeof( MSG ) );mBuffer = new CBuffer;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/CWin32::~CWin32( ){mButton-&gt;OnExit( );SAFE_DELETE( mBuffer );SAFE_DELETE( mButton );SAFE_DELETE( mEditBox );OnExit( );}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CWin32::OnEnter( ){WNDCLASSEX wc = { 0 };mInstance = GetModuleHandle( NULL );wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.cbSize = sizeof( WNDCLASSEX );wc.hbrBackground = NULL;//( HBRUSH )( COLOR_WINDOW + 1 );wc.hCursor = LoadCursor( NULL, IDC_ARROW );wc.hIconSm = LoadIcon( NULL, IDI_WINLOGO );wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );wc.hInstance = mInstance;wc.lpfnWndProc = WndProc;wc.lpszClassName = mClassName.GetConstChar( );wc.lpszMenuName = NULL;wc.style = NULL;//CS_VREDRAW | CS_HREDRAW;if( ! RegisterClassEx( &wc ) ){CLogger::GetInstance( )-&gt;WriteLog( "Couldn't register the windows class." );return false;}if( ! CreateAppWindow( ) ){CLogger::GetInstance( )-&gt;WriteLog( "Couldn't create app window." );return false;}if( ! mBuffer-&gt;OnEnter( mWnd ) ){CLogger::GetInstance( )-&gt;WriteLog( "Couldn't setup double buffering." );return false;}mID = CBmpHandler::GetInstance( )-&gt;LoadBmp( mBuffer-&gt;GetHDC( ), "test.bmp" );mButton = new CButton( mBuffer-&gt;GetHDC( ), PosVector2D( 200, 200 ), "test.bmp" );mButton-&gt;OnEnter( );mEditBox = new CEditBox( WndRect( 20, 20, 400, 60 ), mWnd, mInstance );mEditBox-&gt;OnEnter( );ShowWindow( mWnd, SW_SHOW );UpdateWindow( mWnd );return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CWin32::OnUpdate( ){while( 1 ){int msg = MessagePump( );switch( msg ){case EXIT:return false;break;case IDLE:CMouseHandler::GetInstance( )-&gt;OnUpdate( );//Graphics firstmBuffer-&gt;OnPreRender( );mButton-&gt;OnUpdate( mBuffer-&gt;GetMemDC( ) );mBuffer-&gt;OnPostRender( );//Windowing secondmEditBox-&gt;OnUpdate( );break;}}return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/int CWin32::MessagePump( ){if( PeekMessage( &mMsg, NULL, 0, 0, PM_REMOVE ) ){if( mMsg.message == WM_QUIT ){return EXIT;}TranslateMessage( &mMsg );DispatchMessage( &mMsg );return BUSY;}return IDLE;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/bool CWin32::CreateAppWindow( ){mWnd = CreateWindowEx( NULL, mClassName.GetConstChar( ), mClassName.GetConstChar( ), WS_OVERLAPPEDWINDOW, mRect.GetLeft( ), mRect.GetTop( ), mRect.GetRight( ), mRect.GetBottom( ), NULL, NULL, mInstance, NULL );if( ! mWnd ){CLogger::GetInstance( )-&gt;WriteLog( "mWnd == NULL" );return false;}return true;}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/void CWin32::OnExit( ){UnregisterClass( mClassName.GetConstChar( ), mInstance );if( mWnd ){DestroyWindow( mWnd );mWnd = NULL;}}/*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*/LRESULT CWin32::WndProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ){switch( msg ){case WM_CLOSE:case WM_DESTROY:PostQuitMessage( 0 );break;}return DefWindowProc( wnd, msg, wparam, lparam );}[Edited by - ApochPiQ on June 6, 2009 11:58:50 AM]
  Since you do drawing on the HDC directly you need to spare the rect of the edit.Either that, or you could also draw the edit manually (which does bring quite a few input handling issues with it).   