Problem with loading a bitmap with the LoadImage() function - c++

I develop an application in C++ on Windows CE 2013.
I want to load a bitmap from file and show it on-screen.
The problem is the LoadImage() function always returns NULL.
HDC hdcOkno;
hdcOkno = GetDC(hWnd);
HBITMAP hbmObraz;
hbmObraz = (HBITMAP)LoadImage(NULL, L"C:\\Users\\tykab\\OneDrive\\Pulpit\\bitmapy\\background_blue.bmp", IMAGE_BITMAP, 0, 0, NULL);
BITMAP bmInfo;
GetObject(hbmObraz, sizeof(bmInfo), &bmInfo);
BitBlt(hdcOkno, 50, 50, bmInfo.bmWidth, bmInfo.bmHeight, hdcOkno, 0, 0, SRCCOPY);

Update:
Since you are working on Windows CE platform, LoadImage() can not load bitmaps from files. You should use SHLoadDIBitmap() instead.
Original Answer:
From the LoadImage documentation:
name
Type: LPCTSTR
...
If the hinst parameter is NULL and the fuLoad parameter omits the LR_LOADFROMFILE value, the lpszName specifies the OEM image to load...
...
If the fuLoad parameter includes the LR_LOADFROMFILE value, lpszName is the name of the file that contains the stand-alone resource (icon, cursor, or bitmap file). Therefore, set hinst to NULL.
You are not specifying the LR_LOADFROMFILE flag in the fuLoad parameter. The last parameter should be set to the following when loading a file:
LR_DEFAULTSIZE | LR_LOADFROMFILE
As mentioned in the comments, it's always a good idea to check GetLastError() on errors.

Related

How can I add a transparent PNG as a toolbar icon?

