Thread: Drawing HBITMAP into CWnd, Acquired from "screenshot"

  1. #1
    Registered User
    Join Date
    May 2009
    Posts
    4

    Drawing HBITMAP into CWnd, Acquired from "screenshot"

    Hello everyone,

    So I have my own "simpleBitmap" class which I use to acquire screenshots, and in turn I to a lot of low level manipulation of the pixels (the reason for making a class). Now I know my "screenshots" are working fine, I can save them to file, I can analyze individual pixels etc.

    Now I want to be able to draw these simpleBitmap objects into a CWnd, however I want my class to remain MFC independant. Following is the code used to acquire the screenshot.

    Code:
    bool simpleBitmap::acquire( const string& wind_name, RECT rect )
    {
    	cleanup_resources();
    
    	HWND hWnd = ::FindWindow(NULL,wind_name.c_str());
    	if (!hWnd)
    		return false;
    
    	// If the target rect is 0,0,0,0 take the whole window.
    	POINT start = {rect.left,rect.top};
    	if ( (rect.left == 0 && rect.right == 0) || (rect.top == 0 && rect.bottom == 0) )
    	{	
    		RECT wndRect;
    		::GetWindowRect(hWnd,&wndRect);
    		rect = wndRect;
    	}
    
    	int w = rect.right-rect.left;
    	int h = rect.bottom-rect.top;
    
    	HDC hDc = ::GetWindowDC(hWnd);
    	hMemDc = CreateCompatibleDC(hDc);
    	hBmp = CreateCompatibleBitmap(hDc,w,h);
    
    	if ( !hDc || !hMemDc || !hBmp )
    		return false;
    	
    	::SelectObject(hMemDc,hBmp);
    
    	::BitBlt(hMemDc,0,0,w,h,hDc,start.x,start.y,SRCCOPY);
    
    	::ReleaseDC(hWnd, hDc);
    
    	bmpRect = rect;
    
    	return true;
    }
    Now the member variables hMemDC, and hBmp are stored within the class. Here is my... attempt at drawing to a window. Note however that this custom CWnd class is drawn onto a dialog, I know the class is capable of drawing succesfully (I have used simple CDC drawing stuff like coloring the background white).

    Code:
    void CBitmapWnd::OnPaint()
    {
    	CPaintDC dc(this); // device context for painting
    	
    	// Check if the simple bitmap is initialized.
    	if ( sBmp )
    	{
    		// Get HDC and make sure the bitmap is selected into it.
    		HBITMAP hBmp = sBmp->get_hbitmap();
    		HDC hDC = sBmp->getSafeDC();
    		::SelectObject(hDC,hBmp);
    
    		// The rectangle describing the bitmap.
    		CRect bmpRect;
    		bmpRect = sBmp->get_rect();
    
    		// Convert to MFC CDC
    		CDC CMemDC;
    		CMemDC.FromHandle(hDC);
    		CRect wndRect;
    		this->GetClientRect(&wndRect);	
    
    		//Draw
    		dc.StretchBlt(0,0,wndRect.Width(),wndRect.Height(),&CMemDC,0,0,bmpRect.Width()-1,bmpRect.Height()-1,SRCCOPY);
    
    		/*		
    		// This call works, and draws the background white.
    		CBrush b(RGB(255,255,255));
    		dc.SelectObject(&b);
    		dc.Rectangle(wndRect);
    		*/
    	}
    }
    Sorry for the large amount of code, just trying to be complete in my question. So of course the question is... what would be the appropriate way to draw an HBITMAP/HDC acquired in the above manner to a simple CWnd class. I have looked around a lot, but there seem to be a huge number of combinations to draw Bitmaps, none of which have worked for me yet.

    Thank you

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4
    Ok well I seem to have... 5 minutes later found a solution to my own problem. The only change I made was:

    Code:
    // Replace:
    CMemDC.FromHandle(hDC);
    // With:
    CMemDC.Attach(hDC);
    Now any suggestions explanations are still welcome!! I have no idea why MFC has FromHandle then? The documentation states:

    Returns a pointer to a CDC object when given a handle to a device context.
    Which I assumed meant it gave me a valid CDC object assuming my HDC was valid. Oh well.

  3. #3
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    FromHandle creates fills an the internal data structure to be compatible with and a copy of the platforms SDK's DC. CDC is just a wrapper around various DC functionality.

    In the first case you are returning a CDC that has been created from a DC, in the second case you are internally creating a DC on the current object from the handle.

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Is there a reason you are mixing MFC and WIN32? [HDC and CDC]

    You seem to be doing more work than required because of this mix.

    You can access the WIN32 GDI handle (HDC, HBITMAP etc) by casting the m_hObject member of any MFC CGdiObject.

    I use something like….

    Code:
     CWnd *pWnd=NULL;
    
    if (pWnd = CWnd::FindWindow(wind_name.c_str(),NULL))
    {
    	CRect Area(&Rect);//init 
    	if(!Area.Width() || !Area.Height())//validate
    		pWnd->GetWindowRect(Area);
    
    	//get the DC
    	CDC *pDC=NULL;
    	pDC = pWnd->GetWindowDC();
    
    	//free members if required
    	//TODO add free GDI resource code
    
    	//fill members
    	m_DC.CreateCompatibleDC(pDC);// CDC (is public in this example)
    	m_Bmp.CreateCompatibleBitmap(pDC, Area.Width(),Area.Height()); // CBitmap
    
    	//save original CBitmap to return our CDC to the default state before DeleteDC() 
    	m_OrBmp=m_DC.SelectObject(&m_Bmp); // CBitmap *
    
    	//copy
    	m_DC.BitBlt(Area.left, Area.top, Area.Width(),Area.Height(),pDC,0,0, SRCCOPY );
    
    	//clean up
    	pWnd->ReleaseDC(pDC);
    }
    Then paint becomes
    Code:
    void CBitmapWnd::OnPaint()
    {
    	CPaintDC dc(this); // device context for painting
    	
    	// Check if the simple bitmap is initialized.
    	if ( sBmp )
    	{
    		//get areas
    		CRect Area;
    		GetClientRect(Area,0);
    		CRect bmpRect;
    		bmpRect = sBmp->get_rect();
    		//Draw	
    		dc.StretchBlt(0, 0, Area.Width(),Area.Height(),&sBmp.m_DC,0,0,bmpRect.Width()-1,bmpRect.Height()-1,SRCCOPY);
    	}
    }
    Last edited by novacain; 06-08-2009 at 12:37 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
    Registered User
    Join Date
    Jun 2009
    Posts
    5

    CDC::FromHandle in winapi

    I am trying to convert all my mfc codes to my own class (pure winapi). Since MFC is actually wrapping around the WinAPI. But I am having problem with CDC::FromHandle, there is no equivalent in WinAPI. I know, I can replace any call CDC::FromHandle and directly get the DC from ::GetDC, but it means I have to change all my code as well. Is there any way to replace CDC::FromHandle with pure WinAPI ? or any clue ?

    thx

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by binyo66 View Post
    I am trying to convert all my mfc codes to my own class (pure winapi). Since MFC is actually wrapping around the WinAPI. But I am having problem with CDC::FromHandle, there is no equivalent in WinAPI. I know, I can replace any call CDC::FromHandle and directly get the DC from ::GetDC, but it means I have to change all my code as well. Is there any way to replace CDC::FromHandle with pure WinAPI ? or any clue ?

    thx
    Please start your own thread, not necro others (which is against the forum rules)....



    What EXACTLY are you trying to do?

    BitBlt()? just use the HDC.
    Change GDI objects? use SelectObject(), catching the released GDI object so you can clean up correctly.

    Without details it is hard to give a meaningful response.


    You appear to want to know how to construct a CDC (an MFC object) in pure WIN32, which is impossible.

    CDC::FromHandle(HDC ) takes a WIN32 handle to a DC (a HDC) and returns a pointer to an MFC class CDC, initialised with that DC. You can't use a CDC in pure WIN32.



    BTW anything with '::' in front of it is MFC not WIN32.
    "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

  7. #7
    Registered User
    Join Date
    Jun 2009
    Posts
    5
    Quote Originally Posted by novacain View Post
    Please start your own thread, not necro others (which is against the forum rules)....
    Well, because I see the comment above me about CDC::FromHandle. Sorry if it is misplaced.


    You appear to want to know how to construct a CDC (an MFC object) in pure WIN32, which is impossible.
    We have managed already all dialog based and its derived common controls (CWnd and its derived), and we are doing CDC, but got stuck with CDC::FromHandle. I believe there is nothing impossible in here

    CDC::FromHandle(HDC ) takes a WIN32 handle to a DC (a HDC) and returns a pointer to an MFC class CDC, initialised with that DC. You can't use a CDC in pure WIN32.
    This is what I am guessing. CDC::FromHandle is static, and it accept only HDC as input, so it means MFC somehow have all attach HDCs in a global array or link list (so it can search from static function). MSDN said if the HDC is not attach when calling CDC::FromHandle, then it will attach to it. If i can know where MS start attaching HDC to MFC and put it in MFC object or when the array been created, then I can do similarity for it, and I can handle CDC::FromHandle (Like dialog based CWnd, we assume MFC has to store HWND somewhere in an array during the class initialization and enum all the childs so that all control child members variable can be attached to the right HWND).

    Well you are probably right, it is not the right thread. again my apology for it (I just doesnt want to duplicate theread), and I will not attempt to reply this thread again, if u need to comment this post just pm me ). thx

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. drawing on bitmaps
    By eth0 in forum Windows Programming
    Replies: 2
    Last Post: 03-24-2006, 05:56 PM
  2. HBITMAP in Class
    By Born_2B_Alone in forum Windows Programming
    Replies: 1
    Last Post: 10-09-2004, 05:47 PM