Strange StretchBlt behaviour in right to left mode - c++

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?

Related

Why TransparentBlt function cannot work on a bmp picture with a black background?

I want to embed a picture with a black background in another picture of green woods. But I discovered the TransparentBlt() function cannot work. While I embed a picture with a white background, the function works properly. Why?
This is my code:
HBITMAP hbm = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 1280, 720, LR_LOADFROMFILE);
HBITMAP hbm3 = (HBITMAP)LoadImage(NULL, L"character3.bmp", IMAGE_BITMAP, 535, 650, LR_LOADFROMFILE)
HBITMAP hbm5 = (HBITMAP)LoadImage(NULL, L"character5.bmp", IMAGE_BITMAP, 276, 418, LR_LOADFROMFILE);
HDC memdc = CreateCompatibleDC(hdc);
SelectObject(memdc, hbm);
BitBlt(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, memdc, 0, 0, SRCCOPY);
SelectObject(memdc, hbm3);
TransparentBlt(hdc, 40, 60, 506, 650, memdc, 0, 0, 535, 650, RGB(0,0,0));
SelectObject(memdc, hbm5);
TransparentBlt(hdc, 40, 60, 506, 650, memdc, 0, 0, 276, 418,RGB(253,253,253));
This is a failure result:
This is a success result:
To make the black background transparent, you need to create a new compatible DC like this:
HDC memdc = CreateCompatibleDC(hdc);
HDC memdc2 = CreateCompatibleDC(hdc);
SelectObject(memdc, hbm3);
TransparentBlt(memdc2, 40, 60, 506, 650, memdc, 0, 0, 535, 650, RGB(0,0,0));
BitBlt(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, memdc2, 0, 0, SRCCOPY);
Although not sure why, this works on my computer.

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

Use a sprite C++ MFC

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.

Converting ICON to BITMAP -- side-effect

How do I make it so that this code strictly does the conversion from a Windows ICON to a CBitmap?
The code is incorrectly displaying the new bitmap on screen. :(
This code was acquired from 'someone' on the web. And though it achieves it's goal of converting the ICON, it also displays the icon on screen (upper left hand corner) which it should not be doing.
D'oh!
void CUIHelper::ConvertIconToBitmap2(CBitmap& bmpObj, HICON hIcon)
{
CClientDC clientDC(NULL);
CDC memDC;
memDC.CreateCompatibleDC(&clientDC);
ASSERT(hIcon);
ICONINFO info;
VERIFY(GetIconInfo(hIcon, &info));
BITMAP bmp;
GetObject(info.hbmColor, sizeof(bmp), &bmp);
HBITMAP hBitmap = (HBITMAP)CopyImage(info.hbmColor, IMAGE_BITMAP, 0, 0, 0);
ASSERT(hBitmap);
ASSERT(memDC.GetSafeHdc());
HBITMAP hOldBmp = (HBITMAP)memDC.SelectObject(hBitmap);
clientDC.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(hOldBmp);
VERIFY( bmpObj.Attach(hBitmap) );
DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);
}
I am dumb when it comes to GDI.
clientDC.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);
should be
memDC.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);