CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Nov 2011
    Posts
    3

    Question GDI Problem - BitBlt() Doesn't Seem To Be Doing Anything

    I'm using the GDI to draw to a memory bitmap, which is then copied to the window using BitBlt(). When I redraw the whole window it works correctly, but when I try to update only part of the window it doesn't redraw correctly and, after weeks of trying, I still can't work out why.

    Below I've included the relevant code along with the values for one debug run.

    When an area of the window needs to be updated I call this function to invalidate the updated region:

    Code:
    void RedrawActiveArea()
    {
    	m_bRedrawActiveArea = true;
    	InvalidateRect(&m_rctActiveAreaRect, false);
    }
    The values of m_rctActiveAreaRect are {top=0 bottom=373 left=586 right=605}

    Invalidating a region obviously causes OnPaint to be called:

    Code:
    void OnPaint() 
    {
    	RECT rctUpdateRect;
    	if (GetUpdateRect(&rctUpdateRect))
    	{
    		PAINTSTRUCT Ps;
    		CDC* pDC = BeginPaint(&Ps);
    
    		if (m_bFullRedraw)
    		{
    			m_pMainArea->FullRedraw(pDC);
    			m_bFullRedraw = false;
    		}
    		else if (bRedrawActiveArea)
    		{
    			m_pMainArea->DrawActiveArea(pDC);
    			m_bRedrawActiveArea = false;
    		}
    		else
    		{
    			m_pMainArea->CopyToWindow(pDC, m_rctUpdateRect);
    		}
    		EndPaint(&Ps);
    	}
    }
    Here rctUpdateRect is {top=0 bottom=373 left=586 right=605} as expected. bRedrawActiveArea is true so DrawActiveArea() is called.

    For debugging purposes DrawActiveArea() is just drawing a green rectangle over the invalidated rectangle:

    Code:
    void CMainArea::DrawActiveArea(CDC* pdcWindowDC) 
    {
    	m_pdcMemDC->SelectObject(penGreenPen);
    	m_pdcMemDC->SelectObject(brshGreenBrush);
    	m_pdcMemDC->Rectangle(&m_rctActiveAreaRect);
    
    	int iReturn = pdcWindowDC->BitBlt(m_rctActiveAreaRect.left, 
    					  m_rctActiveAreaRect.top, 
    					  m_rctActiveAreaRect.right-m_rctActiveAreaRect.left,
    					  m_rctActiveAreaRect.bottom-m_rctActiveAreaRect.top,
    					  m_pdcMemDC,
    					  m_rctActiveAreaRect.left,
    					  m_rctActiveAreaRect.top, 
    					  SRCCOPY);
    }
    Here m_rctActiveAreaRect is the same as before: {top=0 bottom=373 left=586 right=605}.

    A green rectangle should be drawn over the active area in the memory bitmap, and that area should then be copied to the window, so the green rectangle should be displayed on the window. Sadly, it doesn't happen and nothing changes in the window.

    If, after this process, I drag another window over my window (causing the invalidated regions to be re-copied from the memory bitmap) the green rectangle appears. It therefore seems that the rectangle is being drawn to the memory bitmap, but is failing when being copied to the window. I therefore assumed that BitBlt() was failing, but it returns 1 and nonzero indicates success.

    I'm therefore completely at a loss as to why the green rectangle isn't appearing on the window first time. All the numbers are as I'd expect them to be when I debug and everything looks right to me.

    Can anyone suggest what might be going wrong?

    Thanks for any advice you can offer.

  2. #2
    Join Date
    May 2004
    Location
    45,000FT Above Nevada
    Posts
    1,539

    Re: GDI Problem - BitBlt() Doesn't Seem To Be Doing Anything

    Quote Originally Posted by Gav80K View Post
    Below I've included the relevant code along with the values for one debug run.
    Are you sure ???? as bRedrawActiveArea is not defined, initialized nor modified...should this actually be m_bRedrawActiveArea ??

    Code:
    else if (bRedrawActiveArea)
    {
       m_pMainArea->DrawActiveArea(pDC);
       m_bRedrawActiveArea = false;
    }
    Jim
    ATP BE400 CE500 (C550B-SPW) CE560XL MU300 CFI CFII

    "The speed of non working code is irrelevant"... Of course that is just my opinion, I could be wrong.

    "Nothing in the world can take the place of persistence. Talent will not; nothing is more common than unsuccessful men with talent. Genius will not; unrewarded genius is almost a proverb. Education will not; the world is full of educated derelicts. Persistence and determination are omnipotent. The slogan 'press on' has solved and always will solve the problems of the human race."...Calvin Coolidge 30th President of the USA.

  3. #3
    Join Date
    Jan 2002
    Location
    Houston, TX
    Posts
    1,421

    Re: GDI Problem - BitBlt() Doesn't Seem To Be Doing Anything

    Since you are trying to use BitBlt, it might help if you show how you created your m_pdcMemDC. I also don't see any code showing you drawing into the m_pdcMemDC before the attempt to BitBlt it.

    Also, in your code below, you have selected some objects into a DC, but you don't release them anywhere I can see. This can cause problems further down the road.

    Quote Originally Posted by Gav80K View Post
    Code:
    void CMainArea::DrawActiveArea(CDC* pdcWindowDC) 
    {
    	m_pdcMemDC->SelectObject(penGreenPen);
    	m_pdcMemDC->SelectObject(brshGreenBrush);
    	m_pdcMemDC->Rectangle(&m_rctActiveAreaRect);
    
    	int iReturn = pdcWindowDC->BitBlt(m_rctActiveAreaRect.left, 
    					  m_rctActiveAreaRect.top, 
    					  m_rctActiveAreaRect.right-m_rctActiveAreaRect.left,
    					  m_rctActiveAreaRect.bottom-m_rctActiveAreaRect.top,
    					  m_pdcMemDC,
    					  m_rctActiveAreaRect.left,
    					  m_rctActiveAreaRect.top, 
    					  SRCCOPY);
    }
    Be sure to rate those who help!
    -------------------------------------------------------------
    Karl - WK5M
    PP-ASEL-IA (N43CS)
    PGP Key: 0xDB02E193
    PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193

  4. #4
    Join Date
    Nov 2011
    Posts
    3

    Re: GDI Problem - BitBlt() Doesn't Seem To Be Doing Anything

    Thanks for the replies. It seems the problem wasn't in the part of the code I included, but where I created the window. Unfortunately solving it creates a bigger problem.

    I read that creating the window with WS_EX_COMPOSITED solved the GDI flicker issue. It did but it also lead to you having to redraw parts of the window unnecessarily, so I switch to using a memory bitmap which allowed you to copy invalidated areas to the window without having to redraw them. After implementing the memory bitmap I forgot to remove the WS_EX_COMPOSITED, so it was effectively triple buffered which was presumably why the updates to the bitmap weren't ending up on the window.

    After removing WS_EX_COMPOSITED the drawing now works correctly. However, it also causes the whole program to break. For example, all timers created with SetTimer() stop working and the timer function never gets called, and the applications windows or no longer receiving paint messages when they become partially obscured by another window, so they don't get redrawn. It's like something is going wrong with the message queue.

    I'm at a loss as to how changing:

    Code:
    LPCSTR szWinClass = AfxRegisterWndClass(0, LoadCursor(NULL, IDC_CROSS));
    CreateEx(WS_EX_COMPOSITED, szWinClass, "Graph", WS_POPUP | WS_VISIBLE | WS_BORDER, *kprctPosition, I.m_pMainWnd, NULL);
    to

    Code:
    LPCSTR szWinClass = AfxRegisterWndClass(0, LoadCursor(NULL, IDC_CROSS));
    CreateEx(0, szWinClass, "Graph", WS_POPUP | WS_VISIBLE | WS_BORDER, *kprctPosition, I.m_pMainWnd, NULL);
    could cause these problems. If I add the WS_EX_COMPOSITED back in everything starts working again.

    Any idea what could have caused this?

  5. #5
    Join Date
    Nov 2011
    Posts
    3

    Re: GDI Problem - BitBlt() Doesn't Seem To Be Doing Anything

    Further to the above post, I've got three transparent overlay windows that can appear on top of the graph. All of them are created with WS_EX_COMPOSITED purely because I remember finding that if I didn't the whole program breaks. They're created like this

    Code:
    LPCSTR szWinClass = AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW));
    CreateEx(WS_EX_COMPOSITED | WS_EX_LAYERED | WS_EX_TRANSPARENT, 
    	 szWinClass,
    	 "LineOverlay",
    	 WS_POPUP | WS_VISIBLE,
    	 pntWinPos.x,
    	 pntWinPos.y,
    	 m_pchtChart->m_iChartWidth,
    	 m_pchtChart->m_iChartHeight,
    	 m_pchtChart->m_hWnd,
    	 NULL);
    If I remove the WS_EX_COMPOSITED from any one of these I get the problem where everything breaks. I hoped removing it from all of them would solve the problem, but sadly it doesn't. I assume I'm an invalid combination when creating the windows or something, but I can't see what's wrong.

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: GDI Problem - BitBlt() Doesn't Seem To Be Doing Anything

    Quote Originally Posted by Gav80K View Post
    Further to the above post, I've got three transparent overlay windows that can appear on top of the graph. All of them are created with WS_EX_COMPOSITED purely because I remember finding that if I didn't the whole program breaks.
    If you googled "WS_EX_COMPOSITED", you would find many issues with this style.

    Regards,

    Paul McKenzie

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured