ATL MFC shell extension DLL LoadImage fails with 1813
-
Not sure if this is the right forum since it also has to do with ATL but.. I'm programming a shell extension dll (context menu) based off the article "The Complete Idiot's Guide to Writing Shell Extensions" by Michael Dunn. So I made an ATL project with MFC and COM support. At first I started by using SetMenuItemBitmaps() to set the menu item icons, but then I found out that this method doesn't support transparency. Because achieving transparency for menu icons is apparently far from straightforward, I had the marvelous idea of looking at the Tortoise CVS shell code. I incorporated some of the ideas like using LoadImage() and GDI plus on Vista to blit the icons to a bitmap and make them look good that way, but I also noticed that they didn't use ATL and did reference counting themselves (and as such are also easily able to access the DLL's instance handle). My problem now is that each LoadImage() call fails with error code 1813 which according to MSDN means "The specified resource type cannot be found in the image file.". Now my best bet is that I'm somehow using the wrong module handle (the one of the EXE perhaps instead of the DLL), but I've tried everything I can think of to get the correct handle including: 1. Use the m_hInstance member of the global CWinApp instance. 2. Just pass in NULL for LoadImage(). 3. Use GetModuleHandle() with the dll name passed in. This returns a handle but it still fails with 1813. 4. Use MFC's AfxFindResourceHandle() to get a handle to the dll instance. This fails with an assertion error in some MFC file saying the current resource handle is not set (so i tried setting it with AfxSetResourceHandle() to the theApp.m_hInstance handle, but that just crashed). I'm starting to wonder if the people from tortoise intentionally decided not to use ATL so they could get the instance handle from DllMain(). Either way, it seems to me that I've bumped into some internal MFC/ATL funkyness and I can't figure it out. So if anyone knows more about this or has any suggestions, do tell :) Oh yea, note: For the resource I'm testing with I'm simply using a string id such as "IDI_TORTU" which I then pass to LoadImage(). greets
Kuniva --------------------------------------------
-
Not sure if this is the right forum since it also has to do with ATL but.. I'm programming a shell extension dll (context menu) based off the article "The Complete Idiot's Guide to Writing Shell Extensions" by Michael Dunn. So I made an ATL project with MFC and COM support. At first I started by using SetMenuItemBitmaps() to set the menu item icons, but then I found out that this method doesn't support transparency. Because achieving transparency for menu icons is apparently far from straightforward, I had the marvelous idea of looking at the Tortoise CVS shell code. I incorporated some of the ideas like using LoadImage() and GDI plus on Vista to blit the icons to a bitmap and make them look good that way, but I also noticed that they didn't use ATL and did reference counting themselves (and as such are also easily able to access the DLL's instance handle). My problem now is that each LoadImage() call fails with error code 1813 which according to MSDN means "The specified resource type cannot be found in the image file.". Now my best bet is that I'm somehow using the wrong module handle (the one of the EXE perhaps instead of the DLL), but I've tried everything I can think of to get the correct handle including: 1. Use the m_hInstance member of the global CWinApp instance. 2. Just pass in NULL for LoadImage(). 3. Use GetModuleHandle() with the dll name passed in. This returns a handle but it still fails with 1813. 4. Use MFC's AfxFindResourceHandle() to get a handle to the dll instance. This fails with an assertion error in some MFC file saying the current resource handle is not set (so i tried setting it with AfxSetResourceHandle() to the theApp.m_hInstance handle, but that just crashed). I'm starting to wonder if the people from tortoise intentionally decided not to use ATL so they could get the instance handle from DllMain(). Either way, it seems to me that I've bumped into some internal MFC/ATL funkyness and I can't figure it out. So if anyone knows more about this or has any suggestions, do tell :) Oh yea, note: For the resource I'm testing with I'm simply using a string id such as "IDI_TORTU" which I then pass to LoadImage(). greets
Kuniva --------------------------------------------
Try using the resource ID (numeric) with MAKEINTRESOURCE instead of the "IDI_TORTU" thing... aside of that, you sure you are specifying the right flags to LoadImage, maybe you are trying to load a BITMAP instead of an ICON and it cannot find a BITMAP among the resources with that ID (since it is an ICON) thus the error?
> The problem with computers is that they do what you tell them to do and not what you want them to do. < > Life: great graphics, but the gameplay sux. <
-
Try using the resource ID (numeric) with MAKEINTRESOURCE instead of the "IDI_TORTU" thing... aside of that, you sure you are specifying the right flags to LoadImage, maybe you are trying to load a BITMAP instead of an ICON and it cannot find a BITMAP among the resources with that ID (since it is an ICON) thus the error?
> The problem with computers is that they do what you tell them to do and not what you want them to do. < > Life: great graphics, but the gameplay sux. <
Code-o-mat, The LoadImage call looks like this:
HICON hIcon = (HICON) LoadImageA(handle, sIcon.c_str(), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
So it is loaded as type IMAGE_ICON, which it is in the resource file (I just copied the tortoise icon). Hmm I just tried it with a numeric identifier with MAKEINTRESOURCE and that does work however.. I want to use string identifiers like tortoise does because I'll be loading which icon to use from a configuration file (and I don't want to use numbers to indicate icons in that). I must be doing something wrong with the resources.. :/
Kuniva --------------------------------------------
-
Code-o-mat, The LoadImage call looks like this:
HICON hIcon = (HICON) LoadImageA(handle, sIcon.c_str(), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
So it is loaded as type IMAGE_ICON, which it is in the resource file (I just copied the tortoise icon). Hmm I just tried it with a numeric identifier with MAKEINTRESOURCE and that does work however.. I want to use string identifiers like tortoise does because I'll be loading which icon to use from a configuration file (and I don't want to use numbers to indicate icons in that). I must be doing something wrong with the resources.. :/
Kuniva --------------------------------------------
Alternatively you could "convert" the strings you use in the configuration file into numeric IDs in your code (like
if (strid == "IDI_TORTU") numid = IDI_TORTU; else ...
). I always used MAKEINTRESOURCE with LoadImage so i'm not sure about string-identification...could it be that the method doesn't actually expects you to specify "IDI_TORTU" but rather the file name the resource was imported from, for example "my_tortu_icon.ico"?> The problem with computers is that they do what you tell them to do and not what you want them to do. < > Life: great graphics, but the gameplay sux. <
-
Alternatively you could "convert" the strings you use in the configuration file into numeric IDs in your code (like
if (strid == "IDI_TORTU") numid = IDI_TORTU; else ...
). I always used MAKEINTRESOURCE with LoadImage so i'm not sure about string-identification...could it be that the method doesn't actually expects you to specify "IDI_TORTU" but rather the file name the resource was imported from, for example "my_tortu_icon.ico"?> The problem with computers is that they do what you tell them to do and not what you want them to do. < > Life: great graphics, but the gameplay sux. <
Eureka! : ) No it was nothing like that. Seems all this time I've been looking in the wrong place. I didn't know that for your resources to have string identifiers, you need to remove the define in whatever your numeric resource header file is maintained by visual studio. I just deleted IDI_TORTU in resource.h and now it works like a charm (doh :) ). Thanks for your help, if I hadn't simply tested with MAKEINTRESOURCE I'd still be debugging for instance handles ;)
Kuniva --------------------------------------------
-
Eureka! : ) No it was nothing like that. Seems all this time I've been looking in the wrong place. I didn't know that for your resources to have string identifiers, you need to remove the define in whatever your numeric resource header file is maintained by visual studio. I just deleted IDI_TORTU in resource.h and now it works like a charm (doh :) ). Thanks for your help, if I hadn't simply tested with MAKEINTRESOURCE I'd still be debugging for instance handles ;)
Kuniva --------------------------------------------
We always learn something new... :)
> The problem with computers is that they do what you tell them to do and not what you want them to do. < > Life: great graphics, but the gameplay sux. <