: OK, my OGG-player is skinning properly (except for the main one, but I know why). Now, when I start the app, it preloads all the button bitmap images into an array of HBITMAPs. When I exit, whether due to an error or regular, I have a function to clean up the memory used by those images. I want to verify that I'm doing this properly. I check to make sure each HBITMAP isn't NULL in case I load half of the images, then one doesn't, so it calls the clean function to free JUST those that got allocated.
:
: void FreeSkin()
: {
: for(char Loop = 0; Loop < 20; Loop++)
: if(BtnImages[Loop] != NULL)
: DeleteObject(BtnImages[Loop]);
: }
:
: Would those images being selected into the button DCs be a problem? I Set them as the buttons in the function below. I only mess with them in this function, nowhere else.
:
: void DrawButtons(WPARAM ID, LPARAM ItemStruct)
: {
: HDC MemoryDC;
: HBITMAP OldImage;
: LPDRAWITEMSTRUCT Item;
:
: Item = (LPDRAWITEMSTRUCT)ItemStruct;
: if(Item->CtlType != ODT_BUTTON)
: return;
:
: MemoryDC = CreateCompatibleDC(Item->hDC);
: switch(ID)
: {
: case IDW_OPEN:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[0]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[1]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_PLAY:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[2]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[3]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_PAUSE:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[4]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[5]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_LAST:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[6]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[7]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_RW:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[8]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[9]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_STOP:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[10]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[11]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_FF:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[12]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[13]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_NEXT:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[14]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[15]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_CONFIG:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[16]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[17]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
:
: case IDW_EXIT:
: if(SendMessage(Item->hwndItem, BM_GETSTATE, 0, 0) & BST_PUSHED)
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[18]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: else
: {
: OldImage = (HBITMAP)SelectObject(MemoryDC, BtnImages[19]);
: StretchBlt(Item->hDC, Item->rcItem.left, Item->rcItem.top, Item->rcItem.right, Item->rcItem.bottom, MemoryDC, 0, 0, 32, 32, SRCCOPY);
: }
: break;
: }
:
: SelectObject(MemoryDC, OldImage);
: DeleteObject(OldImage);
: DeleteDC(MemoryDC);
: }
:
: So is my cleanup function good to go for a release?
: -
Sephiroth
:
I once made an interesting research: MSDN clearly states that HBITMAP being deleted by DeleteObject() MUST be deselected out of HDC. But when perform the DeleteObject() call on a still selected HBITMAP I got TRUE back from it, meaning that it was a sucess. I did not run this research on every Windows out there, but I think that any programmer should follow MSDN if he/she codes for Windows. So, my advice - before using DeleteObject() - deselect the images from HDC.