My intention is to create a toolbar in Win32 containing a transparent icon. I have tried the following code to create a simple toolbar with one button having a custom image:
// Create the toolbar
HWND hToolbar = CreateWindow(TOOLBARCLASSNAME,
NULL,
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_AUTOSIZE | TBSTYLE_LIST | CCS_BOTTOM,
0, 0, 0, 0,
hwnd,
NULL,
ghInstance, // <-this is the HINSTANCE of the application
NULL);
// Set the font (this cannot be the problem)
SendMessage(hToolbar,
WM_SETFONT,
(WPARAM)hFontBold,
static_cast<LPARAM>(MAKELONG(TRUE, 0)));
auto hImagelist = ImageList_Create(32, 32,ILC_COLOR24 | ILC_MASK, 1, 0);
HBITMAP bitmap = static_cast<HBITMAP>(LoadImage(ghInstance,
/* ID_IMG_SPAWN is my custom resource -> */ MAKEINTRESOURCE(ID_IMG_SPAWN),
IMAGE_BITMAP,
32, 32,
NULL));
ImageList_AddMasked(hImagelist,
bitmap,
RGB(255,255,255) /* white is the transparent color */);
SendMessage(hToolbar,
TB_SETIMAGELIST,
static_cast<WPARAM>(0),
(LPARAM)hImagelist);
ImageList_Create only supports 24-bit bitmaps, which means there is no alpha channel for transparency. However, I can simulate a transparency effect by using a mask color via ImageList_AddMasked. (Here, I am setting white (RGB(255, 255, 255)) to the mask color.)
This worked fine, but the image displayed this way is extremely sharp/jagged because of the lack of granularity in the alpha channel (each pixel is either transparent or fully opaque).
I understand that the PNG format can solve this, since it provides a true alpha channel. I know that the PNG format is supported by Win32 ImageLists, but I don't know how to use it properly. (PNG resources can be added to Visual Studio resources, but I don't know how to use them from code.)
I couldn't find any way to make LoadImage load a PNG. The only supported types are IMAGE_BITMAP IMAGE_CURSOR and IMAGE_ICON. I changed the resource (ID_IMG_SPAWN) to a PNG file and tried each of those three types one by one, but all resulted in merely a blank display like this:
Can anyone help me out? How can I use LoadImage to load a transparent PNG and use it as a toolbar image?
ImageList_Create only supports 24-bit bitmaps, which means there is no alpha channel for transparency.
No, that's wrong. ImageList_Create supports 32-bit bitmaps as well.
Since you intend to create a toolbar in Win32 containing a transparent icon, you do NOT need to load a PNG at all. If you desire PNG you may have to work around with GdiPlus as #barmak says.
32-bit bitmap has 8 bits for ALPHA. Using 32-bit bitmaps can make the same effect as PNG does.
You say your button image was showing blank when you did these:
changed ILC_COLOR24 to ILC_COLOR32
changed the resource of ID_IMG_SPAWN to a 32-bit bitmap
IN FACT To show a 32-bit bitmap properly, you have to:
change ILC_COLOR24 to ILC_COLOR32
change the resource of ID_IMG_SPAWN to a 32-bit bitmap with premultiplied alpha.
create a DIB section to your bitmap when loading
(Win32's format requirement is very strict)
Q: How to create a DIB section to the bitmap?
A: Specify LR_CREATEDIBSECTION in the last parameter of LoadImage.
Explanation:
LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),MAKEINTRESOURCE(ID_IMG_SPAWN), IMAGE_BITMAP,32, 32,NULL)
This is your code of the LoadImage function. See the MSDN document of LoadImage, to create the DIB section, all you need is to specify LR_CREATEDIBSECTION in the last parameter of LoadImage.
Q: How to get a BMP with premultiplied alpha?
A: Pixelformer can help you convert your alpha-channeled file to a premultiplied-alpha BMP.
The steps are
Open your image (any format) in Pixelformer and choose Export from the menu
Select A8:R8:G8: B8 (32bpp) and Premultiplied Alpha, then click Ok.
Then you can save your BMP file! Import this BMP file to Visual Studio resources, replacing your previous 24-bit BMP.
Then, you don't need to use the ImageList_AddMasked (which makes the image sharp) anymore, because you already have a recognizable ALPHA in your 32-bit BMP. So, straight use ImageList_Add.
Okay, after the manipulations explained above your code should be this:
// Create the toolbar
HWND hToolbar = CreateWindow(TOOLBARCLASSNAME,NULL,
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_AUTOSIZE | TBSTYLE_LIST | CCS_BOTTOM,
0, 0, 0, 0, hwnd, NULL, ghInstance, NULL);
// Set the font (this cannot be the problem)
SendMessage(hToolbar, WM_SETFONT, (WPARAM)hFontBold,
static_cast<LPARAM>(MAKELONG(TRUE, 0)));
auto hImagelist =
ImageList_Create(32, 32,ILC_COLOR32 /*DON'T NEED THE MASK. CHANGED TO ILC_COLOR32.*/, 1, 0);
HBITMAP bitmap = static_cast<HBITMAP>(LoadImage((HINSTANCE)GetWindowLong(hwnd,
GWL_HINSTANCE), MAKEINTRESOURCE(ID_IMG_SPAWN), IMAGE_BITMAP,
32, 32, LR_CREATEDIBSECTION /*THIS IS IMPORTANT*/ ));
ImageList_Add(hImagelist, bitmap, NULL);
SendMessage(hToolbar, TB_SETIMAGELIST, static_cast<WPARAM>(0), (LPARAM)hImagelist);
This worked fine as below.
These I answered above is well enough to solve this problem.
For more information about DIB bitmaps and Premultiplied Alpha, see the links.
LoadImage will return NULL when trying to load PNG resource.
You can add your PNG resource as ICON. Otherwise use Windows Imaging Component, or Gdiplus+ to load the png resource.
Read PNG resource as follows:
HBITMAP loadimage(HINSTANCE hinst, const wchar_t* name)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if(auto hres = FindResource(hinst, name, RT_RCDATA))
if(auto size = SizeofResource(hinst, hres))
if(auto data = LockResource(LoadResource(hinst, hres)))
if(auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
return hbitmap;
}
...
auto hbitmap = loadimage(ghinst, MAKEINTRESOURCE(ID_PNG1 ));
if(hbitmap)
{
ImageList_AddMasked(himage, hbitmap, 0);
DeleteObject(hbitmap);
}
Resource definition should look like this:
ID_PNG1 RCDATA "file.png"

CMFCButton::SetImage - Bitmaps won't show

