Use a sprite C++ MFC - c++

I need to display an image from a sprite using MFC. A search on google led me to this link which led me to this code :
//This code is in the OnPaint function
//img is a CImage, declared as a class member
img.Load(_T("icon-sprite.png"));
HDC imgDc = img.GetDC();
int height = 24;
int width = 24;
//Sprite Icon is a CStatic
CDC* spriteDc = spriteIcon.GetDC();
HDC spriteHdc = spriteDc->GetSafeHdc();
CClientDC pDC(this);
HDC hdcWindow = pDC->GetSafeHdc();
//img.StretchBlt(imgDc, 0, 0, 600, 203, SRCCOPY);
//img.BitBlt(imgDc, width, height, 600, 203, 0, 0, SRCAND);
//img.BitBlt(imgDc, width, height, 640, 480, 0, 0, SRCPAINT);
StretchBlt(imgDc, 0, 0, 600, 203,
imgDc, 0, 0, 200, 203, SRCCOPY);
BitBlt(imgDc, width, height, 600, 203,
imgDc, 0, 0, SRCAND);
BitBlt(imgDc, width, height, 640, 480,
imgDc, 0, 0, SRCPAINT);
spriteIcon.SetBitmap((HBITMAP)img);
With this code spriteIcon only display a rectangle of the size of the sprite image.
What did I do wrong ?

