Create a cursor from .cur format bytes? - c++

I can find a couple ways to create a cursor in win32 but I need the third, the one I can't find.
The first I can find is to use LoadXXX() to open a file or resource and load the cursor that way.
The second I can find is to use CreateCursor to take the hot-spot points, some data arrays, and make one out of bits.
I want the third way that's between the two: I have an array of bytes that contains a .cur file data. I want to use that data to make a cursor. Can this be done?

As I more briefly posted in a comment, I think the easiest and most sensible way is to just write the binary data stored in the array out to a temporary .CUR file on disk, and then use the LoadCursorFromFile function to read that .CUR file. You can then remove the temporary file. There's no reason to go hunting for complicated solutions when simpler ones will do.
That being said, if you really need a way to do this, you might consider doing something similar to what the .NET Framework team did to load a cursor object from a memory stream. This takes advantage of the similarity between cursors and icons.
Use the OleCreatePictureIndirect function to create a new uninitialized IPicture object, which you then initialize from your array of bytes in memory via the IPersistStream::Load method. Once you've done that, just use the CopyImage function to create a cursor from the loaded image.

Arguments to CreateCursor() are here: http://msdn.microsoft.com/en-us/library/ms648385(VS.85).aspx
HCURSOR WINAPI CreateCursor(
__in_opt HINSTANCE hInst,
__in int xHotSpot,
__in int yHotSpot,
__in int nWidth,
__in int nHeight,
__in const VOID *pvANDPlane,
__in const VOID *pvXORPlane
);
The .cur file format is documented on Wikipedia here: http://en.wikipedia.org/wiki/ICO_(file_format)#Legacy_format
You can get all the arguments to CreateCursor() out of that icon file header; I think the pointer to the image data probably has a bitmap for the and plane directly followed by a bitmap for the xor plane.

Whilst looking for the answer to this, I stumbled across CreateIconIndirect, which "Creates an icon or cursor from an ICONINFO structure" that specifies a bitmap handle (HBITMAP) for the cursor image (so you can use the Win32 API bitmap routines to prepare the cursor):
https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createiconindirect
HICON CreateIconIndirect(
PICONINFO piconinfo
);
Though its return type is HICON, the documentation says it returns an icon or cursor.
The ICONINFO structure has a boolean fIcon member to determine whether it is an icon (TRUE) or a cursor (FALSE):
typedef struct _ICONINFO {
BOOL fIcon;
DWORD xHotspot;
DWORD yHotspot;
HBITMAP hbmMask;
HBITMAP hbmColor;
} ICONINFO;
I've not yet used this in my program and realise this is a really old question, but hopefully it will point anyone else that is trying to do this in the right direction.

Can't be done. Best not to waste time trying. I was only trying to avoid having to convert a bunch of .cur files to something that sensible libraries support. Thought I'd use the HCURSOR constructor for QCursor, and I could, but it's just not worth the f'n bother trying to work around the worse imaginable API when I can just use PNG files or something.

Related

Trying to load a Bitmap from Resources returns NULL with an error code of 1813

I've been trying to load a bitmap from my resources in order to set it as an icon in one of my programs control for a good while now, with no success at all.
What I did so far:
First, I went into the code of my .rc file, and added all my bitmaps like this in the corresponding BMP section. Note that all .bmp files are saved as 256-color-bitmaps:
IDB_01d BMP "<path>"
Afterwards, I went into my Resource.h file and inserted a define for every bitmap, looking like this:
#define IDB_01d 2000
After adding my resources, this is what I tried in my code so far:
HBITMAP hbmp = LoadBitmap(m_hInstance, MAKEINTRESOURCE(IDB_01d));
DWORD lastError = GetLastError();
m_weatherIcon.SetIcon(hbmp);
Note that m_hInstance is the HINSTANCE i got from my _tWinMain-method.
However, this is not working. The problem is currently the fact, that hbmp is NULL, due to LoadBitmap returning a NULL value.
I added a call to get the last error, and the error code I'm getting is 1813 all the time. I already did some research, and it seems like the HINSTANCE might be the problem, but I don't see how exactly.
Any advice?
you need declare in .rc file
IDB_01d BITMAP "<path>"
but you using unknown resource type BMP

SDL and Visual Studio 2010 resources