I'm trying to load bitmaps for my buttons with the function SetImage from the CMFCButton. I don't get any error or something, just a plain button. I'm doing the same thing with icons and it works, but I need it to load bitmap too. I need to LoadImage from a path and not from the resources.
Here's my code :
iconResource = path + m_type + _T("U") + extension; //i.e : C:\test\earthU.bmp
HANDLE hIcon = ::LoadImage(nullptr, iconResource, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//same thing for Hot and Disable bitmap
and the call for the SetImage function :
SetImage((HBITMAP)hIcon, 0, (HBITMAP)hIconHot, 0 , (HBITMAP)hIconDis);
Use LR_CREATEDIBSECTION|LR_LOADFROMFILE flag when loading bitmap files for CMFCButton
::LoadImage(nullptr, bitmapfile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
Partial explanation:
MFC source code for CMFCButton ("afxbutton.cpp") shows it adds LR_CREATEDIBSECTION for LoadImage. This is not documented and it is not clear why it needs that. It seems LR_CREATEDIBSECTION is required when source bitmap is not 32-bit.

Load Bitmap Image into WINApi C++ and Display

I am building a GUI using WINApi C++ Unicode. My ultimate goal is not to load the .bmp image from a file because i will be passing around the GUI as a .exe file.
Is it possible to load the .bmp image into the GUI's resource and load the image from there every time I want to display on my GUI?
Sure. There's a resource type specially for bitmaps. Just use "Add resource" in the Visual Studio resource view. Example code on how to use it should be available in the MSDN.
Put this in the resource (.rc) file
IDI_NORMAL BITMAP "Normal.bmp"
Then this in main colde (.cpp) file
HBITMAP hBMP = (HBITMAP)LoadBitmapW(hInst, MAKEINTRESOURCEW(IDI_NORMAL)); //test bitmap
HDC hMemDC = CreateCompatibleDC(hdc);
::SelectObject(hMemDC, hBMP);
BitBlt(hdc, 0, 0, 1000, 1000, hMemDC, 0, 0, SRCCOPY);
::DeleteDC(hMemDC);
Works perfectly

Drawing Image using WinAPI: LoadBitmap works but LoadImage() won't?

I'm pretty new to Windows programming and have been following theForger's Win32 API Programming Tutorial. I've been trying to draw an image inside a window.
Having looked at similar problems, this code seems to be correct for loading a bitmap:
HBITMAP testImage == NULL;
case WM_CREATE:
testImage = (HBITMAP)LoadImage(NULL, L"C:\\ScreenSnip.bmp", IMAGE_BITMAP, 498, 304, LR_LOADFROMFILE);
if(testImage == NULL) {
MessageBox(NULL, L"NO IMAGE LOADED!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
}
break;
I have an image called ScreenSnip.bmp at the location above, and its dimensions are 498*304. However, LoadImage doesn't work and the value of testImage is always null.
I have tried loading an image as a resource using LoadBitmap() and that works, which is why I haven't included the rest of my code. It seems to be LoadImage() above that's causing the problem, but I can't figure out why.
Anyone have any ideas? I'm running this using VC++ on Windows 7 64bit.
use testImage = (HBITMAP)LoadImage(NULL, L"C:\\ScreenSnip.bmp", IMAGE_BITMAP, 498, 304, LR_LOADFROMFILE);
you use wide wiht L"C:.." so you have to use LoadImageW

Load HBITMAP from *.bmp file in Win32 project

Is it possible to load a *.bmp file into a HBITMAP in a Win32 project, using only WINAPI functions?
Yes, it is possible using only the standard win32 library.
HBITMAP hBMP = (HBITMAP) LoadImage( NULL, "Your/ImagePath/a.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
hBMP is a handle to the BITMAP to use as you want.
Note: It is important to pass NULL as the first argument, from the docs:
hinst [in, optional]
To load a stand-alone resource (icon, cursor, or bitmap file)—for
example, c:\myimage.bmp—set this parameter to NULL.
From the msdn documentation for LoadImage.
Yes, you can use the OleLoadPictureFromPath or whatever it was called. Check it. The docs are probably still inconsistent and wrong about supported formats but in modern Windows also JPEG and PNG supported.