Most probably CImage is local and going out of scope, thus the image (and HBITMAP) is invalid. You have two options:
Declare CImage such that it would exist even after this function returns.
Use CImage::Detach which returns a HBITMAP and relinquishes its ownership with handle (i.e. won't delete on destructor).
Please ensure that given image exists and is loaded properly.
Also, you don't need to new CClientDC, you can have it on stack.

Related

LoadImage() function not works

I have a problem with LoadImage.(Invalid Handle Error*)
HDC screen = CreateCompatibleDC(0);
HDC imageDC = CreateDC(0, 0, 0, 0);
HBITMAP filebmp = (HBITMAP)LoadImage(NULL,_T("C:\\file.bmp"),IMAGE_BITMAP,200,200, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
SelectObject(imageDC, filebmp);
BOOL d = BitBlt(screen, 0, 0, 1920, 1080, imageDC, 0, 0, SRCCOPY);
This is my main Code. Where am I doing wrong?
I searched about it but couldn't find any solution for this.
Problem you may have is that your bitmap file is invalid, you can't just change .jpg to .bmp, your image needs to be saved as bmp.

C++ BitBlt displaying checkerboard and skewed colors

I'm attempting to draw to an off-screen device context / bitmap and move the image to the main hdc using bitblt. Here's the result I'm currently seeing:
The blue, yellow, and green bars on the left are being drawn directly to the window's hdc. The strange-looking ones on the right were drawn to the back buffer and copied over as a single frame. They should be identical, but clearly that's not the case.
Here's the code I'm using, reduced to a minimal example:
COLORREF color_yellow = RGB (224, 224, 0);
COLORREF color_green = RGB (0, 192, 0);
COLORREF color_blue = RGB (0, 0, 192);
HBRUSH brush_yellow = CreateSolidBrush (color_yellow);
HBRUSH brush_green = CreateSolidBrush (color_green);
HBRUSH brush_blue = CreateSolidBrush (color_blue);
HDC hdc = GetDC (Window);
HDC hdc_buffer = CreateCompatibleDC (hdc);
HBITMAP bitmap_buffer = CreateCompatibleBitmap (hdc_buffer, blit.screen_width, blit.screen_height);
SelectObject (hdc_buffer, bitmap_buffer);
draw_rectangle (hdc, 0, 0, 100, 30, brush_blue);
draw_rectangle (hdc, 0, 30, 100, 60, brush_yellow);
draw_rectangle (hdc, 0, 60, 100, 90, brush_green);
draw_rectangle (hdc_buffer, 0, 0, 100, 30, brush_blue);
draw_rectangle (hdc_buffer, 0, 30, 100, 60, brush_yellow);
draw_rectangle (hdc_buffer, 0, 60, 100, 90, brush_green);
BitBlt (hdc, 120, 0, 100, 90, hdc_buffer, 0, 0, SRCCOPY);
void draw_rectangle (HDC hdc, int left, int top, int right, int bottom, HBRUSH brush)
{
RECT rect;
SetRect (&rect, left, top, right, bottom);
FillRect (hdc, &rect, brush);
}
I'm creating a new hdc (compatible with the window's), creating a compatible bitmap, selecting it, drawing the rectangles, and bit blitting over with SRCCOPY. All of this looks right to me.
I'm sure there's some small thing I'm not doing, but I can't find it.
This is explained in documentation for CreateCompatibleBitmap:
Note: When a memory device context is created, it initially has a 1-by-1 monochrome bitmap selected into it. If this memory device context is used in CreateCompatibleBitmap, the bitmap that is created is a monochrome bitmap. To create a color bitmap, use the HDC that was used to create the memory device context
Therefore, change
CreateCompatibleBitmap(hdc_buffer, width, height);//monochrome
to
CreateCompatibleBitmap(hdc, width, height);//colored bitmap

C++ WinAPI Bitmap Memory Leaks?

So, I'm very new to WinAPI and I've succeeded in loading a sprite which I can move with the arrow keys. My teacher told me to be very careful with 'memory leaks' and I'm not sure how to free memory the right way because C++ has done it for me when I was doing console programming. I ran the program and it froze my computer for a minute after moving the character for a while so I guess I've done something wrong. Can you tell me how to properly free memory (if I've done it wrong) and if there's anything bad with my bitmap method that needs optimising? Thanks! Here's the code.
void LoadAndBlitBitmap(LPCSTR szFileName, HWND hwnd, HDC winDC, int xPos, int yPos)
{
//DEFINITIONS
/*TransparentBlt(destDC, destXpos, destYpos, sizeX, sizeY, srcDC, 0, 0, sizeX, sizeY, RGB(a, b, c)) = TRANSPARENT BITMAP BLIT. Ex. RGB(255, 255, 255) if background is white*/
/*BitBlt(destDC, destXpos, destYpos, sizeX, sizeY, srcDC, 0, 0, SRCCOPY); = SOLID BITMAP BLIT WITH NO TRANSPARENCY*/
//END DEFINITIONS
//-----Get the size of the window---------
RECT rect;
int win_width = 0;
int win_height = 0;
if(GetWindowRect(hwnd, &rect))
{
win_width = rect.right - rect.left; //Subtracting the right coordinate with the left gives the width
win_height = rect.bottom - rect.top; //Subtracting the bottom coordinate with the top gives the height
}
//----------------------------------------
HDC hdcMem = CreateCompatibleDC(winDC); //Create the DC that will hold the off-screen printing. (Double Buffering "Anti-Flicker" Method)
HBITMAP hbmMem = CreateCompatibleBitmap(winDC, win_width, win_height); //Create the bitmap with the size of the window
HANDLE hOld = SelectObject(hdcMem, hbmMem); //Set the paintable bitmap to the off-screen DC
//Draw to the off-screen DC
HBITMAP bitmap = (HBITMAP)LoadImage(NULL, szFileName, IMAGE_BITMAP, 69, 69, LR_LOADFROMFILE); //Load the .bmp from a file
HDC blockDC = CreateCompatibleDC(NULL); //Create a DC to hold the .bmp
SelectObject(blockDC, bitmap); //Select the .bmp to the DC
TransparentBlt(hdcMem, xPos, yPos, 69, 69, blockDC, 0, 0, 69, 69, RGB(255, 255, 255)); //Blit the .bmp to the DC*/
//Transfer off-screen DC to the screen
BitBlt(winDC, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);
// Uninitialize and deallocate resources
SelectObject(hdcMem, hOld);
DeleteDC(hdcMem);
SelectObject(blockDC, hOld);
DeleteDC(blockDC);
DeleteObject(bitmap);
}
Two things are wrong:
SelectObject(blockDC, hOld);
hOld did not come from blockDC, it came from hdcMem. You are not even saving the old bitmap from blockDC. Change to:
HBITMAP hOld2 = SelectObject(blockDC, bitmap);
// and
SelectObject(blockDC, hOld2);
Secondly, you are not deleting hbmMem anywhere. At the bottom, add:
DeleteObject(hbmMem);
Actually, a third thing is wrong too - you're not checking for failure in any of the API calls you make. You should check if things like CreateCompatibleDC return NULL, and abort and cleanup if so.

Strange StretchBlt behaviour in right to left mode

In my application I'm drawing a bitmap in all fammilar and usual way using StretchBlt:
hBitmap = (HBITMAP)LoadImage(hInst, L"NewBitmapImage.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBitmap);
StretchBlt(hdc, 100, 185, 100, 50, hdcMem, 0, 0, 100, 50, SRCCOPY);
It all works fine until WS_EX_LAYOUTRTL style is used for the main application window which results in the image width getting cropped by 1px. So, the problem only occurs when source width == destination width and when RTL style is used.
Is it a bug in StretchBlt or am I just not using it correctly?

Finding width of text

I am setting the font for a control like this:
HDC hdc = GetDC(NULL);
int lfHeight = -MulDiv(szFont, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(NULL, hdc);
HFONT font = CreateFont(lfHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Font.c_str());
SendMessage(hwnd,WM_SETFONT,(WPARAM)font,0);
The control is a static. How would I find the width of the text in the static for a given string?
Use GetTextExtentPoint32. You'll need to select the font into the DC first.
CDC::GetTextExtent() and CDC::GetOutputTextExtent() should help.