Click here to Skip to main content
15,885,546 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I have a Visual Studio 12 C++ issue:

I have within OnDraw(CDC* pDC) code below to try to write the display in the background and then show it in the foreground later with bitblt ... but during run-time the compatible DC cdcMemory is created (isCDCcreated returns true). However hbmMemory returns null (CreateCompatibleBitmap fails) and I do not know why.... I appreciate any suggestions or follow-up.

ISSUE: CreateCompatibleBitmap fails

With bmpLoad demonstration code, CreateCompatibleBitmap fails

C++
    // Following: http://stackoverflow.com/questions/17416152/transfer-an-image-from-cdc-to-cbitmap
    // and https://msdn.microsoft.com/en-us/library/kwxzck32.aspx
    // Create an in-memory CDC compatible with the display DC we're using to paint
    CDC cdcMemory;  //A background memory version of the CDC to draw on to make the final update appear faster
    BOOL isCDCcreated = cdcMemory.CreateCompatibleDC(pDC);

...

    // Create a compatible bitmap from the previously created compatible CDC cdcMemory
    // See https://msdn.microsoft.com/en-us/library/25kc2k5s.aspx for HBITMAP conversion from Cbitmap
    // See explanation at http://forums.codeguru.com/showthread.php?314588-a-quick-question-how-to-use-CDC-operator-HDC
    // See additinal important explanation at http://www.codeproject.com/Articles/224754/Guide-to-Win32-Memory-DC
    HDC hdcfromcdc_pDC = (HDC) pDC; // Get the HDC for the existing window's PDC to create the compatible bitmap
    // Now create the compatible bitmap in background memory to draw on.
    HBITMAP hbmMemory = CreateCompatibleBitmap(hdcfromcdc_pDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
    if (hbmMemory == NULL) // Error message if cannot create compatible HBITMAP
        {
            MessageBox(L"CreateCompatibleBitmap has failed", L"Failed", MB_OK);
            goto restoreandexit;  // go to end to restore and exit
        }

hbmMemory returns Null and the error message comes up. Why is this, and how can I get CreateCompatibleBitmap to work?
Posted
Updated 13-Jan-16 1:17am
v3

This part seems to be wrong:

C++
HDC hdcfromcdc_pDC = (HDC) pDC; // Get the HDC for the existing window's PDC to create the compatible bitmap


You try to cast pointer to CDC to HDC!

Try this:

C++
HDC hdcfromcdc_pDC = (HDC) *pDC; // Get the HDC for the existing window's PDC to create the compatible bitmap
 
Share this answer
 
Comments
StephenJElliott 13-Jan-16 7:35am    
The above answer is most likely correct. I just realized how "dangerous" using the built-in type conversion function is, because it ignores type conversion errors. Visual Studio 12 automatically lets you know what methods a particular function has with the popup, and these are "safe" generally and are fully type-checked. So finally, I used (very nearly the same):

HDC hdcfromcdc_pDC = pDC->m_hDC; // Get the HDC for the existing window's PDC to create the compatible bitmap

It compiled beautifully and this portion thankfully worked on the first shot! Thank you so much for your wonderful assistance!
_duDE_'s largely hit the problem on the head - at least as far as the cause goes: If pDC is a pointer to a CDC object you can't cast it to a Windows GDI HDC. If you dereference the pointer first (the way _duDE_ does) the cast function in CDC kicks in and you'll get the HDC. However that's a bit clunky and a bit hard to follow if you don't know what you're up to.

So here's a bit of advice - stop casting and use automatic type deduction! You don't need casting in this case AND you never need a C style cast in C++. Instead why not just not read the HDC from the CDC object? I'd suggest:

C++
auto hdc = pDC->m_hDC;


and let the compiler deduce the type of hdc AND subsequently warn you if you try and use the object in a weird way.
 
Share this answer
 
Comments
Leo Chapiro 13-Jan-16 8:03am    
Thank you for advice, +5!
StephenJElliott 13-Jan-16 8:17am    
Thank you... like in the comment for Solution 1, this highlights the approach I took that basically works; except I recommend explicitly type casting the variable to avoid these situations as here:

HDC hdcfromcdc_pDC = pDC->m_hDC; // Get the HDC for the existing window's PDC to create the compatible bitmap

The "auto" keyword "Specifies that the type of the variable that is being declared will be automatically deduced from its initializer." (quote from http://en.cppreference.com/w/cpp/language/auto ); it is important to allow the compiler to perform all of its checks by explicitly typing the variables whenever possible. Plus it makes the code a little easier to understand, I believe, mostly in the case that there is a compiler error that catches the issue before run-time. Then, the coder can just view on the left the type, and then highlight the method at right (at least in Visual Studio 12) and see what type it should be, compare the two of them right away, and get the compile-time bug cleaned up right away.

More for the programmer than the compiler would be the use of the explicit type casting. Even an advanced programmer may want the code to be easily readable and maintainable by a programmer at the lowest-common-possible denominator so that it is easy to support down the road.
Aescleal 13-Jan-16 9:37am    
I'd disagree in the general case: You don't need types checked at initialisation time, you need them checked when they're used. I'd contend that explicit typing often makes code far harder to read (the type of a declaration is often longer than the expression it's initialised from) while implicit typing removes the need for long lists of typedefs. As an example consider what std::find returns when operating on an array of lists of unique pointers to widgets. And all the ways you can write the declaration of the return type using the typedefs declared by vector, list and unique_ptr.

This is doubly true (as in your case) when all you're using the variable for is a simple alias - you could have used pDC->m_hDC everywhere you used verylongnameforadevicecontext. If you keep your functions short your initialisations will never be far away from their usage and if it turns out that the type of a variable is not what you thought it was it means that whatever you used to initialise it wasn't quite what you thought it was.

And really you never want to use explicit type casting - except in some rare cases (low level bit fiddling/hardware interfaces) - in well designed code. Explicit type casting in C++ is usually a sign that you're mangling the intent of an interface and the code you're calling is trying to tell you something that you're avoiding.
If you want to work with Handles most classes have GetSafe method. e.g. GetSafeHdc in current case?
Also you should use wrappers for CreateCompaitbleBitmap which operate on CDC directly?
Also you have a bool which you dont seem to check? Also you should always check what does GetLastError say when some API fails?
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900