I'm trying to work with bitmaps now, but I'm quite confused about it.
1) Use the LoadBitmap function. I understand this.
2) Use the GetObject function so you can get information about the bitmap (height etc.). I understand this.
Up to this point I have no trouble understanding it. But now the painting...
3) Get a HDC with BeginPaint and end this with EndPaint at the end.
4) Use the CreateCompatibleDC function to create a new system memory device context.
This last one I don't really understand. What is a "system memory device context"?
I understand what a device context is, but why use a second one here and why is it's parameter the first dc?
5) Use SelectObject. That line of code is this:
oldBM = (HBITMAP)SelectObject(bitmHDC, hBitMap);
Why is this line of code needed?
6) Use BitBlt to copy the pixels - I understand this.
7) Use SelectObject again. Why? The code looks like this:
SelectObject(bitmHDC, oldBM);
It seems this is not nessesary, but what happens here?
8) Use DeleteDC to remove this "system memory device context". Why remove this and not the "normal" (or however I should call it) hdc?
9) Use DeleteObject to remove the bitmap. I understand this.
So I have trouble understanding this "system memory device context" and all functions related to it. Can someone explain these for me?
A system memDC is pretty much the same as a regular DC, except that it resides in memory and does not show anywhere in the screen.
4) You create a memDC to be able to select the bitmap object. You need to do this because you must blit from one DC to the other. If you did not use a memDC, what else would you use? Another on-screen DC? That would look bad, and it is not possible.
5) Read a bit more about device contexts and graphic objects. Pretty much a device context has a default object already in it for each type of object (pen, brush, bitmap, font, etc.). The SelectObject() function returns the old object. If you don't want memory and resource leaks, you must leave the DC as you found it. This is why #7.
8) You created a memDC. If you don't want your application to leak resources, you must undo what you did. Part of that undo is the deletion of the created memDC. You don't do this for the regular DC because you did not create it in the first place. Its cleanup takes place elsewhere and you need not worry about it.
3. By the way BeginPaint and EndPaint are only valid when processing a WM_PAINT
message - they should not be used outside of this.
If you need to get the DC at any other time use GetDC function.
In either case, the DC returned is the DC of the screen. Anthing drawn in this DC ends up on the screen.
To be more specific a DC to the client area of the specified window is returned.
4. CreateCompatibleDC.
This creates an in memory DC which matches the type of DC that you passed to it.
There is more than one type of DC. You can get a DC for the Screen (as described above) and you can get a DC for a printer.
This memory DC is used when doing complicated stuff - and you don't want screen flicker - you
do your stuff on the memory DC then blit it to the screen DC (or printer DC for that matter).
The compatible DC created is only 1 pixel in size.
To size it to what ever size you want - you select a bitmap into it - see next point.
5. To make the memory DC the size you want you select a bitmap into it.
You can load one from your exe file resource, or from a file - OR you can create one by using CreateCompatibleBitmap
When created, the memory DC has a default pen(black), default brush(white), default 1x1 bitmap, and default font.
To do your own thing, you will create pens, brushes fonts as needed, BUT before you can use them in the DC you must select them into the DC - hence the SelectObject function.
Note you can only have one of each GDI Object like a pen active in the dc at a time.
When SelectObject is called, the return value is the handle of the current object in the dc of that type. That is to say if you select a pen into the dc, then the handle of the current pen is returned.
Like a good programmer once you have finished with the dc - you should return it to the state
that you were given it. That is you select the original pen, brush, font back into the DC.
Also like a good programmer, once you have finsihed with the pens/brushes/etc.. that you
created you should delete them to avoid memory leaks.
This also includes deleting the memory DC when you have finished with it.
Note: You should NOT delete an object whilst it is selected into the DC.
Thank you for the clear explaination. But when we have this:
oldBM = (HBITMAP)SelectObject(bitmHDC, hBitMap);
What will oldBM contain after this? I understand that will be the handle of the current object in the dc, but there is nothing in there yet? Will oldBM contain the default things ("default pen(black), default brush(white), default 1x1 bitmap, and default font.")?
If you select a bitmap object into the DC, then the handle of the previous bitmap that was in the DC is returned.
It is like for like - select a pen and the previous pen handle is returned.
As I said earlier, the DC is created with a default 1X1 pixel monochrome bitmap already selected into it.
Since you can only delete pens, brushes, bitmaps, etc. when they are NOT selected inside a device context, not deselecting them (by selecting the previous objects) makes it impossible to delete them. Since they can't be deleted, memory is leaked.
Is it ok to continue using the same memory DC throughout the program and delete it only before shutting down the program? After BitBlt to the screen DC, can the memory DC not just be overwritten again for the next screen? Or does it have to be deleted and then recreated each time?