c++ - win32 - my image class

i'm trying reading a ICO file an draw it:
1
2
3
4
5
6
7
HDC hdcimage=NULL;

    HICON hicon;
    HICON hiconimage;
hiconimage =  (HICON)LoadImage(NULL, filename.c_str(), IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
            hdcimage = CreateCompatibleDC(NULL);
            DrawIcon(hdcimage,0,0,hiconimage);

what i'm doing wrong for draw the image?
Try using the LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName) function.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648072(v=vs.85).aspx
Last edited on
As far as I can see the image should be loading correctly. So using LoadIcon should not be necessary.


You are creating a DC that is compatible with the display -- but you are not putting a bitmap in that DC. The default bitmap, IIRC, is a 1x1 monochrome bitmap. So it obviously is not going to work for holding the icon's image.

You'll have to create a new bitmap to put in your hdcimage DC. Of course... with all the usual cleanup crap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// this stufff is OK:
HICON hiconimage =  (HICON)LoadImage(NULL, filename.c_str(), IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
HDC hdcimage = CreateCompatibleDC(NULL);

// but now we need to make a bitmap for our DC
HBITMAP bmp = CreateBitmap(200,200,1,32,NULL);  // create a 200x200 32-bit bitmap
HBITMAP old = (HBITMAP)SelectObject(hdcimage,bmp);  // put that bitmap in the DC
    // be sure to capture the old one for cleanup

DrawIcon(hdcimage,0,0,hiconimage);  // <- now this will work.



//  ... for cleanup
SelectObject(hdcimage,old);  // put the old bmp back in
DeleteDC(hdcimage);  // kill the DC we created
DeleteObject(bmp);  // kill the bitmap we created
DeleteObject(hiconimage);  // kill the icon we loaded 
Dish: thanks for all ;)
but i see some problems:
1
2
3
4
5
6
7
8
9
10
11
 hicon = (HICON)LoadImage(NULL, "C:\\acrobat.ico", IMAGE_ICON, 0 , 0 , LR_LOADFROMFILE|LR_SHARED);
            ICONINFO s;
            GetIconInfo(hicon,&s);
            bm.bmHeight=s.yHotspot;
            bm.bmWidth=s.xHotspot;

            hdcimage = CreateCompatibleDC(NULL);
            HBITMAP bmp = CreateBitmap(s.xHotspot,s.yHotspot,1,32,NULL);  // create a 200x200 32-bit bitmap
            HBITMAP old = (HBITMAP)SelectObject(hdcimage,bmp);  // put that bitmap in the DC
            // be sure to capture the old one for cleanup
            DrawIcon(hdcimage,0,0,hicon);

