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.
Related
A very weird problem I encountered today. Running codes below on VC6 with MFC project and it is black screen, it works perfectly and shows desktop picture if I take out the comment. However these codes are executed in a infinite loop, so I try to reduce memory copy and memory spend like BitBlt and CreateCompatibleBitmap etc. I do not understand how is my program related to these commented codes. Anyone knows what cause the problem and why?
HDC hdcDesktop = ::CreateDC("DISPLAY", NULL, NULL, NULL);
RECT desktopRect;
::GetWindowRect(::GetDesktopWindow(), &desktopRect);
int desktopWidth = desktopRect.right - desktopRect.left;
int desktopHeight = desktopRect.bottom - desktopRect.top;
HBITMAP hBitmap = CreateCompatibleBitmap(hdcDesktop, desktopWidth, desktopHeight);
/*
HDC hdcMemory = CreateCompatibleDC(hdcDesktop);
SelectObject(hdcMemory, hBitmap);
BitBlt(hdcMemory, 0, 0, desktopWidth, desktopHeight, hdcDesktop, 0, 0, SRCCOPY);
*/
BITMAPINFO bitmapInfo = {0};
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
GetDIBits(hdcDesktop, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS);
BYTE *pData = new BYTE[bitmapInfo.bmiHeader.biSizeImage];
memset(pData, 0, bitmapInfo.bmiHeader.biSizeImage);
GetDIBits(hdcDesktop, hBitmap, 0, bitmapInfo.bmiHeader.biHeight, pData, &bitmapInfo, DIB_RGB_COLORS);
CRect destRect;
GetClientRect(&destRect);
StretchDIBits(::GetDC(m_hWnd), 0, 0, destRect.Width(), destRect.Height(), 0, 0, bitmapInfo.bmiHeader.biWidth, bitmapInfo.bmiHeader.biHeight,
pData, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
Here's why commenting out the section doesn't work...
HBITMAP hBitmap = CreateCompatibleBitmap(hdcDesktop, desktopWidth, desktopHeight);
HDC hdcMemory = CreateCompatibleDC(hdcDesktop);
SelectObject(hdcMemory, hBitmap);
// BitBlt makes a copy of the desktop here.
BitBlt(hdcMemory, 0, 0, desktopWidth, desktopHeight, hdcDesktop, 0, 0, SRCCOPY);
BITMAPINFO bitmapInfo = {0};
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// the following lines make use of the contents of bitmap in hBitmap
// commenting out the BitBlt would mean the bitmap is uninitialized.
//
GetDIBits(hdcDesktop, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS);
BYTE *pData = new BYTE[bitmapInfo.bmiHeader.biSizeImage];
memset(pData, 0, bitmapInfo.bmiHeader.biSizeImage); // <-- this is unnecessary.
GetDIBits(hdcDesktop, hBitmap, 0, bitmapInfo.bmiHeader.biHeight, pData, &bitmapInfo, DIB_RGB_COLORS);
You can optimize you code by creating a DIBSection, its associated BITMAPINFO and pData buffer at global scope for your app. Its dimensions are valid for quite a bit of time... You'd have to watch out for changes to screen resolution by handling WM_DISPLAYCHANGE messages (https://msdn.microsoft.com/en-us/library/windows/desktop/dd145210(v=vs.85).aspx).
This would save you the repeated call to CreateCompatibleBitmap().
There is no workaround that I can see to using BitBlt() and GetDIBits() for getting the desktop bits, though.
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);
UPDATED LOOK AT BOTTOM OF THIS POST
What I am doing is trying to use one Black and White bitmap, to lay a background bitmap on the white, and the tile overlay on the black. The problem I am having is adding the overlay.
and this is my BitBlt() code, this code produces #5.
hOldBitmap = (HBITMAP)SelectObject(hdcMem, bitmap.hbmBackground); // #2
BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem, 0, 0, SRCCOPY);
hOldBitmap = (HBITMAP)SelectObject(hdcMem, bitmap.hbmMap); // #1
BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem, 0, 0, SRCAND);
hOldBitmap = (HBITMAP)SelectObject(hdcMem, bitmap.hbmMapOverlay); // #4
BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem, 0, 0, SRCAND);
I am unsure about using the same "hOldBitmp", but it seems to do the same thing either way.
The transparent blt function would not fully suffice here, either.
Thanks.
NEW
I have been having trouble combining and rastoring. I can somewhat handle DC's and bitmaps, but this is one thing I cant figure out how to do... Creating memory dcs, and dcs to hold a bitmap, dc for another bitmap, then bitblt to the mem. I think...
Heres my redundant code I have at the moment. Really I am needing help with pseudo code, how to combine the bitmaps... how many DC's are necessary, etc..
buffer.getBufferDC() is the main DC that displays on the screen.
HDC hdc = GetDC(hWnd);
HDC hdcMem = CreateCompatibleDC(hdc);
HDC hdcMem2 = CreateCompatibleDC(hdc);
HDC hdcMem3 = CreateCompatibleDC(hdc);
HDC hdcMem4 = CreateCompatibleDC(hdc);
HBITMAP hbmMem3 = CreateCompatibleBitmap(hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
HBITMAP hbmMem4 = CreateCompatibleBitmap(hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
ReleaseDC(hWnd, hdc);
// Copy the map and clean the hdcMem
HBITMAP hbmOld;
hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.hbmMap);
BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
hbmOld = (HBITMAP)SelectObject(hdcMem2, bitmap.hbmBackground);
BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem2, 0, 0, SRCAND);
SelectObject(hdcMem2, hbmOld);
hbmOld = (HBITMAP)SelectObject(hdcMem3, bitmap.hbmMapOverlay);
hbmOld = (HBITMAP)SelectObject(hdcMem4, bitmap.hbmMap);
BitBlt(hdcMem3, 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem4, 0, 0, SRCINVERT);
BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem3, 0, 0, SRCPAINT);
//hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.hbmMap);
//BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem, 0, 0, SRCPAINT);
//SelectObject(hdcMem, hbmOld);
//hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.hbmMapOverlay);
//BitBlt(buffer.getBufferDC(), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, hdcMem, 0, 0, SRCAND);
//SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
DeleteDC(hdcMem2);
DeleteDC(hdcMem3);
DeleteDC(hdcMem4);
Combine hbmpBackground with hbmMap using SRCAND, as you've done in 3.
Combine hbmMapOverlay with an inverted hbmMap (SRCINVERT should do it).
Combine those two results using OR (SRCPAINT)
Although this can be done with BitBlt, it's usually quite a bit easier to use PlgBlt.
Start by BitBlting the background bitmap to the destination. Then call PlgBlt, passing it both the foreground bitmap and the mask.
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?
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.