I have a simple question. I use SDL and SDL_image in my c++ program and image loading is fine from a single png file.
SDL_Surface *dot = NULL;
dot = load_image("dot.png");
But how can I load the png file if I add it to the resources? so I don't want to store in a png file next to the exe. Is it possible to load from the resources?
Tried
dot = load_image(MAKEINTRESOURCE(IDB_PNG1));
but it didn't work.
It is fully possible to load an image or something else into SDL from a windows resource. To do this you need to get the raw data and pass it to the appropriate RWOPS.
HMODULE hModule = GetModuleHandle(_T("myapp.exe"));
HRSRC hWhite = FindResource(hModule, MAKEINTRESOURCE(IDB_WHITE_PNG), _T("PNG"));
unsigned int white_size = SizeofResource(hModule, hWhite);
HGLOBAL hgWhite = LoadResource(hModule, hWhite);
unsigned char* white_data = (unsigned char*)LockResource(hgWhite);
SDL_Surface* white = IMG_Load_RW(SDL_RWFromConstMem(white_data, white_size), 1);
This assumes that you have something similar in your *.rc file:
IDB_WHITE_PNG PNG "White.png"
According to the MAKEINTRESOURCE documentation :
The return value should be passed only to functions which explicitly indicate that they accept MAKEINTRESOURCE as a parameter.
You don't give the content of load_image (BTW, please include the content of the functions you use in your question, you'll get better answers ...) but I bet it's not using its parameter to call one of the Windows SDK functions which accept MAKEINTRESOURCE ... as far as I know these resources are supposed to hold some specific Windows UI data like mouse cursors, icons, etc.. for use with Windows functions, not with other libraries like SDL, so I'm not surprised it doesn't work.

How can I load a jpg file into CBitmap (visual c++ 6.0)?

How can I load a jpg into a CBitmap where I am using visual c++ 6.0 and don't have access to CImage?
thx
I would simply call OleLoadPicturePath api to load not just jpg but other common formats also.
After loading it into the IPicture object you can call get_Handle to get the handle to HBITMAP.
Thanks
There's no native way I know of. I've always used FreeImage for JPGs and PNGs - it's robust and there's example code in the FAQ on how to load a PNG into an HBITMAP (which works exactly the same for a JPG).
One word of warning from experience - if you're storing your JPG as a resource, make sure you create a "JPG" resource type and store it as that, don't try and add it as a BITMAP resource or you'll have all sorts of problems trying to load it. I know it sounds obvious but it took me a while to figure out.
You can't, or at least, there isn't a build-in way. Have a look at CxImage, you can probably get that to work, especially when you only need jpg support.
This kind of conversion is complex so i would reccoment using an external libary, take a look at this.
CBitmap bmp;
HANDLE h = ::LoadImage(NULL, _T("c:\\MyImage.jpg"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
bmp.Attach(h);

How do you copy/paste image data?

Using C++ and the WinAPI, how do I copy the image data from a pre-loaded image into the clipboard?
You need to create an object that implements IDataObject, and then place it on the clipboard using OleSetClipboard.
When you place data in the clipboard you have the ability to specify multiple formats. This is so that the application reading the clipboard can enumerate the formats and decide which one to use.
There are quite a few "standard" clipboard formats (with known constant values), e.g.:
CF_BITMAP: A handle to a bitmap (HBITMAP).
CF_DIB: A memory object containing a BITMAPINFO structure followed by the bitmap bits.
CF_DIBV5: A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits.
You can also register custom formats using RegisterClipboardFormat. Office exposes images as a number of different formats that they've registered, e.g.:
DWORD CF_PNG = RegisterClipboardFormat("PNG");
DWORD CF_JFIF = RegisterClipboardFormat("JFIF");
DWORD CF_GIF = RegisterClipboardFormat("GIF");
DWORD CF_ENHMETAFILE = RegisterClipboardFormat("CF_ENHMETAFILE");
DWORD CF_METAFILEPICT = RegisterClipboardFormat("CF_METAFILEPICT ");
The EditCopy function on this page of MSDN gives a good example of what you want to achieve:
http://msdn.microsoft.com/en-us/library/ms649016(v=vs.85).aspx
You will need to change the data type from CF_TEXT to CF_BITMAP in order to tell windows it is of an bitmap mime type.

converting HBITMAP to byte array

I'm working with some scanner api which returns a HANDLE to an image in BMP format(so it is said so in documentation). I'm trying to somehow get BITMAP from this handle, but for example this code doesn't work:
HANDLE handle = getHandleFromScanner();
BITMAP bitmap;
int u = GetObject(handle, sizeof(BITMAP), &bitmap);
u is 0 here and getLastError() returns 6 which means that handle is invalid. But I cannot get any other handle except through getHandleFromScanner() function.
May be some transformations should be done with this handle? any ideas? What is the proper way to work with bitmap handles? Or any simple api exists? Samples I found via google didn't help me.
Thanks a lot.
Have you tried GetDIBits()? This should work but you'll need the device context as well. You may always want to call GetObjectType() on the handle to see if it is really returning an HBITMAP.
Thanks guys.
The handle appeared to be the image itself, so the following code solved the problem:
char* pImage = NULL;
HANDLE hImage= getHandleFromScanner();
pImage = (char *)GlobalLock(hImage);
// pImage now contains the bytes of the image
If someone will ever need it, the Scanner is Olivetti PR2 plus scanner.