Thread: Offscreen Drawing Problem

  1. #1
    Dump Truck Internet valis's Avatar
    Join Date
    Jul 2005
    Posts
    357

    Offscreen Drawing Problem

    I am doing some offscreen drawing and then blitting it to the screen, but it doesn't seem to show up so I'm obviously doing something wrong or overlooking something.
    What I am doing is more complex but I can't get even something this simple to work:
    Code:
    HDC hdc ;
    
    BeginPaint ( hWnd, &ps ) ;
    
    // quick fix *****
    GetClientRect ( hWnd, &ps.rcPaint ) ;
    
    // create a dc and a bitmap to work on
    hdc = CreateCompatibleDC ( ps.hdc ) ;
    hMem = CreateCompatibleBitmap ( ps.hdc, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top ) ;
    
    SelectObject ( hdc, hMem ) ;
    FillRect ( hdc, &ps.rcPaint, GetStockObject ( WHITE_BRUSH ) ) ;
    
    // move it to our display
    BitBlt ( ps.hdc, 0, 0,
    			ps.rcPaint.right - ps.rcPaint.left,
    			ps.rcPaint.bottom - ps.rcPaint.top,
    			hdc, 0, 0, SRCCOPY ) ;
    
    DeleteDC ( hdc ) ;
    
    EndPaint ( hWnd, &ps ) ;
    I also handle WM_ERASEBKGND
    Code:
    case WM_ERASEBKGND:
        return ( 1 ) ;
    break ;
    The background of the window is still 'transparent' after this runs. Looking at it with a debugger all my handles are non-zero so I'm really stuck with this.
    I'm basically trying to use an 'oldschool' back buffer to avoid that annoying flickering.
    I'm rather new to the windows gdi so it could be something really simple, help is greatly appreciated.

    thanks
    Last edited by valis; 07-13-2005 at 02:08 PM.

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>I'm basically trying to use an 'oldschool' back buffer to avoid that annoying flickering.

    Thats not realy a backbuffer.......you should not create a DC during paint. You should create it during init and free it on close.
    Your paint should only be a single BitBlt() for maximum speed.

    If the update rect is empty then there will be no painting

    Code:
    //to find area to paint before BeginPaint
    if( !GetUpdateRect(hWnd, &Rect, FALSE) )//if empty return is zero
    //check your InvalidateRect call	
    
    BeginPaint(.....
    
    ......
    	//watch the GDI mem leak (unless using a .NET IDE)
    HBITMAP     hOldBMP = SelectObject(hdc, hMem);//catch the original bmp
    
    .....
    
    EndPaint(...
    
    //clean up to stop GDI leak
    SelectObject(hdc,hOldBMP);//return hdc to original state
    DelectObject(hMem);
    DeleteDC(hdc);
    Last edited by novacain; 07-13-2005 at 07:28 PM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Dump Truck Internet valis's Avatar
    Join Date
    Jul 2005
    Posts
    357
    thankyou for the cleanup tips, I will implement them.
    I will almost always have new information to draw, so usually I will be updating my whole window.
    However I still have the problem that my final BitBlt to my display doesn't display anything, I say backbuffer because if you don't have enough video memory to just flip a pointer you just copy it from a pre-drawn buffer.

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Whats in the paint rect before you fill it with the client rect?
    How are you calling for the paint?

    >>CreateCompatibleDC ( ps.hdc ) ;

    try...
    HDC hdcTemp = GetDC(hWnd);//or NULL for desktop
    HDC hdc = CreateCompatibleDC(hdcTemp );
    hMem = CreateCompatibleBitmap (hdc,......
    .......
    ReleaseDC(hdcTemp);


    Try changing SCRCOPY to WHITENESS



    Other than that everything looks good.....
    Last edited by novacain; 07-14-2005 at 01:16 AM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  5. #5
    Dump Truck Internet valis's Avatar
    Join Date
    Jul 2005
    Posts
    357
    how can I draw bitmaps onto my offscreen dc without calling more than one BitBlt?
    I currently can draw text, flood fill, draw lines and shapes, but a BitBlt with a bitmap breaks it:
    Code:
    HDC hdc = GetDC ( hWnd ) ;
    HDC hdcMem = CreateCompatibleDC ( hdc ) ;
    HBITMAP hMem = CreateCompatibleBitmap ( hdc, width, height ) ;
    HBITMAP hOldBmp = SelectObject ( hdcMem, hMem ) ;
    // do offscreen drawing to hdc, involves multiple calls to BitBlt
    ReleaseDC ( hWnd, hdc ) ;
    
    hdc = BeginPaint ( hWnd, &ps ) ;
    // BitBlt hdcMem to hdc
    EndPaint ( hWnd, &ps ) ;
    
    SelectObject ( hdcMem, hOldBmp ) ;
    DeleteObject ( hMem ) ;
    DeleteObject ( hOldBmp ) ;
    DeleteDC ( hdcMem ) ;
    
    DeleteDC ( hdc ) ;
    Last edited by valis; 07-22-2005 at 03:07 PM.

  6. #6
    Registered User joed's Avatar
    Join Date
    Mar 2004
    Posts
    59
    You can use CreateDIBSection to link an array of DIB bitmap data (stored in BGR format!) to a memory DC. This lets you draw to it using GDI routines (through bufferDC), or your own custom drawing routines (to the actual buffer data). You'd normally hang on to the DC until program exit, might initialize window with CS_OWNDC style out of paranoia. I tried to put everything in the order it would be executed, for clarity.

    Note that the user can change the screen resolution, so the back buffer needs reallocation in that event or the program will crash.

    Code:
    // initialization begins
    // initialize bitmap info structure used by CreateDIBSection
     	BITMAPINFO *bi;
    
    	bi = malloc(sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
    
    	ZeroMemory(&bi->bmiHeader, sizeof(BITMAPINFOHEADER));
    
    	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    	bi->bmiHeader.biBitCount = 32;
    
    	bi->bmiHeader.biPlanes = 1;
    	bi->bmiHeader.biClrUsed = 0;
    
    // get screen resolution
    	int xmax, ymax;
    	
    	xmax = GetSystemMetrics(SM_CXSCREEN);
    	ymax = GetSystemMetrics(SM_CYSCREEN);
    	bi->bmiHeader.biWidth = xmax;
    	bi->bmiHeader.biHeight = -ymax; // DIBs are upside-down
    
    // allocate screen buffer
    
    	HDC mainDC;
    	HDC bufferDC;
    	HBUFFER hbuffer;
    	int *backbuf;	// screen buffer
    	
    	mainDC = GetDC(hwnd);
    	bufferDC = CreateCompatibleDC(mainDC);
    	backbuf = malloc(xmax * ymax * sizeof(int))
    	if(!backbuf)
    		error();
    
    // make a DIB section and link to screen buffer
    	hbuffer = CreateDIBSection(bufferDC, bi, DIB_RGB_COLORS,
    			(void **)&backbuf, NULL, 0);
    	SelectObject(bufferDC, hbuffer);
    
    // program begins
    // WM_SIZE updates screen.right & screen.bottom
    	RECT screen;	
     
    	case WM_SIZE:
    		GetClientRect(mainHwnd, &screen);
    		break;
    // WM_PAINT
    	case WM_PAINT:
    		if(screen.right > 0 && screen.bottom > 0) {
    			BitBlt(mainDC, 0, 0, screen.right, screen.bottom,
    				bufferDC, 0, 0, SRCCOPY);
    		}
    		break;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  2. Replies: 5
    Last Post: 11-07-2005, 11:34 PM
  3. searching problem
    By DaMenge in forum C Programming
    Replies: 9
    Last Post: 09-12-2005, 01:04 AM
  4. half ADT (nested struct) problem...
    By CyC|OpS in forum C Programming
    Replies: 1
    Last Post: 10-26-2002, 08:37 AM