i see the image, but not in right size :(
EDIT:

Apparently I'm wrong. After a bit more reading I discovered something that suggests icon groups are not stored in .ico files. So 1 .ico file = 1 image... not several images as I suggest below.

If you are loading the wrong size icon... make sure you are loading the right .ico file.

/EDIT



Icons are weird because they consist of several images -- each of varying size. When you use DrawIcon, you are drawing whichever the icon marks as the default size... which clearly is not the size you want.

That said... this bit of your code baffles me:

HBITMAP bmp = CreateBitmap(s.xHotspot,s.yHotspot,1,32,NULL);

The hotspot is not the dims of the icon. According to MSDN... for icons, the hotspot is in the center of the image. So this probably isn't what you want.



You probably need to see which size images are in the icon. Then pull out one of them. AFAIK this can't be done with GetIconInfo/DrawIcon. But perhaps can be done with GetIconInfoEx/DrawIconEx? I've never done this before so I'm not sure.


Looking at DrawIconEx, it appears to operate more or less the same as DrawIcon, but allows you to specify the width/height:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms648065%28v=vs.85%29.aspx

So if you want to draw a 32x32 icon:

1
2
3
4
5
6
7
8
9
10
11
hicon = (HICON)LoadImage(NULL, "C:\\acrobat.ico", IMAGE_ICON, 0 , 0 , LR_LOADFROMFILE|LR_SHARED);

// no need to GetIconInfo -- that doesn't give you any information you need

hdcimage = CreateCompatibleDC(NULL);

HBITMAP bmp = CreateBitmap(32,32,1,32,NULL);  // <- 32x32 image
HBITMAP old = (HBITMAP)SelectObject(hdcimage,bmp);

// draw a 32x32 image at coord 'x','y':
DrawIconEx( hdcimage, x, y, hicon, 32, 32, 0, NULL, DI_NORMAL );




As for enumerating all the available sizes in an Icon... I have no idea how to do that. I didn't find anything useful on MSDN.
Last edited on
hicon = (HICON)LoadImage(NULL, "C:\\acrobat.ico", IMAGE_ICON, 0 , 0 , LR_LOADFROMFILE|LR_SHARED);

MSDN wrote:
HANDLE WINAPI LoadImage(
_In_opt_ HINSTANCE hinst,
_In_ LPCTSTR lpszName,
_In_ UINT uType,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuLoad
);

cxDesired [in]
Type: int
The width, in pixels, of the icon or cursor. If this parameter is zero and the fuLoad parameter is LR_DEFAULTSIZE, the function uses the SM_CXICON or SM_CXCURSOR system metric value to set the width. If this parameter is zero and LR_DEFAULTSIZE is not used, the function uses the actual resource width.
MSDN wrote:
LR_SHARED Do not use LR_SHARED for images that have non-standard sizes, that may change after loading, or that are loaded from a file.
When loading a system icon or cursor, you must use LR_SHARED or the function will fail to load the resource.
This function finds the first image in the cache with the requested resource name, regardless of the size requested.

but how can i get the icon size?
i found another way for reading the size, but i'm getting problems for reading the binary file:
1
2
3
4
5
6
const char *filePath = "C:\\acrobat.ico";
            char fileBuf;
            FILE *file = NULL;
            file = fopen(filePath, "rb");
            fread(&fileBuf, 1, 1, file);
            fclose(file);

ICON file structure:
- the 1st byte, in file, with 1 byte, of size, give me the width;
- the 2nd byte, in file, with 1 byte, of size, give me the height;
both sizes are in pixels.
what i'm doing wrong for read the file?
heres how i read the icon file and the size:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//create the transparent icon handle
            HICON hicon =  (HICON)LoadImage(NULL, filename.c_str(), IMAGE_ICON, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE|LR_LOADTRANSPARENT);

            //open the file for read the icon size
            FILE *file=fopen(filename.c_str(),"rb");

            //getting the icon size
            char width,height;
            fseek(file, 6, SEEK_SET);
            fread(&width,1,1,file);
            fread(&height,1,1,file);

            //close the file
            fclose(file);

            //save the icon size
            imageweight=width;
            imageheight=height;


            HBITMAP hbitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
            hdcimage = CreateCompatibleDC(NULL);//create a memory DC
            SelectObject(hdcimage, hbitmap);//add the bitmap to memory DC
            DrawIconEx(hdcimage,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);//draw the icon to DC with right size
            //seems the DrawIcon(), always, draw it with 32X32 size 

readers: never use the DrawIcon() for original size.
now i'm trying draw the cursor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//create the transparent icon handle
            HCURSOR hicon =  (HCURSOR)LoadImage(NULL, filename.c_str(), IMAGE_CURSOR, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE|LR_LOADTRANSPARENT);

            //open the file for read the icon size
            FILE *file=fopen(filename.c_str(),"rb");

            //getting the icon size
            char width,height;
            fseek(file, 6, SEEK_SET);
            fread(&width,1,1,file);
            fread(&height,1,1,file);

            //close the file
            fclose(file);

            //save the icon size
            imageweight=width;
            imageheight=height;

            MessageBox(NULL,to_string(imageheight).c_str(),"size",MB_OK);

            HBITMAP hbitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
            hdcimage = CreateCompatibleDC(NULL);//create a memory DC
            SelectObject(hdcimage, hbitmap);//add the bitmap to memory DC
            DrawIconEx(hdcimage,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);//draw the icon to DC with right size
            //seems the DrawIcon(), always, draw it with 32X32 size 

the cursor is drawed but not in right size :(
see the image:

http://s27.postimg.org/kps2yddir/cursor_size_problem.gif
i have seen the the cursor file structure from here: https://www.daubnet.com/en/file-format-cur
like you see is like ico.
(for show it transparent i must use the width and height or i can lose some curor color)
Topic archived. No new replies allowed.